Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2004 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Common Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/cpl-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(); |
130 |
} |
131 |
nextChar = source[next]; |
132 |
if (nextChar == 'X' || nextChar == 'x') { |
133 |
next++; |
134 |
} else { |
135 |
throw new NumberFormatException(); |
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(); |
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(); |
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 |
} |