KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > util > FloatUtil


1 /*******************************************************************************
2  * Copyright (c) 2004, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.util;
12
13 /**
14  * Internal utility for declaing with hexadecimal double and float literals.
15  *
16  * @since 3.1
17  */

18 public class FloatUtil {
19
20     private static final int DOUBLE_FRACTION_WIDTH = 52;
21
22     private static final int DOUBLE_PRECISION = 53;
23
24     private static final int MAX_DOUBLE_EXPONENT = +1023;
25     
26     private static final int MIN_NORMALIZED_DOUBLE_EXPONENT = -1022;
27
28     private static final int MIN_UNNORMALIZED_DOUBLE_EXPONENT = MIN_NORMALIZED_DOUBLE_EXPONENT
29             - DOUBLE_PRECISION;
30
31     private static final int DOUBLE_EXPONENT_BIAS = +1023;
32
33     private static final int DOUBLE_EXPONENT_SHIFT = 52;
34
35     private static final int SINGLE_FRACTION_WIDTH = 23;
36
37     private static final int SINGLE_PRECISION = 24;
38
39     private static final int MAX_SINGLE_EXPONENT = +127;
40
41     private static final int MIN_NORMALIZED_SINGLE_EXPONENT = -126;
42
43     private static final int MIN_UNNORMALIZED_SINGLE_EXPONENT = MIN_NORMALIZED_SINGLE_EXPONENT
44             - SINGLE_PRECISION;
45
46     private static final int SINGLE_EXPONENT_BIAS = +127;
47
48     private static final int SINGLE_EXPONENT_SHIFT = 23;
49
50     /**
51      * Returns the float value corresponding to the given
52      * hexadecimal floating-point single precision literal.
53      * The literal must be syntactially correct, and must be
54      * a float literal (end in a 'f' or 'F'). It must not
55      * include either leading or trailing whitespace or
56      * a sign.
57      * <p>
58      * This method returns the same answer as
59      * Float.parseFloat(new String(source)) does in JDK 1.5,
60      * except that this method returns Floal.NaN if it
61      * would underflow to 0 (parseFloat just returns 0).
62      * The method handles all the tricky cases, including
63      * fraction rounding to 24 bits and gradual underflow.
64      * </p>
65      *
66      * @param source source string containing single precision
67      * hexadecimal floating-point literal
68      * @return the float value, including Float.POSITIVE_INFINITY
69      * if the non-zero value is too large to be represented, and
70      * Float.NaN if the non-zero value is too small to be represented
71      */

72     public static float valueOfHexFloatLiteral(char[] source) {
73         long bits = convertHexFloatingPointLiteralToBits(source);
74         return Float.intBitsToFloat((int) bits);
75     }
76
77     /**
78      * Returns the double value corresponding to the given
79      * hexadecimal floating-point double precision literal.
80      * The literal must be syntactially correct, and must be
81      * a double literal (end in an optional 'd' or 'D').
82      * It must not include either leading or trailing whitespace or
83      * a sign.
84      * <p>
85      * This method returns the same answer as
86      * Double.parseDouble(new String(source)) does in JDK 1.5,
87      * except that this method throw NumberFormatException in
88      * the case of overflow to infinity or underflow to 0.
89      * The method handles all the tricky cases, including
90      * fraction rounding to 53 bits and gradual underflow.
91      * </p>
92      *
93      * @param source source string containing double precision
94      * hexadecimal floating-point literal
95      * @return the double value, including Double.POSITIVE_INFINITY
96      * if the non-zero value is too large to be represented, and
97      * Double.NaN if the non-zero value is too small to be represented
98      */

99     public static double valueOfHexDoubleLiteral(char[] source) {
100         long bits = convertHexFloatingPointLiteralToBits(source);
101         return Double.longBitsToDouble(bits);
102     }
103
104     /**
105      * Returns the given hexadecimal floating-point literal as
106      * the bits for a single-precision (float) or a
107      * double-precision (double) IEEE floating point number.
108      * The literal must be syntactially correct. It must not
109      * include either leading or trailing whitespace or a sign.
110      *
111      * @param source source string containing hexadecimal floating-point literal
112      * @return for double precision literals, bits suitable
113      * for passing to Double.longBitsToDouble; for single precision literals,
114      * bits suitable for passing to Single.intBitsToDouble in the bottom
115      * 32 bits of the result
116      * @throws NumberFormatException if the number cannot be parsed
117      */

118     private static long convertHexFloatingPointLiteralToBits(char[] source) {
119         int length = source.length;
120         long mantissa = 0;
121
122         // Step 1: process the '0x' lead-in
123
int next = 0;
124         char nextChar = source[next];
125         nextChar = source[next];
126         if (nextChar == '0') {
127             next++;
128         } else {
129             throw new NumberFormatException JavaDoc();
130         }
131         nextChar = source[next];
132         if (nextChar == 'X' || nextChar == 'x') {
133             next++;
134         } else {
135             throw new NumberFormatException JavaDoc();
136         }
137
138         // Step 2: process leading '0's either before or after the '.'
139
int binaryPointPosition = -1;
140         loop: while (true) {
141             nextChar = source[next];
142             switch (nextChar) {
143             case '0':
144                 next++;
145                 continue loop;
146             case '.':
147                 binaryPointPosition = next;
148                 next++;
149                 continue loop;
150             default:
151                 break loop;
152             }
153         }
154
155         // Step 3: process the mantissa
156
// leading zeros have been trimmed
157
int mantissaBits = 0;
158         int leadingDigitPosition = -1;
159         loop: while (true) {
160             nextChar = source[next];
161             int hexdigit;
162             switch (nextChar) {
163             case '0':
164             case '1':
165             case '2':
166             case '3':
167             case '4':
168             case '5':
169             case '6':
170             case '7':
171             case '8':
172             case '9':
173                 hexdigit = nextChar - '0';
174                 break;
175             case 'a':
176             case 'b':
177             case 'c':
178             case 'd':
179             case 'e':
180             case 'f':
181                 hexdigit = (nextChar - 'a') + 10;
182                 break;
183             case 'A':
184             case 'B':
185             case 'C':
186             case 'D':
187             case 'E':
188             case 'F':
189                 hexdigit = (nextChar - 'A') + 10;
190                 break;
191             case '.':
192                 binaryPointPosition = next;
193                 next++;
194                 continue loop;
195             default:
196                 if (binaryPointPosition < 0) {
197                     // record virtual '.' as being to right of all digits
198
binaryPointPosition = next;
199                 }
200                 break loop;
201             }
202             if (mantissaBits == 0) {
203                 // this is the first non-zero hex digit
204
// ignore leading binary 0's in hex digit
205
leadingDigitPosition = next;
206                 mantissa = hexdigit;
207                 mantissaBits = 4;
208             } else if (mantissaBits < 60) {
209                 // middle hex digits
210
mantissa <<= 4;
211                 mantissa |= hexdigit;
212                 mantissaBits += 4;
213             } else {
214                 // more mantissa bits than we can handle
215
// drop this hex digit on the ground
216
}
217             next++;
218             continue loop;
219         }
220
221         // Step 4: process the 'P'
222
nextChar = source[next];
223         if (nextChar == 'P' || nextChar == 'p') {
224             next++;
225         } else {
226             throw new NumberFormatException JavaDoc();
227         }
228
229         // Step 5: process the exponent
230
int exponent = 0;
231         int exponentSign = +1;
232         loop: while (next < length) {
233             nextChar = source[next];
234             switch (nextChar) {
235             case '+':
236                 exponentSign = +1;
237                 next++;
238                 continue loop;
239             case '-':
240                 exponentSign = -1;
241                 next++;
242                 continue loop;
243             case '0':
244             case '1':
245             case '2':
246             case '3':
247             case '4':
248             case '5':
249             case '6':
250             case '7':
251             case '8':
252             case '9':
253                 int digit = nextChar - '0';
254                 exponent = (exponent * 10) + digit;
255                 next++;
256                 continue loop;
257             default:
258                 break loop;
259             }
260         }
261
262         // Step 6: process the optional 'f' or 'd'
263
boolean doublePrecision = true;
264         if (next < length) {
265             nextChar = source[next];
266             switch (nextChar) {
267             case 'f':
268             case 'F':
269                 doublePrecision = false;
270                 next++;
271                 break;
272             case 'd':
273             case 'D':
274                 doublePrecision = true;
275                 next++;
276                 break;
277             default:
278                 throw new NumberFormatException JavaDoc();
279             }
280         }
281
282         // at this point, all the parsing is done
283
// Step 7: handle mantissa of zero
284
if (mantissa == 0) {
285             return 0L;
286         }
287
288         // Step 8: normalize non-zero mantissa
289
// mantissa is in right-hand mantissaBits
290
// ensure that top bit (as opposed to hex digit) is 1
291
int scaleFactorCompensation = 0;
292         long top = (mantissa >>> (mantissaBits - 4));
293         if ((top & 0x8) == 0) {
294             mantissaBits--;
295             scaleFactorCompensation++;
296             if ((top & 0x4) == 0) {
297                 mantissaBits--;
298                 scaleFactorCompensation++;
299                 if ((top & 0x2) == 0) {
300                     mantissaBits--;
301                     scaleFactorCompensation++;
302                 }
303             }
304         }
305         
306         // Step 9: convert double literals to IEEE double
307
long result = 0L;
308         if (doublePrecision) {
309             long fraction;
310             if (mantissaBits > DOUBLE_PRECISION) {
311                 // more bits than we can keep
312
int extraBits = mantissaBits - DOUBLE_PRECISION;
313                 // round to DOUBLE_PRECISION bits
314
fraction = mantissa >>> (extraBits - 1);
315                 long lowBit = fraction & 0x1;
316                 fraction += lowBit;
317                 fraction = fraction >>> 1;
318                 if ((fraction & (1L << DOUBLE_PRECISION)) != 0) {
319                     fraction = fraction >>> 1;
320                     scaleFactorCompensation -= 1;
321                 }
322             } else {
323                 // less bits than the faction can hold - pad on right with 0s
324
fraction = mantissa << (DOUBLE_PRECISION - mantissaBits);
325             }
326
327             int scaleFactor = 0; // how many bits to move '.' to before leading hex digit
328
if (mantissaBits > 0) {
329                 if (leadingDigitPosition < binaryPointPosition) {
330                     // e.g., 0x80.0p0 has scaleFactor == +8
331
scaleFactor = 4 * (binaryPointPosition - leadingDigitPosition);
332                     // e.g., 0x10.0p0 has scaleFactorCompensation == +3
333
scaleFactor -= scaleFactorCompensation;
334                 } else {
335                     // e.g., 0x0.08p0 has scaleFactor == -4
336
scaleFactor = -4
337                             * (leadingDigitPosition - binaryPointPosition - 1);
338                     // e.g., 0x0.01p0 has scaleFactorCompensation == +3
339
scaleFactor -= scaleFactorCompensation;
340                 }
341             }
342
343             int e = (exponentSign * exponent) + scaleFactor;
344             if (e - 1 > MAX_DOUBLE_EXPONENT) {
345                 // overflow to +infinity
346
result = Double.doubleToLongBits(Double.POSITIVE_INFINITY);
347             } else if (e - 1 >= MIN_NORMALIZED_DOUBLE_EXPONENT) {
348                 // can be represented as a normalized double
349
// the left most bit must be discarded (it's always a 1)
350
long biasedExponent = e - 1 + DOUBLE_EXPONENT_BIAS;
351                 result = fraction & ~(1L << DOUBLE_FRACTION_WIDTH);
352                 result |= (biasedExponent << DOUBLE_EXPONENT_SHIFT);
353             } else if (e - 1 > MIN_UNNORMALIZED_DOUBLE_EXPONENT) {
354                 // can be represented as an unnormalized double
355
long biasedExponent = 0;
356                 result = fraction >>> (MIN_NORMALIZED_DOUBLE_EXPONENT - e + 1);
357                 result |= (biasedExponent << DOUBLE_EXPONENT_SHIFT);
358             } else {
359                 // underflow - return Double.NaN
360
result = Double.doubleToLongBits(Double.NaN);
361             }
362             return result;
363         }
364
365         // Step 10: convert float literals to IEEE single
366
long fraction;
367         if (mantissaBits > SINGLE_PRECISION) {
368             // more bits than we can keep
369
int extraBits = mantissaBits - SINGLE_PRECISION;
370             // round to DOUBLE_PRECISION bits
371
fraction = mantissa >>> (extraBits - 1);
372             long lowBit = fraction & 0x1;
373             fraction += lowBit;
374             fraction = fraction >>> 1;
375             if ((fraction & (1L << SINGLE_PRECISION)) != 0) {
376                 fraction = fraction >>> 1;
377                 scaleFactorCompensation -= 1;
378             }
379         } else {
380             // less bits than the faction can hold - pad on right with 0s
381
fraction = mantissa << (SINGLE_PRECISION - mantissaBits);
382         }
383
384         int scaleFactor = 0; // how many bits to move '.' to before leading hex digit
385
if (mantissaBits > 0) {
386             if (leadingDigitPosition < binaryPointPosition) {
387                 // e.g., 0x80.0p0 has scaleFactor == +8
388
scaleFactor = 4 * (binaryPointPosition - leadingDigitPosition);
389                 // e.g., 0x10.0p0 has scaleFactorCompensation == +3
390
scaleFactor -= scaleFactorCompensation;
391             } else {
392                 // e.g., 0x0.08p0 has scaleFactor == -4
393
scaleFactor = -4
394                         * (leadingDigitPosition - binaryPointPosition - 1);
395                 // e.g., 0x0.01p0 has scaleFactorCompensation == +3
396
scaleFactor -= scaleFactorCompensation;
397             }
398         }
399
400         int e = (exponentSign * exponent) + scaleFactor;
401         if (e - 1 > MAX_SINGLE_EXPONENT) {
402             // overflow to +infinity
403
result = Float.floatToIntBits(Float.POSITIVE_INFINITY);
404         } else if (e - 1 >= MIN_NORMALIZED_SINGLE_EXPONENT) {
405             // can be represented as a normalized single
406
// the left most bit must be discarded (it's always a 1)
407
long biasedExponent = e - 1 + SINGLE_EXPONENT_BIAS;
408             result = fraction & ~(1L << SINGLE_FRACTION_WIDTH);
409             result |= (biasedExponent << SINGLE_EXPONENT_SHIFT);
410         } else if (e - 1 > MIN_UNNORMALIZED_SINGLE_EXPONENT) {
411             // can be represented as an unnormalized single
412
long biasedExponent = 0;
413             result = fraction >>> (MIN_NORMALIZED_SINGLE_EXPONENT - e + 1);
414             result |= (biasedExponent << SINGLE_EXPONENT_SHIFT);
415         } else {
416             // underflow - return Float.NaN
417
result = Float.floatToIntBits(Float.NaN);
418         }
419         return result;
420     }
421 }
422
Popular Tags