/[classpath]/classpath/native/jni/java-lang/java_lang_VMDouble.c
ViewVC logotype

Diff of /classpath/native/jni/java-lang/java_lang_VMDouble.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.8 by mkoch, Sat Apr 9 17:37:42 2005 UTC revision 1.9 by mkoch, Sat Apr 16 09:19:54 2005 UTC
# Line 1  Line 1 
1  /* VMDouble.c - java.lang.VMDouble native functions  /* VMDouble.c - java.lang.VMDouble native functions
2     Copyright (C) 1998, 1999, 2001, 2003, 2004 Free Software Foundation, Inc.     Copyright (C) 1998, 1999, 2001, 2003, 2004i, 2005
3       Free Software Foundation, Inc.
4    
5  This file is part of GNU Classpath.  This file is part of GNU Classpath.
6    
# Line 37  exception statement from your version. * Line 38  exception statement from your version. *
38    
39    
40  #include <config.h>  #include <config.h>
41    #include <stdlib.h>
42    #include <stdio.h>
43    #include <string.h>
44    
45    #include "mprec.h"
46    #include "fdlibm.h"
47    #include "jcl.h"
48    
 #include "java_lang_Double.h"  
49  #include "java_lang_VMDouble.h"  #include "java_lang_VMDouble.h"
50    
51    static jclass clsDouble;
52    static jmethodID isNaNID;
53    static jdouble NEGATIVE_INFINITY;
54    static jdouble POSITIVE_INFINITY;
55    static jdouble NaN;
56    
57    /*
58     * Class:     java_lang_VMDouble
59     * Method:    initIDs
60     * Signature: ()V
61     */
62    JNIEXPORT void JNICALL
63    Java_java_lang_VMDouble_initIDs (JNIEnv * env, jclass cls __attribute__ ((__unused__)))
64    {
65      jfieldID negInfID;
66      jfieldID posInfID;
67      jfieldID nanID;
68    
69      clsDouble = (*env)->FindClass (env, "java/lang/Double");
70      if (clsDouble == NULL)
71        {
72          DBG ("unable to get class java.lang.Double\n") return;
73        }
74      isNaNID = (*env)->GetStaticMethodID (env, clsDouble, "isNaN", "(D)Z");
75      if (isNaNID == NULL)
76        {
77          DBG ("unable to determine method id of isNaN\n") return;
78        }
79      negInfID = (*env)->GetStaticFieldID (env, clsDouble, "NEGATIVE_INFINITY", "D");
80      if (negInfID == NULL)
81        {
82          DBG ("unable to determine field id of NEGATIVE_INFINITY\n") return;
83        }
84      posInfID = (*env)->GetStaticFieldID (env, clsDouble, "POSITIVE_INFINITY", "D");
85      if (posInfID == NULL)
86        {
87          DBG ("unable to determine field id of POSITIVE_INFINITY\n") return;
88        }
89      nanID = (*env)->GetStaticFieldID (env, clsDouble, "NaN", "D");
90      if (posInfID == NULL)
91        {
92          DBG ("unable to determine field id of NaN\n") return;
93        }
94      POSITIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, posInfID);
95      NEGATIVE_INFINITY = (*env)->GetStaticDoubleField (env, clsDouble, negInfID);
96      NaN = (*env)->GetStaticDoubleField (env, clsDouble, nanID);
97    
98    #ifdef DEBUG
99      fprintf (stderr, "java.lang.Double.initIDs() POSITIVE_INFINITY = %g\n",
100               POSITIVE_INFINITY);
101      fprintf (stderr, "java.lang.Double.initIDs() NEGATIVE_INFINITY = %g\n",
102               NEGATIVE_INFINITY);
103      fprintf (stderr, "java.lang.Double.initIDs() NaN = %g\n", NaN);
104    #endif
105    }
106    
107  /*  /*
108   * Class:     java_lang_VMDouble   * Class:     java_lang_VMDouble
109   * Method:    doubleToLongBits   * Method:    doubleToLongBits
# Line 93  Java_java_lang_VMDouble_longBitsToDouble Line 156  Java_java_lang_VMDouble_longBitsToDouble
156    val.j = longValue;    val.j = longValue;
157    return val.d;    return val.d;
158  }  }
159    
160    /*
161     * Class:     java_lang_VMDouble
162     * Method:    toString
163     * Signature: (DZ)Ljava/lang/String;
164     */
165    JNIEXPORT jstring JNICALL
166    Java_java_lang_VMDouble_toString
167      (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jdouble value, jboolean isFloat)
168    {
169      char buffer[50], result[50];
170      int decpt, sign;
171      char *s, *d;
172      int i;
173    
174    #ifdef DEBUG
175      fprintf (stderr, "java.lang.VMDouble.toString (%g)\n", value);
176    #endif
177    
178      if ((*env)->CallStaticBooleanMethod (env, clsDouble, isNaNID, value))
179        return (*env)->NewStringUTF (env, "NaN");
180    
181      if (value == POSITIVE_INFINITY)
182        return (*env)->NewStringUTF (env, "Infinity");
183    
184      if (value == NEGATIVE_INFINITY)
185        return (*env)->NewStringUTF (env, "-Infinity");
186    
187      _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int) isFloat);
188    
189      value = fabs (value);
190    
191      s = buffer;
192      d = result;
193    
194      if (sign)
195        *d++ = '-';
196    
197      if ((value >= 1e-3 && value < 1e7) || (value == 0))
198        {
199          if (decpt <= 0)
200            *d++ = '0';
201          else
202            {
203              for (i = 0; i < decpt; i++)
204                if (*s)
205                  *d++ = *s++;
206                else
207                  *d++ = '0';
208            }
209    
210          *d++ = '.';
211    
212          if (*s == 0)
213            {
214              *d++ = '0';
215              decpt++;
216            }
217    
218          while (decpt++ < 0)
219            *d++ = '0';
220    
221          while (*s)
222            *d++ = *s++;
223    
224          *d = 0;
225    
226          return (*env)->NewStringUTF (env, result);
227        }
228    
229      *d++ = *s++;
230      decpt--;
231      *d++ = '.';
232    
233      if (*s == 0)
234        *d++ = '0';
235    
236      while (*s)
237        *d++ = *s++;
238    
239      *d++ = 'E';
240    
241      if (decpt < 0)
242        {
243          *d++ = '-';
244          decpt = -decpt;
245        }
246    
247      {
248        char exp[4];
249        char *e = exp + sizeof exp;
250    
251        *--e = 0;
252        do
253          {
254            *--e = '0' + decpt % 10;
255            decpt /= 10;
256          }
257        while (decpt > 0);
258    
259        while (*e)
260          *d++ = *e++;
261      }
262    
263      *d = 0;
264    
265      return (*env)->NewStringUTF (env, result);
266    }
267    
268    /*
269     * Class:     java_lang_VMDouble
270     * Method:    parseDouble
271     * Signature: (Ljava/lang/String;)D
272     */
273    JNIEXPORT jdouble JNICALL
274    Java_java_lang_VMDouble_parseDouble
275      (JNIEnv * env, jclass cls __attribute__ ((__unused__)), jstring str)
276    {
277      jboolean isCopy;
278      const char *buf;
279      char *endptr;
280      jdouble val = 0.0;
281    
282      if (str == NULL)
283        {
284          JCL_ThrowException (env, "java/lang/NullPointerException", "null");
285          return val;
286        }
287    
288      buf = (char *) (*env)->GetStringUTFChars (env, str, &isCopy);
289      if (buf == NULL)
290        {
291          /* OutOfMemoryError already thrown */
292        }
293      else
294        {
295          const char *p = buf, *end, *last_non_ws, *temp;
296          int ok = 1;
297    
298    #ifdef DEBUG
299          fprintf (stderr, "java.lang.VMDouble.parseDouble (%s)\n", buf);
300    #endif
301    
302          /* Trim the buffer, similar to String.trim().  First the leading
303             characters.  */
304          while (*p && *p <= ' ')
305            ++p;
306    
307          /* Find the last non-whitespace character.  This method is safe
308             even with multi-byte UTF-8 characters.  */
309          end = p;
310          last_non_ws = NULL;
311          while (*end)
312            {
313              if (*end > ' ')
314                last_non_ws = end;
315              ++end;
316            }
317    
318          if (last_non_ws == NULL)
319            last_non_ws = p + strlen (p);
320          else
321            {
322              /* Skip past the last non-whitespace character.  */
323              ++last_non_ws;
324            }
325    
326          /* Check for infinity and NaN */
327          temp = p;
328          if (temp[0] == '+' || temp[0] == '-')
329            temp++;
330          if (strncmp ("Infinity", temp, (size_t) 8) == 0)
331            {
332              if (p[0] == '-')
333                return NEGATIVE_INFINITY;
334              return POSITIVE_INFINITY;
335            }
336          if (strncmp ("NaN", temp, (size_t) 3) == 0)
337            return NaN;
338    
339          /* Skip a trailing `f' or `d'.  */
340          if (last_non_ws > p
341              && (last_non_ws[-1] == 'f'
342                  || last_non_ws[-1] == 'F'
343                  || last_non_ws[-1] == 'd' || last_non_ws[-1] == 'D'))
344            --last_non_ws;
345    
346          if (last_non_ws > p)
347            {
348              struct _Jv_reent reent;
349              memset (&reent, 0, sizeof reent);
350    
351    #ifdef KISSME_LINUX_USER
352              /* FIXME: The libc strtod may not be reliable. */
353              val = strtod (p, &endptr);
354    #else
355              val = _strtod_r (&reent, p, &endptr);
356    #endif
357    
358    #ifdef DEBUG
359              fprintf (stderr, "java.lang.VMDouble.parseDouble val = %g\n", val);
360              fprintf (stderr, "java.lang.VMDouble.parseDouble %i != %i ???\n",
361                       endptr, last_non_ws);
362    #endif
363              if (endptr != last_non_ws)
364                ok = 0;
365            }
366          else
367            ok = 0;
368    
369          if (!ok)
370            {
371              val = 0.0;
372              JCL_ThrowException (env,
373                                  "java/lang/NumberFormatException",
374                                  "unable to parse double");
375            }
376    
377          (*env)->ReleaseStringUTFChars (env, str, buf);
378        }
379    
380      return val;
381    }

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26