classlib: make difference between raw and normal floating points to int conversion

This commit is contained in:
Ivan Hetman 2023-09-20 23:51:55 +03:00 committed by GitHub
parent 3b6b31ff8f
commit 8277671376
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 19 deletions

View File

@ -252,15 +252,18 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
@Unmanaged
public static native boolean isFinite(double v);
public static long doubleToRawLongBits(double value) {
return doubleToLongBits(value);
}
@InjectedBy(DoubleGenerator.class)
@Import(name = "teavm_reinterpretDoubleToLong")
@NoSideEffects
@Unmanaged
public static native long doubleToLongBits(double value);
public static native long doubleToRawLongBits(double value);
public static long doubleToLongBits(double value) {
if (isNaN(value)) {
return 0x7ff8000000000000L;
}
return doubleToRawLongBits(value);
}
@InjectedBy(DoubleGenerator.class)
@Import(name = "teavm_reinterpretLongToDouble")

View File

@ -256,15 +256,18 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
return compare(value, other.value);
}
public static int floatToRawIntBits(float value) {
return floatToIntBits(value);
}
@JSBody(params = "value", script = "return $rt_floatToIntBits(value);")
@JSBody(params = "value", script = "return $rt_floatToRawIntBits(value);")
@Import(name = "teavm_reinterpretFloatToInt")
@NoSideEffects
@Unmanaged
public static native int floatToIntBits(float value);
public static native int floatToRawIntBits(float value);
public static int floatToIntBits(float value) {
if (isNaN(value)) {
return 0x7fc00000;
}
return floatToRawIntBits(value);
}
@JSBody(params = "bits", script = "return $rt_intBitsToFloat(bits);")
@Import(name = "teavm_reinterpretIntToFloat")

View File

