Implement more precise comparison logic

This commit is contained in:
Alexey Andreev 2023-09-19 17:33:04 +02:00
parent 95f802718c
commit 3b6b31ff8f
5 changed files with 31 additions and 24 deletions

View File

@ -40,12 +40,6 @@ public class NumericClassTransformer implements ClassHolderTransformer {
case "java.lang.Long": case "java.lang.Long":
transformLong(cls); transformLong(cls);
break; break;
case "java.lang.Float":
transformFloat(cls);
break;
case "java.lang.Double":
transformDouble(cls);
break;
} }
} }
@ -57,14 +51,6 @@ public class NumericClassTransformer implements ClassHolderTransformer {
transformCompareMethod(cls, ValueType.LONG, NumericOperandType.LONG); transformCompareMethod(cls, ValueType.LONG, NumericOperandType.LONG);
} }
private void transformFloat(ClassHolder cls) {
transformCompareMethod(cls, ValueType.FLOAT, NumericOperandType.FLOAT);
}
private void transformDouble(ClassHolder cls) {
transformCompareMethod(cls, ValueType.DOUBLE, NumericOperandType.DOUBLE);
}
private void transformCompareMethod(ClassHolder cls, ValueType type, NumericOperandType insnType) { private void transformCompareMethod(ClassHolder cls, ValueType type, NumericOperandType insnType) {
MethodHolder method = cls.getMethod(new MethodDescriptor("compare", type, type, ValueType.INTEGER)); MethodHolder method = cls.getMethod(new MethodDescriptor("compare", type, type, ValueType.INTEGER));
Program program = new Program(); Program program = new Program();

View File

@ -215,7 +215,11 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
} }
@NoSideEffects @NoSideEffects
public static native int compare(double a, double b); public static int compare(double a, double b) {
var diff = (a > b ? 1 : 0) - (b > a ? 1 : 0);
return diff != 0 ? diff : (1 / a > 1 / b ? 1 : 0) - (1 / b > 1 / a ? 1 : 0)
+ (b == b ? 1 : 0) - (a == a ? 1 : 0);
}
@Override @Override
public int compareTo(TDouble other) { public int compareTo(TDouble other) {

View File

@ -245,7 +245,11 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
} }
@NoSideEffects @NoSideEffects
public static native int compare(float f1, float f2); public static int compare(float a, float b) {
var diff = (a > b ? 1 : 0) - (b > a ? 1 : 0);
return diff != 0 ? diff : (1 / a > 1 / b ? 1 : 0) - (1 / b > 1 / a ? 1 : 0)
+ (b == b ? 1 : 0) - (a == a ? 1 : 0);
}
@Override @Override
public int compareTo(TFloat other) { public int compareTo(TFloat other) {

View File

@ -17,7 +17,6 @@ package org.teavm.classlib.java.lang;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.util.Random; import java.util.Random;
import org.junit.Test; import org.junit.Test;
@ -134,8 +133,15 @@ public class DoubleTest {
@Test @Test
public void compares() { public void compares() {
assertTrue(Double.compare(10, 5) > 0); assertEquals(1, Double.compare(10, 5));
assertTrue(Double.compare(5, 10) < 0); assertEquals(-1, Double.compare(5, 10));
assertTrue(Double.compare(5, 5) == 0); assertEquals(0, Double.compare(5, 5));
assertEquals(0, Double.compare(0.0f, 0.0f));
assertEquals(1, Double.compare(Double.NaN, Double.POSITIVE_INFINITY));
assertEquals(-1, Double.compare(Double.POSITIVE_INFINITY, Double.NaN));
assertEquals(1, Double.compare(Double.NaN, 0.0));
assertEquals(-1, Double.compare(-0.0, Double.NaN));
assertEquals(1, Double.compare(0.0, -0.0));
assertEquals(-1, Double.compare(-0.0, 0.0));
} }
} }

View File

@ -17,7 +17,6 @@ package org.teavm.classlib.java.lang;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -115,8 +114,16 @@ public class FloatTest {
@Test @Test
public void compares() { public void compares() {
assertTrue(Float.compare(10, 5) > 0); assertEquals(1, Float.compare(10, 5));
assertTrue(Float.compare(5, 10) < 0); assertEquals(-1, Float.compare(5, 10));
assertTrue(Float.compare(5, 5) == 0); assertEquals(0, Float.compare(5, 5));
assertEquals(0, Float.compare(0.0f, 0.0f));
assertEquals(0, Float.compare(-0.0f, -0.0f));
assertEquals(1, Float.compare(Float.NaN, Float.POSITIVE_INFINITY));
assertEquals(-1, Float.compare(Float.POSITIVE_INFINITY, Float.NaN));
assertEquals(1, Float.compare(Float.NaN, 0.0f));
assertEquals(-1, Float.compare(-0.0f, Float.NaN));
assertEquals(1, Float.compare(0.0f, -0.0f));
assertEquals(-1, Float.compare(-0.0f, 0.0f));
} }
} }