mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 08:24:10 -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 {
|
} else {
|
||||||
doubleMantissa = abs * 0x1p1022 * binaryExponent(negExp - 1022);
|
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);
|
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;
|
boolean negative = (bits & (1 << 63)) != 0;
|
||||||
int rawExp = (int)((bits >> 52) & 0x7FFL) - 1023;
|
int rawExp = (int)((bits >> 52) & 0x7FFL);
|
||||||
long mantissa = bits & 0xFFFFFFFFFFFFFL;
|
long mantissa = bits & 0xFFFFFFFFFFFFFL;
|
||||||
if (rawExp == 0) {
|
if (rawExp == 0) {
|
||||||
mantissa <<= 1;
|
mantissa <<= 1;
|
||||||
|
@ -350,7 +350,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
return new TString(buffer, 0, sz);
|
return new TString(buffer, 0, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double binaryExponent(int n) {
|
private static double binaryExponent(int n) {
|
||||||
double result = 1;
|
double result = 1;
|
||||||
if (n >= 0) {
|
if (n >= 0) {
|
||||||
double d = 2;
|
double d = 2;
|
||||||
|
|
|
@ -89,6 +89,11 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
return other instanceof TFloat && ((TFloat)other).value == value;
|
return other instanceof TFloat && ((TFloat)other).value == value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return floatToIntBits(value);
|
||||||
|
}
|
||||||
|
|
||||||
@GeneratedBy(FloatNativeGenerator.class)
|
@GeneratedBy(FloatNativeGenerator.class)
|
||||||
public static native boolean isNaN(float v);
|
public static native boolean isNaN(float v);
|
||||||
|
|
||||||
|
@ -231,4 +236,144 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
public int compareTo(TFloat other) {
|
public int compareTo(TFloat other) {
|
||||||
return compare(value, other.value);
|
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) {
|
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) {
|
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,
|
public static double[] negativeExponents = { 0x1p-1, 0x1p-2, 0x1p-4, 0x1p-8, 0x1p-16, 0x1p-32,
|
||||||
0x1p-64, 0x1p-128, 0x1p-256, 0x1p-512 };
|
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"), 1E-12);
|
||||||
assertEquals(0, Double.parseDouble("00000.0000"), 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