@ -379,7 +379,7 @@ class TByteBufferImpl extends TByteBuffer {
@Override
public TByteBuffer putDouble(double value) {
return putLong(Double.doubleToLongBits(value));
return putLong(Double.doubleToRawLongBits(value));
}
@Override
@ -389,7 +389,7 @@ class TByteBufferImpl extends TByteBuffer {
@Override
public TByteBuffer putDouble(int index, double value) {
return putLong(index, Double.doubleToLongBits(value));
return putLong(index, Double.doubleToRawLongBits(value));
}
@Override

View File

@ -658,10 +658,10 @@ function $rt_eraseClinit(target) {
var $rt_numberConversionView = new DataView(new ArrayBuffer(8));
var $rt_doubleToLongBits;
var $rt_doubleToRawLongBits;
var $rt_longBitsToDouble;
if (typeof BigInt !== 'function') {
$rt_doubleToLongBits = function(n) {
$rt_doubleToRawLongBits = function(n) {
$rt_numberConversionView.setFloat64(0, n, true);
return new Long($rt_numberConversionView.getInt32(0, true), $rt_numberConversionView.getInt32(4, true));
}
@ -671,7 +671,7 @@ if (typeof BigInt !== 'function') {
return $rt_numberConversionView.getFloat64(0, true);
}
} else {
$rt_doubleToLongBits = function(n) {
$rt_doubleToRawLongBits = function(n) {
$rt_numberConversionView.setFloat64(0, n, true);
// For compatibility with Safari
var lo = $rt_numberConversionView.getInt32(0, true);
@ -688,7 +688,7 @@ if (typeof BigInt !== 'function') {
}
}
function $rt_floatToIntBits(n) {
function $rt_floatToRawIntBits(n) {
$rt_numberConversionView.setFloat32(0, n);
return $rt_numberConversionView.getInt32(0);
}

View File

@ -25,6 +25,8 @@ import org.teavm.junit.TeaVMTestRunner;
@RunWith(TeaVMTestRunner.class)
public class DoubleTest {
public static final double OTHER_NAN = Double.longBitsToDouble(Double.doubleToLongBits(Double.NaN) + 1);
@Test
public void parsed() {
assertEquals(23, Double.parseDouble("23"), 1E-12);
@ -60,7 +62,6 @@ public class DoubleTest {
public void testEquals() {
assertNotEquals(Double.valueOf(-0.0), Double.valueOf(0.0));
assertEquals(Double.valueOf(3.0), Double.valueOf(3.0));
assertEquals(Double.valueOf(Double.NaN), Double.valueOf(Double.NaN));
assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), Double.valueOf(Double.POSITIVE_INFINITY));
assertNotEquals(Double.valueOf(Double.NEGATIVE_INFINITY), Double.valueOf(Double.POSITIVE_INFINITY));
assertEquals(Double.valueOf(Double.NEGATIVE_INFINITY), Double.valueOf(Double.NEGATIVE_INFINITY));
@ -144,4 +145,16 @@ public class DoubleTest {
assertEquals(1, Double.compare(0.0, -0.0));
assertEquals(-1, Double.compare(-0.0, 0.0));
}
@Test
public void testNaN() {
assertTrue(Double.isNaN(OTHER_NAN));
assertTrue(OTHER_NAN != OTHER_NAN);
assertTrue(OTHER_NAN != Double.NaN);
assertEquals(Double.valueOf(Double.NaN), Double.valueOf(Double.NaN));
assertEquals(Double.valueOf(OTHER_NAN), Double.valueOf(Double.NaN));
assertEquals(Double.valueOf(OTHER_NAN), Double.valueOf(OTHER_NAN));
assertNotEquals(Double.doubleToRawLongBits(OTHER_NAN), Double.doubleToRawLongBits(Double.NaN));
assertEquals(Double.doubleToLongBits(OTHER_NAN), Double.doubleToLongBits(Double.NaN));
}
}

View File

@ -24,6 +24,8 @@ import org.teavm.junit.TeaVMTestRunner;
@RunWith(TeaVMTestRunner.class)
public class FloatTest {
private static final float OTHER_NAN = Float.intBitsToFloat(Float.floatToIntBits(Float.NaN) + 1);
@Test
public void parsed() {
assertEquals(23, Float.parseFloat("23"), 1E-12F);
@ -58,7 +60,6 @@ public class FloatTest {
public void testEquals() {
assertNotEquals(Float.valueOf(-0.0f), Float.valueOf(0.0f));
assertEquals(Float.valueOf(5.0f), Float.valueOf(5.0f));
assertEquals(Float.valueOf(Float.NaN), Float.valueOf(Float.NaN));
assertEquals(Float.valueOf(Float.POSITIVE_INFINITY), Float.valueOf(Float.POSITIVE_INFINITY));
assertNotEquals(Float.valueOf(Float.NEGATIVE_INFINITY), Float.valueOf(Float.POSITIVE_INFINITY));
assertEquals(Float.valueOf(Float.NEGATIVE_INFINITY), Float.valueOf(Float.NEGATIVE_INFINITY));
@ -126,4 +127,16 @@ public class FloatTest {
assertEquals(1, Float.compare(0.0f, -0.0f));
assertEquals(-1, Float.compare(-0.0f, 0.0f));
}
@Test
public void testNaN() {
assertTrue(Float.isNaN(OTHER_NAN));
assertTrue(OTHER_NAN != OTHER_NAN);
assertTrue(OTHER_NAN != Double.NaN);
assertEquals(Float.valueOf(Float.NaN), Float.valueOf(Float.NaN));
assertEquals(Float.valueOf(OTHER_NAN), Float.valueOf(Float.NaN));
assertEquals(Float.valueOf(OTHER_NAN), Float.valueOf(OTHER_NAN));
assertNotEquals(Float.floatToRawIntBits(OTHER_NAN), Float.floatToRawIntBits(Float.NaN));
assertEquals(Float.floatToIntBits(OTHER_NAN), Float.floatToIntBits(Float.NaN));
}
}

View File

@ -29,6 +29,7 @@ import java.nio.InvalidMarkException;
import java.nio.ReadOnlyBufferException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.classlib.java.lang.DoubleTest;
import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.WholeClassCompilation;
@ -632,6 +633,8 @@ public class ByteBufferTest {
buffer.putDouble(1, 2.0);
assertArrayEquals(new byte[] { 63, 64, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0 }, array);
buffer.putDouble(0, DoubleTest.OTHER_NAN);
assertArrayEquals(new byte[] { 127, -8, 0, 0, 0, 0, 0, 1, 0, 55, 0, 0, 0, 0, 0, 0 }, array);
}
@Test