Skip to content

Commit

Permalink
classlib: make difference between raw and normal floating points to i…
Browse files Browse the repository at this point in the history
…nt conversion
  • Loading branch information
Ihromant authored Sep 20, 2023
1 parent 3b6b31f commit 8277671
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 19 deletions.
13 changes: 8 additions & 5 deletions classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java
Original file line number Diff line number Diff line change
Expand Up @@ -252,15 +252,18 @@ public boolean isInfinite() {
@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")
Expand Down
15 changes: 9 additions & 6 deletions classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,18 @@ public int compareTo(TFloat other) {
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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ public double getDouble() {

@Override
public TByteBuffer putDouble(double value) {
return putLong(Double.doubleToLongBits(value));
return putLong(Double.doubleToRawLongBits(value));
}

@Override
Expand All @@ -389,7 +389,7 @@ public double getDouble(int index) {

@Override
public TByteBuffer putDouble(int index, double value) {
return putLong(index, Double.doubleToLongBits(value));
return putLong(index, Double.doubleToRawLongBits(value));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand All @@ -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);
Expand All @@ -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);
}
Expand Down
15 changes: 14 additions & 1 deletion tests/src/test/java/org/teavm/classlib/java/lang/DoubleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

@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);
Expand Down Expand Up @@ -60,7 +62,6 @@ public void parsed() {
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));
Expand Down Expand Up @@ -144,4 +145,16 @@ public void compares() {
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));
}
}
15 changes: 14 additions & 1 deletion tests/src/test/java/org/teavm/classlib/java/lang/FloatTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

@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);
Expand Down Expand Up @@ -58,7 +60,6 @@ public void parsed() {
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));
Expand Down Expand Up @@ -126,4 +127,16 @@ public void compares() {
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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
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;

Expand Down Expand Up @@ -632,6 +633,8 @@ public void putsDouble() {

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
Expand Down

0 comments on commit 8277671

Please sign in to comment.