diff options
Diffstat (limited to 'libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c')
-rw-r--r-- | libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c b/libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c new file mode 100644 index 00000000000..6b4aed42d27 --- /dev/null +++ b/libjava/classpath/native/jni/java-lang/java_lang_VMDouble.c @@ -0,0 +1,381 @@ +/* VMDouble.c - java.lang.VMDouble native functions + Copyright (C) 1998, 1999, 2001, 2003, 2004i, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "mprec.h" +#include "fdlibm.h" +#include "jcl.h" + +#include "java_lang_VMDouble.h" + +static jclass clsDouble; +static jmethodID isNaNID; +static jdouble NEGATIVE_INFINITY; +static jdouble POSITIVE_INFINITY; +static jdouble NaN; + +/* + * Class: java_lang_VMDouble + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_lang_VMDouble_initIDs (JNIEnv * env, jclass cls __attribute__ ((__unused__))) +{ + jfieldID negInfID; + jfieldID posInfID; + jfieldID nanID; + + clsDouble = (*env)->FindClass (env, "java/lang/Double"); + if (clsDouble == NULL) + { + DBG ("unable to get class java.lang.Double\n") return; + } + isNaNID = (*env)->GetStaticMethodID (env, clsDouble, "isNaN", "(D)Z"); + if (isNaNID == NULL) + { + DBG ("unable to determine method id of isNaN\n") return; + } + negInfID = (*env)->GetStaticFieldID (env, clsDouble, "NEGATIVE_INFINITY", "D"); + if (negInfID == NULL) + { + DBG ("unable to determine field id of NEGATIVE_INFINITY\n") return; + } + posInfID = (*env)->GetStaticFieldID (env, clsDouble, "POSITIVE_INFINITY", "D"); + if (posInfID == NULL) + { + DBG ("unable to determine field id of POSITIVE_INFINITY\n") return; + } + nanID = (*env)->GetStaticFieldID (env, clsDouble, "NaN", "D"); + if (posInfID == NULL) + { + DBG ("unable to determine field id of NaN\n") return; + } + POSITIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, posInfID); + NEGATIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, negInfID); + NaN = (*env)->GetStaticDoubleField (env, clsDouble, nanID); + +#ifdef DEBUG + fprintf (stderr, "java.lang.Double.initIDs() POSITIVE_INFINITY = %g\n", + POSITIVE_INFINITY); + fprintf (stderr, "java.lang.Double.initIDs() NEGATIVE_INFINITY = %g\n", + NEGATIVE_INFINITY); + fprintf (stderr, "java.lang.Double.initIDs() NaN = %g\n", NaN); +#endif +} + +/* + * Class: java_lang_VMDouble + * Method: doubleToLongBits + * Signature: (D)J + */ +JNIEXPORT jlong JNICALL +Java_java_lang_VMDouble_doubleToLongBits + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble doubleValue) +{ + jvalue val; + jlong e, f; + val.d = doubleValue; + + e = val.j & 0x7ff0000000000000LL; + f = val.j & 0x000fffffffffffffLL; + + if (e == 0x7ff0000000000000LL && f != 0L) + val.j = 0x7ff8000000000000LL; + + return val.j; +} + +/* + * Class: java_lang_VMDouble + * Method: doubleToRawLongBits + * Signature: (D)J + */ +JNIEXPORT jlong JNICALL +Java_java_lang_VMDouble_doubleToRawLongBits + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jdouble doubleValue) +{ + jvalue val; + val.d = doubleValue; + return val.j; +} + +/* + * Class: java_lang_VMDouble + * Method: longBitsToDouble + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL +Java_java_lang_VMDouble_longBitsToDouble + (JNIEnv * env __attribute__ ((__unused__)), + jclass cls __attribute__ ((__unused__)), jlong longValue) +{ + jvalue val; + val.j = longValue; + return val.d; +} + +/* + * Class: java_lang_VMDouble + * Method: toString + * Signature: (DZ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_java_lang_VMDouble_toString + (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jdouble value, jboolean isFloat) +{ + char buffer[50], result[50]; + int decpt, sign; + char *s, *d; + int i; + +#ifdef DEBUG + fprintf (stderr, "java.lang.VMDouble.toString (%g)\n", value); +#endif + + if ((*env)->CallStaticBooleanMethod (env, clsDouble, isNaNID, value)) + return (*env)->NewStringUTF (env, "NaN"); + + if (value == POSITIVE_INFINITY) + return (*env)->NewStringUTF (env, "Infinity"); + + if (value == NEGATIVE_INFINITY) + return (*env)->NewStringUTF (env, "-Infinity"); + + _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int) isFloat); + + value = fabs (value); + + s = buffer; + d = result; + + if (sign) + *d++ = '-'; + + if ((value >= 1e-3 && value < 1e7) || (value == 0)) + { + if (decpt <= 0) + *d++ = '0'; + else + { + for (i = 0; i < decpt; i++) + if (*s) + *d++ = *s++; + else + *d++ = '0'; + } + + *d++ = '.'; + + if (*s == 0) + { + *d++ = '0'; + decpt++; + } + + while (decpt++ < 0) + *d++ = '0'; + + while (*s) + *d++ = *s++; + + *d = 0; + + return (*env)->NewStringUTF (env, result); + } + + *d++ = *s++; + decpt--; + *d++ = '.'; + + if (*s == 0) + *d++ = '0'; + + while (*s) + *d++ = *s++; + + *d++ = 'E'; + + if (decpt < 0) + { + *d++ = '-'; + decpt = -decpt; + } + + { + char exp[4]; + char *e = exp + sizeof exp; + + *--e = 0; + do + { + *--e = '0' + decpt % 10; + decpt /= 10; + } + while (decpt > 0); + + while (*e) + *d++ = *e++; + } + + *d = 0; + + return (*env)->NewStringUTF (env, result); +} + +/* + * Class: java_lang_VMDouble + * Method: parseDouble + * Signature: (Ljava/lang/String;)D + */ +JNIEXPORT jdouble JNICALL +Java_java_lang_VMDouble_parseDouble + (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jstring str) +{ + jboolean isCopy; + const char *buf; + char *endptr; + jdouble val = 0.0; + + if (str == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", "null"); + return val; + } + + buf = (char *) (*env)->GetStringUTFChars (env, str, &isCopy); + if (buf == NULL) + { + /* OutOfMemoryError already thrown */ + } + else + { + const char *p = buf, *end, *last_non_ws, *temp; + int ok = 1; + +#ifdef DEBUG + fprintf (stderr, "java.lang.VMDouble.parseDouble (%s)\n", buf); +#endif + + /* Trim the buffer, similar to String.trim(). First the leading + characters. */ + while (*p && *p <= ' ') + ++p; + + /* Find the last non-whitespace character. This method is safe + even with multi-byte UTF-8 characters. */ + end = p; + last_non_ws = NULL; + while (*end) + { + if (*end > ' ') + last_non_ws = end; + ++end; + } + + if (last_non_ws == NULL) + last_non_ws = p + strlen (p); + else + { + /* Skip past the last non-whitespace character. */ + ++last_non_ws; + } + + /* Check for infinity and NaN */ + temp = p; + if (temp[0] == '+' || temp[0] == '-') + temp++; + if (strncmp ("Infinity", temp, (size_t) 8) == 0) + { + if (p[0] == '-') + return NEGATIVE_INFINITY; + return POSITIVE_INFINITY; + } + if (strncmp ("NaN", temp, (size_t) 3) == 0) + return NaN; + + /* Skip a trailing `f' or `d'. */ + if (last_non_ws > p + && (last_non_ws[-1] == 'f' + || last_non_ws[-1] == 'F' + || last_non_ws[-1] == 'd' || last_non_ws[-1] == 'D')) + --last_non_ws; + + if (last_non_ws > p) + { + struct _Jv_reent reent; + memset (&reent, 0, sizeof reent); + +#ifdef KISSME_LINUX_USER + /* FIXME: The libc strtod may not be reliable. */ + val = strtod (p, &endptr); +#else + val = _strtod_r (&reent, p, &endptr); +#endif + +#ifdef DEBUG + fprintf (stderr, "java.lang.VMDouble.parseDouble val = %g\n", val); + fprintf (stderr, "java.lang.VMDouble.parseDouble %i != %i ???\n", + endptr, last_non_ws); +#endif + if (endptr != last_non_ws) + ok = 0; + } + else + ok = 0; + + if (!ok) + { + val = 0.0; + JCL_ThrowException (env, + "java/lang/NumberFormatException", + "unable to parse double"); + } + + (*env)->ReleaseStringUTFChars (env, str, buf); + } + + return val; +} |