From f85aa977eba3daed645575cb927d8d969b14b8ad Mon Sep 17 00:00:00 2001 From: Ivan Hetman Date: Mon, 23 Sep 2024 16:46:05 +0300 Subject: [PATCH] classlib: add Math cell/floor div/mod versions, add exact versions of methods --- .../org/teavm/classlib/java/lang/TMath.java | 80 ++++++++++++++++++- .../teavm/classlib/java/lang/MathTest.java | 20 +++++ 2 files changed, 97 insertions(+), 3 deletions(-) diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java index eb705a331..15f79502a 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java @@ -143,6 +143,13 @@ public final class TMath extends TObject { return (a ^ b) < 0 && div * b != a ? div - 1 : div; } + public static int floorDivExact(int a, int b) { + if (a == Integer.MIN_VALUE && b == -1) { + throw new ArithmeticException(); + } + return floorDiv(a, b); + } + public static long floorDiv(long a, int b) { return floorDiv(a, (long) b); } @@ -152,16 +159,67 @@ public final class TMath extends TObject { return (a ^ b) < 0 && div * b != a ? div - 1 : div; } + public static long floorDivExact(long a, long b) { + if (a == Long.MIN_VALUE && b == -1) { + throw new ArithmeticException(); + } + return floorDiv(a, b); + } + + public static int ceilDiv(int a, int b) { + int div = a / b; + return (a ^ b) >= 0 && div * b != a ? div + 1 : div; + } + + public static int ceilDivExact(int a, int b) { + if (a == Integer.MIN_VALUE && b == -1) { + throw new ArithmeticException(); + } + return ceilDiv(a, b); + } + + public static long ceilDiv(long a, int b) { + return ceilDiv(a, (long) b); + } + + public static long ceilDiv(long a, long b) { + long div = a / b; + return (a ^ b) >= 0 && div * b != a ? div + 1 : div; + } + + public static long ceilDivExact(long a, long b) { + if (a == Long.MIN_VALUE && b == -1) { + throw new ArithmeticException(); + } + return ceilDiv(a, b); + } + public static int floorMod(int a, int b) { - return a - floorDiv(a, b) * b; + int mod = a % b; + return (a ^ b) < 0 && mod != 0 ? mod + b : mod; } public static int floorMod(long a, int b) { - return (int) (a - floorDiv(a, b) * b); + return (int) floorMod(a, (long) b); } public static long floorMod(long a, long b) { - return a - floorDiv(a, b) * b; + long mod = a % b; + return (a ^ b) < 0 && mod != 0 ? mod + b : mod; + } + + public static int ceilMod(int a, int b) { + int mod = a % b; + return (a ^ b) >= 0 && mod != 0 ? mod - b : mod; + } + + public static int ceilMod(long a, int b) { + return (int) ceilMod(a, (long) b); + } + + public static long ceilMod(long a, long b) { + long mod = a % b; + return (a ^ b) >= 0 && mod != 0 ? mod - b : mod; } public static int incrementExact(int a) { @@ -419,10 +477,26 @@ public final class TMath extends TObject { return n >= 0 ? n : -n; } + public static int absExact(int n) { + if (n == Integer.MIN_VALUE) { + throw new ArithmeticException(); + } else { + return abs(n); + } + } + public static long abs(long n) { return n >= 0 ? n : -n; } + public static long absExact(long n) { + if (n == Long.MIN_VALUE) { + throw new ArithmeticException(); + } else { + return abs(n); + } + } + @GeneratedBy(MathNativeGenerator.class) @NoSideEffects private static native float absImpl(float d); diff --git a/tests/src/test/java/org/teavm/classlib/java/lang/MathTest.java b/tests/src/test/java/org/teavm/classlib/java/lang/MathTest.java index 6a882a9f9..2cc2974b9 100644 --- a/tests/src/test/java/org/teavm/classlib/java/lang/MathTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/lang/MathTest.java @@ -291,4 +291,24 @@ public class MathTest { }); }); } + + @Test + public void ceilFloorModDiv() { + assertEquals(-2, Math.ceilMod(+4, +3)); + assertEquals(+2, Math.ceilMod(-4, -3)); + assertEquals(+1, Math.ceilMod(+4, -3)); + assertEquals(-1, Math.ceilMod(-4, +3)); + assertEquals(+1, Math.floorMod(+4, +3)); + assertEquals(-1, Math.floorMod(-4, -3)); + assertEquals(-2, Math.floorMod(+4, -3)); + assertEquals(+2, Math.floorMod(-4, +3)); + assertEquals(+2, Math.ceilDiv(5, 3)); + assertEquals(+2, Math.ceilDiv(6, 3)); + assertEquals(-1, Math.ceilDiv(-5, 3)); + assertEquals(-2, Math.ceilDiv(-6, 3)); + assertEquals(+1, Math.floorDiv(5, 3)); + assertEquals(+2, Math.floorDiv(6, 3)); + assertEquals(-2, Math.floorDiv(-5, 3)); + assertEquals(-2, Math.floorDiv(-6, 3)); + } }