8229485: Add decrementExact(), incrementExact(), and negateExact() to java.lang.StrictMath
authordfuchs
Fri, 23 Aug 2019 19:55:08 +0100
changeset 57867 36f5e20be69a
parent 57866 1e85670cb9ee
child 57868 7ae075afc72f
8229485: Add decrementExact(), incrementExact(), and negateExact() to java.lang.StrictMath Summary: three methods are added to StrictMath for consistency with Math. Tests are updated accordingly. Reviewed-by: bpb, lancea, igerasim, dfuchs, joehw, rriggs Contributed-by: Julia Boes <julia.boes@oracle.com>
src/java.base/share/classes/java/lang/StrictMath.java
test/jdk/java/lang/Math/ExactArithTests.java
test/jdk/java/lang/StrictMath/ExactArithTests.java
--- a/src/java.base/share/classes/java/lang/StrictMath.java	Fri Aug 23 14:04:38 2019 -0400
+++ b/src/java.base/share/classes/java/lang/StrictMath.java	Fri Aug 23 19:55:08 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -67,12 +67,12 @@
  * The best practice is to choose the primitive type and algorithm to avoid
  * overflow. In cases where the size is {@code int} or {@code long} and
  * overflow errors need to be detected, the methods {@code addExact},
- * {@code subtractExact}, {@code multiplyExact}, and {@code toIntExact}
+ * {@code subtractExact}, {@code multiplyExact}, {@code toIntExact},
+ * {@code incrementExact}, {@code decrementExact} and {@code negateExact}
  * throw an {@code ArithmeticException} when the results overflow.
- * For other arithmetic operations such as divide, absolute value,
- * 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.
+ * For the arithmetic operations divide and absolute value, overflow
+ * occurs only with a specific minimum or maximum value and
+ * should be checked against the minimum or maximum as appropriate.
  *
  * @author  unascribed
  * @author  Joseph D. Darcy
