mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
classlib: improve accuracy of float parsing and formatting
This commit is contained in:
parent
e1706f242d
commit
062d4ae4e9
|
@ -21,6 +21,7 @@ public final class FloatAnalyzer {
|
|||
public static final int PRECISION = 9;
|
||||
public static final int MAX_POS = 100000000;
|
||||
static final int MAX_ABS_DEC_EXP = 50;
|
||||
private static final int MAX_MANTISSA = Integer.divideUnsigned(-1, 10);
|
||||
|
||||
private FloatAnalyzer() {
|
||||
}
|
||||
|
@ -54,13 +55,11 @@ public final class FloatAnalyzer {
|
|||
int mantissaShift = 9 + binExponentCorrection;
|
||||
|
||||
int decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
||||
if (decMantissa >= 1000000000) {
|
||||
++decExponent;
|
||||
binExponentCorrection = exponent - exp10Table[decExponent + 1];
|
||||
mantissaShift = 9 + binExponentCorrection;
|
||||
decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
||||
} else if (decMantissa < 100000000) {
|
||||
--decExponent;
|
||||
if (decMantissa < MAX_MANTISSA) {
|
||||
while (Integer.compareUnsigned(decMantissa, MAX_MANTISSA) <= 0) {
|
||||
--decExponent;
|
||||
decMantissa = decMantissa * 10 + 9;
|
||||
}
|
||||
binExponentCorrection = exponent - exp10Table[decExponent + 1];
|
||||
mantissaShift = 9 + binExponentCorrection;
|
||||
decMantissa = mulAndShiftRight(mantissa, mantissa10Table[decExponent + 1], mantissaShift);
|
||||
|
@ -72,18 +71,21 @@ public final class FloatAnalyzer {
|
|||
|
||||
var lowerPos = findLowerDistance(decMantissa, decMantissaLow);
|
||||
var upperPos = findUpperDistance(decMantissa, decMantissaHi);
|
||||
if (lowerPos > upperPos) {
|
||||
decMantissa = (decMantissa / lowerPos) * lowerPos;
|
||||
} else if (lowerPos < upperPos) {
|
||||
decMantissa = (decMantissa / upperPos) * upperPos + upperPos;
|
||||
var posCmp = Integer.compareUnsigned(lowerPos, upperPos);
|
||||
if (posCmp > 0) {
|
||||
decMantissa = Integer.divideUnsigned(decMantissa, lowerPos) * lowerPos;
|
||||
} else if (posCmp < 0) {
|
||||
decMantissa = Integer.divideUnsigned(decMantissa, upperPos) * upperPos + upperPos;
|
||||
} else {
|
||||
decMantissa = ((decMantissa + (upperPos / 2)) / upperPos) * upperPos;
|
||||
decMantissa = Integer.divideUnsigned(decMantissa + (upperPos / 2), upperPos) * upperPos;
|
||||
}
|
||||
|
||||
if (decMantissa >= 1000000000) {
|
||||
decExponent++;
|
||||
decMantissa /= 10;
|
||||
} else if (decMantissa < 100000000) {
|
||||
if (Long.compareUnsigned(decMantissa, 1000000000) >= 0) {
|
||||
do {
|
||||
decExponent++;
|
||||
decMantissa = Integer.divideUnsigned(decMantissa, 10);
|
||||
} while (Integer.compareUnsigned(decMantissa, 1000000000) >= 0);
|
||||
} else if (Integer.compareUnsigned(decMantissa, 100000000) < 0) {
|
||||
decExponent--;
|
||||
decMantissa *= 10;
|
||||
}
|
||||
|
@ -94,7 +96,9 @@ public final class FloatAnalyzer {
|
|||
|
||||
private static int findLowerDistance(int mantissa, int lower) {
|
||||
int pos = 1;
|
||||
while (mantissa / (pos * 10) > lower / (pos * 10)) {
|
||||
while (Integer.compareUnsigned(
|
||||
Integer.divideUnsigned(mantissa, pos * 10),
|
||||
Integer.divideUnsigned(lower, pos * 10)) > 0) {
|
||||
pos *= 10;
|
||||
}
|
||||
return pos;
|
||||
|
@ -102,7 +106,9 @@ public final class FloatAnalyzer {
|
|||
|
||||
private static int findUpperDistance(int mantissa, int upper) {
|
||||
int pos = 1;
|
||||
while (mantissa / (pos * 10) < upper / (pos * 10)) {
|
||||
while (Integer.compareUnsigned(
|
||||
Integer.divideUnsigned(mantissa, pos * 10),
|
||||
Integer.divideUnsigned(upper, pos * 10)) < 0) {
|
||||
pos *= 10;
|
||||
}
|
||||
return pos;
|
||||
|
@ -110,10 +116,6 @@ public final class FloatAnalyzer {
|
|||
|
||||
static int mulAndShiftRight(int a, int b, int shift) {
|
||||
var result = (a & 0xFFFFFFFFL) * (b & 0xFFFFFFFFL);
|
||||
var nextBit = ((result >> (31 - shift)) & 1) != 0;
|
||||
if (nextBit) {
|
||||
result += 1L << (31 - shift);
|
||||
}
|
||||
return (int) (result >>> (32 - shift));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,26 +20,30 @@ public final class FloatSynthesizer {
|
|||
}
|
||||
|
||||
public static float synthesizeFloat(int mantissa, int exp, boolean negative) {
|
||||
var indexInTable = FloatAnalyzer.MAX_ABS_DEC_EXP - exp;
|
||||
var indexInTable = FloatAnalyzer.MAX_ABS_DEC_EXP + exp;
|
||||
if (mantissa == 0 || indexInTable > mantissa10Table.length || indexInTable < 0) {
|
||||
return Float.intBitsToFloat(negative ? (1 << 31) : 0);
|
||||
}
|
||||
|
||||
var binMantissa = FloatAnalyzer.mulAndShiftRight(mantissa, mantissa10Table[indexInTable], 0);
|
||||
var binExp = exp10Table[indexInTable] - 1;
|
||||
while ((binMantissa & (-1L << 30L)) != 0) {
|
||||
binMantissa >>>= 1;
|
||||
binExp++;
|
||||
|
||||
var binMantissaShift = (32 - Integer.numberOfLeadingZeros(binMantissa)) - 30;
|
||||
if (binMantissaShift >= 0) {
|
||||
binMantissa >>>= binMantissaShift;
|
||||
} else {
|
||||
binMantissa <<= -binMantissaShift;
|
||||
}
|
||||
while (binMantissa < (1L << 29)) {
|
||||
binMantissa <<= 1;
|
||||
binExp--;
|
||||
}
|
||||
binExp += 5;
|
||||
binExp += binMantissaShift;
|
||||
|
||||
if (binExp >= 255) {
|
||||
return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
|
||||
}
|
||||
binMantissa += 1 << 5;
|
||||
if ((binMantissa & (-1 << 30)) != 0) {
|
||||
binMantissa >>>= 1;
|
||||
binExp++;
|
||||
}
|
||||
if (binExp <= 0) {
|
||||
binMantissa >>= Math.min(-binExp + 1, 32);
|
||||
binExp = 0;
|
||||
|
@ -54,208 +58,208 @@ public final class FloatSynthesizer {
|
|||
}
|
||||
|
||||
private static final int[] mantissa10Table = {
|
||||
-1213479385,
|
||||
-1829776968,
|
||||
-350662770,
|
||||
-1139523676,
|
||||
-1770612400,
|
||||
-255999462,
|
||||
-1063793029,
|
||||
-1710027882,
|
||||
-159064234,
|
||||
-986244846,
|
||||
-1647989336,
|
||||
-59802560,
|
||||
-906835507,
|
||||
-1584461865,
|
||||
-2126562952,
|
||||
-825520345,
|
||||
-1519409735,
|
||||
-2074521247,
|
||||
-742253618,
|
||||
-1452796353,
|
||||
-2021230542,
|
||||
-656988489,
|
||||
-1384584251,
|
||||
-1966660860,
|
||||
-569676998,
|
||||
-1314735058,
|
||||
-1910781505,
|
||||
-480270031,
|
||||
-1243209484,
|
||||
-1853561046,
|
||||
-388717296,
|
||||
-1169967296,
|
||||
-1794967296,
|
||||
-294967296,
|
||||
-1094967296,
|
||||
-1734967296,
|
||||
-198967296,
|
||||
-1018167296,
|
||||
-1673527296,
|
||||
-100663296,
|
||||
-939524096,
|
||||
-1610612736,
|
||||
-2147483648,
|
||||
-858993460,
|
||||
-1546188227,
|
||||
-2095944041,
|
||||
-776530088,
|
||||
-1480217529,
|
||||
-2043167483,
|
||||
-692087595,
|
||||
-1412663535,
|
||||
-1989124287,
|
||||
-605618482,
|
||||
-1343488245,
|
||||
-1933784055,
|
||||
-517074110,
|
||||
-1272652747,
|
||||
-1877115657,
|
||||
-426404674,
|
||||
-1200117198,
|
||||
-1819087218,
|
||||
-333559171,
|
||||
-1125840796,
|
||||
-1759666096,
|
||||
-238485376,
|
||||
-1049781760,
|
||||
-1698818867,
|
||||
-141129810,
|
||||
-971897307,
|
||||
-1636511305,
|
||||
-41437710,
|
||||
-892143627,
|
||||
-1572708361,
|
||||
-2117160148,
|
||||
-810475859,
|
||||
-1507374147,
|
||||
-2064892777,
|
||||
-726848065,
|
||||
-1440471911,
|
||||
-2011370988,
|
||||
-641213203,
|
||||
-1371964022,
|
||||
-1956564677,
|
||||
-553523105,
|
||||
-1301811943,
|
||||
-1900443014,
|
||||
-463728444,
|
||||
-1229976215,
|
||||
-1842974431,
|
||||
-371778712,
|
||||
-1156416429,
|
||||
-1784126602,
|
||||
-277622186,
|
||||
-1081091208,
|
||||
-1723866426,
|
||||
-181205903,
|
||||
-1003958182,
|
||||
-1662160005,
|
||||
-82475630,
|
||||
-1598972629,
|
||||
-924973963,
|
||||
-82475629,
|
||||
-1662160004,
|
||||
-1003958181,
|
||||
-181205903,
|
||||
-1723866425,
|
||||
-1081091207,
|
||||
-277622185,
|
||||
-1784126602,
|
||||
-1156416428,
|
||||
-371778711,
|
||||
-1842974431,
|
||||
-1229976214,
|
||||
-463728444,
|
||||
-1900443013,
|
||||
-1301811943,
|
||||
-553523104,
|
||||
-1956564676,
|
||||
-1371964021,
|
||||
-641213203,
|
||||
-2011370988,
|
||||
-1440471911,
|
||||
-726848064,
|
||||
-2064892776,
|
||||
-1507374146,
|
||||
-810475859,
|
||||
-2117160148,
|
||||
-1572708361,
|
||||
-892143627,
|
||||
-41437709,
|
||||
-1636511304,
|
||||
-971897307,
|
||||
-141129809,
|
||||
-1698818867,
|
||||
-1049781759,
|
||||
-238485375,
|
||||
-1759666096,
|
||||
-1125840795,
|
||||
-333559170,
|
||||
-1819087217,
|
||||
-1200117198,
|
||||
-426404673,
|
||||
-1877115657,
|
||||
-1272652747,
|
||||
-517074110,
|
||||
-1933784055,
|
||||
-1343488244,
|
||||
-605618481,
|
||||
-1989124287,
|
||||
-1412663534,
|
||||
-692087594,
|
||||
-2043167482,
|
||||
-1480217529,
|
||||
-776530087,
|
||||
-2095944040,
|
||||
-1546188227,
|
||||
-858993459,
|
||||
-2147483648,
|
||||
-1610612736,
|
||||
-939524096,
|
||||
-100663296,
|
||||
-1673527296,
|
||||
-1018167296,
|
||||
-198967296,
|
||||
-1734967296,
|
||||
-1094967296,
|
||||
-294967296,
|
||||
-1794967296,
|
||||
-1169967296,
|
||||
-388717296,
|
||||
-1853561046,
|
||||
-1243209483,
|
||||
-480270030,
|
||||
-1910781505,
|
||||
-1314735057,
|
||||
-569676998,
|
||||
-1966660859,
|
||||
-1384584250,
|
||||
-656988489,
|
||||
-2021230542,
|
||||
-1452796353,
|
||||
-742253617,
|
||||
-2074521247,
|
||||
-1519409734,
|
||||
-825520344,
|
||||
-2126562951,
|
||||
-1584461865,
|
||||
-906835507,
|
||||
-59802560,
|
||||
-1647989336,
|
||||
-986244846,
|
||||
-159064233,
|
||||
-1710027882,
|
||||
-1063793028,
|
||||
-255999461,
|
||||
-1770612399,
|
||||
-1139523675,
|
||||
-350662770,
|
||||
-1829776967,
|
||||
};
|
||||
|
||||
private static int[] exp10Table = {
|
||||
292,
|
||||
289,
|
||||
285,
|
||||
282,
|
||||
279,
|
||||
275,
|
||||
272,
|
||||
269,
|
||||
265,
|
||||
262,
|
||||
259,
|
||||
255,
|
||||
252,
|
||||
249,
|
||||
246,
|
||||
242,
|
||||
239,
|
||||
236,
|
||||
232,
|
||||
229,
|
||||
226,
|
||||
222,
|
||||
219,
|
||||
216,
|
||||
212,
|
||||
209,
|
||||
206,
|
||||
202,
|
||||
199,
|
||||
196,
|
||||
192,
|
||||
189,
|
||||
186,
|
||||
182,
|
||||
179,
|
||||
176,
|
||||
172,
|
||||
169,
|
||||
166,
|
||||
162,
|
||||
159,
|
||||
156,
|
||||
153,
|
||||
149,
|
||||
146,
|
||||
143,
|
||||
139,
|
||||
136,
|
||||
133,
|
||||
129,
|
||||
126,
|
||||
123,
|
||||
119,
|
||||
116,
|
||||
113,
|
||||
109,
|
||||
106,
|
||||
103,
|
||||
99,
|
||||
96,
|
||||
93,
|
||||
89,
|
||||
86,
|
||||
83,
|
||||
79,
|
||||
76,
|
||||
73,
|
||||
69,
|
||||
66,
|
||||
63,
|
||||
59,
|
||||
56,
|
||||
53,
|
||||
50,
|
||||
46,
|
||||
43,
|
||||
40,
|
||||
36,
|
||||
33,
|
||||
30,
|
||||
26,
|
||||
23,
|
||||
20,
|
||||
16,
|
||||
13,
|
||||
10,
|
||||
6,
|
||||
3,
|
||||
0,
|
||||
-4,
|
||||
-7,
|
||||
-10,
|
||||
-14,
|
||||
-17,
|
||||
-20,
|
||||
-24,
|
||||
-27,
|
||||
-30,
|
||||
-34,
|
||||
-37,
|
||||
-35,
|
||||
-32,
|
||||
-29,
|
||||
-25,
|
||||
-22,
|
||||
-19,
|
||||
-15,
|
||||
-12,
|
||||
-9,
|
||||
-5,
|
||||
-2,
|
||||
1,
|
||||
5,
|
||||
8,
|
||||
11,
|
||||
15,
|
||||
18,
|
||||
21,
|
||||
25,
|
||||
28,
|
||||
31,
|
||||
35,
|
||||
38,
|
||||
41,
|
||||
45,
|
||||
48,
|
||||
51,
|
||||
55,
|
||||
58,
|
||||
61,
|
||||
64,
|
||||
68,
|
||||
71,
|
||||
74,
|
||||
78,
|
||||
81,
|
||||
84,
|
||||
88,
|
||||
91,
|
||||
94,
|
||||
98,
|
||||
101,
|
||||
104,
|
||||
108,
|
||||
111,
|
||||
114,
|
||||
118,
|
||||
121,
|
||||
124,
|
||||
128,
|
||||
131,
|
||||
134,
|
||||
138,
|
||||
141,
|
||||
144,
|
||||
148,
|
||||
151,
|
||||
154,
|
||||
158,
|
||||
161,
|
||||
164,
|
||||
167,
|
||||
171,
|
||||
174,
|
||||
177,
|
||||
181,
|
||||
184,
|
||||
187,
|
||||
191,
|
||||
194,
|
||||
197,
|
||||
201,
|
||||
204,
|
||||
207,
|
||||
211,
|
||||
214,
|
||||
217,
|
||||
221,
|
||||
224,
|
||||
227,
|
||||
231,
|
||||
234,
|
||||
237,
|
||||
241,
|
||||
244,
|
||||
247,
|
||||
251,
|
||||
254,
|
||||
257,
|
||||
260,
|
||||
264,
|
||||
267,
|
||||
270,
|
||||
274,
|
||||
277,
|
||||
280,
|
||||
284,
|
||||
287,
|
||||
290,
|
||||
294,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,29 +24,26 @@ public final class FloatSynthesizerGenerator {
|
|||
public static void main(String[] args) {
|
||||
var mantissaList = new int[100];
|
||||
var expList = new int[100];
|
||||
var shift = 57;
|
||||
|
||||
var exp = 0;
|
||||
var binOneShift = 256;
|
||||
var binOne = BigInteger.ONE.shiftLeft(binOneShift);
|
||||
var dec = BigInteger.valueOf(100000000);
|
||||
for (var i = 0; i < 50; ++i) {
|
||||
while (BigInteger.ONE.shiftLeft(shift + exp + 1).divide(dec).bitLength() <= 32) {
|
||||
++exp;
|
||||
}
|
||||
mantissaList[50 + i] = BigInteger.ONE.shiftLeft(shift + exp).divide(dec).intValue();
|
||||
for (var i = 0; i <= 50; ++i) {
|
||||
var quot = binOne.divide(dec);
|
||||
mantissaList[50 - i] = extractInt(quot);
|
||||
var exp = quot.bitLength() - binOneShift + 30;
|
||||
expList[50 - i] = 127 + exp;
|
||||
dec = dec.multiply(BigInteger.valueOf(10));
|
||||
expList[50 + i] = 127 - exp;
|
||||
}
|
||||
|
||||
exp = 1;
|
||||
dec = BigInteger.valueOf(100000000).multiply(BigInteger.ONE.shiftLeft(128));
|
||||
var q = BigInteger.valueOf(10L);
|
||||
for (var i = 1; i <= 50; ++i) {
|
||||
while (BigInteger.ONE.shiftLeft(shift + 128 - exp).multiply(q).divide(dec).bitLength() > 32) {
|
||||
++exp;
|
||||
}
|
||||
mantissaList[50 - i] = BigInteger.ONE.shiftLeft(shift + 128 - exp).multiply(q).divide(dec).intValue();
|
||||
q = q.multiply(BigInteger.valueOf(10));
|
||||
expList[50 - i] = 127 + exp;
|
||||
dec = BigInteger.valueOf(100000000);
|
||||
var q = BigInteger.TEN;
|
||||
for (var i = 1; i < 50; ++i) {
|
||||
var quot = q.shiftLeft(binOneShift).divide(dec);
|
||||
mantissaList[50 + i] = extractInt(quot);
|
||||
var exp = quot.bitLength() - binOneShift + 30;
|
||||
expList[50 + i] = 127 + exp;
|
||||
q = q.multiply(BigInteger.TEN);
|
||||
}
|
||||
|
||||
System.out.println("[mantissa]");
|
||||
|
@ -60,4 +57,8 @@ public final class FloatSynthesizerGenerator {
|
|||
System.out.println(value + ",");
|
||||
}
|
||||
}
|
||||
|
||||
private static int extractInt(BigInteger n) {
|
||||
return n.shiftRight(n.bitLength() - 33).add(BigInteger.ONE).shiftRight(1).intValue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,17 +114,17 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
@Unmanaged
|
||||
public static native boolean isFinite(float v);
|
||||
|
||||
public static float parseFloat(String string) throws TNumberFormatException {
|
||||
public static float parseFloat(String string) throws NumberFormatException {
|
||||
// TODO: parse infinite and different radix
|
||||
|
||||
if (string.isEmpty()) {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
int start = 0;
|
||||
int end = string.length();
|
||||
while (string.charAt(start) <= ' ') {
|
||||
if (++start == end) {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
}
|
||||
while (string.charAt(end - 1) <= ' ') {
|
||||
|
@ -140,7 +140,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
++index;
|
||||
}
|
||||
if (index == end) {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
char c = string.charAt(index);
|
||||
|
||||
|
@ -152,7 +152,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
if (c != '.') {
|
||||
hasOneDigit = true;
|
||||
if (c < '0' || c > '9') {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
while (index < end && string.charAt(index) == '0') {
|
||||
|
@ -189,18 +189,18 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
hasOneDigit = true;
|
||||
}
|
||||
if (!hasOneDigit) {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
}
|
||||
if (index < end) {
|
||||
c = string.charAt(index);
|
||||
if (c != 'e' && c != 'E') {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
++index;
|
||||
boolean negativeExp = false;
|
||||
if (index == end) {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
if (string.charAt(index) == '-') {
|
||||
++index;
|
||||
|
@ -220,7 +220,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
++index;
|
||||
}
|
||||
if (!hasOneDigit) {
|
||||
throw new TNumberFormatException();
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
if (negativeExp) {
|
||||
numExp = -numExp;
|
||||
|
|
Loading…
Reference in New Issue
Block a user