summaryrefslogtreecommitdiff
path: root/libjava/java/lang/natVMDouble.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/lang/natVMDouble.cc')
-rw-r--r--libjava/java/lang/natVMDouble.cc215
1 files changed, 215 insertions, 0 deletions
diff --git a/libjava/java/lang/natVMDouble.cc b/libjava/java/lang/natVMDouble.cc
new file mode 100644
index 000000000..f770bc422
--- /dev/null
+++ b/libjava/java/lang/natVMDouble.cc
@@ -0,0 +1,215 @@
+// natVMDouble.cc - Implementation of java.lang.VMDouble native methods.
+
+/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007
+ Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <gcj/cni.h>
+#include <java/lang/String.h>
+#include <java/lang/Double.h>
+#include <java/lang/VMDouble.h>
+#include <java/lang/Character.h>
+#include <java/lang/NumberFormatException.h>
+#include <jvm.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "fdlibm.h"
+
+union u
+{
+ jlong l;
+ jdouble d;
+};
+
+jlong
+java::lang::VMDouble::doubleToLongBits(jdouble value)
+{
+ union u u;
+ u.d = value;
+
+ jlong e = u.l & 0x7ff0000000000000LL;
+ jlong f = u.l & 0x000fffffffffffffLL;
+
+ if (e == 0x7ff0000000000000LL && f != 0L)
+ u.l = 0x7ff8000000000000LL;
+
+ return u.l;
+}
+
+jlong
+java::lang::VMDouble::doubleToRawLongBits(jdouble value)
+{
+ union u u;
+ u.d = value;
+ return u.l;
+}
+
+jdouble
+java::lang::VMDouble::longBitsToDouble(jlong bits)
+{
+ union u u;
+ u.l = bits;
+ return u.d;
+}
+
+jstring
+java::lang::VMDouble::toString(jdouble value, jboolean isFloat)
+{
+ if (Double::isNaN (value))
+ return JvNewStringLatin1 ("NaN", sizeof ("NaN") - 1);
+
+ if (value == Double::POSITIVE_INFINITY)
+ return JvNewStringLatin1 ("Infinity", sizeof ("Infinity") - 1);
+
+ if (value == Double::NEGATIVE_INFINITY)
+ return JvNewStringLatin1 ("-Infinity", sizeof ("-Infinity") - 1);
+
+ char buffer[50], result[50];
+ int decpt, sign;
+
+ _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int)isFloat);
+
+ value = fabs (value);
+
+ char *s = buffer;
+ char *d = result;
+
+ if (sign)
+ *d++ = '-';
+
+ if ((value >= 1e-3 && value < 1e7) || value == 0)
+ {
+ if (decpt <= 0)
+ *d++ = '0';
+ else
+ {
+ for (int 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 JvNewStringLatin1 (result, strlen (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 JvNewStringLatin1 (result, strlen (result));
+}
+
+jdouble
+java::lang::VMDouble::parseDouble(jstring str)
+{
+ int length = str->length();
+
+ while (length > 0
+ && Character::isWhitespace(str->charAt(length - 1)))
+ length--;
+
+ // The String could end with a f/F/d/D which is valid but we don't need.
+ bool saw_trailer = false;
+ if (length > 0)
+ {
+ jchar last = str->charAt(length-1);
+ if (last == 'f' || last == 'F' || last == 'd' || last == 'D')
+ {
+ length--;
+ saw_trailer = true;
+ }
+ }
+
+ jsize start = 0;
+ while (length > 0
+ && Character::isWhitespace(str->charAt(start)))
+ start++, length--;
+
+ if (length > 0)
+ {
+ // Note that UTF can expand 3x.
+ char *data = (char *) __builtin_alloca (3 * length + 1);
+ jsize blength = _Jv_GetStringUTFRegion (str, start, length, data);
+ data[blength] = 0;
+
+ if (! saw_trailer)
+ {
+ if (! strcmp (data, "NaN") || ! strcmp (data, "+NaN")
+ || ! strcmp (data, "-NaN"))
+ return Double::NaN;
+ else if (! strcmp (data, "Infinity") || ! strcmp (data, "+Infinity"))
+ return Double::POSITIVE_INFINITY;
+ else if (! strcmp (data, "-Infinity"))
+ return Double::NEGATIVE_INFINITY;
+ }
+
+ struct _Jv_reent reent;
+ memset (&reent, 0, sizeof reent);
+
+ char *endptr;
+ double val = _strtod_r (&reent, data, &endptr);
+ if (endptr == data + blength)
+ return val;
+ }
+ throw new NumberFormatException(str);
+}