View | Details | Raw Unified | Return to bug 74126 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java (-21 / +44 lines)
Lines 10-20 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
11
package org.eclipse.jdt.internal.compiler.ast;
12
12
13
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.internal.compiler.ASTVisitor;
14
import org.eclipse.jdt.internal.compiler.ASTVisitor;
14
import org.eclipse.jdt.internal.compiler.impl.*;
15
import org.eclipse.jdt.internal.compiler.impl.*;
15
import org.eclipse.jdt.internal.compiler.codegen.*;
16
import org.eclipse.jdt.internal.compiler.codegen.*;
16
import org.eclipse.jdt.internal.compiler.lookup.*;
17
import org.eclipse.jdt.internal.compiler.lookup.*;
17
import org.eclipse.jdt.internal.compiler.util.Util;
18
import org.eclipse.jdt.internal.compiler.util.FloatUtil;
18
19
19
public class DoubleLiteral extends NumberLiteral {
20
public class DoubleLiteral extends NumberLiteral {
20
	double value;
21
	double value;
Lines 22-65 Link Here
22
		super(token, s, e);
23
		super(token, s, e);
23
	}
24
	}
24
	public void computeConstant() {
25
	public void computeConstant() {
25
		//the source is correctly formated so the exception should never occurs
26
		if (CharOperation.indexOf('x', source) >= 0
27
			&& CharOperation.indexOf('p', source) >= 0) {
28
			// hex floating point literal
29
			try {
30
				double v = FloatUtil.valueOfHexDoubleLiteral(source);
31
				if (v == Double.POSITIVE_INFINITY) {
32
					// error: the number is too large to represent
33
					return;
34
				}
35
				if (Double.isNaN(v)) {
36
					// error: the number is too small to represent
37
					return;
38
				}
39
				value = v;
40
				constant = Constant.fromValue(v);
41
			} catch (NumberFormatException e) {
42
				// the source is correctly formated so the exception should never occurs
43
				return;
44
			}
45
		}
46
			
47
		// non-hexadecimal floating point literals
26
		Double computedValue;
48
		Double computedValue;
27
		try {
49
		try {
28
			computedValue = Double.valueOf(String.valueOf(source));
50
			computedValue = Double.valueOf(String.valueOf(source));
29
		} catch (NumberFormatException e) {
51
		} catch (NumberFormatException e) {
30
			/*
52
			// the source is correctly formated so the exception should never occurs
31
			 * this can happen if this is an hexadecimal floating-point literal and the libraries used 
53
			return;
32
			 * are < 1.5
33
			 */
34
			computedValue = new Double(Util.getFloatingPoint(source));
35
		}
54
		}
36
55
37
		final double doubleValue = computedValue.doubleValue();
56
		final double doubleValue = computedValue.doubleValue();
38
		if (doubleValue > Double.MAX_VALUE)
57
		if (doubleValue > Double.MAX_VALUE) {
39
			return; //may be Infinity
58
			// error: the number is too large to represent
40
		if (doubleValue < Double.MIN_VALUE) { //only a true 0 can be made of zeros
59
			return;
41
			//2.00000000000000000e-324 is illegal .... 
60
		}
61
		if (doubleValue < Double.MIN_VALUE) {
62
			// see 1F6IGUU
63
			// a true 0 only has '0' and '.' in mantissa
64
			// 1.0e-5000d is non-zero, but underflows to 0
42
			label : for (int i = 0; i < source.length; i++) { //it is welled formated so just test against '0' and potential . D d  
65
			label : for (int i = 0; i < source.length; i++) { //it is welled formated so just test against '0' and potential . D d  
43
				switch (source[i]) {
66
				switch (source[i]) {
44
					case '0' :
67
					case '0' :
45
					case '.' :
68
					case '.' :
46
					case 'd' :
47
					case 'D' :
48
					case 'x' :
49
					case 'X' :
50
						break;
69
						break;
51
					case 'e' :
70
					case 'e' :
52
					case 'E' :
71
					case 'E' :
53
					case 'p' :
72
						// starting the exponent - mantissa is all zero
54
					case 'P' :
73
						break label;
55
						break label; //exposant are valid....!
74
					case 'f' :
75
					case 'F' :
76
						// no exponent - mantissa is all zero
77
						break label;
56
					default :
78
					default :
79
						// error: the number is too small to represent
57
						return;
80
						return;
58
				}
81
				}
59
			}
82
			}
60
		} //error
83
		}
61
84
		value = doubleValue;
62
		constant = Constant.fromValue(value = doubleValue);
85
		constant = Constant.fromValue(value);
63
	}
86
	}
