Skip to content

Commit ce3face

Browse files
Julia Boesdfuch
authored andcommitted
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
1 parent ed17c3a commit ce3face

File tree

3 files changed

+184
-31
lines changed

3 files changed

+184
-31
lines changed

src/java.base/share/classes/java/lang/StrictMath.java

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -67,12 +67,12 @@
6767
* The best practice is to choose the primitive type and algorithm to avoid
6868
* overflow. In cases where the size is {@code int} or {@code long} and
6969
* overflow errors need to be detected, the methods {@code addExact},
70-
* {@code subtractExact}, {@code multiplyExact}, and {@code toIntExact}
70+
* {@code subtractExact}, {@code multiplyExact}, {@code toIntExact},
71+
* {@code incrementExact}, {@code decrementExact} and {@code negateExact}
7172
* throw an {@code ArithmeticException} when the results overflow.
72-
* For other arithmetic operations such as divide, absolute value,
73-
* increment by one, decrement by one, and negation overflow occurs only with
74-
* a specific minimum or maximum value and should be checked against
75-
* the minimum or maximum as appropriate.
73+
* For the arithmetic operations divide and absolute value, overflow
74+
* occurs only with a specific minimum or maximum value and
75+
* should be checked against the minimum or maximum as appropriate.
7676
*
7777
* @author unascribed
7878
* @author Joseph D. Darcy
@@ -835,8 +835,92 @@ public static long multiplyExact(long x, long y) {
835835
}
836836

