8023217: Additional floorDiv/floorMod/multiplyExact methods for java.lang.Math
Summary: Add new methods with long, int signatures.
Reviewed-by: darcy, scolebourne
--- a/jdk/src/java.base/share/classes/java/lang/Math.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Math.java Tue Sep 29 17:28:44 2015 -0700
@@ -95,7 +95,7 @@
* {@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 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 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");
}
@@ -909,6 +909,20 @@
}
/**
+ * 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 @@
* 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 @@
* 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 @@
* @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);
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java Tue Sep 29 17:28:44 2015 -0700
@@ -70,7 +70,7 @@
* {@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.
*
@@ -803,6 +803,21 @@
}
/**
+ * 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}.
*
@@ -888,6 +903,30 @@
* 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.
+ * 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}.
* <p>
* See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and
@@ -932,6 +971,35 @@
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>
--- a/jdk/src/java.base/share/classes/java/time/Instant.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/Instant.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 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);
}
--- a/jdk/src/java.base/share/classes/java/time/LocalDate.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/LocalDate.java Tue Sep 29 17:28:44 2015 -0700
@@ -826,7 +826,7 @@
* @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 @@
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);
}
--- a/jdk/src/java.base/share/classes/java/time/LocalDateTime.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/LocalDateTime.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 @@
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);
--- a/jdk/src/java.base/share/classes/java/time/LocalTime.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/LocalTime.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 @@
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());
}
--- a/jdk/src/java.base/share/classes/java/time/OffsetTime.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/OffsetTime.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 @@
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);
}
--- a/jdk/src/java.base/share/classes/java/time/YearMonth.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/YearMonth.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 @@
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);
}
--- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 @@
* @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;
}
--- a/jdk/test/java/lang/Math/DivModTests.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/test/java/lang/Math/DivModTests.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 @@
}
/**
- * 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) {
@@ -253,6 +253,110 @@
}
/**
+ * 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
* @param y the y value
@@ -272,6 +376,20 @@
* @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
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
static Object doFloorDiv(long x, long y) {
try {
return Math.floorDiv(x, y);
@@ -300,6 +418,20 @@
* @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
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
static Object doFloorMod(long x, long y) {
try {
return Math.floorMod(x, y);
@@ -328,6 +460,20 @@
* @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
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
static Object doStrictFloorDiv(long x, long y) {
try {
return StrictMath.floorDiv(x, y);
@@ -356,6 +502,20 @@
* @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
+ * @param y the y value
+ * @return the result Integer or an exception.
+ */
static Object doStrictFloorMod(long x, long y) {
try {
return StrictMath.floorMod(x, y);
--- a/jdk/test/java/lang/Math/ExactArithTests.java Fri May 20 15:50:20 2016 -0700
+++ b/jdk/test/java/lang/Math/ExactArithTests.java Tue Sep 29 17:28:44 2015 -0700
@@ -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 static void main(String[] args) {
testIntegerExact();
testLongExact();
+ testLongIntExact();
if (errors > 0) {
throw new RuntimeException(errors + " errors found in ExactArithTests.");
@@ -132,6 +133,7 @@
fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
}
}
+
try {
// Test incrementExact
int inc = Math.incrementExact(x);
@@ -345,4 +347,60 @@
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);
+ }
+ }
+ }
}