| // natDouble.cc - Implementation of java.lang.Double native methods. |
| |
| /* Copyright (C) 1998, 1999 Cygnus Solutions |
| |
| 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. */ |
| |
| /* AIX requires this to be the first thing in the file. */ |
| #ifndef __GNUC__ |
| # if HAVE_ALLOCA_H |
| # include <alloca.h> |
| # else |
| # ifdef _AIX |
| #pragma alloca |
| # else |
| # ifndef alloca /* predefined by HP cc +Olibcalls */ |
| char *alloca (); |
| # endif |
| # endif |
| # endif |
| #endif |
| |
| #include <stdlib.h> |
| |
| #include <cni.h> |
| #include <java/lang/String.h> |
| #include <java/lang/Double.h> |
| #include <java/lang/NumberFormatException.h> |
| #include <jvm.h> |
| |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "mprec.h" |
| |
| union u |
| { |
| jlong l; |
| jdouble d; |
| }; |
| |
| jlong |
| java::lang::Double::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; |
| } |
| |
| jdouble |
| java::lang::Double::longBitsToDouble(jlong bits) |
| { |
| union u u; |
| u.l = bits; |
| return u.d; |
| } |
| |
| jstring |
| java::lang::Double::toString(jdouble value, jboolean isFloat) |
| { |
| if (isNaN (value)) |
| return JvNewStringLatin1 ("NaN", sizeof ("NaN") - 1); |
| |
| if (value == POSITIVE_INFINITY) |
| return JvNewStringLatin1 ("Infinity", sizeof ("Infinity") - 1); |
| |
| if (value == 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::Double::doubleValueOf(jstring str) |
| { |
| int length = str->length(); |
| // Note that UTF can expand 3x. |
| |
| #ifdef HAVE_ALLOCA |
| char *data = (char *) alloca (3 * length + 1); |
| #else |
| #error --- need an alternate implementation here --- |
| #endif |
| |
| data[_Jv_GetStringUTFRegion (str, 0, length, data)] = 0; |
| |
| struct _Jv_reent reent; |
| memset (&reent, 0, sizeof reent); |
| |
| double val = _strtod_r (&reent, data, NULL); |
| |
| if (reent._errno) |
| _Jv_Throw (new NumberFormatException); |
| |
| return val; |
| } |