changeset 14575:1241537c9721

8023217: Additional floorDiv/floorMod/multiplyExact methods for java.lang.Math Summary: Add new methods with long, int signatures. Reviewed-by: darcy, scolebourne
author bpb
date Tue, 29 Sep 2015 17:28:44 -0700
parents d9c7e8e76afc
children 4cd0d71cf20e
files src/java.base/share/classes/java/lang/Math.java src/java.base/share/classes/java/lang/StrictMath.java src/java.base/share/classes/java/time/Instant.java src/java.base/share/classes/java/time/LocalDate.java src/java.base/share/classes/java/time/LocalDateTime.java src/java.base/share/classes/java/time/LocalTime.java src/java.base/share/classes/java/time/OffsetTime.java src/java.base/share/classes/java/time/YearMonth.java src/java.base/share/classes/java/time/chrono/HijrahDate.java test/java/lang/Math/DivModTests.java test/java/lang/Math/ExactArithTests.java
diffstat 11 files changed, 382 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/Math.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/lang/StrictMath.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/time/Instant.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/time/LocalDate.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/time/LocalDateTime.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/time/LocalTime.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/time/OffsetTime.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/time/YearMonth.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/src/java.base/share/classes/java/time/chrono/HijrahDate.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/test/java/lang/Math/DivModTests.java	Fri May 20 15:50:20 2016 -0700
+++ b/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/test/java/lang/Math/ExactArithTests.java	Fri May 20 15:50:20 2016 -0700
+++ b/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);
+            }
+        }
+    }
 }