OSDN Git Service

2007-01-18 Gary Benson <gbenson@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natVMDouble.cc
1 // natVMDouble.cc - Implementation of java.lang.VMDouble native methods.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007
4    Free Software Foundation
5
6    This file is part of libgcj.
7
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
10 details.  */
11
12 #include <config.h>
13
14 #include <stdlib.h>
15
16 #include <gcj/cni.h>
17 #include <java/lang/String.h>
18 #include <java/lang/Double.h>
19 #include <java/lang/VMDouble.h>
20 #include <java/lang/Character.h>
21 #include <java/lang/NumberFormatException.h>
22 #include <jvm.h>
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "fdlibm.h"
28
29 union u
30 {
31   jlong l;
32   jdouble d;
33 };
34
35 jlong 
36 java::lang::VMDouble::doubleToLongBits(jdouble value)
37 {
38   union u u;
39   u.d = value;
40   
41   jlong e = u.l & 0x7ff0000000000000LL;
42   jlong f = u.l & 0x000fffffffffffffLL;
43
44   if (e == 0x7ff0000000000000LL && f != 0L)
45     u.l = 0x7ff8000000000000LL;
46
47   return u.l;
48 }
49
50 jlong 
51 java::lang::VMDouble::doubleToRawLongBits(jdouble value)
52 {
53   union u u;
54   u.d = value;
55   return u.l;
56 }
57
58 jdouble 
59 java::lang::VMDouble::longBitsToDouble(jlong bits)
60 {
61   union u u;
62   u.l = bits;
63   return u.d;
64 }
65
66 jstring 
67 java::lang::VMDouble::toString(jdouble value, jboolean isFloat)
68 {
69   if (Double::isNaN (value))
70     return JvNewStringLatin1 ("NaN", sizeof ("NaN") - 1);
71     
72   if (value == Double::POSITIVE_INFINITY)
73     return JvNewStringLatin1 ("Infinity", sizeof ("Infinity") - 1);
74     
75   if (value == Double::NEGATIVE_INFINITY)
76     return JvNewStringLatin1 ("-Infinity", sizeof ("-Infinity") - 1);
77     
78   char buffer[50], result[50];
79   int decpt, sign;
80
81   _dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int)isFloat);
82
83   value = fabs (value);
84
85   char *s = buffer;
86   char *d = result;
87
88   if (sign)
89     *d++ = '-';
90
91   if ((value >= 1e-3 && value < 1e7) || value == 0)
92     {
93       if (decpt <= 0)
94         *d++ = '0';
95       else
96         {
97           for (int i = 0; i < decpt; i++)
98             if (*s)
99               *d++ = *s++;
100             else
101               *d++ = '0';
102         }
103
104       *d++ = '.';
105
106       if (*s == 0)
107         {
108           *d++ = '0';
109           decpt++;
110         }
111           
112       while (decpt++ < 0)
113         *d++ = '0';      
114       
115       while (*s)
116         *d++ = *s++;
117
118       *d = 0;
119
120       return JvNewStringLatin1 (result, strlen (result));
121     }
122
123   *d++ = *s++;
124   decpt--;
125   *d++ = '.';
126   
127   if (*s == 0)
128     *d++ = '0';
129
130   while (*s)
131     *d++ = *s++;
132
133   *d++ = 'E';
134   
135   if (decpt < 0)
136     {
137       *d++ = '-';
138       decpt = -decpt;
139     }
140
141   {
142     char exp[4];
143     char *e = exp + sizeof exp;
144     
145     *--e = 0;
146     do
147       {
148         *--e = '0' + decpt % 10;
149         decpt /= 10;
150       }
151     while (decpt > 0);
152
153     while (*e)
154       *d++ = *e++;
155   }
156   
157   *d = 0;
158
159   return JvNewStringLatin1 (result, strlen (result));
160 }
161
162 jdouble 
163 java::lang::VMDouble::parseDouble(jstring str)
164 {
165   int length = str->length();
166
167   while (length > 0
168          && Character::isWhitespace(str->charAt(length - 1)))
169     length--;
170
171   // The String could end with a f/F/d/D which is valid but we don't need.
172   bool saw_trailer = false;
173   if (length > 0)
174     {
175       jchar last = str->charAt(length-1);
176       if (last == 'f' || last == 'F' || last == 'd' || last == 'D')
177         {
178           length--;
179           saw_trailer = true;
180         }
181     }
182
183   jsize start = 0;
184   while (length > 0
185          && Character::isWhitespace(str->charAt(start)))
186     start++, length--;
187
188   if (length > 0)
189     {
190       // Note that UTF can expand 3x.
191       char *data = (char *) __builtin_alloca (3 * length + 1);
192       jsize blength = _Jv_GetStringUTFRegion (str, start, length, data);
193       data[blength] = 0; 
194
195       if (! saw_trailer)
196         {
197           if (! strcmp (data, "NaN") || ! strcmp (data, "+NaN")
198               || ! strcmp (data, "-NaN"))
199             return Double::NaN;
200           else if (! strcmp (data, "Infinity") || ! strcmp (data, "+Infinity"))
201             return Double::POSITIVE_INFINITY;
202           else if (! strcmp (data, "-Infinity"))
203             return Double::NEGATIVE_INFINITY;
204         }
205
206       struct _Jv_reent reent;  
207       memset (&reent, 0, sizeof reent);
208
209       char *endptr;
210       double val = _strtod_r (&reent, data, &endptr);
211       if (endptr == data + blength)
212         return val;
213     }
214   throw new NumberFormatException(str);
215 }