mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
Completes java.lang.Float implementation
This commit is contained in:
parent
4143e6c8d7
commit
ca6e325b74
|
@ -260,7 +260,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
|||
} else {
|
||||
doubleMantissa = abs * 0x1p1022 * binaryExponent(negExp - 1022);
|
||||
}
|
||||
long mantissa = (long)(doubleMantissa) & 0xFFFFFFFFFFFFFL;
|
||||
long mantissa = (long)(doubleMantissa + 0.5) & 0xFFFFFFFFFFFFFL;
|
||||
return mantissa | ((exp + 1023L) << 52) | (value < 0 ? (1L << 63) : 0);
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
|||
}
|
||||
}
|
||||
boolean negative = (bits & (1 << 63)) != 0;
|
||||
int rawExp = (int)((bits >> 52) & 0x7FFL) - 1023;
|
||||
int rawExp = (int)((bits >> 52) & 0x7FFL);
|
||||
long mantissa = bits & 0xFFFFFFFFFFFFFL;
|
||||
if (rawExp == 0) {
|
||||
mantissa <<= 1;
|
||||
|
@ -350,7 +350,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
|||
return new TString(buffer, 0, sz);
|
||||
}
|
||||
|
||||
public static double binaryExponent(int n) {
|
||||
private static double binaryExponent(int n) {
|
||||
double result = 1;
|
||||
if (n >= 0) {
|
||||
double d = 2;
|
||||
|
|
|
@ -89,6 +89,11 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
return other instanceof TFloat && ((TFloat)other).value == value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return floatToIntBits(value);
|
||||
}
|
||||
|
||||
@GeneratedBy(FloatNativeGenerator.class)
|
||||
public static native boolean isNaN(float v);
|
||||
|
||||
|
@ -231,4 +236,144 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
public int compareTo(TFloat other) {
|
||||
return compare(value, other.value);
|
||||
}
|
||||
|
||||
public static int floatToRawIntBits(float value) {
|
||||
return floatToIntBits(value);
|
||||
}
|
||||
|
||||
public static int floatToIntBits(float value) {
|
||||
if (value == POSITIVE_INFINITY) {
|
||||
return 0x7F800000;
|
||||
} else if (value == NEGATIVE_INFINITY) {
|
||||
return 0xFF800000;
|
||||
} else if (isNaN(value)) {
|
||||
return 0x7FC00000;
|
||||
}
|
||||
float abs = TMath.abs(value);
|
||||
int exp = TMath.getExponent(abs);
|
||||
int negExp = -exp + 23;
|
||||
if (exp < -126) {
|
||||
exp = -127;
|
||||
negExp = 126 + 23;
|
||||
}
|
||||
float doubleMantissa;
|
||||
if (negExp <= 126) {
|
||||
doubleMantissa = abs * binaryExponent(negExp);
|
||||
} else {
|
||||
doubleMantissa = abs * 0x1p126f * binaryExponent(negExp - 126);
|
||||
}
|
||||
int mantissa = (int)(doubleMantissa + 0.5f) & 0x7FFFFF;
|
||||
return mantissa | ((exp + 127) << 23) | (value < 0 ? (1 << 31) : 0);
|
||||
}
|
||||
|
||||
public static float intBitsToFloat(int bits) {
|
||||
if ((bits & 0x7F800000) == 0x7F800000) {
|
||||
if (bits == 0x7F800000) {
|
||||
return POSITIVE_INFINITY;
|
||||
} else if (bits == 0xFF800000) {
|
||||
return NEGATIVE_INFINITY;
|
||||
} else {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
boolean negative = (bits & (1 << 31)) != 0;
|
||||
int rawExp = ((bits >> 23) & 0x7F8) - 127;
|
||||
int mantissa = bits & 0x7FFFFF;
|
||||
if (rawExp == 0) {
|
||||
mantissa <<= 1;
|
||||
} else {
|
||||
mantissa |= (1L << 23);
|
||||
}
|
||||
float value = mantissa * binaryExponent(rawExp - 127 - 23);
|
||||
return !negative ? value : -value;
|
||||
}
|
||||
|
||||
private static float binaryExponent(int n) {
|
||||
float result = 1;
|
||||
if (n >= 0) {
|
||||
float d = 2;
|
||||
while (n != 0) {
|
||||
if (n % 2 != 0) {
|
||||
result *= d;
|
||||
}
|
||||
n /= 2;
|
||||
d *= d;
|
||||
}
|
||||
} else {
|
||||
n = -n;
|
||||
float d = 0.5f;
|
||||
while (n != 0) {
|
||||
if (n % 2 != 0) {
|
||||
result *= d;
|
||||
}
|
||||
n /= 2;
|
||||
d *= d;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TString toHexString(float f) {
|
||||
if (isNaN(f)) {
|
||||
return TString.wrap("NaN");
|
||||
} else if (isInfinite(f)) {
|
||||
return f > 0 ? TString.wrap("Infinity") : TString.wrap("-Infinity");
|
||||
}
|
||||
char[] buffer = new char[18];
|
||||
int sz = 0;
|
||||
int bits = floatToIntBits(f);
|
||||
boolean subNormal = false;
|
||||
int exp = ((bits >>> 23) & 0xFF) - 127;
|
||||
int mantissa = (bits & 0x7FFFFF) << 1;
|
||||
if (exp == -127) {
|
||||
++exp;
|
||||
subNormal = true;
|
||||
}
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
int digit = mantissa & 0xF;
|
||||
if (digit > 0 || sz > 0) {
|
||||
buffer[sz++] = TCharacter.forDigit(digit, 16);
|
||||
}
|
||||
mantissa >>>= 4;
|
||||
}
|
||||
if (sz == 0) {
|
||||
buffer[sz++] = '0';
|
||||
}
|
||||
buffer[sz++] = '.';
|
||||
|
||||
buffer[sz++] = subNormal ? '0' : '1';
|
||||
buffer[sz++] = 'x';
|
||||
buffer[sz++] = '0';
|
||||
if ((bits & (1L << 31)) != 0) {
|
||||
buffer[sz++] = '-';
|
||||
}
|
||||
int half = sz / 2;
|
||||
for (int i = 0; i < half; ++i) {
|
||||
char tmp = buffer[i];
|
||||
buffer[i] = buffer[sz - i - 1];
|
||||
buffer[sz - i - 1] = tmp;
|
||||
}
|
||||
|
||||
buffer[sz++] = 'p';
|
||||
if (exp < 0) {
|
||||
exp = -exp;
|
||||
buffer[sz++] = '-';
|
||||
}
|
||||
int pos = 100;
|
||||
boolean first = true;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
int digit = exp / pos;
|
||||
if (digit > 0 || !first) {
|
||||
buffer[sz++] = TCharacter.forDigit(digit, 10);
|
||||
first = false;
|
||||
}
|
||||
exp %= pos;
|
||||
pos /= 10;
|
||||
}
|
||||
if (first) {
|
||||
buffer[sz++] = '0';
|
||||
}
|
||||
|
||||
return new TString(buffer, 0, sz);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,7 +242,36 @@ public final class TMath extends TObject {
|
|||
}
|
||||
|
||||
public static int getExponent(float f) {
|
||||
return getExponent(f);
|
||||
f = abs(f);
|
||||
int exp = 0;
|
||||
float[] exponents = FloatExponents.exponents;
|
||||
float[] negativeExponents = FloatExponents.negativeExponents;
|
||||
if (f > 1) {
|
||||
int expBit = 1 << (exponents.length - 1);
|
||||
for (int i = exponents.length - 1; i >= 0; --i) {
|
||||
if (f >= exponents[i]) {
|
||||
f *= negativeExponents[i];
|
||||
exp |= expBit;
|
||||
}
|
||||
expBit >>>= 1;
|
||||
}
|
||||
} else if (f < 1) {
|
||||
int expBit = 1 << (negativeExponents.length - 1);
|
||||
int offset = 0;
|
||||
if (f <= 0x1p-127) {
|
||||
f *= 0x1p23f;
|
||||
offset = 23;
|
||||
}
|
||||
for (int i = negativeExponents.length - 1; i >= 0; --i) {
|
||||
if (f <= negativeExponents[i]) {
|
||||
f *= exponents[i];
|
||||
exp |= expBit;
|
||||
}
|
||||
expBit >>>= 1;
|
||||
}
|
||||
exp = -(exp + offset);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
public static double nextAfter(double start, double direction) {
|
||||
|
@ -273,4 +302,10 @@ public final class TMath extends TObject {
|
|||
public static double[] negativeExponents = { 0x1p-1, 0x1p-2, 0x1p-4, 0x1p-8, 0x1p-16, 0x1p-32,
|
||||
0x1p-64, 0x1p-128, 0x1p-256, 0x1p-512 };
|
||||
}
|
||||
|
||||
private static class FloatExponents {
|
||||
public static float[] exponents = { 0x1p1f, 0x1p2f, 0x1p4f, 0x1p8f, 0x1p16f, 0x1p32f, 0x1p64f };
|
||||
public static float[] negativeExponents = { 0x1p-1f, 0x1p-2f, 0x1p-4f, 0x1p-8f, 0x1p-16f, 0x1p-32f,
|
||||
0x1p-64f };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,4 +48,37 @@ public class FloatTest {
|
|||
assertEquals(0, Double.parseDouble("00000"), 1E-12);
|
||||
assertEquals(0, Double.parseDouble("00000.0000"), 1E-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void floatBitsExtracted() {
|
||||
assertEquals(0x4591A2B4, Float.floatToIntBits(0x1.234567p+12f));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subNormalFloatBitsExtracted() {
|
||||
assertEquals(0x000092, Float.floatToIntBits(0x0.000123p-126f));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void floatBitsPacked() {
|
||||
assertEquals(0x1.234567p+12f, Float.intBitsToFloat(0x4591A2B4), 1e7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subNormalFloatBitsPacked() {
|
||||
assertEquals(0x0.000123p-126f, Float.intBitsToFloat(0x000092), 0x000008p-126);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hexStringBuilt() {
|
||||
assertEquals("0x1.23456p17", Float.toHexString(0x1.23456p17f));
|
||||
assertEquals("0x1.0p0", Float.toHexString(1));
|
||||
assertEquals("-0x1.0p0", Float.toHexString(-1));
|
||||
assertEquals("0x1.0p1", Float.toHexString(2));
|
||||
assertEquals("0x1.8p1", Float.toHexString(3));
|
||||
assertEquals("0x1.0p-1", Float.toHexString(0.5f));
|
||||
assertEquals("0x1.0p-2", Float.toHexString(0.25f));
|
||||
assertEquals("0x1.0p-126", Float.toHexString(0x1.0p-126f));
|
||||
assertEquals("0x0.001p-126", Float.toHexString(0x0.001p-126f));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user