Skip to content

Instantly share code, notes, and snippets.

@cab1729
Created January 4, 2012 21:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cab1729/1562150 to your computer and use it in GitHub Desktop.
Save cab1729/1562150 to your computer and use it in GitHub Desktop.
MPFloat
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "MPFloat.h"
#include "jcl.h"
#include <gmp.h>
static jfieldID native_ptr;
#if DEBUG
#define TRACE(msg) fprintf (stderr, "%s(%s:%d) -- %s\n", __FUNCTION__, __FILE__, __LINE__, msg)
#else
#define TRACE(msg)
#endif
/*
* Initialize the native library. Specifically this method:
*
* a. Pass NULLs to the mp_set_memory_functions implying that GMP should use
* malloc, realloc and free for memory allocation, and if they fail GMP
* will print a message to the standard error output and terminates the
* program.
* b. Find out and store the reference to the NativeMPF class's 'native_ptr'
* field. This is done so later in the method invocations we can access that
* field and acquire the native value associated with that Pointer instance.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfInitializeLibrary (JNIEnv *env, jclass nativeMPF)
{
mp_set_memory_functions (NULL, NULL, NULL);
native_ptr = (*env)->GetFieldID (env, nativeMPF, "native_ptr", "Ljgmp/Pointer;");
}
/*
* Allocate and initialize the data structure for an instance of a nativeMPF.
*
* @param jthis an instance of nativeMPF.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfInitialize__ (JNIEnv *env, jobject jthis)
{
mpf_ptr _this;
jobject native_ptr_fld;
_this = (mpf_ptr)JCL_malloc (env, sizeof (mpf_t));
//initialize --GMP sets the value to zero.
mpf_init (_this);
//instantiate the Pointer instance for this nativeMPF.
native_ptr_fld = JCL_NewRawDataObject (env, _this);
//... and assign it to the native_ptr field.
(*env)->SetObjectField (env, jthis, native_ptr, native_ptr_fld);
}
/*
* Allocate and initialize the data structure for an instance of a nativeMPF
* and set default precision.
*
* @param jthis an instance of nativeMPF.
* @param defaultPrec default precision to set
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfInitialize__I (JNIEnv *env, jobject jthis, jint defaultPrec)
{
mpf_ptr _this;
jobject native_ptr_fld;
_this = (mpf_ptr)JCL_malloc (env, sizeof (mpf_t));
//initialize --GMP sets the value to zero.
mpf_init2 (_this, (int)defaultPrec);
//instantiate the Pointer instance for this nativeMPF.
native_ptr_fld = JCL_NewRawDataObject (env, _this);
//... and assign it to the native_ptr field.
(*env)->SetObjectField (env, jthis, native_ptr, native_ptr_fld);
}
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfFinalize (JNIEnv *env, jobject jthis)
{
mpf_ptr _this;
TRACE("begin");
_this = (mpf_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
if (_this != NULL)
{
mpf_clear (_this);
free (_this);
_this = NULL;
}
else
{
TRACE("WARNING: Already cleared + freed");
}
TRACE("end");
}
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfFromLong (JNIEnv *env, jobject jthis, jlong n)
{
mpf_ptr _this;
TRACE("begin");
_this = (mpf_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
//the size of jlong (64-bit) is either the same as a long, or that of a long long.
//if it's the former, we use as is.
if (sizeof (jlong) == sizeof (long))
{
mpf_set_si (_this, (signed long)n);
}
else
{
/*...otherwise, we operate on the two halves of the long long, each half
* being 32-bit wide. for simplicity, we work with positive
* values negating, if necessary, the final outcome.
*/
const int isnegative = n < 0 ? 1 : 0;
if (isnegative)
{
n = -n;
}
mpf_set_ui (_this, (unsigned long)(((unsigned long long)n) >> 32));
mpf_mul_2exp (_this, _this, 32); //shift left by 32 bits
mpf_add_ui (_this, _this, (unsigned long)n);
if (isnegative)
{
mpf_neg (_this, _this);
}
}
TRACE("end");
}
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfFromDouble (JNIEnv *env, jobject jthis, jdouble n)
{
mpf_ptr _this;
TRACE("begin");
_this = (mpf_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
mpf_set_d (_this, (double)n);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF. On exit, this will have the same
* value as x.
* @param x an instance of a nativeMPF's native pointer.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfFromMPF (JNIEnv *env, jobject jthis, jobject x)
{
mpf_ptr _this;
mpf_srcptr _x;
TRACE("begin");
_this = (mpf_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_x = (mpf_srcptr)JCL_GetRawData (env, x);
mpf_set (_this, _x);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF. On exit, this will have the value
* represented by the s Java string.
* @param s a Java string containing, a possibly signed, value to assign to
* this.
* @param rdx the base in which the symbols, in s, are represented.
* @return 0 if the entire string is a valid number in base rdx. Otherwise it
* returns -1.
*/
JNIEXPORT jint JNICALL
Java_jgmp_MPFloat_mpfFromString (JNIEnv *env, jobject jthis, jstring s, jint rdx)
{
mpf_ptr _this;
const char *_s;
int result;
TRACE("begin");
_this = (mpf_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_s = (*env)->GetStringUTFChars (env, s, NULL);
result = mpf_set_str (_this, _s, (int)rdx);
JCL_free_cstring (env, s, _s);
TRACE("end");
return (result);
}
/*
* @param jthis an instance of nativeMPF. On exit, this will have the value
* represented by the m Java byte array (most significant byte at
* index position 0). It will be positive, or negative, depending on
* the value of isnegative.
* @param m a Java byte array containing the byte representation of the
* absolute value (most significant byte being at index position 0)
* to assign to this.
* @param isnegative true if this should be negative and false if it should
* be positive.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfFromSignedMagnitude (JNIEnv *env, jobject jthis, jbyteArray m, jboolean isnegative)
{
mpf_ptr _this;
jbyte *_m;
int mlength, i;
TRACE("begin");
_this = (mpf_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_m = (*env)->GetByteArrayElements (env, m, NULL);
mlength = (*env)->GetArrayLength (env, m);
mpf_set_ui (_this, 0);
for (i = 0; i < mlength; i++)
{
mpf_mul_2exp (_this, _this, 8);
mpf_add_ui (_this, _this, (unsigned long)(_m[i] & 0xFF));
}
(*env)->ReleaseByteArrayElements (env, m, _m, JNI_ABORT);
if (isnegative == JNI_TRUE)
{
mpf_neg (_this, _this);
}
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param n the base in which to represent this.
* @return the Java string representing the value of this in base n.
* fix: changed to get string with gmp_snprintf no longer requires base value
*/
JNIEXPORT jstring JNICALL
Java_jgmp_MPFloat_mpfToString (JNIEnv *env, jobject jthis, jint n)
{
mpf_srcptr _this;
char buf[10 * GMP_LIMB_BITS + 5];
int p;
jstring result;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
p = mpf_get_prec(_this)/2;
gmp_snprintf (buf, sizeof(buf), "%.*Fe", p, _this, p);
result = (*env)->NewStringUTF (env, buf);
TRACE("end");
return (result);
}
/*
* @param jthis an instance of nativeMPF.
* @return the, eventually truncated, double value of this nativeMPF.
*/
JNIEXPORT jdouble JNICALL
Java_jgmp_MPFloat_mpfDoubleValue (JNIEnv *env, jobject jthis)
{
mpf_srcptr _this;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
TRACE("end");
return ((jdouble)mpf_get_d (_this));
}
/*
* @param jthis an instance of nativeMPF.
* @return the signed long integer value of this nativeMPF.
*/
JNIEXPORT jlong JNICALL
Java_jgmp_MPFloat_mpfLongValue (JNIEnv *env, jobject jthis)
{
mpf_srcptr _this;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
TRACE("end");
return ((jlong)mpf_get_si (_this));
}
/*
* @param jthis an instance of nativeMPF.
* @return the possibly truncated float value of this nativeMPF.
*/
JNIEXPORT jfloat JNICALL
Java_jgmp_MPFloat_mpfFloatValue (JNIEnv *env, jobject jthis)
{
mpf_srcptr _this;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
TRACE("end");
return ((jfloat)mpf_get_si (_this));
}
JNIEXPORT jint JNICALL
Java_jgmp_MPFloat_mpfGetDefaultPrec (JNIEnv *env, jclass nativeMPF)
{
return ((jint) mpf_get_default_prec ());
}
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfSetDefaultPrec (JNIEnv *env, jclass nativeMPF, jint p)
{
mpf_set_default_prec ((int)p);
}
JNIEXPORT jint JNICALL
Java_jgmp_MPFloat_mpfGetCurrentPrec (JNIEnv *env, jobject jthis)
{
mpf_srcptr _this;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
TRACE("end");
return ((jint) mpf_get_prec (_this));
}
JNIEXPORT jint JNICALL
Java_jgmp_MPFloat_mpfCompare (JNIEnv *env, jobject jthis, jobject x)
{
mpf_ptr _this, _x;
int res;
TRACE("begin");
_this = (mpf_ptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_x = (mpf_ptr)JCL_GetRawData (env, x);
res = mpf_cmp (_this, _x);
TRACE("end");
if (res == 0)
return ((jint)0);
else if (res < 0)
return ((jint)-1);
else
return ((jint)1);
}
/* @param jthis an instance of nativeMPF.
* @param x an instance of nativeMPF's Pointer.
* output:
* @param r a nativeMPF's Pointer such that r = this + x.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfAdd (JNIEnv *env, jobject jthis, jobject x, jobject r)
{
mpf_srcptr _this, _x;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_x = (mpf_srcptr)JCL_GetRawData (env, x);
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_add (_r, _this, _x);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param n a non-negative number to add to this.
*
* output:
* @param r a nativeMPF's Pointer such that r = this + n.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfAddUI (JNIEnv *env, jobject jthis, jint n, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_add_ui (_r, _this, (unsigned long)n);
TRACE("end");
}
/* @param jthis an instance of nativeMPF. */
/* @param x an instance of nativeMPF's Pointer. */
/* output: */
/* @param r a nativeMPF's Pointer such that r = this - x. */
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfSubtract (JNIEnv *env, jobject jthis, jobject x, jobject r)
{
mpf_srcptr _this, _x;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_x = (mpf_srcptr)JCL_GetRawData (env, x);
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_sub (_r, _this, _x);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param n a non-negative number to subtract from this.
*
* output:
* @param r a nativeMPF's Pointer such that r = this - n.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfSubUI (JNIEnv *env, jobject jthis, jint n, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_sub_ui (_r, _this, (unsigned long)n);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param x an instance of nativeMPF's Pointer.
* output:
* @param r a nativeMPF's Pointer such that r = this * x.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfMultiply (JNIEnv *env, jobject jthis, jobject x, jobject r)
{
mpf_srcptr _this, _x;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_x = (mpf_srcptr)JCL_GetRawData (env, x);
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_mul (_r, _this, _x);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param n a non-negative number to multiply this by.
*
* output:
* @param r a nativeMPF's Pointer such that r = this * n.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfMultUI (JNIEnv *env, jobject jthis, jint n, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_mul_ui (_r, _this, (unsigned long)n);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param n a non-negative number to raise this to.
*
* output:
* @param r a nativeMPF's Pointer such that r = this ** n.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfPow (JNIEnv *env, jobject jthis, jint n, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_pow_ui (_r, _this, (unsigned long)n);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param n a nativeMPF to divide this by.
*
* output:
* @param r a NativeMPF's Pointer such that r = this / n.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfDiv (JNIEnv *env, jobject jthis, jobject x, jobject r)
{
mpf_srcptr _this, _x;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_x = (mpf_srcptr)JCL_GetRawData (env, x);
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_div (_r, _this, _x);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
* @param n a non-negative number to divide this by.
*
* output:
* @param r a nativeMPF's Pointer such that r = this / n.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfDivUI (JNIEnv *env, jobject jthis, jint n, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_div_ui (_r, _this, (unsigned long)n);
TRACE("end");
}
/*
* @param jthis an instance of NativeMPF.
*
* output:
* @param r a NativeMPF's Pointer such that r = absolute value of this.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfAbs (JNIEnv *env, jobject jthis, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_abs (_r, _this);
TRACE("end");
}
/*
* @param jthis an instance of NativeMPF.
*
* output:
* @param r a NativeMPF's Pointer such that r = -this.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfNegate (JNIEnv *env, jobject jthis, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_neg (_r, _this);
TRACE("end");
}
/*
* @param jthis an instance of NativeMPF.
*
* output:
* @param r a NativeMPF's Pointer such that r = square root of this.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfSqrt (JNIEnv *env, jobject jthis, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_sqrt (_r, _this);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
*
* output:
* @param r a nativeMPF's Pointer such that r = this rounded to the next lower integer.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfFloor (JNIEnv *env, jobject jthis, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_floor (_r, _this);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
*
* output:
* @param r a nativeMPF's Pointer such that r = this rounded to the next higher integer.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfCeil (JNIEnv *env, jobject jthis, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_ceil (_r, _this);
TRACE("end");
}
/*
* @param jthis an instance of nativeMPF.
*
* output:
* @param r a nativeMPF's Pointer such that r = this rounded to the integer towards zero.
*/
JNIEXPORT void JNICALL
Java_jgmp_MPFloat_mpfTrunc (JNIEnv *env, jobject jthis, jobject r)
{
mpf_srcptr _this;
mpf_ptr _r;
TRACE("begin");
_this = (mpf_srcptr)JCL_GetRawData (env, (*env)->GetObjectField (env, jthis, native_ptr));
_r = (mpf_ptr)JCL_GetRawData (env, r);
mpf_trunc (_r, _this);
TRACE("end");
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jgmp_MPFloat */
#ifndef _Included_jgmp_MPFloat
#define _Included_jgmp_MPFloat
#ifdef __cplusplus
extern "C" {
#endif
#undef jgmp_MPFloat_serialVersionUID
#define jgmp_MPFloat_serialVersionUID -8742448824652078965i64
#undef jgmp_MPFloat_serialVersionUID
#define jgmp_MPFloat_serialVersionUID 6326861026105157637i64
/*
* Class: jgmp_MPFloat
* Method: mpfInitializeLibrary
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfInitializeLibrary
(JNIEnv *, jclass);
/*
* Class: jgmp_MPFloat
* Method: mpfInitialize
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfInitialize__
(JNIEnv *, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfInitialize
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfInitialize__I
(JNIEnv *, jobject, jint);
/*
* Class: jgmp_MPFloat
* Method: mpfFinalize
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfFinalize
(JNIEnv *, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfFromLong
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfFromLong
(JNIEnv *, jobject, jlong);
/*
* Class: jgmp_MPFloat
* Method: mpfFromDouble
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfFromDouble
(JNIEnv *, jobject, jdouble);
/*
* Class: jgmp_MPFloat
* Method: mpfFromMPF
* Signature: (Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfFromMPF
(JNIEnv *, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfFromString
* Signature: (Ljava/lang/String;I)I
*/
JNIEXPORT jint JNICALL Java_jgmp_MPFloat_mpfFromString
(JNIEnv *, jobject, jstring, jint);
/*
* Class: jgmp_MPFloat
* Method: mpfFromSignedMagnitude
* Signature: ([BZ)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfFromSignedMagnitude
(JNIEnv *, jobject, jbyteArray, jboolean);
/*
* Class: jgmp_MPFloat
* Method: mpfToString
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jgmp_MPFloat_mpfToString
(JNIEnv *, jobject, jint);
/*
* Class: jgmp_MPFloat
* Method: mpfDoubleValue
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_jgmp_MPFloat_mpfDoubleValue
(JNIEnv *, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfLongValue
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_jgmp_MPFloat_mpfLongValue
(JNIEnv *, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfFloatValue
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_jgmp_MPFloat_mpfFloatValue
(JNIEnv *, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfGetDefaultPrec
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jgmp_MPFloat_mpfGetDefaultPrec
(JNIEnv *, jclass);
/*
* Class: jgmp_MPFloat
* Method: mpfSetDefaultPrec
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfSetDefaultPrec
(JNIEnv *, jclass, jint);
/*
* Class: jgmp_MPFloat
* Method: mpfGetCurrentPrec
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_jgmp_MPFloat_mpfGetCurrentPrec
(JNIEnv *, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfCompare
* Signature: (Ljgmp/Pointer;)I
*/
JNIEXPORT jint JNICALL Java_jgmp_MPFloat_mpfCompare
(JNIEnv *, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfAdd
* Signature: (Ljgmp/Pointer;Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfAdd
(JNIEnv *, jobject, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfAddUI
* Signature: (ILjgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfAddUI
(JNIEnv *, jobject, jint, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfSubtract
* Signature: (Ljgmp/Pointer;Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfSubtract
(JNIEnv *, jobject, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfSubUI
* Signature: (ILjgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfSubUI
(JNIEnv *, jobject, jint, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfMultiply
* Signature: (Ljgmp/Pointer;Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfMultiply
(JNIEnv *, jobject, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfMultUI
* Signature: (ILjgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfMultUI
(JNIEnv *, jobject, jint, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfPow
* Signature: (ILjgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfPow
(JNIEnv *, jobject, jint, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfDiv
* Signature: (Ljgmp/Pointer;Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfDiv
(JNIEnv *, jobject, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfDivUI
* Signature: (ILjgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfDivUI
(JNIEnv *, jobject, jint, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfAbs
* Signature: (Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfAbs
(JNIEnv *, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfNegate
* Signature: (Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfNegate
(JNIEnv *, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfSqrt
* Signature: (Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfSqrt
(JNIEnv *, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfFloor
* Signature: (Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfFloor
(JNIEnv *, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfCeil
* Signature: (Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfCeil
(JNIEnv *, jobject, jobject);
/*
* Class: jgmp_MPFloat
* Method: mpfTrunc
* Signature: (Ljgmp/Pointer;)V
*/
JNIEXPORT void JNICALL Java_jgmp_MPFloat_mpfTrunc
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
package jgmp;
/**
* @author jmenes
* Implement arbitrary precision float using GMP
* based on code from GNU Classpath (GMP & Pointer classes)
*
*/
public final class MPFloat extends Number implements Comparable<MPFloat> {
private static final long serialVersionUID = 6326861026105157637L;
private int refCount = 1;
private static int defaultPrec = 64; // precision bit count - if not given, set from default
private Pointer native_ptr;
static {
System.loadLibrary("libgmp-3.dll");
System.loadLibrary("jgmp");
mpfInitializeLibrary();
}
// special values conforming to IEEE-754 float definitions
// TODO need to fix representation - using Double values crashes
public static final MPFloat NaN =
// (Double.longBitsToDouble(0x7ff8000000000000L));
//new MPFloat(0.0).mult(new MPFloat("1e400", 10));
new MPFloat("-10000000000000000000000e11111111", 2);
public static final MPFloat NEGATIVE_INFINITY =
// (Double.longBitsToDouble(0xfff0000000000000L));
new MPFloat("-1e400", 10);
//new MPFloat("-00000000000000000000000e11111111", 2);
public static final MPFloat POSITIVE_INFINITY =
// (Double.longBitsToDouble(0x7ff0000000000000L));
new MPFloat("1e400", 10);
//new MPFloat("00000000000000000000000e11111111", 2);
public MPFloat() {
super();
mpfInitialize();
defaultPrec = mpfGetDefaultPrec();
}
public MPFloat(int prec) {
super();
mpfInitialize(prec);
defaultPrec = mpfGetDefaultPrec();
}
public MPFloat(String s, int base, int prec)
{
this(prec);
fromString(s,base);
}
public MPFloat(String s, int base)
{
this();
fromString(s,base);
}
public MPFloat(String s)
{
this(s, 10);
}
public MPFloat(long n, int prec)
{
this(prec);
fromLong(n);
}
public MPFloat(long n)
{
this();
fromLong(n);
}
public MPFloat(double n)
{
this();
fromDouble(n);
}
public void fromMPF(MPFloat x)
{
acquireRef();
x.acquireRef();
mpfFromMPF(x.native_ptr);
x.releaseRef();
releaseRef();
}
public void fromLong(long n)
{
acquireRef();
mpfFromLong(n);
releaseRef();
}
public void fromDouble(double n)
{
// TODO implement a native mpfFromDouble
acquireRef();
mpfFromDouble(n);
releaseRef();
}
public int fromString(String s, int rdx)
{
acquireRef();
int result = mpfFromString(s, rdx);
releaseRef();
return result;
}
public void fromSignedMagnitude(byte[] m, boolean isNegative)
{
acquireRef();
mpfFromSignedMagnitude(m, isNegative);
releaseRef();
}
public String toString(int b)
{
acquireRef();
String result = mpfToString(b);
//String result = String.valueOf(mpfDoubleValue());
releaseRef();
return result;
}
public String toString()
{
return toString(10);
}
@Override
public int compareTo(MPFloat x) {
acquireRef();
x.acquireRef();
int result = mpfCompare(x.native_ptr);
x.releaseRef();
releaseRef();
return result;
}
@Override
public int intValue() {
acquireRef();
double result = mpfDoubleValue();
releaseRef();
return Double.valueOf(result).intValue();
}
@Override
public long longValue() {
acquireRef();
long result = mpfLongValue();
releaseRef();
return result;
}
@Override
public float floatValue() {
acquireRef();
double result = mpfDoubleValue();
releaseRef();
return Double.valueOf(result).floatValue();
}
@Override
public double doubleValue() {
acquireRef();
double result = mpfDoubleValue();
releaseRef();
return result;
}
/**
* @return default precision bits count
*/
public static int getDefaultPrec() {
defaultPrec = mpfGetDefaultPrec();
return defaultPrec;
}
/**
* @param prec default precision bit count to set
*/
public static void setDefaultPrec(int prec) {
defaultPrec = prec;
mpfSetDefaultPrec(defaultPrec);
}
/**
* @param x MPFloat object to add
* @return MPFloat object set to this + x
*/
public MPFloat add(MPFloat x) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
x.acquireRef();
mpfAdd(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return r;
}
/**
* @param x MPFloat value to add
* @param r MPFloat object to hold result of this + x
*/
public void add(MPFloat x, MPFloat r) {
acquireRef();
r.acquireRef();
x.acquireRef();
mpfAdd(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return;
}
/**
* @param x double object to add
* @return MPFloat object set to this + x
*/
public MPFloat add(double x) {
MPFloat r = new MPFloat(defaultPrec);
MPFloat s = new MPFloat(x);
acquireRef();
r.acquireRef();
s.acquireRef();
mpfAdd(s.native_ptr, r.native_ptr);
s.releaseRef();
r.releaseRef();
releaseRef();
return r;
}
/**
* @param x double value to add
* @param r MPFloat object to hold result of this + x
*/
public void add(double x, MPFloat r) {
MPFloat s = new MPFloat(x);
acquireRef();
r.acquireRef();
s.acquireRef();
mpfAdd(s.native_ptr, r.native_ptr);
s.releaseRef();
r.releaseRef();
releaseRef();
return;
}
/**
* @param n integer value to add to this
* return r MPFloat object to hold result of this + n
*/
public MPFloat add(int n) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfAddUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param n integer value to add to this
* @param r MPFloat object to hold result of this + n
*/
public void add(int n, MPFloat r) {
acquireRef();
r.acquireRef();
mpfAddUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @param x MPFloat object to subtract from this
* @return MPFloat object set to this - x
*/
public MPFloat sub(MPFloat x) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
x.acquireRef();
mpfSubtract(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return r;
}
/**
* @param x MPFloat object to subtract from this
* @param r MPFloat object to hold result of to this - x
*/
public void sub(MPFloat x, MPFloat r) {
acquireRef();
r.acquireRef();
x.acquireRef();
mpfSubtract(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return;
}
/**
* @param x double value to subtract from this
* @return MPFloat object set to this - x
*/
public MPFloat sub(double x) {
MPFloat r = new MPFloat(defaultPrec);
MPFloat s = new MPFloat(x);
acquireRef();
r.acquireRef();
s.acquireRef();
mpfSubtract(s.native_ptr, r.native_ptr);
s.releaseRef();
r.releaseRef();
releaseRef();
return r;
}
/**
* @param x double value to subtract from this
* @param r MPFloat object to hold result of to this - x
*/
public void sub(double x, MPFloat r) {
MPFloat s = new MPFloat(x);
acquireRef();
r.acquireRef();
s.acquireRef();
mpfSubtract(s.native_ptr, r.native_ptr);
s.releaseRef();
r.releaseRef();
releaseRef();
return;
}
/**
* @param n integer value to subtract from this
* return r MPFloat object to hold result of this - n
*/
public MPFloat sub(int n) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfSubUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param n integer value to subtract from this
* @param r MPFloat object to hold result of this - n
*/
public void sub(int n, MPFloat r) {
acquireRef();
r.acquireRef();
mpfSubUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @param x MPFloat object to multiply by this
* @return MPfloat object set to this * x
*/
public MPFloat mult(MPFloat x) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
x.acquireRef();
mpfMultiply(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return r;
}
/**
* @param x MPFloat object to multiply by this
* @param r MPFloat object to hold result of this * x
*/
public void mult(MPFloat x, MPFloat r) {
acquireRef();
r.acquireRef();
x.acquireRef();
mpfMultiply(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return;
}
/**
* @param n integer value to multiply by this
* return r MPFloat object to hold result of this * n
*/
public MPFloat mult(int n) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfMultUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param n integer value to multiply by this
* @param r MPFloat object to hold result of this * n
*/
public void mult(int n, MPFloat r) {
acquireRef();
r.acquireRef();
mpfMultUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @param x double value to multiply by this
* return r MPFloat object to hold result of this * n
*/
public MPFloat mult(double x) {
MPFloat r = new MPFloat(defaultPrec);
MPFloat m = new MPFloat(x);
acquireRef();
r.acquireRef();
m.acquireRef();
mpfMultiply(m.native_ptr, r.native_ptr);
r.releaseRef();
m.releaseRef();
releaseRef();
return r;
}
/**
* @param x double value to multiply by this
* @param r MPFloat object to hold result of this * n
*/
public void mult(double x, MPFloat r) {
MPFloat m = new MPFloat(x);
acquireRef();
r.acquireRef();
m.acquireRef();
mpfMultiply(m.native_ptr, r.native_ptr);
r.releaseRef();
m.releaseRef();
releaseRef();
return;
}
/**
* @param x MPFloat object to divide this by
* @return MPfloat object set to this / x
*/
public MPFloat div(MPFloat x) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
x.acquireRef();
mpfDiv(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return r;
}
/**
* @param x MPFloat object to divide this by
* @param r MPfloat object to hold result of this / x
*/
public void div(MPFloat x, MPFloat r) {
acquireRef();
r.acquireRef();
x.acquireRef();
mpfDiv(x.native_ptr, r.native_ptr);
x.releaseRef();
r.releaseRef();
releaseRef();
return;
}
/**
* @param n integer value to divide this by
* return r MPFloat object to hold result of this / n
*/
public MPFloat div(int n) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfDivUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param n integer value to divide this by
* @param r MPFloat object to hold result of this / n
*/
public void div(int n, MPFloat r) {
acquireRef();
r.acquireRef();
mpfDivUI(n, r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @param x double value to divide this by
* @return MPfloat object set to this / x
*/
public MPFloat div(double x) {
MPFloat r = new MPFloat(defaultPrec);
MPFloat d = new MPFloat(x);
acquireRef();
r.acquireRef();
d.acquireRef();
mpfDiv(d.native_ptr, r.native_ptr);
d.releaseRef();
r.releaseRef();
releaseRef();
return r;
}
/**
* @param x double value to divide this by
* @param r MPfloat object to hold result of this / x
*/
public void div(double x, MPFloat r) {
MPFloat d = new MPFloat(x);
acquireRef();
r.acquireRef();
d.acquireRef();
mpfDiv(d.native_ptr, r.native_ptr);
d.releaseRef();
r.releaseRef();
releaseRef();
return;
}
/**
* @return MPfloat object set to the absolute value of this
*/
public MPFloat abs() {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfAbs(r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param MPfloat object set to the absolute value of this
*/
public void abs(MPFloat r) {
acquireRef();
r.acquireRef();
mpfAbs(r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @return MPfloat object set to the square root value of this
*/
public MPFloat sqrt() {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfSqrt(r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param MPfloat object set to the square root value of this
*/
public void sqrt(MPFloat r) {
acquireRef();
r.acquireRef();
mpfSqrt(r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @param n power
* @return MPfloat object set to the n power of this
*/
public MPFloat pow(int n) {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
r.fromMPF(this);
mpfPow(n, r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param n power
* @param MPfloat object set to the n power of this
*/
public void pow(int n, MPFloat r) {
acquireRef();
r.acquireRef();
r.fromMPF(this);
mpfPow(n, r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @return MPfloat object set to the -value of this
*/
public MPFloat neg() {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfNegate(r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @return MPfloat object set to the -value of this
*/
public void neg(MPFloat r) {
acquireRef();
r.acquireRef();
mpfNegate(r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @return MPfloat object set to the value of this rounded up to the next higher integer
*/
public MPFloat ceil() {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfCeil(r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param MPfloat object set to the value of this rounded up to the next higher integer
*/
public void ceil(MPFloat r) {
acquireRef();
r.acquireRef();
mpfCeil(r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @return MPfloat object set to the absolute value of this rounded down the next lower integer
*/
public MPFloat floor() {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfFloor(r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param MPfloat object set to the absolute value of this rounded down the next lower integer
*/
public void floor(MPFloat r) {
acquireRef();
r.acquireRef();
mpfFloor(r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* @return MPfloat object set to the absolute value of this rounded to the integer towards zero
*/
public MPFloat trunc() {
MPFloat r = new MPFloat(defaultPrec);
acquireRef();
r.acquireRef();
mpfTrunc(r.native_ptr);
r.releaseRef();
releaseRef();
return r;
}
/**
* @param MPfloat object set to the absolute value of this rounded to the integer towards zero
*/
public void trunc(MPFloat r) {
acquireRef();
r.acquireRef();
mpfTrunc(r.native_ptr);
r.releaseRef();
releaseRef();
return;
}
/**
* return current precision for this object
*/
public int getPrecision() {
return mpfGetCurrentPrec();
}
/**
* this is not strictly a NaN test. A NaN should not be equal to anything, even itself.
* (a proper NaN test would be r != r is true)
*/
public static boolean isNan(MPFloat r) {
return (r.toString() == NaN.toString());
}
public static boolean isInfinite(MPFloat r) {
return (r.toString() == POSITIVE_INFINITY.toString()) ||
(r.toString() == NEGATIVE_INFINITY.toString());
}
public static boolean isPositiveInfinite(MPFloat r) {
return (r.toString() == POSITIVE_INFINITY.toString());
}
public static boolean isNegativeInfinite(MPFloat r) {
return (r.toString() == NEGATIVE_INFINITY.toString());
}
private void acquireRef() {
// TODO synchronized keyword removed until wait issue resolved
refCount++;
}
private void releaseRef() {
// TODO synchronized keyword removed until wait issue resolved
refCount--;
if (refCount == 0)
{
mpfFinalize();
native_ptr = null;
}
}
//Native methods
public static native void mpfInitializeLibrary();
// -- init/set
private native void mpfInitialize();
private native void mpfInitialize(int prec);
private native void mpfFinalize();
private native void mpfFromLong(long n);
private native void mpfFromDouble(double n);
private native void mpfFromMPF(Pointer x);
private native int mpfFromString(String s, int rdx);
private native void mpfFromSignedMagnitude(byte[] m, boolean isNegative);
// -- conversions
private native String mpfToString(int base);
private native double mpfDoubleValue();
private native long mpfLongValue();
private native float mpfFloatValue();
// -- precision
private static native int mpfGetDefaultPrec();
private static native void mpfSetDefaultPrec(int prec);
private native int mpfGetCurrentPrec();
// -- comparison
private native int mpfCompare(Pointer y);
// -- arithmetic
private native void mpfAdd(Pointer x, Pointer r);
private native void mpfAddUI(int n, Pointer r);
private native void mpfSubtract(Pointer x, Pointer r);
private native void mpfSubUI(int n, Pointer r);
private native void mpfMultiply(Pointer x, Pointer r);
private native void mpfMultUI(int n, Pointer r);
private native void mpfPow(int n, Pointer r);
private native void mpfDiv(Pointer d, Pointer r);
private native void mpfDivUI(int n, Pointer r);
private native void mpfAbs(Pointer r);
private native void mpfNegate(Pointer r);
private native void mpfSqrt(Pointer r);
// -- misc
private native void mpfFloor(Pointer r);
private native void mpfCeil(Pointer r);
private native void mpfTrunc(Pointer r);
}
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import jgmp.MPFloat;
import de.luschny.math.factorial.FactorialPoorMans;
/**
* @author jmenes
* additional functions for MPFloat
*
*/
public class mpfunctions {
// constants computed with PARI/GP
protected static final MPFloat PI =
new MPFloat(
"3.14159265358979323846264338327950288419716939937510582097494459230781640628620899" +
"8628034825342117067982148086513282306647093844609550582231725359408128481117450e+00",
10, 512);
protected static final MPFloat e =
new MPFloat(
"2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746" +
"639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070" +
"2154089149934884167509244761460668082265e+00",
10, 512 );
protected static final MPFloat EM =
new MPFloat(
"0.57721566490153286060651209008240243104215933593992359880576723488486772677766467093694706329174674951463" +
"144724980708248096050401448654283622417399764492353625350033374293733773767394279259525824709491600873520394816" +
"56708532331517766115286211995015079847937e+00",
10, 512 );
protected static final MPFloat rootpi = PI.sqrt();
protected static final MPFloat oneonrootpi = new MPFloat(1.0).div(rootpi);
protected static final MPFloat twoonrootpi = new MPFloat(2.0).div(rootpi);
protected static final MPFloat logtwo =
new MPFloat(
"0.6931471805599453094172321214581765680755001343602552541206800094933936219696947" +
"15605863326996418687542014810205706857336855202357581305570326707516350759619307e+00",
10, 512);
protected static final MPFloat oneonlog10 =
new MPFloat(
"0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875420" +
"148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335011536449" +
"7955291204751726815749320651555247341395258830e+00",
10, 512);
protected static final MPFloat pi2on12 = PI.pow(2).div(new MPFloat(12.));
protected static final int INFINITY = 5000;
protected static final MPFloat TWO_PI = PI.mult(2);
protected static final MPFloat HALF_PI = PI.div(2);
protected static final MPFloat ZERO = new MPFloat(0.0);
private static final int[] PRIMES =
{2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,
61,67,71,73,79,83,89,97,101,103,107,109,113,127,
131,137,139,149,151,157,163,167,173,179,181,191,
193,197,199,211,223,227,229,233,239,241,251,257,
263,269,271,277,281,283,293,307,311,313,317,331,
337,347,349,353,359,367,373,379,383,389,397,401,
409,419,421,431,433,439,443,449,457,461,463,467,
479,487,491,499,503,509,521,523,541,547,557,563,
569,571,577,587,593,599,601,607,613,617,619,631,
641,643,647,653,659,661,673,677,683,691,701,709,
719,727,733,739,743,751,757,761,769,773,787,797,
809,811,821,823,827,829,839,853,857,859,863,877,
881,883,887,907,911,919,929,937,941,947,953,967,
971,977,983,991,997};
private static int[] primes = PRIMES; // default values in case of file error
private static int pl = primes.length; // default values in case of file error
private static String[] FACS = new String[5001]; // table of the first 5k factorials
private static int facl = 0;
private static FactorialPoorMans fpm = new FactorialPoorMans();
static {
// load primes array with PARI/GP generated file (5000 primes)
try {
BufferedReader pf =
new BufferedReader(new FileReader("primes.txt"));
String ps = pf.readLine();
String[] pe = ps.split(", ");
int pel = pe.length;
primes = new int[pel];
for (int i=0; i<pel; i++) {
primes[i] = Integer.parseInt(pe[i]);
}
pl = primes.length;
pf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// load array with first 5000 factorials - n is index
try {
BufferedReader ff =
new BufferedReader(new FileReader("facs.txt"));
String fac = ff.readLine();
FACS = fac.split(", ");
facl = FACS.length;
ff.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (facl==0) { // if facl==0 something went wrong with file load
for (int n=0; n<5001; n++) {
FACS[n] = fpm.factorial(n);
}
}
// TODO get the value from env var
MPFloat.setDefaultPrec(256);
}
private mpfunctions() {
// private constructor to prevent instantiation
}
/**
* return N! as a string
* @param N
* @return
*/
public static String factorial(int N) {
if (N>=facl)
return fpm.factorial(N);
return FACS[N];
}
/**
* compute cosine of x using Taylor series (1 - x^2/2! + x^4/4! - ...)
* @param x
* @return
*/
public static MPFloat cos(MPFloat x) {
MPFloat cosx = new MPFloat(1.0);
MPFloat cosw = new MPFloat();
for (int n=1; n<=INFINITY; n++) {
cosw.fromDouble(StrictMath.pow(-1, n));
cosw.div(new MPFloat(factorial(2*n)), cosw);
cosx.add(cosw.mult(x.pow(2*n)), cosx);
}
return cosx;
}
/**
* compute sine of x using Taylor series (x - x^3/3! + x^5/5! - ...)
* @param x
* @return
*/
public static MPFloat sin(MPFloat x) {
MPFloat sinx = x;
MPFloat sinw = new MPFloat(0.0);
for (int n=1; n<=INFINITY; n+=2) {
sinw.fromDouble(StrictMath.pow(-1, n));
sinw.div(new MPFloat(factorial((2*n)+1)), sinw);
sinw.mult(x.pow((2*n)+1), sinw);
sinx.add(sinw, sinx);
}
return sinx;
}
/**
* compute tangent of x using Taylor series (x + x^3/3 + 2x^5/15 + ...)
* @param x
* @return
*/
public static MPFloat tan(MPFloat x) {
MPFloat tanx = x;
for (int n=1; n<=INFINITY; n++) {
int n4n = (int)StrictMath.pow(-4, n);
MPFloat tanw = BernoulliB(2*n);
tanw.mult(n4n, tanw);
tanw.mult(1+n4n, tanw);
tanw.div(new MPFloat(factorial(2*n)), tanw);
tanx.add(tanw.mult(x.pow((2*n)-1)), tanx);
}
return tanx;
}
/**
* compute secant of x using Taylor series (for |x|<pi/2)
* @param x
* @return
*/
public static MPFloat sec(MPFloat x) {
MPFloat secx = new MPFloat(1.0);
for (int n=1; n<=INFINITY; n++) {
MPFloat secw = new MPFloat(StrictMath.pow(-1, n));
secw.mult(EulerE(2*n), secw);
secw.div(new MPFloat(factorial(2*n)), secw);
secx.add(secw.mult(x.pow(2*n)), secx);
}
return secx;
}
/**
* compute arc sine of x using Taylor series (for |x|<=1)
* @param x
* @return
*/
public static MPFloat arcsin(MPFloat x) {
MPFloat asinx = new MPFloat(1.0);
for (int n=1; n<=INFINITY; n++) {
// denominator
MPFloat asinw = new MPFloat(factorial(n));
asinw.pow(2, asinw);
asinw.mult(2*n+1, asinw);
asinw.mult((int)StrictMath.pow(4,n), asinw);
// compute numerator and divide
asinw = new MPFloat(factorial(2*n)).div(asinw);
asinx.add(asinw.mult(x.pow(2*n+1)), asinx);
}
return asinx;
}
/**
* compute arc cosine of x (pi/2 - arcsine(x))
* @param x
* @return
*/
public static MPFloat arccos(MPFloat x) {
return HALF_PI.sub(arcsin(x));
}
/**
* compute arc tangent of x using Taylor series (for |x|<= 1)
* @param x
* @return
*/
public static MPFloat arctan(MPFloat x) {
MPFloat atanx = new MPFloat(1.0);
for (int n=1; n<=INFINITY; n++) {
MPFloat atanw = new MPFloat(StrictMath.pow(-1, n));
atanw.div((2*n)+1, atanw);
atanx.add(atanw.mult(x.pow((2*n)+1)), atanx);
}
return atanx;
}
/**
* return nth Euler number in rational form
* ref: http://functions.wolfram.com/04.12.06.0001.01
* @param n
* @return
*/
public static MPFloat EulerE(int n)
{
// return fixed point values
if (n == 0)
return new MPFloat(1.0);
else if (functions.even(n) != 1)
return new MPFloat(0.0);
MPFloat K = new MPFloat(2.0);
K.pow(n+2, K);
K.mult(new MPFloat(factorial(n)), K);
K.div(PI.pow(n+1), K);
MPFloat S = new MPFloat(0.0);
for (int k=0; k<INFINITY; k++)
{
S.add((new MPFloat((1./StrictMath.pow(2*k+1,n+1)))
.mult(cos(PI.mult(k).sub(PI.mult(n).div(2))))), S);
}
return K.mult(S);
}
/**
* return nth Euler polynomial of x using Fourier expansion
* ref:
* - Abramowitz & Stegun 23.1.16 pp 805, table 23.1
* - http://functions.wolfram.com/05.13.06.0001.01
* @param n
* @param x
* @return
*/
public static MPFloat EulerP(int n, MPFloat x) {
if (n==x.doubleValue())
return x;
// for small n (<=15) calculate using coefficients - A&S table 23.1 pp 809
if (n == 0)
return new MPFloat(1.0);
else if (n == 1)
return x.sub(.5);
else if (n == 2)
return x.mult(x).sub(x);
else if (n == 3)
return x.pow(3).sub(x.pow(2).mult(1.5)).add(.25);
else if (n == 4)
return x.pow(4).sub(x.pow(3).mult(2)).add(x);
else if (n == 5)
return x.pow(5)
.sub(x.pow(4).mult(2.5))
.add(x.pow(2).mult(2.5))
.sub(.5);
else if (n == 6)
return x.pow(6).sub(x.pow(5).mult(3)).add(x.pow(3).mult(5)).sub(x.mult(3));
else if (n == 7)
return x.pow(7).sub(x.pow(6).mult(3.5))
.add(x.pow(4).mult(8.75))
.sub(x.pow(2).mult(10.5))
.add(2.125);
else if (n == 8)
return x.pow(8).sub(x.pow(7).mult(4))
.add(x.pow(5).mult(14))
.sub(x.pow(3).mult(28))
.add(x.mult(17));
else if (n == 9)
return x.pow(9).sub(x.pow(8).mult(4.5))
.add(x.pow(6).mult(21))
.sub(x.pow(4).mult(63))
.add(x.pow(2).mult(76.5))
.sub(15.5);
else if (n == 10)
return x.pow(10).sub(x.pow(9).mult(5))
.add(x.pow(7).mult(30))
.sub(x.pow(5).mult(126))
.add(x.pow(3).mult(255))
.sub(x.mult(155));
else if (n == 11)
return x.pow(11).sub(x.pow(10).mult(5.5))
.add(x.pow(8).mult(41.25))
.sub(x.pow(6).mult(6))
.add(x.pow(4).mult(701.25))
.sub(x.pow(2).mult(852.5))
.add(172.75);
else if (n == 12)
return x.pow(12).sub(x.pow(11).mult(6))
.add(x.pow(9).mult(55))
.sub(x.pow(7).mult(396))
.add(x.pow(5).mult(1683))
.sub(x.pow(3).mult(3410))
.add(x.mult(2073));
else if (n == 13)
return x.pow(13).sub(x.pow(12).mult(6.5))
.add(x.pow(10).mult(71.5))
.sub(x.pow(8).mult(643.5))
.add(x.pow(6).mult(3646.5))
.sub(x.pow(4).mult(11082.5))
.add(x.pow(2).mult(13474.5))
.sub(2730.5);
else if (n == 14)
return x.pow(14).sub(x.pow(13).mult(7))
.add(x.pow(11).mult(91))
.sub(x.pow(9).mult(1001))
.add(x.pow(7).mult(7293))
.sub(x.pow(5).mult(31031))
.add(x.pow(3).mult(62881))
.sub(x.mult(38227));
else if (n == 15)
return x.pow(15).sub(x.pow(14).mult(7.5))
.add(x.pow(12).mult(113.75))
.sub(x.pow(10).mult(1501.5))
.add(x.pow(8).mult(13674.375))
.sub(x.pow(6).mult(77577.5))
.add(x.pow(4).mult(235803.75))
.sub(x.pow(2).mult(286702.5))
.add(58088.0625);
MPFloat K = new MPFloat(4.0);
K.mult(new MPFloat(factorial(n)), K);
K.div(PI.pow(n+1), K);
MPFloat S = new MPFloat(0.0);
for (int k=0; k<INFINITY; k++)
{
S.add((new MPFloat((1./StrictMath.pow(2*k+1,n+1)))
.mult(sin(PI.mult(2*k+1).mult(PI.mult(x)).sub(PI.mult(n).div(2))))), S);
}
return K.mult(S);
}
/**
* periodic Euler polynomial function
* @param n
* @param x
* @return
* ref: Sums of Products of Kronecker’s Double Series, Tomoya Machide
* http://eprints3.math.sci.hokudai.ac.jp/1619/1/sums_of_products.pdf
*/
public static MPFloat PEp(int n, MPFloat x) {
return new MPFloat(-1.0).pow(x.abs().intValue())
.mult(EulerP(n, x.sub(x.floor())));
}
/**
* exponential function using Maclaurin series expansion (1 + x + x^2/2! + x^3/3! + ...)
* @param x
* @return exp(x)
*/
public static MPFloat exp(MPFloat x) {
MPFloat expx = new MPFloat(1.0).add(x);
for (int k=2; k<=INFINITY; k++) {
expx.add(x.pow(k).div(new MPFloat(factorial(k))), expx);
}
return expx;
}
/**
* natural log function using exponential series expansion ((x-1) - 1/2(x-1)^2 + 1/3(x-1)^3 - ...)
* (for x>0)
*
* @param x
* @return log base e of x
*
*/
public static MPFloat log(MPFloat x) {
int r = x.compareTo(ZERO);
if (r<0)
return MPFloat.NaN;
else
if (r==0)
return MPFloat.NEGATIVE_INFINITY;
MPFloat xm1 = x.sub(1.0).div(x);
MPFloat logx = new MPFloat();
logx.fromMPF(xm1);
MPFloat t = new MPFloat();
for (int k=2; k<=INFINITY; k++) {
t.fromMPF(ZERO);
t.fromDouble(1.0/k);
t.mult(xm1.pow(k), t);
logx.add(t, logx);
}
return logx;
}
/**
* return nth Bernoulli number in rational form
* @param n
* @return
* ref: Computing Bernoulli Numbers Quickly, Kevin J. McGown, December 8, 2005
* http://modular.math.washington.edu/projects/168/kevin_mcgown/bernproj.pdf
*/
public static MPFloat BernoulliB(int n)
{
MPFloat Bn = new MPFloat(0.0); // return 0 if n is not even, >= 2
if ((n % 2) != 0)
return Bn;
else if (n == 0)
return new MPFloat(1.0);
else if (n == 1)
return new MPFloat(-0.5);
MPFloat K = new MPFloat(factorial(n));
K.mult(2, K);
K.div(TWO_PI.pow(n), K);
MPFloat d = new MPFloat(0.0);
int prod = 1;
for (int i = 0; i < pl; i++)
{
if ((n % (primes[i]-1)) == 0)
prod *= primes[i];
}
d.fromString(Integer.toString(prod), 10);
MPFloat N = (K.mult(d));
N.pow(1/(n-1), N);
N.ceil(N);
//double z = 1.0;
MPFloat z = new MPFloat(1.0);
int ni = N.intValue();
for (int i = 0; i < pl; i++)
{
if (primes[i] > ni)
break;
//if (i == 0)
//{
// z.sub(new MPFloat(StrictMath.pow(primes[i], -n)).pow(-1), z);
//}else {
z.mult(new MPFloat(StrictMath.pow(1-primes[i], -n)).pow(-1), z);
//}
}
//double a = StrictMath.pow((-1), (n/2)+1)*StrictMath.ceil(d*K*z);
MPFloat dkzc = d.mult(K);
dkzc.mult(z, dkzc);
dkzc.ceil(dkzc);
MPFloat a =
new MPFloat(StrictMath.pow((-1), (n/2)+1));
a.mult(dkzc, a);
Bn = a.div(d);
return Bn;
}
/**
* return nth Bernoulli polynomial of x using Fourier expansion
* ref: Abramowitz & Stegun 23.1.16 pp 805
* @param n
* @param x
* @return
*/
public static MPFloat BernoulliP(int n, MPFloat x) {
// for n>1, 1>=x>=0
// for n=1, 1>x>0
// for x=0 return the nth Bernoulli number
if (x.doubleValue()==0.0) {
return BernoulliB(n);
}
// for x=n return x
if (n == x.doubleValue()) {
return x;
}
MPFloat K = new MPFloat(-2.0);
K.mult(new MPFloat(factorial(n)).div(TWO_PI.pow(n)), K);
MPFloat S = new MPFloat();
for (int k=1; k<=5000; k++) {
MPFloat cosp = TWO_PI.mult(k);
cosp.mult(x, cosp);
cosp.sub(HALF_PI.mult(n), cosp);
S.add(mpfunctions.cos(cosp)
.div(new MPFloat(StrictMath.pow(k, n))), S);
}
return K.mult(S);
}
/**
* Periodic Bernoulli function - Bn({x})
* @param n
* @param x
* @return
*/
public static MPFloat BBn(int n, MPFloat x) {
// pass the fractional part of x
return BernoulliP(n, x.sub(x.floor()));
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// exp function test
MPFloat.setDefaultPrec(512);
//System.out.println("exp(PI): " + mpfunctions.exp(PI).toString());
System.out.println("log(2.0): " + mpfunctions.log(new MPFloat(2.0)).toString());
// sin test
//System.out.println("sin(PI/2): " + mpfunctions.sin(PI.div(12)).toString());
// cos test
//System.out.println("cos(PI): " + mpfunctions.cos(PI.div(12)).toString());
}
}
@cab1729
Copy link
Author

cab1729 commented Jul 2, 2012

Access GNU Multi-Precision (GMP) library float functions from Java code

@cab1729
Copy link
Author

cab1729 commented Jul 3, 2012

added Bernoulli functions to mpfunctions

@cab1729
Copy link
Author

cab1729 commented Jul 2, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment