blob: 19b600baaf156b89924c290d596736125258e857 [file] [log] [blame]
// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package backport;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.desugar.backports.AbstractBackportTest;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.math.BigInteger;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public final class MathBackportJava9Test extends AbstractBackportTest {
@Parameters(name = "{0}")
public static Iterable<?> data() {
return TestBase.getTestParameters()
.withDexRuntimes()
.withCfRuntimesStartingFromIncluding(CfVm.JDK9)
.withAllApiLevelsAlsoForCf()
.build();
}
public MathBackportJava9Test(TestParameters parameters) {
super(parameters, Math.class, MathBackportJava9Main.class);
// Math.floorDiv, Math.floorMod, Math.multiplyExact, Math.multiplyFull and Math.multiplyHigh
// added in API 31.
registerTarget(AndroidApiLevel.S, 27);
}
public static class MathBackportJava9Main {
public static void main(String[] args) {
testMultiplyExactLongInt();
testMultiplyFull();
testMultiplyHigh();
testFloorDivLongInt();
testFloorModLongInt();
}
public static void testMultiplyExactLongInt() {
assertEquals(8L, Math.multiplyExact(2L, 4));
assertEquals(Long.MAX_VALUE, Math.multiplyExact(Long.MAX_VALUE, 1));
assertEquals(Long.MIN_VALUE, Math.multiplyExact(Long.MIN_VALUE / 2L, 2));
try {
throw new AssertionError(Math.multiplyExact(Long.MAX_VALUE, 2));
} catch (ArithmeticException expected) {
}
try {
throw new AssertionError(Math.multiplyExact(Long.MIN_VALUE, 2));
} catch (ArithmeticException expected) {
}
}
public static void testMultiplyFull() {
assertEquals(8L, Math.multiplyFull(2, 4));
assertEquals(4611686014132420609L, Math.multiplyFull(Integer.MAX_VALUE, Integer.MAX_VALUE));
assertEquals(-4611686016279904256L, Math.multiplyFull(Integer.MAX_VALUE, Integer.MIN_VALUE));
assertEquals(4611686018427387904L, Math.multiplyFull(Integer.MIN_VALUE, Integer.MIN_VALUE));
}
public static void testMultiplyHigh() {
long[] interestingValues = {
Long.MIN_VALUE,
Long.MAX_VALUE,
Integer.MIN_VALUE,
Integer.MAX_VALUE,
Short.MIN_VALUE,
Short.MAX_VALUE,
Byte.MIN_VALUE,
Byte.MAX_VALUE,
0L,
-1L,
1L,
-42L,
42L
};
for (long x : interestingValues) {
for (long y : interestingValues) {
long expected =
BigInteger.valueOf(x).multiply(BigInteger.valueOf(y)).shiftRight(64).longValue();
assertEquals(expected, Math.multiplyHigh(x, y));
}
}
}
public static void testFloorDivLongInt() {
assertEquals(1L, Math.floorDiv(4L, 4));
assertEquals(1L, Math.floorDiv(-4L, -4));
assertEquals(-1L, Math.floorDiv(-4L, 4));
assertEquals(-1L, Math.floorDiv(4L, -4));
assertEquals(1L, Math.floorDiv(4L, 3));
assertEquals(1L, Math.floorDiv(-4L, -3));
assertEquals(-2L, Math.floorDiv(-4L, 3));
assertEquals(-2L, Math.floorDiv(4L, -3));
// Spec edge case: result is actually MAX_VALUE+1 which becomes MIN_VALUE.
assertEquals(Long.MIN_VALUE, Math.floorDiv(Long.MIN_VALUE, -1));
}
public static void testFloorModLongInt() {
assertEquals(0, Math.floorMod(4L, 4));
assertEquals(0, Math.floorMod(-4L, -4));
assertEquals(0, Math.floorMod(-4L, 4));
assertEquals(0, Math.floorMod(4L, -4));
assertEquals(1, Math.floorMod(4L, 3));
assertEquals(-1, Math.floorMod(-4L, -3));
assertEquals(2, Math.floorMod(-4L, 3));
assertEquals(-2, Math.floorMod(4L, -3));
}
private static void assertEquals(int expected, int actual) {
if (expected != actual) {
throw new AssertionError("Expected <" + expected + "> but was <" + actual + '>');
}
}
private static void assertEquals(long expected, long actual) {
if (expected != actual) {
throw new AssertionError("Expected <" + expected + "> but was <" + actual + '>');
}
}
}
}