@@ -835,8 +835,92 @@
     }
 
     /**
-     * Returns the value of the {@code long} argument;
-     * throwing an exception if the value overflows an {@code int}.
+     * Returns the argument incremented by one,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param a the value to increment
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @see Math#incrementExact(int)
+     * @since 14
+     */
+    public static int incrementExact(int a) {
+        return Math.incrementExact(a);
+    }
+
+    /**
+     * Returns the argument incremented by one,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param a the value to increment
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @see Math#incrementExact(long)
+     * @since 14
+     */
+    public static long incrementExact(long a) {
+        return Math.incrementExact(a);
+    }
+
+    /**
+     * Returns the argument decremented by one,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param a the value to decrement
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @see Math#decrementExact(int)
+     * @since 14
+     */
+    public static int decrementExact(int a) {
+        return Math.decrementExact(a);
+    }
+
+    /**
+     * Returns the argument decremented by one,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param a the value to decrement
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @see Math#decrementExact(long)
+     * @since 14
+     */
+    public static long decrementExact(long a) {
+        return Math.decrementExact(a);
+    }
+
+    /**
+     * Returns the negation of the argument,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param a the value to negate
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @see Math#negateExact(int)
+     * @since 14
+     */
+    public static int negateExact(int a) {
+        return Math.negateExact(a);
+    }
+
+    /**
+     * Returns the negation of the argument,
+     * throwing an exception if the result overflows a {@code long}.
+     *
+     * @param a the value to negate
+     * @return the result
+     * @throws ArithmeticException if the result overflows a long
+     * @see Math#negateExact(long)
+     * @since 14
+     */
+    public static long negateExact(long a) {
+        return Math.negateExact(a);
+    }
+
+    /**
+     * Returns the value of the {@code long} argument, throwing an exception
+     * if the value overflows an {@code int}.
      *
      * @param value the long value
      * @return the argument as an int
--- a/test/jdk/java/lang/Math/ExactArithTests.java	Fri Aug 23 14:04:38 2019 -0400
+++ b/test/jdk/java/lang/Math/ExactArithTests.java	Fri Aug 23 19:55:08 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -56,8 +56,8 @@
     }
 
     /**
-     * Test Math.addExact, multiplyExact, subtractExact, toIntValue methods
-     * with {@code int} arguments.
+     * Test Math.addExact, multiplyExact, subtractExact, incrementExact,
+     * decrementExact, negateExact methods with {@code int} arguments.
      */
     static void testIntegerExact() {
         testIntegerExact(0, 0);
@@ -76,7 +76,6 @@
         testIntegerExact(Integer.MAX_VALUE, -1);
         testIntegerExact(Integer.MIN_VALUE, -2);
         testIntegerExact(Integer.MAX_VALUE, -2);
-
     }
 
     /**
@@ -101,7 +100,6 @@
             long sum2 = (long) x + (long) y;
             if ((int) sum2 == sum2) {
                 fail("FAIL: int Math.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
-
             }
         }
 
@@ -147,7 +145,6 @@
             long inc2 = (long) x + 1L;
             if ((int) inc2 == inc2) {
                 fail("FAIL: int Math.incrementExact(" + x + ")" + "; Unexpected exception: " + ex);
-
             }
         }
 
@@ -164,31 +161,29 @@
             long dec2 = (long) x - 1L;
             if ((int) dec2 == dec2) {
                 fail("FAIL: int Math.decrementExact(" + x + ")" + "; Unexpected exception: " + ex);
-
             }
         }
 
         try {
             // Test negateExact
             int neg = Math.negateExact(x);
-            long neg2 = -((long)x) ;
+            long neg2 = -((long)x);
             if ((int) neg2 != neg2) {
                 fail("FAIL: int Math.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception");
             } else if (neg != neg2) {
                 fail("FAIL: long Math.negateExact(" + x + ") = " + neg + "; expected: " + neg2);
             }
         } catch (ArithmeticException ex) {
-            long neg2 = (long) x - 1L;
+            long neg2 = -((long)x);
             if ((int) neg2 == neg2) {
                 fail("FAIL: int Math.negateExact(" + x + ")" + "; Unexpected exception: " + ex);
-
             }
         }
     }
 
     /**
-     * Test Math.addExact, multiplyExact, subtractExact, toIntExact methods
-     * with {@code long} arguments.
+     * Test Math.addExact, multiplyExact, subtractExact, incrementExact,
+     * decrementExact, negateExact, toIntExact methods with {@code long} arguments.
      */
     static void testLongExact() {
         testLongExactTwice(0, 0);
@@ -215,7 +210,6 @@
         testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
         testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
         testLongExactTwice(Integer.MIN_VALUE/2, 2);
-
     }
 
     /**
@@ -319,7 +313,6 @@
                 fail("FAIL: long Math.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
             }
         }
-
     }
 
     /**
--- a/test/jdk/java/lang/StrictMath/ExactArithTests.java	Fri Aug 23 14:04:38 2019 -0400
+++ b/test/jdk/java/lang/StrictMath/ExactArithTests.java	Fri Aug 23 19:55:08 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -55,8 +55,8 @@
     }
 
     /**
-     * Test StrictMath.addExact, multiplyExact, subtractExact, toIntValue methods
-     * with {@code int} arguments.
+     * Test StrictMath.addExact, multiplyExact, subtractExact, incrementExact,
+     * decrementExact, negateExact methods with {@code int} arguments.
      */
     static void testIntegerExact() {
         testIntegerExact(0, 0);
@@ -75,7 +75,6 @@
         testIntegerExact(Integer.MAX_VALUE, -1);
         testIntegerExact(Integer.MIN_VALUE, -2);
         testIntegerExact(Integer.MAX_VALUE, -2);
-
     }
 
     /**
@@ -100,7 +99,6 @@
             long sum2 = (long) x + (long) y;
             if ((int) sum2 == sum2) {
                 fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
-
             }
         }
 
@@ -133,11 +131,58 @@
             }
         }
 
+        try {
+            // Test incrementExact
+            int inc = StrictMath.incrementExact(x);
+            long inc2 = (long) x + 1L;
+            if ((int) inc2 != inc2) {
+                fail("FAIL: int StrictMath.incrementExact(" + x + ") = " + inc + "; expected Arithmetic exception");
+            } else if (inc != inc2) {
+                fail("FAIL: long StrictMath.incrementExact(" + x + ") = " + inc + "; expected: " + inc2);
+            }
+        } catch (ArithmeticException ex) {
+            long inc2 = (long) x + 1L;
+            if ((int) inc2 == inc2) {
+                fail("FAIL: int StrictMath.incrementExact(" + x + ")" + "; Unexpected exception: " + ex);
+            }
+        }
+
+        try {
+            // Test decrementExact
+            int dec = StrictMath.decrementExact(x);
+            long dec2 = (long) x - 1L;
+            if ((int) dec2 != dec2) {
+                fail("FAIL: int StrictMath.decrementExact(" + x + ") = " + dec + "; expected Arithmetic exception");
+            } else if (dec != dec2) {
+                fail("FAIL: long StrictMath.decrementExact(" + x + ") = " + dec + "; expected: " + dec2);
+            }
+        } catch (ArithmeticException ex) {
+            long dec2 = (long) x - 1L;
+            if ((int) dec2 == dec2) {
+                fail("FAIL: int StrictMath.decrementExact(" + x + ")" + "; Unexpected exception: " + ex);
+            }
+        }
+
+        try {
+            // Test negateExact
+            int neg = StrictMath.negateExact(x);
+            long neg2 = -((long)x);
+            if ((int) neg2 != neg2) {
+                fail("FAIL: int StrictMath.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception");
+            } else if (neg != neg2) {
+                fail("FAIL: long StrictMath.negateExact(" + x + ") = " + neg + "; expected: " + neg2);
+            }
+        } catch (ArithmeticException ex) {
+            long neg2 = -((long)x);
+            if ((int) neg2 == neg2) {
+                fail("FAIL: int StrictMath.negateExact(" + x + ")" + "; Unexpected exception: " + ex);
+            }
+        }
     }
 
     /**
-     * Test StrictMath.addExact, multiplyExact, subtractExact, toIntExact methods
-     * with {@code long} arguments.
+     * Test StrictMath.addExact, multiplyExact, subtractExact, incrementExact,
+     * decrementExact, negateExact, toIntExact methods with {@code long} arguments.
      */
     static void testLongExact() {
         testLongExactTwice(0, 0);
@@ -164,7 +209,6 @@
         testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
         testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
         testLongExactTwice(Integer.MIN_VALUE/2, 2);
-
     }
 
     /**
@@ -225,6 +269,39 @@
         }
 
         try {
+            // Test incrementExact
+            resultBig = xBig.add(BigInteger.ONE);
+            long inc = StrictMath.incrementExact(x);
+            checkResult("long Math.incrementExact", x, 1L, inc, resultBig);
+        } catch (ArithmeticException ex) {
+            if (inLongRange(resultBig)) {
+                fail("FAIL: long Math.incrementExact(" + x + "); Unexpected exception: " + ex);
+            }
+        }
+
+        try {
+            // Test decrementExact
+            resultBig = xBig.subtract(BigInteger.ONE);
+            long dec = StrictMath.decrementExact(x);
+            checkResult("long Math.decrementExact", x, 1L, dec, resultBig);
+        } catch (ArithmeticException ex) {
+            if (inLongRange(resultBig)) {
+                fail("FAIL: long Math.decrementExact(" + x + "); Unexpected exception: " + ex);
+            }
+        }
+
+        try {
+            // Test negateExact
+            resultBig = xBig.negate();
+            long dec = StrictMath.negateExact(x);
+            checkResult("long Math.negateExact", x, 0L, dec, resultBig);
+        } catch (ArithmeticException ex) {
+            if (inLongRange(resultBig)) {
+                fail("FAIL: long Math.negateExact(" + x + "); Unexpected exception: " + ex);
+            }
+        }
+
+        try {
             // Test toIntExact
             int value = StrictMath.toIntExact(x);
             if ((long)value != x) {
@@ -235,7 +312,6 @@
                 fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
             }
         }
-
     }
 
     /**