8023217: Additional floorDiv/floorMod/multiplyExact methods for java.lang.Math

Add new methods with long, int signatures.

Reviewed-by: darcy, scolebourne
This commit is contained in:
Brian Burkhalter 2015-09-29 17:28:44 -07:00
parent 1a2c01a37c
commit 3497da36a2
11 changed files with 382 additions and 27 deletions

View File

@ -95,7 +95,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
* {@code subtractExact}, {@code multiplyExact}, and {@code toIntExact}
* throw an {@code ArithmeticException} when the results overflow.
* For other arithmetic operations such as divide, absolute value,
* increment, decrement, and negation overflow occurs only with
* increment by one, decrement by one, and negation, overflow occurs only with
* a specific minimum or maximum value and should be checked against
* the minimum or maximum as appropriate.
*
@ -861,7 +861,7 @@ public final class Math {
public static int subtractExact(int x, int y) {
int r = x - y;
// HD 2-12 Overflow iff the arguments have different signs and
// the sign of the result is different than the sign of x
// the sign of the result is different from the sign of x
if (((x ^ y) & (x ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
@ -882,7 +882,7 @@ public final class Math {
public static long subtractExact(long x, long y) {
long r = x - y;
// HD 2-12 Overflow iff the arguments have different signs and
// the sign of the result is different than the sign of x
// the sign of the result is different from the sign of x
if (((x ^ y) & (x ^ r)) < 0) {
throw new ArithmeticException("long overflow");
}
@ -908,6 +908,20 @@ public final class Math {
return (int)r;
}
/**
* Returns the product of the arguments, throwing an exception if the result
* overflows a {@code long}.
*
* @param x the first value
* @param y the second value
* @return the result
* @throws ArithmeticException if the result overflows a long
* @since 1.9
*/
public static long multiplyExact(long x, int y) {
return multiplyExact(x, (long)y);
}
/**
* Returns the product of the arguments,
* throwing an exception if the result overflows a {@code long}.
@ -1112,12 +1126,12 @@ public final class Math {
* There is one special case, if the dividend is the
* {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1},
* then integer overflow occurs and
* the result is equal to the {@code Integer.MIN_VALUE}.
* the result is equal to {@code Integer.MIN_VALUE}.
* <p>
* Normal integer division operates under the round to zero rounding mode
* (truncation). This operation instead acts under the round toward
* negative infinity (floor) rounding mode.
* The floor rounding mode gives different results than truncation
* The floor rounding mode gives different results from truncation
* when the exact result is negative.
* <ul>
* <li>If the signs of the arguments are the same, the results of
@ -1155,12 +1169,41 @@ public final class Math {
* There is one special case, if the dividend is the
* {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
* then integer overflow occurs and
* the result is equal to the {@code Long.MIN_VALUE}.
* the result is equal to {@code Long.MIN_VALUE}.
* <p>
* Normal integer division operates under the round to zero rounding mode
* (truncation). This operation instead acts under the round toward
* negative infinity (floor) rounding mode.
* The floor rounding mode gives different results than truncation
* The floor rounding mode gives different results from truncation
* when the exact result is negative.
* <p>
* For examples, see {@link #floorDiv(int, int)}.
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* @throws ArithmeticException if the divisor {@code y} is zero
* @see #floorMod(long, int)
* @see #floor(double)
* @since 1.9
*/
public static long floorDiv(long x, int y) {
return floorDiv(x, (long)y);
}
/**
* Returns the largest (closest to positive infinity)
* {@code long} value that is less than or equal to the algebraic quotient.
* There is one special case, if the dividend is the
* {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
* then integer overflow occurs and
* the result is equal to {@code Long.MIN_VALUE}.
* <p>
* Normal integer division operates under the round to zero rounding mode
* (truncation). This operation instead acts under the round toward
* negative infinity (floor) rounding mode.
* The floor rounding mode gives different results from truncation
* when the exact result is negative.
* <p>
* For examples, see {@link #floorDiv(int, int)}.
@ -1228,8 +1271,34 @@ public final class Math {
* @since 1.8
*/
public static int floorMod(int x, int y) {
int r = x - floorDiv(x, y) * y;
return r;
return x - floorDiv(x, y) * y;
}
/**
* Returns the floor modulus of the {@code long} and {@int} arguments.
* <p>
* The floor modulus is {@code x - (floorDiv(x, y) * y)},
* has the same sign as the divisor {@code y}, and
* is in the range of {@code -abs(y) < r < +abs(y)}.
*
* <p>
* The relationship between {@code floorDiv} and {@code floorMod} is such that:
* <ul>
* <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
* </ul>
* <p>
* For examples, see {@link #floorMod(int, int)}.
*
* @param x the dividend
* @param y the divisor
* @return the floor modulus {@code x - (floorDiv(x, y) * y)}
* @throws ArithmeticException if the divisor {@code y} is zero
* @see #floorDiv(long, int)
* @since 1.9
*/
public static int floorMod(long x, int y) {
// Result cannot overflow the range of int.
return (int)(x - floorDiv(x, y) * y);
}
/**

View File

@ -70,7 +70,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
* {@code subtractExact}, {@code multiplyExact}, and {@code toIntExact}
* throw an {@code ArithmeticException} when the results overflow.
* For other arithmetic operations such as divide, absolute value,
* increment, decrement, and negation overflow occurs only with
* increment by one, decrement by one, and negation overflow occurs only with
* a specific minimum or maximum value and should be checked against
* the minimum or maximum as appropriate.
*
@ -802,6 +802,21 @@ public final class StrictMath {
return Math.multiplyExact(x, y);
}
/**
* Returns the product of the arguments, throwing an exception if the result
* overflows a {@code long}.
*
* @param x the first value
* @param y the second value
* @return the result
* @throws ArithmeticException if the result overflows a long
* @see Math#multiplyExact(long,int)
* @since 1.9
*/
public static long multiplyExact(long x, int y) {
return Math.multiplyExact(x, y);
}
/**
* Returns the product of the arguments,
* throwing an exception if the result overflows a {@code long}.
@ -882,6 +897,30 @@ public final class StrictMath {
return Math.floorDiv(x, y);
}
/**
* Returns the largest (closest to positive infinity)
* {@code long} value that is less than or equal to the algebraic quotient.
* There is one special case, if the dividend is the
* {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
* then integer overflow occurs and
* the result is equal to {@code Long.MIN_VALUE}.
* <p>
* See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and
* a comparison to the integer division {@code /} operator.
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* @throws ArithmeticException if the divisor {@code y} is zero
* @see Math#floorDiv(long, int)
* @see Math#floor(double)
* @since 1.9
*/
public static long floorDiv(long x, int y) {
return Math.floorDiv(x, y);
}
/**
* Returns the largest (closest to positive infinity)
* {@code long} value that is less than or equal to the algebraic quotient.
@ -932,6 +971,35 @@ public final class StrictMath {
public static int floorMod(int x, int y) {
return Math.floorMod(x , y);
}
/**
* Returns the floor modulus of the {@code long} and {@int} arguments.
* <p>
* The floor modulus is {@code x - (floorDiv(x, y) * y)},
* has the same sign as the divisor {@code y}, and
* is in the range of {@code -abs(y) < r < +abs(y)}.
*
* <p>
* The relationship between {@code floorDiv} and {@code floorMod} is such that:
* <ul>
* <li>{@code floorDiv(x, y) * y + floorMod(x, y) == x}
* </ul>
* <p>
* See {@link Math#floorMod(int, int) Math.floorMod} for examples and
* a comparison to the {@code %} operator.
*
* @param x the dividend
* @param y the divisor
* @return the floor modulus {@code x - (floorDiv(x, y) * y)}
* @throws ArithmeticException if the divisor {@code y} is zero
* @see Math#floorMod(long, int)
* @see StrictMath#floorDiv(long, int)
* @since 1.9
*/
public static int floorMod(long x, int y) {
return Math.floorMod(x , y);
}
/**
* Returns the floor modulus of the {@code long} arguments.
* <p>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -342,7 +342,7 @@ public final class Instant
*/
public static Instant ofEpochMilli(long epochMilli) {
long secs = Math.floorDiv(epochMilli, 1000);
int mos = (int)Math.floorMod(epochMilli, 1000);
int mos = Math.floorMod(epochMilli, 1000);
return create(secs, mos * 1000_000);
}

View File

@ -826,7 +826,7 @@ public final class LocalDate
* @return the day-of-week, not null
*/
public DayOfWeek getDayOfWeek() {
int dow0 = (int)Math.floorMod(toEpochDay() + 3, 7);
int dow0 = Math.floorMod(toEpochDay() + 3, 7);
return DayOfWeek.of(dow0 + 1);
}
@ -1329,7 +1329,7 @@ public final class LocalDate
long monthCount = year * 12L + (month - 1);
long calcMonths = monthCount + monthsToAdd; // safe overflow
int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));
int newMonth = (int)Math.floorMod(calcMonths, 12) + 1;
int newMonth = Math.floorMod(calcMonths, 12) + 1;
return resolvePreviousValid(newYear, newMonth, day);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -418,7 +418,7 @@ public final class LocalDateTime
NANO_OF_SECOND.checkValidValue(nanoOfSecond);
long localSecond = epochSecond + offset.getTotalSeconds(); // overflow caught later
long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);
int secsOfDay = (int)Math.floorMod(localSecond, SECONDS_PER_DAY);
int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
LocalDate date = LocalDate.ofEpochDay(localEpochDay);
LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + nanoOfSecond);
return new LocalDateTime(date, time);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -361,7 +361,7 @@ public final class LocalTime
Objects.requireNonNull(zone, "zone");
ZoneOffset offset = zone.getRules().getOffset(instant);
long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
int secsOfDay = (int) Math.floorMod(localSecond, SECONDS_PER_DAY);
int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -258,7 +258,7 @@ public final class OffsetTime
ZoneRules rules = zone.getRules();
ZoneOffset offset = rules.getOffset(instant);
long localSecond = instant.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later
int secsOfDay = (int) Math.floorMod(localSecond, SECONDS_PER_DAY);
int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
return new OffsetTime(time, offset);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -850,7 +850,7 @@ public final class YearMonth
long monthCount = year * 12L + (month - 1);
long calcMonths = monthCount + monthsToAdd; // safe overflow
int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));
int newMonth = (int)Math.floorMod(calcMonths, 12) + 1;
int newMonth = Math.floorMod(calcMonths, 12) + 1;
return with(newYear, newMonth);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -497,7 +497,7 @@ public final class HijrahDate
* @return the day-of-week; computed from the epochday
*/
private int getDayOfWeek() {
int dow0 = (int)Math.floorMod(toEpochDay() + 3, 7);
int dow0 = Math.floorMod(toEpochDay() + 3, 7);
return dow0 + 1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -184,7 +184,7 @@ public class DivModTests {
}
/**
* Test the integer floorDiv and floorMod methods.
* Test the long floorDiv and floorMod methods.
* Math and StrictMath are tested and the same results are expected for both.
*/
static void testLongFloorDivMod(long x, long y, Object divExpected, Object modExpected) {
@ -252,6 +252,110 @@ public class DivModTests {
}
}
/**
* Test the floorDiv and floorMod methods for mixed long and int.
*/
static void testLongIntFloorDivMod() {
testLongIntFloorDivMod(4L, 0, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException
testLongIntFloorDivMod(4L, 3, 1L, 1);
testLongIntFloorDivMod(3L, 3, 1L, 0);
testLongIntFloorDivMod(2L, 3, 0L, 2);
testLongIntFloorDivMod(1L, 3, 0L, 1);
testLongIntFloorDivMod(0L, 3, 0L, 0);
testLongIntFloorDivMod(4L, -3, -2L, -2);
testLongIntFloorDivMod(3L, -3, -1L, 0);
testLongIntFloorDivMod(2L, -3, -1L, -1);
testLongIntFloorDivMod(1L, -3, -1L, -2);
testLongIntFloorDivMod(0L, -3, 0L, 0);
testLongIntFloorDivMod(-1L, 3, -1L, 2);
testLongIntFloorDivMod(-2L, 3, -1L, 1);
testLongIntFloorDivMod(-3L, 3, -1L, 0);
testLongIntFloorDivMod(-4L, 3, -2L, 2);
testLongIntFloorDivMod(-1L, -3, 0L, -1);
testLongIntFloorDivMod(-2L, -3, 0L, -2);
testLongIntFloorDivMod(-3L, -3, 1L, 0);
testLongIntFloorDivMod(-4L, -3, 1L, -1);
testLongIntFloorDivMod(Long.MAX_VALUE, 1, Long.MAX_VALUE, 0L);
testLongIntFloorDivMod(Long.MAX_VALUE, -1, -Long.MAX_VALUE, 0L);
testLongIntFloorDivMod(Long.MAX_VALUE, 3, Long.MAX_VALUE / 3L, 1L);
testLongIntFloorDivMod(Long.MAX_VALUE - 1L, 3, (Long.MAX_VALUE - 1L) / 3L, 0L);
testLongIntFloorDivMod(Long.MIN_VALUE, 3, Long.MIN_VALUE / 3L - 1L, 1L);
testLongIntFloorDivMod(Long.MIN_VALUE + 1L, 3, Long.MIN_VALUE / 3L - 1L, 2L);
testLongIntFloorDivMod(Long.MIN_VALUE + 1, -1, Long.MAX_VALUE, 0L);
// Special case of integer overflow
testLongIntFloorDivMod(Long.MIN_VALUE, -1, Long.MIN_VALUE, 0L);
}
/**
* Test the integer floorDiv and floorMod methods.
* Math and StrictMath are tested and the same results are expected for both.
*/
static void testLongIntFloorDivMod(long x, int y, Object divExpected, Object modExpected) {
testLongIntFloorDiv(x, y, divExpected);
testLongIntFloorMod(x, y, modExpected);
}
/**
* Test FloorDiv with long arguments against expected value.
* The expected value is usually a Long but in some cases is
* an ArithmeticException.
*
* @param x dividend
* @param y modulus
* @param expected expected value,
*/
static void testLongIntFloorDiv(long x, int y, Object expected) {
Object result = doFloorDiv(x, y);
if (!resultEquals(result, expected)) {
fail("FAIL: long Math.floorDiv(%d, %d) = %s; expected %s%n", x, y, result, expected);
}
Object strict_result = doStrictFloorDiv(x, y);
if (!resultEquals(strict_result, expected)) {
fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
}
}
/**
* Test FloorMod of long arguments against expected value.
* The expected value is usually a Long but in some cases is
* an ArithmeticException.
*
* @param x dividend
* @param y modulus
* @param expected expected value
*/
static void testLongIntFloorMod(long x, int y, Object expected) {
Object result = doFloorMod(x, y);
if (!resultEquals(result, expected)) {
fail("FAIL: long Math.floorMod(%d, %d) = %s; expected %s%n", x, y, result, expected);
}
Object strict_result = doStrictFloorMod(x, y);
if (!resultEquals(strict_result, expected)) {
fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
}
try {
// Verify the result against BigDecimal rounding mode.
BigDecimal xD = new BigDecimal(x);
BigDecimal yD = new BigDecimal(y);
BigDecimal resultD = xD.divide(yD, RoundingMode.FLOOR);
resultD = resultD.multiply(yD);
resultD = xD.subtract(resultD);
long fr = resultD.longValue();
if (!result.equals(fr)) {
fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n", x, y, result, fr);
}
} catch (ArithmeticException ae) {
if (y != 0) {
fail("FAIL: long Math.floorMod(%d, %d); unexpected ArithmeticException from bigdecimal");
}
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
@ -266,6 +370,20 @@ public class DivModTests {
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
* @param y the y value
* @return the result Integer or an exception.
*/
static Object doFloorDiv(long x, int y) {
try {
return Math.floorDiv(x, y);
} catch (ArithmeticException ae) {
return ae;
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
@ -294,6 +412,20 @@ public class DivModTests {
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
* @param y the y value
* @return the result Integer or an exception.
*/
static Object doFloorMod(long x, int y) {
try {
return Math.floorMod(x, y);
} catch (ArithmeticException ae) {
return ae;
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
@ -322,6 +454,20 @@ public class DivModTests {
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
* @param y the y value
* @return the result Integer or an exception.
*/
static Object doStrictFloorDiv(long x, int y) {
try {
return StrictMath.floorDiv(x, y);
} catch (ArithmeticException ae) {
return ae;
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
@ -350,6 +496,20 @@ public class DivModTests {
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value
* @param y the y value
* @return the result Integer or an exception.
*/
static Object doStrictFloorMod(long x, int y) {
try {
return StrictMath.floorMod(x, y);
} catch (ArithmeticException ae) {
return ae;
}
}
/**
* Invoke floorDiv and return the result or any exception.
* @param x the x value

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,6 +43,7 @@ public class ExactArithTests {
public static void main(String[] args) {
testIntegerExact();
testLongExact();
testLongIntExact();
if (errors > 0) {
throw new RuntimeException(errors + " errors found in ExactArithTests.");
@ -132,6 +133,7 @@ public class ExactArithTests {
fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
}
}
try {
// Test incrementExact
int inc = Math.incrementExact(x);
@ -345,4 +347,60 @@ public class ExactArithTests {
static boolean inLongRange(BigInteger value) {
return value.bitLength() <= 63;
}
/**
* Test Math.multiplyExact method with {@code long} and {@code int}
* arguments.
*/
static void testLongIntExact() {
testLongIntExact(0, 0);
testLongIntExact(1, 1);
testLongIntExact(1, -1);
testLongIntExact(1000, 2000);
testLongIntExact(Long.MIN_VALUE, Integer.MIN_VALUE);
testLongIntExact(Long.MAX_VALUE, Integer.MAX_VALUE);
testLongIntExact(Long.MIN_VALUE, 1);
testLongIntExact(Long.MAX_VALUE, 1);
testLongIntExact(Long.MIN_VALUE, 2);
testLongIntExact(Long.MAX_VALUE, 2);
testLongIntExact(Long.MIN_VALUE, -1);
testLongIntExact(Long.MAX_VALUE, -1);
testLongIntExact(Long.MIN_VALUE, -2);
testLongIntExact(Long.MAX_VALUE, -2);
testLongIntExact(Long.MIN_VALUE/2, 2);
testLongIntExact(Long.MAX_VALUE, 2);
testLongIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
testLongIntExact(Integer.MAX_VALUE, -Integer.MAX_VALUE);
testLongIntExact((long)Integer.MAX_VALUE+1L, Integer.MAX_VALUE);
testLongIntExact((long)Integer.MAX_VALUE+1L, -Integer.MAX_VALUE+1);
testLongIntExact((long)Integer.MIN_VALUE-1L, Integer.MIN_VALUE);
testLongIntExact((long)Integer.MIN_VALUE-1, Integer.MAX_VALUE);
testLongIntExact(Integer.MIN_VALUE/2, 2);
}
/**
* Test long-int exact arithmetic by comparing with the same operations using BigInteger
* and checking that the result is the same as the long truncation.
* Errors are reported with {@link fail}.
*
* @param x first parameter
* @param y second parameter
*/
static void testLongIntExact(long x, int y) {
BigInteger resultBig = null;
final BigInteger xBig = BigInteger.valueOf(x);
final BigInteger yBig = BigInteger.valueOf(y);
try {
// Test multiplyExact
resultBig = xBig.multiply(yBig);
long product = Math.multiplyExact(x, y);
checkResult("long Math.multiplyExact", x, y, product, resultBig);
} catch (ArithmeticException ex) {
if (inLongRange(resultBig)) {
fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
}
}
}
}