64
	/**
87
	/**
65
	 * Code generation for the double literak
88
	 * Code generation for the double literak
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java (-21 / +43 lines)
Lines 10-21 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
11
package org.eclipse.jdt.internal.compiler.ast;
12
12
13
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.internal.compiler.ASTVisitor;
14
import org.eclipse.jdt.internal.compiler.ASTVisitor;
14
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
15
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
15
import org.eclipse.jdt.internal.compiler.impl.Constant;
16
import org.eclipse.jdt.internal.compiler.impl.Constant;
16
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
18
import org.eclipse.jdt.internal.compiler.util.Util;
19
import org.eclipse.jdt.internal.compiler.util.FloatUtil;
19
20
20
public class FloatLiteral extends NumberLiteral {
21
public class FloatLiteral extends NumberLiteral {
21
	float value;
22
	float value;
Lines 24-68 Link Here
24
		super(token, s, e);
25
		super(token, s, e);
25
	}
26
	}
26
	public void computeConstant() {
27
	public void computeConstant() {
27
		//the source is correctly formated so the exception should never occurs
28
		if (CharOperation.indexOf('x', source) >= 0
29
			&& CharOperation.indexOf('p', source) >= 0) {
30
			// hex floating point literal
31
			try {
32
				float v = FloatUtil.valueOfHexFloatLiteral(source);
33
				if (v == Float.POSITIVE_INFINITY) {
34
					// error: the number is too large to represent
35
					return;
36
				}
37
				if (Float.isNaN(v)) {
38
					// error: the number is too small to represent
39
					return;
40
				}
41
				value = v;
42
				constant = Constant.fromValue(v);
43
			} catch (NumberFormatException e) {
44
				// the source is correctly formated so the exception should never occurs
45
				return;
46
			}
47
		}
48
		
49
		// non-hexadecimal floating point literals
28
		Float computedValue;
50
		Float computedValue;
29
		try {
51
		try {
30
			computedValue = Float.valueOf(String.valueOf(source));
52
			computedValue = Float.valueOf(String.valueOf(source));
31
		} catch (NumberFormatException e) {
53
		} catch (NumberFormatException e) {
32
			/*
54
			// the source is correctly formated so the exception should never occurs
33
			 * this can happen if this is an hexadecimal floating-point literal and the libraries used 
55
			return;
34
			 * are < 1.5
35
			 */
36
			computedValue = new Float(Util.getFloatingPoint(source));
37
		}
56
		}
38
57
39
		if (computedValue.doubleValue() > Float.MAX_VALUE) {
58
		final float floatValue = computedValue.floatValue();
40
			return; //may be Infinity
59
		if (floatValue > Float.MAX_VALUE) {
60
			// error: the number is too large to represent
61
			return;
41
		}
62
		}
