classlib: fix Math exact operations in C and WebAssembly backends

This commit is contained in:
Alexey Andreev 2023-11-19 20:12:44 +01:00
parent 318d4bff93
commit 7108dfbac7
3 changed files with 12 additions and 12 deletions

View File

@ -254,7 +254,7 @@ public final class TMath extends TObject {
return 0; return 0;
} }
int total = a * b; int total = a * b;
if (total / b != a || (a == Integer.MIN_VALUE && b == -1) || (b == Integer.MIN_VALUE && a == -1)) { if ((a == Integer.MIN_VALUE && b == -1) || (b == Integer.MIN_VALUE && a == -1) || total / b != a) {
throw new ArithmeticException(); throw new ArithmeticException();
} }
return total; return total;
@ -273,26 +273,24 @@ public final class TMath extends TObject {
return 0; return 0;
} }
long total = a * b; long total = a * b;
if (total / b != a || (a == Long.MIN_VALUE && b == -1) || (b == Long.MIN_VALUE && a == -1)) { if ((a == Long.MIN_VALUE && b == -1) || (b == Long.MIN_VALUE && a == -1) || total / b != a) {
throw new ArithmeticException(); throw new ArithmeticException();
} }
return total; return total;
} }
public static int divideExact(int a, int b) { public static int divideExact(int a, int b) {
int q = a / b; if (a == Integer.MIN_VALUE && b == -1) {
if ((a & b & q) < 0) { // all 3 are negative
throw new ArithmeticException(); throw new ArithmeticException();
} }
return q; return a / b;
} }
public static long divideExact(long a, long b) { public static long divideExact(long a, long b) {
long q = a / b; if (a == Long.MIN_VALUE && b == -1) {
if ((a & b & q) < 0) { // all 3 are negative
throw new ArithmeticException(); throw new ArithmeticException();
} }
return q; return a / b;
} }
@Unmanaged @Unmanaged

View File

@ -202,7 +202,6 @@ public class MathTest {
} }
@Test @Test
@SkipPlatform({TestPlatform.WEBASSEMBLY, TestPlatform.WASI, TestPlatform.C})
public void exacts() { public void exacts() {
try { try {
Math.incrementExact(Integer.MAX_VALUE); Math.incrementExact(Integer.MAX_VALUE);
@ -258,6 +257,12 @@ public class MathTest {
} catch (ArithmeticException e) { } catch (ArithmeticException e) {
// ok // ok
} }
try {
Math.divideExact(Integer.MIN_VALUE, -1);
fail();
} catch (ArithmeticException e) {
// ok
}
IntStream.rangeClosed(-10, 10).forEach(x -> { IntStream.rangeClosed(-10, 10).forEach(x -> {
assertEquals(x + 1, Math.incrementExact(x)); assertEquals(x + 1, Math.incrementExact(x));
assertEquals(x - 1, Math.decrementExact(x)); assertEquals(x - 1, Math.decrementExact(x));

View File

@ -48,9 +48,7 @@ package org.teavm.classlib.java.time;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.teavm.junit.SkipPlatform;
import org.teavm.junit.TeaVMTestRunner; import org.teavm.junit.TeaVMTestRunner;
import org.teavm.junit.TestPlatform;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -309,7 +307,6 @@ public class TestDateTimesImplementation {
} }
@Test(dataProvider = "safeMultiplyLongLongProviderOverflow", expectedExceptions = ArithmeticException.class) @Test(dataProvider = "safeMultiplyLongLongProviderOverflow", expectedExceptions = ArithmeticException.class)
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
public void test_safeMultiplyLongLong_overflow(long a, long b) { public void test_safeMultiplyLongLong_overflow(long a, long b) {
Math.multiplyExact(a, b); Math.multiplyExact(a, b);
} }