837837
/**
838-
* Returns the value of the {@code long} argument;
839-
* throwing an exception if the value overflows an {@code int}.
838+
* Returns the argument incremented by one,
839+
* throwing an exception if the result overflows an {@code int}.
840+
*
841+
* @param a the value to increment
842+
* @return the result
843+
* @throws ArithmeticException if the result overflows an int
844+
* @see Math#incrementExact(int)
845+
* @since 14
846+
*/
847+
public static int incrementExact(int a) {
848+
return Math.incrementExact(a);
849+
}
850+
851+
/**
852+
* Returns the argument incremented by one,
853+
* throwing an exception if the result overflows a {@code long}.
854+
*
855+
* @param a the value to increment
856+
* @return the result
857+
* @throws ArithmeticException if the result overflows a long
858+
* @see Math#incrementExact(long)
859+
* @since 14
860+
*/
861+
public static long incrementExact(long a) {
862+
return Math.incrementExact(a);
863+
}
864+
865+
/**
866+
* Returns the argument decremented by one,
867+
* throwing an exception if the result overflows an {@code int}.
868+
*
869+
* @param a the value to decrement
870+
* @return the result
871+
* @throws ArithmeticException if the result overflows an int
872+
* @see Math#decrementExact(int)
873+
* @since 14
874+
*/
875+
public static int decrementExact(int a) {
876+
return Math.decrementExact(a);
877+
}
878+
879+
/**
880+
* Returns the argument decremented by one,
881+
* throwing an exception if the result overflows a {@code long}.
882+
*
883+
* @param a the value to decrement
884+
* @return the result
885+
* @throws ArithmeticException if the result overflows a long
886+
* @see Math#decrementExact(long)
887+
* @since 14
888+
*/
889+
public static long decrementExact(long a) {
890+
return Math.decrementExact(a);
891+
}
892+
893+
/**
894+
* Returns the negation of the argument,
895+
* throwing an exception if the result overflows an {@code int}.
896+
*
897+
* @param a the value to negate
898+
* @return the result
899+
* @throws ArithmeticException if the result overflows an int
900+
* @see Math#negateExact(int)
901+
* @since 14
902+
*/
903+
public static int negateExact(int a) {
904+
return Math.negateExact(a);
905+
}
906+
907+
/**
908+
* Returns the negation of the argument,
909+
* throwing an exception if the result overflows a {@code long}.
910+
*
911+
* @param a the value to negate
912+
* @return the result
913+
* @throws ArithmeticException if the result overflows a long
914+
* @see Math#negateExact(long)
915+
* @since 14
916+
*/
917+
public static long negateExact(long a) {
918+
return Math.negateExact(a);
919+
}
920+
921+
/**
922+
* Returns the value of the {@code long} argument, throwing an exception
923+
* if the value overflows an {@code int}.
840924
*
841925
* @param value the long value
842926
* @return the argument as an int

test/jdk/java/lang/Math/ExactArithTests.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -56,8 +56,8 @@ static void fail(String message) {
5656
}
5757

5858
/**
59-
* Test Math.addExact, multiplyExact, subtractExact, toIntValue methods
60-
* with {@code int} arguments.
59+
* Test Math.addExact, multiplyExact, subtractExact, incrementExact,
60+
* decrementExact, negateExact methods with {@code int} arguments.
6161
*/
6262
static void testIntegerExact() {
6363
testIntegerExact(0, 0);
@@ -76,7 +76,6 @@ static void testIntegerExact() {
7676
testIntegerExact(Integer.MAX_VALUE, -1);
7777
testIntegerExact(Integer.MIN_VALUE, -2);
7878
testIntegerExact(Integer.MAX_VALUE, -2);
79-
8079
}
8180

8281
/**
@@ -101,7 +100,6 @@ static void testIntegerExact(int x, int y) {
101100
long sum2 = (long) x + (long) y;
102101
if ((int) sum2 == sum2) {
103102
fail("FAIL: int Math.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
104-
105103
}
106104
}
107105

@@ -147,7 +145,6 @@ static void testIntegerExact(int x, int y) {
147145
long inc2 = (long) x + 1L;
148146
if ((int) inc2 == inc2) {
149147
fail("FAIL: int Math.incrementExact(" + x + ")" + "; Unexpected exception: " + ex);
150-
151148
}
152149
}
153150

@@ -164,31 +161,29 @@ static void testIntegerExact(int x, int y) {
164161
long dec2 = (long) x - 1L;
165162
if ((int) dec2 == dec2) {
166163
fail("FAIL: int Math.decrementExact(" + x + ")" + "; Unexpected exception: " + ex);
167-
168164
}
169165
}
170166

171167
try {
172168
// Test negateExact
173169
int neg = Math.negateExact(x);
174-
long neg2 = -((long)x) ;
170+
long neg2 = -((long)x);
175171
if ((int) neg2 != neg2) {
176172
fail("FAIL: int Math.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception");
177173
} else if (neg != neg2) {
178174
fail("FAIL: long Math.negateExact(" + x + ") = " + neg + "; expected: " + neg2);
179175
}
180176
} catch (ArithmeticException ex) {
181-
long neg2 = (long) x - 1L;
177+
long neg2 = -((long)x);
182178
if ((int) neg2 == neg2) {
183179
fail("FAIL: int Math.negateExact(" + x + ")" + "; Unexpected exception: " + ex);
184-
185180
}
186181
}
187182
}
188183

189184
/**
190-
* Test Math.addExact, multiplyExact, subtractExact, toIntExact methods
191-
* with {@code long} arguments.
185+
* Test Math.addExact, multiplyExact, subtractExact, incrementExact,
186+
* decrementExact, negateExact, toIntExact methods with {@code long} arguments.
192187
*/
193188
static void testLongExact() {
194189
testLongExactTwice(0, 0);
@@ -215,7 +210,6 @@ static void testLongExact() {
215210
testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
216211
testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
217212
testLongExactTwice(Integer.MIN_VALUE/2, 2);
218-
219213
}
220214

221215
/**
@@ -319,7 +313,6 @@ static void testLongExact(long x, long y) {
319313
fail("FAIL: long Math.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
320314
}
321315
}
322-
323316
}
324317

325318
/**

test/jdk/java/lang/StrictMath/ExactArithTests.java

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -55,8 +55,8 @@ static void fail(String message) {
5555
}
5656

5757
/**
58-
* Test StrictMath.addExact, multiplyExact, subtractExact, toIntValue methods
59-
* with {@code int} arguments.
58+
* Test StrictMath.addExact, multiplyExact, subtractExact, incrementExact,
59+
* decrementExact, negateExact methods with {@code int} arguments.
6060
*/
6161
static void testIntegerExact() {
6262
testIntegerExact(0, 0);
@@ -75,7 +75,6 @@ static void testIntegerExact() {
7575
testIntegerExact(Integer.MAX_VALUE, -1);
7676
testIntegerExact(Integer.MIN_VALUE, -2);
7777
testIntegerExact(Integer.MAX_VALUE, -2);
78-
7978
}
8079

8180
/**
@@ -100,7 +99,6 @@ static void testIntegerExact(int x, int y) {
10099
long sum2 = (long) x + (long) y;
101100
if ((int) sum2 == sum2) {
102101
fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
103-
104102
}
105103
}
106104

@@ -133,11 +131,58 @@ static void testIntegerExact(int x, int y) {
133131
}
134132
}
135133

134+
try {
135+
// Test incrementExact
136+
int inc = StrictMath.incrementExact(x);
137+
long inc2 = (long) x + 1L;
138+
if ((int) inc2 != inc2) {
139+
fail("FAIL: int StrictMath.incrementExact(" + x + ") = " + inc + "; expected Arithmetic exception");
140+
} else if (inc != inc2) {
141+
fail("FAIL: long StrictMath.incrementExact(" + x + ") = " + inc + "; expected: " + inc2);
142+
}
143+
} catch (ArithmeticException ex) {
144+
long inc2 = (long) x + 1L;
145+
if ((int) inc2 == inc2) {
146+
fail("FAIL: int StrictMath.incrementExact(" + x + ")" + "; Unexpected exception: " + ex);
147+
}
148+
}
149+
150+
try {
151+
// Test decrementExact
152+
int dec = StrictMath.decrementExact(x);
153+
long dec2 = (long) x - 1L;
154+
if ((int) dec2 != dec2) {
155+
fail("FAIL: int StrictMath.decrementExact(" + x + ") = " + dec + "; expected Arithmetic exception");
156+
} else if (dec != dec2) {
157+
fail("FAIL: long StrictMath.decrementExact(" + x + ") = " + dec + "; expected: " + dec2);
158+
}
159+
} catch (ArithmeticException ex) {
160+
long dec2 = (long) x - 1L;
161+
if ((int) dec2 == dec2) {
162+
fail("FAIL: int StrictMath.decrementExact(" + x + ")" + "; Unexpected exception: " + ex);
163+
}
164+
}
165+
166+
try {
167+
// Test negateExact
168+
int neg = StrictMath.negateExact(x);
169+
long neg2 = -((long)x);
170+
if ((int) neg2 != neg2) {
171+
fail("FAIL: int StrictMath.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception");
172+
} else if (neg != neg2) {
173+
fail("FAIL: long StrictMath.negateExact(" + x + ") = " + neg + "; expected: " + neg2);
174+
}
175+
} catch (ArithmeticException ex) {
176+
long neg2 = -((long)x);
177+
if ((int) neg2 == neg2) {
178+
fail("FAIL: int StrictMath.negateExact(" + x + ")" + "; Unexpected exception: " + ex);
179+
}
180+
}
136181
}
137182

138183
/**
139-
* Test StrictMath.addExact, multiplyExact, subtractExact, toIntExact methods
140-
* with {@code long} arguments.
184+
* Test StrictMath.addExact, multiplyExact, subtractExact, incrementExact,
185+
* decrementExact, negateExact, toIntExact methods with {@code long} arguments.
141186
*/
142187
static void testLongExact() {
143188
testLongExactTwice(0, 0);
@@ -164,7 +209,6 @@ static void testLongExact() {
164209
testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
165210
testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
166211
testLongExactTwice(Integer.MIN_VALUE/2, 2);
167-
168212
}
169213

170214
/**
@@ -224,6 +268,39 @@ static void testLongExact(long x, long y) {
224268
}
225269
}
226270

271+
try {
272+
// Test incrementExact
273+
resultBig = xBig.add(BigInteger.ONE);
274+
long inc = StrictMath.incrementExact(x);
275+
checkResult("long Math.incrementExact", x, 1L, inc, resultBig);
276+
} catch (ArithmeticException ex) {
277+
if (inLongRange(resultBig)) {
278+
fail("FAIL: long Math.incrementExact(" + x + "); Unexpected exception: " + ex);
279+
}
280+
}
281+
282+
try {
283+
// Test decrementExact
284+
resultBig = xBig.subtract(BigInteger.ONE);
285+
long dec = StrictMath.decrementExact(x);
286+
checkResult("long Math.decrementExact", x, 1L, dec, resultBig);
287+
} catch (ArithmeticException ex) {
288+
if (inLongRange(resultBig)) {
289+
fail("FAIL: long Math.decrementExact(" + x + "); Unexpected exception: " + ex);
290+
}
291+
}
292+
293+
try {
294+
// Test negateExact
295+
resultBig = xBig.negate();
296+
long dec = StrictMath.negateExact(x);
297+
checkResult("long Math.negateExact", x, 0L, dec, resultBig);
298+
} catch (ArithmeticException ex) {
299+
if (inLongRange(resultBig)) {
300+
fail("FAIL: long Math.negateExact(" + x + "); Unexpected exception: " + ex);
301+
}
302+
}
303+
227304
try {
228305
// Test toIntExact
229306
int value = StrictMath.toIntExact(x);
@@ -235,7 +312,6 @@ static void testLongExact(long x, long y) {
235312
fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
236313
}
237314
}
238-
239315
}
240316

241317
/**

0 commit comments

Comments
 (0)