42
		if (computedValue.floatValue() < Float_MIN_VALUE) {
63
		if (floatValue < Float_MIN_VALUE) {
43
			// see 1F6IGUU
64
			// see 1F6IGUU
44
			//only a true 0 can be made of zeros
65
			// a true 0 only has '0' and '.' in mantissa
45
			//1.00000000e-46f is illegal ....
66
			// 1.0e-5000f is non-zero, but underflows to 0
46
			label : for (int i = 0; i < source.length; i++) {
67
			label : for (int i = 0; i < source.length; i++) {
47
				switch (source[i]) {
68
				switch (source[i]) {
48
					case '.' :
69
					case '.' :
49
					case 'f' :
50
					case 'F' :
51
					case '0' :
70
					case '0' :
52
					case 'x' :
53
					case 'X' :
54
						break;
71
						break;
55
					case 'e' :
72
					case 'e' :
56
					case 'E' :
73
					case 'E' :
57
					case 'p' :
74
						// starting the exponent - mantissa is all zero
58
					case 'P' :
75
						break label;
59
						break label; //exposant are valid !....
76
					case 'd' :
77
					case 'D' :
78
						// no exponent - mantissa is all zero
79
						break label;
60
					default :
80
					default :
61
						return; //error
81
						// error: the number is too small to represent
82
						return;
62
				}
83
				}
63
			}
84
			}
64
		}
85
		}
65
		constant = Constant.fromValue(value = computedValue.floatValue());
86
		value = floatValue;
87
		constant = Constant.fromValue(value);
66
	}
88
	}
67
	/**
89
	/**
68
	 * Code generation for float literal
90
	 * Code generation for float literal
(-)compiler/org/eclipse/jdt/internal/compiler/util/Util.java (-216 lines)
Lines 520-739 Link Here
520
			return Boolean.FALSE;
520
			return Boolean.FALSE;
521
		}
521
		}
522
	}
522
	}
523
	
524
	/**
525
	 * Returns the double value corresponding to the hexadecimal floating-point literal
526
	 * @return the double value corresponding to the hexadecimal floating-point literal
527
	 */
