Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public static TDouble valueOf(String string) {
}

public static double parseDouble(String string) throws NumberFormatException {
// TODO: parse infinite and different radix
// TODO: parse different radix

if (string.isEmpty()) {
throw new NumberFormatException();
Expand All @@ -95,6 +95,7 @@ public static double parseDouble(String string) throws NumberFormatException {
while (string.charAt(end - 1) <= ' ') {
--end;
}
int endForNamedDouble = end; // InfinityF/f/D/d, NaNF/f/D/d cannot be parsed
if (string.charAt(end - 1) == 'f' || string.charAt(end - 1) == 'F'
|| string.charAt(end - 1) == 'd' || string.charAt(end - 1) == 'D') {
--end;
Expand All @@ -120,6 +121,16 @@ public static double parseDouble(String string) throws NumberFormatException {
if (c != '.') {
hasOneDigit = true;
if (c < '0' || c > '9') {
if (c == 'I') {
if (endForNamedDouble - index == 8 && string.regionMatches(false, index, "Infinity", 0, 8)) {
return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
}
}
if (c == 'N') {
if (endForNamedDouble - index == 3 && string.regionMatches(false, index, "NaN", 0, 3)) {
return NaN;
}
}
throw new NumberFormatException();
}
while (index < end && string.charAt(index) == '0') {
Expand Down Expand Up @@ -257,7 +268,7 @@ public boolean isInfinite() {
@Unmanaged
public static native boolean isNaN(double v);

@JSBody(params = "v", script = "return !isFinite(v);")
@JSBody(params = "v", script = "return (!isFinite(v) && !isNaN(v));")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the most straightforward implementation here would be just turn this method into non-native and call isNaN and isFinite from Java side. This will solve the issue with other backends

@Import(module = "teavm", name = "isinf")
@NoSideEffects
@Unmanaged
Expand Down
15 changes: 13 additions & 2 deletions classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static int hashCode(float f) {
@Unmanaged
public static native boolean isNaN(float v);

@JSBody(params = "v", script = "return !isFinite(v);")
@JSBody(params = "v", script = "return (!isFinite(v) && !isNaN(v));")
@Import(module = "teavm", name = "isinf")
@NoSideEffects
@Unmanaged
Expand All @@ -121,7 +121,7 @@ public static int hashCode(float f) {
public static native boolean isFinite(float v);

public static float parseFloat(String string) throws NumberFormatException {
// TODO: parse infinite and different radix
// TODO: parse different radix

if (string.isEmpty()) {
throw new NumberFormatException();
Expand All @@ -136,6 +136,7 @@ public static float parseFloat(String string) throws NumberFormatException {
while (string.charAt(end - 1) <= ' ') {
--end;
}
int endForNamedFloat = end; // InfinityF/f/D/d, NaNF/f/D/d cannot be parsed
if (string.charAt(end - 1) == 'f' || string.charAt(end - 1) == 'F'
|| string.charAt(end - 1) == 'd' || string.charAt(end - 1) == 'D') {
--end;
Expand All @@ -162,6 +163,16 @@ public static float parseFloat(String string) throws NumberFormatException {
if (c != '.') {
hasOneDigit = true;
if (c < '0' || c > '9') {
if (c == 'I') {
if (endForNamedFloat - index == 8 && string.regionMatches(false, index, "Infinity", 0, 8)) {
return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY;
}
}
if (c == 'N') {
if (endForNamedFloat - index == 3 && string.regionMatches(false, index, "NaN", 0, 3)) {
return NaN;
}
}
throw new NumberFormatException();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ private WasmExpression testNaN(WasmExpression expression, WasmIntrinsicManager m
return block;
}

// TODO: Make isInfinite(NaN) return false on WASM and C
private WasmExpression testIsInfinite(WasmExpression expression) {
var conversion = new WasmConversion(WasmNumType.FLOAT64, WasmNumType.INT64, false, expression);
conversion.setReinterpret(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ private WasmExpression testNaN(WasmExpression expression, WasmGCIntrinsicContext
return block;
}

// TODO: Make isInfinite(NaN) return false on WASM and C
private WasmExpression testIsInfinite(WasmExpression expression) {
var conversion = new WasmConversion(WasmNumType.FLOAT32, WasmNumType.INT32, false, expression);
conversion.setReinterpret(true);
Expand Down
43 changes: 43 additions & 0 deletions tests/src/test/java/org/teavm/classlib/java/lang/DoubleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
package org.teavm.classlib.java.lang;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Random;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.junit.SkipPlatform;
import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.TestPlatform;

@RunWith(TeaVMTestRunner.class)
public class DoubleTest {
Expand Down Expand Up @@ -63,6 +66,15 @@ public void parsed() {
assertEquals(23, Double.parseDouble("23F"), 0.1f);
assertEquals(23, Double.parseDouble("23d"), 0.1f);
assertEquals(23, Double.parseDouble("23D"), 0.1f);

assertEquals(Double.POSITIVE_INFINITY, Double.parseDouble("Infinity"), 1E-12);
assertEquals(Double.POSITIVE_INFINITY, Double.parseDouble("+Infinity"), 1E-12);
assertEquals(Double.NEGATIVE_INFINITY, Double.parseDouble("-Infinity"), 1E-12);
assertEquals(Double.NEGATIVE_INFINITY, Double.parseDouble(" -Infinity "), 1E-12);
assertEquals(Double.NaN, Double.parseDouble("NaN"), 1E-12);
assertEquals(Double.NaN, Double.parseDouble("+NaN"), 1E-12);
assertEquals(Double.NaN, Double.parseDouble("-NaN"), 1E-12);
assertEquals(Double.NaN, Double.parseDouble(" -NaN "), 1E-12);
}

@Test
Expand Down Expand Up @@ -101,6 +113,23 @@ public void parsedWithError() {
checkIllegalFormat(".");
checkIllegalFormat("1e-");
checkIllegalFormat("1e");

checkIllegalFormat("++Infinity");
checkIllegalFormat("--Infinity");
checkIllegalFormat("INFINITY");
checkIllegalFormat("infinity");
checkIllegalFormat("InfinityF");
checkIllegalFormat("InfinityD");
checkIllegalFormat("Infinityf");
checkIllegalFormat("Infinityd");
checkIllegalFormat("++NaN");
checkIllegalFormat("--NaN");
checkIllegalFormat("NAN");
checkIllegalFormat("nan");
checkIllegalFormat("NaNF");
checkIllegalFormat("NaND");
checkIllegalFormat("NaNf");
checkIllegalFormat("NaNd");
}

private void checkIllegalFormat(String string) {
Expand Down Expand Up @@ -166,4 +195,18 @@ public void testNaN() {
assertNotEquals(Double.doubleToRawLongBits(OTHER_NAN), Double.doubleToRawLongBits(Double.NaN));
assertEquals(Double.doubleToLongBits(OTHER_NAN), Double.doubleToLongBits(Double.NaN));
}

@Test
@SkipPlatform({ TestPlatform.WASI, TestPlatform.WEBASSEMBLY, TestPlatform.WEBASSEMBLY_GC, TestPlatform.C })
// TODO: Make isInfinite(NaN) return false on WASM and C
public void testFinity() {
assertTrue(Double.isFinite(1d));
assertFalse(Double.isInfinite(1d));
assertFalse(Double.isFinite(Double.POSITIVE_INFINITY));
assertTrue(Double.isInfinite(Double.POSITIVE_INFINITY));
assertFalse(Double.isFinite(Double.NEGATIVE_INFINITY));
assertTrue(Double.isInfinite(Double.NEGATIVE_INFINITY));
assertFalse(Double.isFinite(Double.NaN));
assertFalse(Double.isInfinite(Double.NaN));
}
}
43 changes: 43 additions & 0 deletions tests/src/test/java/org/teavm/classlib/java/lang/FloatTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
package org.teavm.classlib.java.lang;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.junit.SkipPlatform;
import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.TestPlatform;

@RunWith(TeaVMTestRunner.class)
public class FloatTest {
Expand Down Expand Up @@ -60,6 +63,15 @@ public void parsed() {
assertEquals(23, Float.parseFloat("23F"), 0.1f);
assertEquals(23, Float.parseFloat("23d"), 0.1f);
assertEquals(23, Float.parseFloat("23D"), 0.1f);

assertEquals(Float.POSITIVE_INFINITY, Float.parseFloat("Infinity"), 1E-12F);
assertEquals(Float.POSITIVE_INFINITY, Float.parseFloat("+Infinity"), 1E-12F);
assertEquals(Float.NEGATIVE_INFINITY, Float.parseFloat("-Infinity"), 1E-12F);
assertEquals(Float.NEGATIVE_INFINITY, Float.parseFloat(" -Infinity "), 1E-12F);
assertEquals(Float.NaN, Float.parseFloat("NaN"), 1E-12F);
assertEquals(Float.NaN, Float.parseFloat("+NaN"), 1E-12F);
assertEquals(Float.NaN, Float.parseFloat("-NaN"), 1E-12F);
assertEquals(Float.NaN, Float.parseFloat(" -NaN "), 1E-12F);
}

@Test
Expand All @@ -82,6 +94,23 @@ public void parsedWithError() {
checkIllegalFormat(".");
checkIllegalFormat("1e-");
checkIllegalFormat("1e");

checkIllegalFormat("++Infinity");
checkIllegalFormat("--Infinity");
checkIllegalFormat("INFINITY");
checkIllegalFormat("infinity");
checkIllegalFormat("InfinityF");
checkIllegalFormat("InfinityD");
checkIllegalFormat("Infinityf");
checkIllegalFormat("Infinityd");
checkIllegalFormat("++NaN");
checkIllegalFormat("--NaN");
checkIllegalFormat("NAN");
checkIllegalFormat("nan");
checkIllegalFormat("NaNF");
checkIllegalFormat("NaND");
checkIllegalFormat("NaNf");
checkIllegalFormat("NaNd");
}

private void checkIllegalFormat(String string) {
Expand Down Expand Up @@ -147,4 +176,18 @@ public void testNaN() {
assertNotEquals(Float.floatToRawIntBits(OTHER_NAN), Float.floatToRawIntBits(Float.NaN));
assertEquals(Float.floatToIntBits(OTHER_NAN), Float.floatToIntBits(Float.NaN));
}

@Test
@SkipPlatform({ TestPlatform.WASI, TestPlatform.WEBASSEMBLY, TestPlatform.WEBASSEMBLY_GC, TestPlatform.C })
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What prevents you from implementing this on WasmGC backend?

// TODO: Make isInfinite(NaN) return false on WASM and C
public void testFinity() {
assertTrue(Float.isFinite(1f));
assertFalse(Float.isInfinite(1f));
assertFalse(Float.isFinite(Float.POSITIVE_INFINITY));
assertTrue(Float.isInfinite(Float.POSITIVE_INFINITY));
assertFalse(Float.isFinite(Float.NEGATIVE_INFINITY));
assertTrue(Float.isInfinite(Float.NEGATIVE_INFINITY));
assertFalse(Float.isFinite(Float.NaN));
assertFalse(Float.isInfinite(Float.NaN));
}
}