Merge from mainline.
[official-gcc.git] / libjava / classpath / native / jni / java-lang / java_lang_VMDouble.c
blob8435c3fdba7edac1ecc1cc64a0cbc62ae9931d58
1 /* VMDouble.c - java.lang.VMDouble native functions
2 Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
40 #include <config.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
45 #include "mprec.h"
46 #include "fdlibm.h"
47 #include "jcl.h"
49 #include "java_lang_VMDouble.h"
51 static jclass clsDouble;
52 static jmethodID isNaNID;
53 static jdouble NEGATIVE_INFINITY;
54 static jdouble POSITIVE_INFINITY;
55 static jdouble NaN;
58 * Class: java_lang_VMDouble
59 * Method: initIDs
60 * Signature: ()V
62 JNIEXPORT void JNICALL
63 Java_java_lang_VMDouble_initIDs (JNIEnv * env, jclass cls __attribute__ ((__unused__)))
65 jfieldID negInfID;
66 jfieldID posInfID;
67 jfieldID nanID;
69 clsDouble = (*env)->FindClass (env, "java/lang/Double");
70 if (clsDouble == NULL)
72 DBG ("unable to get class java.lang.Double\n") return;
74 clsDouble = (*env)->NewGlobalRef(env, clsDouble);
75 if (clsDouble == NULL)
77 DBG ("unable to register class java.lang.Double as global ref\n") return;
79 isNaNID = (*env)->GetStaticMethodID (env, clsDouble, "isNaN", "(D)Z");
80 if (isNaNID == NULL)
82 DBG ("unable to determine method id of isNaN\n") return;
84 negInfID = (*env)->GetStaticFieldID (env, clsDouble, "NEGATIVE_INFINITY", "D");
85 if (negInfID == NULL)
87 DBG ("unable to determine field id of NEGATIVE_INFINITY\n") return;
89 posInfID = (*env)->GetStaticFieldID (env, clsDouble, "POSITIVE_INFINITY", "D");
90 if (posInfID == NULL)
92 DBG ("unable to determine field id of POSITIVE_INFINITY\n") return;
94 nanID = (*env)->GetStaticFieldID (env, clsDouble, "NaN", "D");
95 if (posInfID == NULL)
97 DBG ("unable to determine field id of NaN\n") return;
99 POSITIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, posInfID);
100 NEGATIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, negInfID);
101 NaN = (*env)->GetStaticDoubleField (env, clsDouble, nanID);
103 #ifdef DEBUG
104 fprintf (stderr, "java.lang.Double.initIDs() POSITIVE_INFINITY = %g\n",
105 POSITIVE_INFINITY);
106 fprintf (stderr, "java.lang.Double.initIDs() NEGATIVE_INFINITY = %g\n",
107 NEGATIVE_INFINITY);
108 fprintf (stderr, "java.lang.Double.initIDs() NaN = %g\n", NaN);
109 #endif
113 * Class: java_lang_VMDouble
114 * Method: doubleToLongBits
115 * Signature: (D)J
117 JNIEXPORT jlong JNICALL
118 Java_java_lang_VMDouble_doubleToLongBits
119 (JNIEnv * env __attribute__ ((__unused__)),
120 jclass cls __attribute__ ((__unused__)), jdouble doubleValue)
122 jvalue val;
123 jlong e, f;
124 val.d = doubleValue;
126 #if defined(__IEEE_BYTES_LITTLE_ENDIAN)
127 /* On little endian ARM processors when using FPA, word order of
128 doubles is still big endian. So take that into account here. When
129 using VFP, word order of doubles follows byte order. */
131 #define SWAP_DOUBLE(a) (((a) << 32) | (((a) >> 32) & 0x00000000ffffffff))
133 val.j = SWAP_DOUBLE(val.j);
134 #endif
136 e = val.j & 0x7ff0000000000000LL;
137 f = val.j & 0x000fffffffffffffLL;
139 if (e == 0x7ff0000000000000LL && f != 0L)
140 val.j = 0x7ff8000000000000LL;
142 return val.j;
146 * Class: java_lang_VMDouble
147 * Method: doubleToRawLongBits
148 * Signature: (D)J
150 JNIEXPORT jlong JNICALL
151 Java_java_lang_VMDouble_doubleToRawLongBits
152 (JNIEnv * env __attribute__ ((__unused__)),
153 jclass cls __attribute__ ((__unused__)), jdouble doubleValue)
155 jvalue val;
156 val.d = doubleValue;
158 #if defined(__IEEE_BYTES_LITTLE_ENDIAN)
159 val.j = SWAP_DOUBLE(val.j);
160 #endif
162 return val.j;
166 * Class: java_lang_VMDouble
167 * Method: longBitsToDouble
168 * Signature: (J)D
170 JNIEXPORT jdouble JNICALL
171 Java_java_lang_VMDouble_longBitsToDouble
172 (JNIEnv * env __attribute__ ((__unused__)),
173 jclass cls __attribute__ ((__unused__)), jlong longValue)
175 jvalue val;
176 val.j = longValue;
178 #if defined(__IEEE_BYTES_LITTLE_ENDIAN)
179 val.j = SWAP_DOUBLE(val.j);
180 #endif
182 return val.d;
186 * Class: java_lang_VMDouble
187 * Method: toString
188 * Signature: (DZ)Ljava/lang/String;
190 JNIEXPORT jstring JNICALL
191 Java_java_lang_VMDouble_toString
192 (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jdouble value, jboolean isFloat)
194 char buffer[50], result[50];
195 int decpt, sign;
196 char *s, *d;
197 int i;
199 #ifdef DEBUG
200 fprintf (stderr, "java.lang.VMDouble.toString (%g)\n", value);
201 #endif
203 if ((*env)->CallStaticBooleanMethod (env, clsDouble, isNaNID, value))
204 return (*env)->NewStringUTF (env, "NaN");
206 if (value == POSITIVE_INFINITY)
207 return (*env)->NewStringUTF (env, "Infinity");
209 if (value == NEGATIVE_INFINITY)
210 return (*env)->NewStringUTF (env, "-Infinity");
212 _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int) isFloat);
214 value = fabs (value);
216 s = buffer;
217 d = result;
219 if (sign)
220 *d++ = '-';
222 if ((value >= 1e-3 && value < 1e7) || (value == 0))
224 if (decpt <= 0)
225 *d++ = '0';
226 else
228 for (i = 0; i < decpt; i++)
229 if (*s)
230 *d++ = *s++;
231 else
232 *d++ = '0';
235 *d++ = '.';
237 if (*s == 0)
239 *d++ = '0';
240 decpt++;
243 while (decpt++ < 0)
244 *d++ = '0';
246 while (*s)
247 *d++ = *s++;
249 *d = 0;
251 return (*env)->NewStringUTF (env, result);
254 *d++ = *s++;
255 decpt--;
256 *d++ = '.';
258 if (*s == 0)
259 *d++ = '0';
261 while (*s)
262 *d++ = *s++;
264 *d++ = 'E';
266 if (decpt < 0)
268 *d++ = '-';
269 decpt = -decpt;
273 char exp[4];
274 char *e = exp + sizeof exp;
276 *--e = 0;
279 *--e = '0' + decpt % 10;
280 decpt /= 10;
282 while (decpt > 0);
284 while (*e)
285 *d++ = *e++;
288 *d = 0;
290 return (*env)->NewStringUTF (env, result);
294 * Class: java_lang_VMDouble
295 * Method: parseDouble
296 * Signature: (Ljava/lang/String;)D
298 JNIEXPORT jdouble JNICALL
299 Java_java_lang_VMDouble_parseDouble
300 (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jstring str)
302 jboolean isCopy;
303 const char *buf;
304 char *endptr;
305 jdouble val = 0.0;
307 if (str == NULL)
309 JCL_ThrowException (env, "java/lang/NullPointerException", "null");
310 return val;
313 buf = (char *) (*env)->GetStringUTFChars (env, str, &isCopy);
314 if (buf == NULL)
316 /* OutOfMemoryError already thrown */
318 else
320 const char *p = buf, *end, *last_non_ws, *temp;
321 int ok = 1;
323 #ifdef DEBUG
324 fprintf (stderr, "java.lang.VMDouble.parseDouble (%s)\n", buf);
325 #endif
327 /* Trim the buffer, similar to String.trim(). First the leading
328 characters. */
329 while (*p && *p <= ' ')
330 ++p;
332 /* Find the last non-whitespace character. This method is safe
333 even with multi-byte UTF-8 characters. */
334 end = p;
335 last_non_ws = NULL;
336 while (*end)
338 if (*end > ' ')
339 last_non_ws = end;
340 ++end;
343 if (last_non_ws == NULL)
344 last_non_ws = p + strlen (p);
345 else
347 /* Skip past the last non-whitespace character. */
348 ++last_non_ws;
351 /* Check for infinity and NaN */
352 temp = p;
353 if (temp[0] == '+' || temp[0] == '-')
354 temp++;
355 if (strncmp ("Infinity", temp, (size_t) 8) == 0)
357 if (p[0] == '-')
358 return NEGATIVE_INFINITY;
359 return POSITIVE_INFINITY;
361 if (strncmp ("NaN", temp, (size_t) 3) == 0)
362 return NaN;
364 /* Skip a trailing `f' or `d'. */
365 if (last_non_ws > p
366 && (last_non_ws[-1] == 'f'
367 || last_non_ws[-1] == 'F'
368 || last_non_ws[-1] == 'd' || last_non_ws[-1] == 'D'))
369 --last_non_ws;
371 if (last_non_ws > p)
373 struct _Jv_reent reent;
374 memset (&reent, 0, sizeof reent);
376 val = _strtod_r (&reent, p, &endptr);
378 #ifdef DEBUG
379 fprintf (stderr, "java.lang.VMDouble.parseDouble val = %g\n", val);
380 fprintf (stderr, "java.lang.VMDouble.parseDouble %i != %i ???\n",
381 endptr, last_non_ws);
382 #endif
383 if (endptr != last_non_ws)
384 ok = 0;
386 else
387 ok = 0;
389 if (!ok)
391 val = 0.0;
392 JCL_ThrowException (env,
393 "java/lang/NumberFormatException",
394 "unable to parse double");
397 (*env)->ReleaseStringUTFChars (env, str, buf);
400 return val;