528
	public static double getFloatingPoint(char[] source) {
529
		int length = source.length;
530
		long hexValue = 0;
531
		int i = 2;
532
		loop: while (true) {
533
			switch(source[i]) {
534
				case '0' :
535
					hexValue <<= 4;
536
					break;
537
				case '1' :
538
					hexValue <<= 4;
539
					hexValue ++;
540
					break;
541
				case '2' :
542
					hexValue <<= 4;
543
					hexValue += 2;
544
					break;
545
				case '3' :
546
					hexValue <<= 4;
547
					hexValue += 3;
548
					break;
549
				case '4' :
550
					hexValue <<= 4;
551
					hexValue += 4;
552
					break;
553
				case '5' :
554
					hexValue <<= 4;
555
					hexValue += 5;
556
					break;
557
				case '6' :
558
					hexValue <<= 4;
559
					hexValue += 6;
560
					break;
561
				case '7' :
562
					hexValue <<= 4;
563
					hexValue += 7;
564
					break;
565
				case '8' :
566
					hexValue <<= 4;
567
					hexValue += 8;
568
					break;
569
				case '9' :
570
					hexValue <<= 4;
571
					hexValue += 9;
572
					break;
573
				case 'a' :
574
				case 'A' :
575
					hexValue <<= 4;
576
					hexValue += 10;
577
					break;
578
				case 'b' :
579
				case 'B' :
580
					hexValue <<= 4;
581
					hexValue += 11;
582
					break;
583
				case 'c' :
584
				case 'C' :
585
					hexValue <<= 4;
586
					hexValue += 12;
587
					break;
588
				case 'd' :
589
				case 'D' :
590
					hexValue <<= 4;
591
					hexValue += 13;
592
					break;
593
				case 'e' :
594
				case 'E' :
595
					hexValue <<= 4;
596
					hexValue += 14;
597
					break;
598
				case 'F' :
599
				case 'f' :
600
					hexValue <<= 4;
601
					hexValue += 15;
602
					break;
603
				default:
604
					break loop;
605
			}
606
			i++;
607
		}
608
		double decimalsValue = 0.0;
609
		if (source[i] == '.') {
610
			int index = 1;
611
			i++;
612
			loop2 : while (true) {
613
				switch(source[i]) {
614
					case '1' :
615
						decimalsValue += 1.0 / ((2 << 3) << (4 * (index - 1)));
616
						break;
617
					case '2' :
618
						decimalsValue += 2.0 / ((2 << 3) << (4 * (index - 1)));
619
						break;
620
					case '3' :
621
						decimalsValue += 3.0 / ((2 << 3) << (4 * (index - 1)));
622
						break;
623
					case '4' :
624
						decimalsValue += 4.0 / ((2 << 3) << (4 * (index - 1)));
625
						break;
626
					case '5' :
627
						decimalsValue += 5.0 / ((2 << 3) << (4 * (index - 1)));
628
						break;
629
					case '6' :
630
						decimalsValue += 6.0 / ((2 << 3) << (4 * (index - 1)));
631
						break;
632
					case '7' :
633
						decimalsValue += 7.0 / ((2 << 3) << (4 * (index - 1)));
634
						break;
635
					case '8' :
636
						decimalsValue += 8.0 / ((2 << 3) << (4 * (index - 1)));
637
						break;
638
					case '9' :
639
						decimalsValue += 9.0 / ((2 << 3) << (4 * (index - 1)));
640
						break;
641
					case 'a' :
642
					case 'A' :
643
						decimalsValue += 10.0 / ((2 << 3) << (4 * (index - 1)));
644
						break;
645
					case 'b' :
646
					case 'B' :
647
						decimalsValue += 11.0 / ((2 << 3) << (4 * (index - 1)));
648
						break;
649
					case 'c' :
650
					case 'C' :
651
						decimalsValue += 12.0 / ((2 << 3) << (4 * (index - 1)));
652
						break;
653
					case 'd' :
654
					case 'D' :
655
						decimalsValue += 13.0 / ((2 << 3) << (4 * (index - 1)));
656
						break;
657
					case 'e' :
658
					case 'E' :
659
						decimalsValue += 14.0 / ((2 << 3) << (4 * (index - 1)));
660
						break;
661
					case 'F' :
662
					case 'f' :
663
						decimalsValue += 15.0 / ((2 << 3) << (4 * (index - 1)));
664
						break;
665
					default:
666
						break loop2;
667
				}
668
				i++;
669
				index++;
670
			}
671
		}
672
		i++; // read p or P
673
		boolean isNegative = false;
674
		switch(source[i]) {
675
			case '-' :
676
				isNegative = true;
677
				i++;
678
				break;
679
			case '+' :
680
				i++;
681
				break;
682
		}
683
		int exponentValue = 0;
684
		loop3: while (true) {
685
			switch(source[i]) {
686
				case '0' :
687
					exponentValue *= 10;
688
					break;
689
				case '1' :
690
					exponentValue *= 10;
691
					exponentValue++;
692
					break;
693
				case '2' :
694
					exponentValue *= 10;
695
					exponentValue += 2;
696
					break;
697
				case '3' :
698
					exponentValue *= 10;
699
					exponentValue += 3;
700
					break;
701
				case '4' :
702
					exponentValue *= 10;
703
					exponentValue += 4;
704
					break;
705
				case '5' :
706
					exponentValue *= 10;
707
					exponentValue += 5;
708
					break;
709
				case '6' :
710
					exponentValue *= 10;
711
					exponentValue += 6;
712
					break;
713
				case '7' :
714
					exponentValue *= 10;
715
					exponentValue += 7;
716
					break;
717
				case '8' :
718
					exponentValue *= 10;
719
					exponentValue += 8;
720
					break;
721
				case '9' :
722
					exponentValue *= 10;
723
					exponentValue += 9;
724
					break;
725
				default:
726
					break loop3;
727
			}
728
			i++;
729
			if (i >= length) {
730
				break loop3;
731
			}
732
		}
733
		if (exponentValue == 0) {
734
			return hexValue + decimalsValue;
735
		}
736
		exponentValue--;
737
		return (hexValue + decimalsValue) * (isNegative ? 1.0 / (2 << exponentValue) : 2 << exponentValue);
738
	}
739
}
523
}
(-)compiler/org/eclipse/jdt/internal/compiler/util/FloatUtil.java (+421 lines)
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
}

Return to bug 74126