mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-27 19:33:39 +00:00
8229485: Add decrementExact(), incrementExact(), and negateExact() to java.lang.StrictMath
Three methods are added to StrictMath for consistency with Math. Tests are updated accordingly. Reviewed-by: bpb, lancea, igerasim, dfuchs, joehw, rriggs
This commit is contained in:
parent
ed17c3aafb
commit
ce3face998
@ -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 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
* 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 @@ public final class StrictMath {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@ -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 @@ public class ExactArithTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public class ExactArithTests {
|
||||
testIntegerExact(Integer.MAX_VALUE, -1);
|
||||
testIntegerExact(Integer.MIN_VALUE, -2);
|
||||
testIntegerExact(Integer.MAX_VALUE, -2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +100,6 @@ public class ExactArithTests {
|
||||
long sum2 = (long) x + (long) y;
|
||||
if ((int) sum2 == sum2) {
|
||||
fail("FAIL: int Math.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +145,6 @@ public class ExactArithTests {
|
||||
long inc2 = (long) x + 1L;
|
||||
if ((int) inc2 == inc2) {
|
||||
fail("FAIL: int Math.incrementExact(" + x + ")" + "; Unexpected exception: " + ex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,31 +161,29 @@ public class ExactArithTests {
|
||||
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 @@ public class ExactArithTests {
|
||||
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 @@ public class ExactArithTests {
|
||||
fail("FAIL: long Math.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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 @@ public class ExactArithTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public class ExactArithTests {
|
||||
testIntegerExact(Integer.MAX_VALUE, -1);
|
||||
testIntegerExact(Integer.MIN_VALUE, -2);
|
||||
testIntegerExact(Integer.MAX_VALUE, -2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,7 +99,6 @@ public class ExactArithTests {
|
||||
long sum2 = (long) x + (long) y;
|
||||
if ((int) sum2 == sum2) {
|
||||
fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,11 +131,58 @@ public class ExactArithTests {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class ExactArithTests {
|
||||
testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
|
||||
testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
|
||||
testLongExactTwice(Integer.MIN_VALUE/2, 2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,6 +268,39 @@ public class ExactArithTests {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@ -235,7 +312,6 @@ public class ExactArithTests {
|
||||
fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user