/*
* Copyright ( c ) 2012 , 2021 , 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
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
*/
import java.math.BigInteger;
/**
* @ test Test for Math . * Exact integer and long methods .
* @ bug 6708398 8075806 8271225 8271602
* @ summary Basic tests for Math exact arithmetic operations .
*
* @ author Roger Riggs
*/
public class ExactArithTests {
/**
* The count of test errors .
*/
private static int errors = 0 ;
/**
* @ param args the command line arguments
*/
public static void main(String[] args) {
testIntegerExact();
testLongExact();
testLongIntExact();
if (errors > 0 ) {
throw new RuntimeException(errors + " errors found in ExactArithTests." );
}
}
static void fail(String message) {
errors++;
System.err.println(message);
}
/**
* Test Math . addExact , multiplyExact , divideExact , subtractExact ,
* floorDivExact , ceilDivExact , incrementExact , decrementExact , negateExact
* methods with { @ code int } arguments .
*/
static void testIntegerExact() {
testIntegerExact(0 , 0 );
testIntegerExact(1 , 1 );
testIntegerExact(1 , -1 );
testIntegerExact(-1 , 1 );
testIntegerExact(1000 , 2000 );
testIntegerExact(Integer.MIN_VALUE, Integer.MIN_VALUE);
testIntegerExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
testIntegerExact(Integer.MIN_VALUE, 1 );
testIntegerExact(Integer.MAX_VALUE, 1 );
testIntegerExact(Integer.MIN_VALUE, 2 );
testIntegerExact(Integer.MAX_VALUE, 2 );
testIntegerExact(Integer.MIN_VALUE, -1 );
testIntegerExact(Integer.MAX_VALUE, -1 );
testIntegerExact(Integer.MIN_VALUE, -2 );
testIntegerExact(Integer.MAX_VALUE, -2 );
}
/**
* Test exact arithmetic by comparing with the same operations using long
* and checking that the result is the same as the integer truncation .
* Errors are reported with { @ link fail } .
*
* @ param x first parameter
* @ param y second parameter
*/
static void testIntegerExact(int x, int y) {
try {
// Test addExact
int sum = Math.addExact(x, y);
long sum2 = (long ) x + (long ) y;
if ((int ) sum2 != sum2) {
fail("FAIL: int Math.addExact(" + x + " + " + y + ") = " + sum + "; expected Arithmetic exception" );
} else if (sum != sum2) {
fail("FAIL: long Math.addExact(" + x + " + " + y + ") = " + sum + "; expected: " + sum2);
}
} catch (ArithmeticException ex) {
long sum2 = (long ) x + (long ) y;
if ((int ) sum2 == sum2) {
fail("FAIL: int Math.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
}
}
try {
// Test subtractExact
int diff = Math.subtractExact(x, y);
long diff2 = (long ) x - (long ) y;
if ((int ) diff2 != diff2) {
fail("FAIL: int Math.subtractExact(" + x + " - " + y + ") = " + diff + "; expected: " + diff2);
}
} catch (ArithmeticException ex) {
long diff2 = (long ) x - (long ) y;
if ((int ) diff2 == diff2) {
fail("FAIL: int Math.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
}
}
try {
// Test multiplyExact
int product = Math.multiplyExact(x, y);
long m2 = (long ) x * (long ) y;
if ((int ) m2 != m2) {
fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ") = " + product + "; expected: " + m2);
}
} catch (ArithmeticException ex) {
long m2 = (long ) x * (long ) y;
if ((int ) m2 == m2) {
fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
}
}
boolean exceptionExpected = false ;
try {
// Test divideExact
BigInteger q = null ;
try {
q = BigInteger.valueOf(x).divide(BigInteger.valueOf(y));
} catch (ArithmeticException e) {
exceptionExpected = true ;
}
int quotient = 0 ;
if (q != null ) {
try {
quotient = q.intValueExact();
} catch (ArithmeticException e) {
exceptionExpected = true ;
}
}
int z = Math.divideExact(x, y);
if (exceptionExpected) {
fail("FAIL: int Math.divideExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown" );
}
if (z != quotient) {
fail("FAIL: int Math.divideExact(" + x + " / " + y + ") = " +
z + "; expected: " + quotient);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: int Math.divideExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
exceptionExpected = false ;
try {
// Test floorDivExact
int q = 0 ;
try {
q = Math.floorDiv(x, y);
} catch (ArithmeticException e) {
exceptionExpected = true ;
}
if (!exceptionExpected && x == Integer.MIN_VALUE && y == -1 ) {
exceptionExpected = true ;
}
int z = Math.floorDivExact(x, y);
if (exceptionExpected) {
fail("FAIL: int Math.floorDivExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown" );
}
if (z != q) {
fail("FAIL: int Math.floorDivExact(" + x + " / " + y + ") = " +
z + "; expected: " + q);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: int Math.floorDivExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
exceptionExpected = false ;
try {
// Test ceilDivExact
int q = 0 ;
try {
q = Math.ceilDiv(x, y);
} catch (ArithmeticException e) {
exceptionExpected = true ;
}
if (!exceptionExpected && x == Integer.MIN_VALUE && y == -1 ) {
exceptionExpected = true ;
}
int z = Math.ceilDivExact(x, y);
if (exceptionExpected) {
fail("FAIL: int Math.ceilDivExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown" );
}
if (z != q) {
fail("FAIL: int Math.ceilDivExact(" + x + " / " + y + ") = " +
z + "; expected: " + q);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: int Math.ceilDivExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
try {
// Test incrementExact
int inc = Math.incrementExact(x);
long inc2 = (long ) x + 1 L;
if ((int ) inc2 != inc2) {
fail("FAIL: int Math.incrementExact(" + x + ") = " + inc + "; expected Arithmetic exception" );
} else if (inc != inc2) {
fail("FAIL: long Math.incrementExact(" + x + ") = " + inc + "; expected: " + inc2);
}
} catch (ArithmeticException ex) {
long inc2 = (long ) x + 1 L;
if ((int ) inc2 == inc2) {
fail("FAIL: int Math.incrementExact(" + x + ")" + "; Unexpected exception: " + ex);
}
}
try {
// Test decrementExact
int dec = Math.decrementExact(x);
long dec2 = (long ) x - 1 L;
if ((int ) dec2 != dec2) {
fail("FAIL: int Math.decrementExact(" + x + ") = " + dec + "; expected Arithmetic exception" );
} else if (dec != dec2) {
fail("FAIL: long Math.decrementExact(" + x + ") = " + dec + "; expected: " + dec2);
}
} catch (ArithmeticException ex) {
long dec2 = (long ) x - 1 L;
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);
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);
if ((int ) neg2 == neg2) {
fail("FAIL: int Math.negateExact(" + x + ")" + "; Unexpected exception: " + ex);
}
}
}
/**
* Test Math . addExact , multiplyExact , divideExact , subtractExact ,
* floorDivExact , ceilDivExact , incrementExact , decrementExact , negateExact , toIntExact
* methods with { @ code long } arguments .
*/
static void testLongExact() {
testLongExactTwice(0 , 0 );
testLongExactTwice(1 , 1 );
testLongExactTwice(1 , -1 );
testLongExactTwice(1000 , 2000 );
testLongExactTwice(Long .MIN_VALUE, Long .MIN_VALUE);
testLongExactTwice(Long .MAX_VALUE, Long .MAX_VALUE);
testLongExactTwice(Long .MIN_VALUE, 1 );
testLongExactTwice(Long .MAX_VALUE, 1 );
testLongExactTwice(Long .MIN_VALUE, 2 );
testLongExactTwice(Long .MAX_VALUE, 2 );
testLongExactTwice(Long .MIN_VALUE, -1 );
testLongExactTwice(Long .MAX_VALUE, -1 );
testLongExactTwice(Long .MIN_VALUE, -2 );
testLongExactTwice(Long .MAX_VALUE, -2 );
testLongExactTwice(Long .MIN_VALUE/2 , 2 );
testLongExactTwice(Long .MAX_VALUE, 2 );
testLongExactTwice(Integer.MAX_VALUE, Integer.MAX_VALUE);
testLongExactTwice(Integer.MAX_VALUE, -Integer.MAX_VALUE);
testLongExactTwice(Integer.MAX_VALUE+1 , Integer.MAX_VALUE+1 );
testLongExactTwice(Integer.MAX_VALUE+1 , -Integer.MAX_VALUE+1 );
testLongExactTwice(Integer.MIN_VALUE-1 , Integer.MIN_VALUE-1 );
testLongExactTwice(Integer.MIN_VALUE-1 , -Integer.MIN_VALUE-1 );
testLongExactTwice(Integer.MIN_VALUE/2 , 2 );
}
/**
* Test each of the exact operations with the arguments and
* with the arguments reversed .
* @ param x
* @ param y
*/
static void testLongExactTwice(long x, long y) {
testLongExact(x, y);
testLongExact(y, x);
}
/**
* Test long 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 testLongExact(long x, long y) {
BigInteger resultBig = null ;
final BigInteger xBig = BigInteger.valueOf(x);
final BigInteger yBig = BigInteger.valueOf(y);
try {
// Test addExact
resultBig = xBig.add(yBig);
long sum = Math.addExact(x, y);
checkResult("long Math.addExact" , x, y, sum, resultBig);
} catch (ArithmeticException ex) {
if (inLongRange(resultBig)) {
fail("FAIL: long Math.addExact(" + x + " + " + y + "); Unexpected exception: " + ex);
}
}
try {
// Test subtractExact
resultBig = xBig.subtract(yBig);
long diff = Math.subtractExact(x, y);
checkResult("long Math.subtractExact" , x, y, diff, resultBig);
} catch (ArithmeticException ex) {
if (inLongRange(resultBig)) {
fail("FAIL: long Math.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
}
}
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);
}
}
try {
// Test divideExact
resultBig = null ;
try {
resultBig = xBig.divide(yBig);
} catch (ArithmeticException ex) {
}
long quotient = Math.divideExact(x, y);
if (resultBig == null ) {
fail("FAIL: long Math.divideExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown" );
}
checkResult("long Math.divideExact" , x, y, quotient, resultBig);
} catch (ArithmeticException ex) {
if (resultBig != null && inLongRange(resultBig)) {
fail("FAIL: long Math.divideExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
boolean exceptionExpected = false ;
try {
// Test floorDivExact
long q = 0 ;
try {
q = Math.floorDiv(x, y);
} catch (ArithmeticException e) {
exceptionExpected = true ;
}
if (!exceptionExpected && x == Long .MIN_VALUE && y == -1 ) {
exceptionExpected = true ;
}
long z = Math.floorDivExact(x, y);
if (exceptionExpected) {
fail("FAIL: long Math.floorDivExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown" );
}
if (z != q) {
fail("FAIL: long Math.floorDivExact(" + x + " / " + y + ") = " +
z + "; expected: " + q);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: long Math.floorDivExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
exceptionExpected = false ;
try {
// Test ceilDivExact
long q = 0 ;
try {
q = Math.ceilDiv(x, y);
} catch (ArithmeticException e) {
exceptionExpected = true ;
}
if (!exceptionExpected && x == Long .MIN_VALUE && y == -1 ) {
exceptionExpected = true ;
}
long z = Math.ceilDivExact(x, y);
if (exceptionExpected) {
fail("FAIL: long Math.ceilDivExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown" );
}
if (z != q) {
fail("FAIL: long Math.ceilDivExact(" + x + " / " + y + ") = " +
z + "; expected: " + q);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: long Math.ceilDivExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}
try {
// Test incrementExact
resultBig = xBig.add(BigInteger.ONE);
long inc = Math.incrementExact(x);
checkResult("long Math.incrementExact" , x, 1 L, 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 = Math.decrementExact(x);
checkResult("long Math.decrementExact" , x, 1 L, 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 = Math.negateExact(x);
checkResult("long Math.negateExact" , x, 0 L, dec, resultBig);
} catch (ArithmeticException ex) {
if (inLongRange(resultBig)) {
fail("FAIL: long Math.negateExact(" + x + "); Unexpected exception: " + ex);
}
}
try {
// Test toIntExact
int value = Math.toIntExact(x);
if ((long )value != x) {
fail("FAIL: " + "long Math.toIntExact" + "(" + x + ") = " + value + "; expected an arithmetic exception: " );
}
} catch (ArithmeticException ex) {
if (resultBig.bitLength() <= 32 ) {
fail("FAIL: long Math.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
}
}
}
/**
* Compare the expected and actual results .
* @ param message message for the error
* @ param x first argument
* @ param y second argument
* @ param result actual result value
* @ param expected expected result value
*/
static void checkResult(String message, long x, long y, long result, BigInteger expected) {
BigInteger resultBig = BigInteger.valueOf(result);
if (!inLongRange(expected)) {
fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected an arithmetic exception: " );
} else if (!resultBig.equals(expected)) {
fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected " + expected);
}
}
/**
* Check if the value fits in 64 bits ( a long ) .
* @ param value
* @ return true if the value fits in 64 bits ( including the sign ) .
*/
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+1 L, Integer.MAX_VALUE);
testLongIntExact((long )Integer.MAX_VALUE+1 L, -Integer.MAX_VALUE+1 );
testLongIntExact((long )Integer.MIN_VALUE-1 L, 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);
}
}
}
}
Messung V0.5 in Prozent C=95 H=92 G=93
¤ Dauer der Verarbeitung: 0.12 Sekunden
¤
*© Formatika GbR, Deutschland