| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.numbers.core; |
| |
| import java.util.Arrays; |
| import java.math.BigInteger; |
| import java.util.Collections; |
| |
| import org.junit.Assert; |
| import org.junit.jupiter.api.Assertions; |
| import org.junit.jupiter.api.Test; |
| |
| /** |
| * Test cases for the {@link ArithmeticUtils} class. |
| * |
| */ |
| public class ArithmeticUtilsTest { |
| |
| @Test |
| public void testAddAndCheck() { |
| int big = Integer.MAX_VALUE; |
| int bigNeg = Integer.MIN_VALUE; |
| Assert.assertEquals(big, ArithmeticUtils.addAndCheck(big, 0)); |
| try { |
| ArithmeticUtils.addAndCheck(big, 1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| } |
| try { |
| ArithmeticUtils.addAndCheck(bigNeg, -1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| } |
| } |
| |
| @Test |
| public void testAddAndCheckLong() { |
| long max = Long.MAX_VALUE; |
| long min = Long.MIN_VALUE; |
| Assert.assertEquals(max, ArithmeticUtils.addAndCheck(max, 0L)); |
| Assert.assertEquals(min, ArithmeticUtils.addAndCheck(min, 0L)); |
| Assert.assertEquals(max, ArithmeticUtils.addAndCheck(0L, max)); |
| Assert.assertEquals(min, ArithmeticUtils.addAndCheck(0L, min)); |
| Assert.assertEquals(1, ArithmeticUtils.addAndCheck(-1L, 2L)); |
| Assert.assertEquals(1, ArithmeticUtils.addAndCheck(2L, -1L)); |
| Assert.assertEquals(-3, ArithmeticUtils.addAndCheck(-2L, -1L)); |
| Assert.assertEquals(min, ArithmeticUtils.addAndCheck(min + 1, -1L)); |
| Assert.assertEquals(-1, ArithmeticUtils.addAndCheck(min, max)); |
| testAddAndCheckLongFailure(max, 1L); |
| testAddAndCheckLongFailure(min, -1L); |
| testAddAndCheckLongFailure(1L, max); |
| testAddAndCheckLongFailure(-1L, min); |
| testAddAndCheckLongFailure(max, max); |
| testAddAndCheckLongFailure(min, min); |
| } |
| |
| @Test |
| public void testGcd() { |
| int a = 30; |
| int b = 50; |
| int c = 77; |
| |
| Assert.assertEquals(0, ArithmeticUtils.gcd(0, 0)); |
| |
| Assert.assertEquals(b, ArithmeticUtils.gcd(0, b)); |
| Assert.assertEquals(a, ArithmeticUtils.gcd(a, 0)); |
| Assert.assertEquals(b, ArithmeticUtils.gcd(0, -b)); |
| Assert.assertEquals(a, ArithmeticUtils.gcd(-a, 0)); |
| |
| Assert.assertEquals(10, ArithmeticUtils.gcd(a, b)); |
| Assert.assertEquals(10, ArithmeticUtils.gcd(-a, b)); |
| Assert.assertEquals(10, ArithmeticUtils.gcd(a, -b)); |
| Assert.assertEquals(10, ArithmeticUtils.gcd(-a, -b)); |
| |
| Assert.assertEquals(1, ArithmeticUtils.gcd(a, c)); |
| Assert.assertEquals(1, ArithmeticUtils.gcd(-a, c)); |
| Assert.assertEquals(1, ArithmeticUtils.gcd(a, -c)); |
| Assert.assertEquals(1, ArithmeticUtils.gcd(-a, -c)); |
| |
| Assert.assertEquals(3 * (1<<15), ArithmeticUtils.gcd(3 * (1<<20), 9 * (1<<15))); |
| |
| Assert.assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(Integer.MAX_VALUE, 0)); |
| Assert.assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(-Integer.MAX_VALUE, 0)); |
| Assert.assertEquals(1<<30, ArithmeticUtils.gcd(1<<30, -Integer.MIN_VALUE)); |
| try { |
| // gcd(Integer.MIN_VALUE, 0) > Integer.MAX_VALUE |
| ArithmeticUtils.gcd(Integer.MIN_VALUE, 0); |
| Assert.fail("expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| try { |
| // gcd(0, Integer.MIN_VALUE) > Integer.MAX_VALUE |
| ArithmeticUtils.gcd(0, Integer.MIN_VALUE); |
| Assert.fail("expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| try { |
| // gcd(Integer.MIN_VALUE, Integer.MIN_VALUE) > Integer.MAX_VALUE |
| ArithmeticUtils.gcd(Integer.MIN_VALUE, Integer.MIN_VALUE); |
| Assert.fail("expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testGcdConsistency() { |
| // Use Integer to prevent varargs vs array issue with Arrays.asList |
| Integer[] primeList = {19, 23, 53, 67, 73, 79, 101, 103, 111, 131}; |
| |
| for (int i = 0; i < 20; i++) { |
| Collections.shuffle(Arrays.asList(primeList)); |
| int p1 = primeList[0]; |
| int p2 = primeList[1]; |
| int p3 = primeList[2]; |
| int p4 = primeList[3]; |
| int i1 = p1 * p2 * p3; |
| int i2 = p1 * p2 * p4; |
| int gcd = p1 * p2; |
| Assert.assertEquals(gcd, ArithmeticUtils.gcd(i1, i2)); |
| long l1 = i1; |
| long l2 = i2; |
| Assert.assertEquals(gcd, ArithmeticUtils.gcd(l1, l2)); |
| } |
| } |
| |
| @Test |
| public void testGcdLong(){ |
| long a = 30; |
| long b = 50; |
| long c = 77; |
| |
| Assert.assertEquals(0, ArithmeticUtils.gcd(0L, 0)); |
| |
| Assert.assertEquals(b, ArithmeticUtils.gcd(0, b)); |
| Assert.assertEquals(a, ArithmeticUtils.gcd(a, 0)); |
| Assert.assertEquals(b, ArithmeticUtils.gcd(0, -b)); |
| Assert.assertEquals(a, ArithmeticUtils.gcd(-a, 0)); |
| |
| Assert.assertEquals(10, ArithmeticUtils.gcd(a, b)); |
| Assert.assertEquals(10, ArithmeticUtils.gcd(-a, b)); |
| Assert.assertEquals(10, ArithmeticUtils.gcd(a, -b)); |
| Assert.assertEquals(10, ArithmeticUtils.gcd(-a, -b)); |
| |
| Assert.assertEquals(1, ArithmeticUtils.gcd(a, c)); |
| Assert.assertEquals(1, ArithmeticUtils.gcd(-a, c)); |
| Assert.assertEquals(1, ArithmeticUtils.gcd(a, -c)); |
| Assert.assertEquals(1, ArithmeticUtils.gcd(-a, -c)); |
| |
| Assert.assertEquals(3L * (1L<<45), ArithmeticUtils.gcd(3L * (1L<<50), 9L * (1L<<45))); |
| |
| Assert.assertEquals(1L<<45, ArithmeticUtils.gcd(1L<<45, Long.MIN_VALUE)); |
| |
| Assert.assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(Long.MAX_VALUE, 0L)); |
| Assert.assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(-Long.MAX_VALUE, 0L)); |
| Assert.assertEquals(1, ArithmeticUtils.gcd(60247241209L, 153092023L)); |
| try { |
| // gcd(Long.MIN_VALUE, 0) > Long.MAX_VALUE |
| ArithmeticUtils.gcd(Long.MIN_VALUE, 0); |
| Assert.fail("expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| try { |
| // gcd(0, Long.MIN_VALUE) > Long.MAX_VALUE |
| ArithmeticUtils.gcd(0, Long.MIN_VALUE); |
| Assert.fail("expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| try { |
| // gcd(Long.MIN_VALUE, Long.MIN_VALUE) > Long.MAX_VALUE |
| ArithmeticUtils.gcd(Long.MIN_VALUE, Long.MIN_VALUE); |
| Assert.fail("expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| } |
| |
| |
| @Test |
| public void testLcm() { |
| int a = 30; |
| int b = 50; |
| int c = 77; |
| |
| Assert.assertEquals(0, ArithmeticUtils.lcm(0, b)); |
| Assert.assertEquals(0, ArithmeticUtils.lcm(a, 0)); |
| Assert.assertEquals(b, ArithmeticUtils.lcm(1, b)); |
| Assert.assertEquals(a, ArithmeticUtils.lcm(a, 1)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(a, b)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(-a, b)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(a, -b)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(-a, -b)); |
| Assert.assertEquals(2310, ArithmeticUtils.lcm(a, c)); |
| |
| // Assert that no intermediate value overflows: |
| // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b) |
| Assert.assertEquals((1<<20)*15, ArithmeticUtils.lcm((1<<20)*3, (1<<20)*5)); |
| |
| // Special case |
| Assert.assertEquals(0, ArithmeticUtils.lcm(0, 0)); |
| |
| try { |
| // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int |
| ArithmeticUtils.lcm(Integer.MIN_VALUE, 1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| |
| try { |
| // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int |
| ArithmeticUtils.lcm(Integer.MIN_VALUE, 1<<20); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| |
| try { |
| ArithmeticUtils.lcm(Integer.MAX_VALUE, Integer.MAX_VALUE - 1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testLcmLong() { |
| long a = 30; |
| long b = 50; |
| long c = 77; |
| |
| Assert.assertEquals(0, ArithmeticUtils.lcm(0, b)); |
| Assert.assertEquals(0, ArithmeticUtils.lcm(a, 0)); |
| Assert.assertEquals(b, ArithmeticUtils.lcm(1, b)); |
| Assert.assertEquals(a, ArithmeticUtils.lcm(a, 1)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(a, b)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(-a, b)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(a, -b)); |
| Assert.assertEquals(150, ArithmeticUtils.lcm(-a, -b)); |
| Assert.assertEquals(2310, ArithmeticUtils.lcm(a, c)); |
| |
| Assert.assertEquals(Long.MAX_VALUE, ArithmeticUtils.lcm(60247241209L, 153092023L)); |
| |
| // Assert that no intermediate value overflows: |
| // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b) |
| Assert.assertEquals((1L<<50)*15, ArithmeticUtils.lcm((1L<<45)*3, (1L<<50)*5)); |
| |
| // Special case |
| Assert.assertEquals(0L, ArithmeticUtils.lcm(0L, 0L)); |
| |
| try { |
| // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int |
| ArithmeticUtils.lcm(Long.MIN_VALUE, 1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| |
| try { |
| // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int |
| ArithmeticUtils.lcm(Long.MIN_VALUE, 1<<20); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| |
| Assert.assertEquals((long) Integer.MAX_VALUE * (Integer.MAX_VALUE - 1), |
| ArithmeticUtils.lcm((long)Integer.MAX_VALUE, Integer.MAX_VALUE - 1)); |
| try { |
| ArithmeticUtils.lcm(Long.MAX_VALUE, Long.MAX_VALUE - 1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException expected) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testMulAndCheck() { |
| int big = Integer.MAX_VALUE; |
| int bigNeg = Integer.MIN_VALUE; |
| Assert.assertEquals(big, ArithmeticUtils.mulAndCheck(big, 1)); |
| try { |
| ArithmeticUtils.mulAndCheck(big, 2); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| } |
| try { |
| ArithmeticUtils.mulAndCheck(bigNeg, 2); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| } |
| } |
| |
| @Test |
| public void testMulAndCheckLong() { |
| long max = Long.MAX_VALUE; |
| long min = Long.MIN_VALUE; |
| Assert.assertEquals(max, ArithmeticUtils.mulAndCheck(max, 1L)); |
| Assert.assertEquals(min, ArithmeticUtils.mulAndCheck(min, 1L)); |
| Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(max, 0L)); |
| Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(min, 0L)); |
| Assert.assertEquals(max, ArithmeticUtils.mulAndCheck(1L, max)); |
| Assert.assertEquals(min, ArithmeticUtils.mulAndCheck(1L, min)); |
| Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(0L, max)); |
| Assert.assertEquals(0L, ArithmeticUtils.mulAndCheck(0L, min)); |
| Assert.assertEquals(1L, ArithmeticUtils.mulAndCheck(-1L, -1L)); |
| Assert.assertEquals(min, ArithmeticUtils.mulAndCheck(min / 2, 2)); |
| testMulAndCheckLongFailure(max, 2L); |
| testMulAndCheckLongFailure(2L, max); |
| testMulAndCheckLongFailure(min, 2L); |
| testMulAndCheckLongFailure(2L, min); |
| testMulAndCheckLongFailure(min, -1L); |
| testMulAndCheckLongFailure(-1L, min); |
| } |
| |
| @Test |
| public void testSubAndCheck() { |
| int big = Integer.MAX_VALUE; |
| int bigNeg = Integer.MIN_VALUE; |
| Assert.assertEquals(big, ArithmeticUtils.subAndCheck(big, 0)); |
| Assert.assertEquals(bigNeg + 1, ArithmeticUtils.subAndCheck(bigNeg, -1)); |
| Assert.assertEquals(-1, ArithmeticUtils.subAndCheck(bigNeg, -big)); |
| try { |
| ArithmeticUtils.subAndCheck(big, -1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| } |
| try { |
| ArithmeticUtils.subAndCheck(bigNeg, 1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| } |
| } |
| |
| @Test |
| public void testSubAndCheckErrorMessage() { |
| int big = Integer.MAX_VALUE; |
| try { |
| ArithmeticUtils.subAndCheck(big, -1); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| Assert.assertTrue(ex.getMessage().length() > 1); |
| } |
| } |
| |
| @Test |
| public void testSubAndCheckLong() { |
| long max = Long.MAX_VALUE; |
| long min = Long.MIN_VALUE; |
| Assert.assertEquals(max, ArithmeticUtils.subAndCheck(max, 0)); |
| Assert.assertEquals(min, ArithmeticUtils.subAndCheck(min, 0)); |
| Assert.assertEquals(-max, ArithmeticUtils.subAndCheck(0, max)); |
| Assert.assertEquals(min + 1, ArithmeticUtils.subAndCheck(min, -1)); |
| // min == -1-max |
| Assert.assertEquals(-1, ArithmeticUtils.subAndCheck(-max - 1, -max)); |
| Assert.assertEquals(max, ArithmeticUtils.subAndCheck(-1, -1 - max)); |
| testSubAndCheckLongFailure(0L, min); |
| testSubAndCheckLongFailure(max, -1L); |
| testSubAndCheckLongFailure(min, 1L); |
| } |
| |
| @Test |
| public void testPow() { |
| |
| Assert.assertEquals(1801088541, ArithmeticUtils.pow(21, 7)); |
| Assert.assertEquals(1, ArithmeticUtils.pow(21, 0)); |
| try { |
| ArithmeticUtils.pow(21, -7); |
| Assert.fail("Expecting IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| // expected behavior |
| } |
| |
| Assert.assertEquals(1801088541, ArithmeticUtils.pow(21, 7)); |
| Assert.assertEquals(1, ArithmeticUtils.pow(21, 0)); |
| try { |
| ArithmeticUtils.pow(21, -7); |
| Assert.fail("Expecting IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| // expected behavior |
| } |
| |
| Assert.assertEquals(1801088541l, ArithmeticUtils.pow(21l, 7)); |
| Assert.assertEquals(1l, ArithmeticUtils.pow(21l, 0)); |
| try { |
| ArithmeticUtils.pow(21l, -7); |
| Assert.fail("Expecting IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| // expected behavior |
| } |
| |
| BigInteger twentyOne = BigInteger.valueOf(21l); |
| Assert.assertEquals(BigInteger.valueOf(1801088541l), ArithmeticUtils.pow(twentyOne, 7)); |
| Assert.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0)); |
| try { |
| ArithmeticUtils.pow(twentyOne, -7); |
| Assert.fail("Expecting IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| // expected behavior |
| } |
| |
| Assert.assertEquals(BigInteger.valueOf(1801088541l), ArithmeticUtils.pow(twentyOne, 7l)); |
| Assert.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0l)); |
| try { |
| ArithmeticUtils.pow(twentyOne, -7l); |
| Assert.fail("Expecting IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| // expected behavior |
| } |
| |
| Assert.assertEquals(BigInteger.valueOf(1801088541l), ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(7l))); |
| Assert.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, BigInteger.ZERO)); |
| try { |
| ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(-7l)); |
| Assert.fail("Expecting IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| // expected behavior |
| } |
| |
| BigInteger bigOne = |
| new BigInteger("1543786922199448028351389769265814882661837148" + |
| "4763915343722775611762713982220306372888519211" + |
| "560905579993523402015636025177602059044911261"); |
| Assert.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103)); |
| Assert.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103l)); |
| Assert.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(103l))); |
| |
| } |
| |
| @Test() |
| public void testPowIntOverflow() { |
| Assertions.assertThrows(ArithmeticException.class, |
| () -> ArithmeticUtils.pow(21, 8) |
| ); |
| } |
| |
| @Test |
| public void testPowInt() { |
| final int base = 21; |
| |
| Assert.assertEquals(85766121L, |
| ArithmeticUtils.pow(base, 6)); |
| Assert.assertEquals(1801088541L, |
| ArithmeticUtils.pow(base, 7)); |
| } |
| |
| @Test() |
| public void testPowNegativeIntOverflow() { |
| Assertions.assertThrows(ArithmeticException.class, |
| () -> ArithmeticUtils.pow(-21, 8) |
| ); |
| } |
| |
| @Test |
| public void testPowNegativeInt() { |
| final int base = -21; |
| |
| Assert.assertEquals(85766121, |
| ArithmeticUtils.pow(base, 6)); |
| Assert.assertEquals(-1801088541, |
| ArithmeticUtils.pow(base, 7)); |
| } |
| |
| @Test |
| public void testPowMinusOneInt() { |
| final int base = -1; |
| for (int i = 0; i < 100; i++) { |
| final int pow = ArithmeticUtils.pow(base, i); |
| Assert.assertEquals("i: " + i, i % 2 == 0 ? 1 : -1, pow); |
| } |
| } |
| |
| @Test |
| public void testPowOneInt() { |
| final int base = 1; |
| for (int i = 0; i < 100; i++) { |
| final int pow = ArithmeticUtils.pow(base, i); |
| Assert.assertEquals("i: " + i, 1, pow); |
| } |
| } |
| |
| @Test() |
| public void testPowLongOverflow() |
| { |
| Assertions.assertThrows(ArithmeticException.class, |
| () -> ArithmeticUtils.pow(21, 15) |
| ); |
| } |
| |
| @Test |
| public void testPowLong() { |
| final long base = 21; |
| |
| Assert.assertEquals(154472377739119461L, |
| ArithmeticUtils.pow(base, 13)); |
| Assert.assertEquals(3243919932521508681L, |
| ArithmeticUtils.pow(base, 14)); |
| } |
| |
| @Test() |
| public void testPowNegativeLongOverflow() { |
| Assertions.assertThrows(ArithmeticException.class, |
| () -> ArithmeticUtils.pow(-21L, 15) |
| ); |
| } |
| |
| @Test |
| public void testPowNegativeLong() { |
| final long base = -21; |
| |
| Assert.assertEquals(-154472377739119461L, |
| ArithmeticUtils.pow(base, 13)); |
| Assert.assertEquals(3243919932521508681L, |
| ArithmeticUtils.pow(base, 14)); |
| } |
| |
| @Test |
| public void testPowMinusOneLong() { |
| final long base = -1; |
| for (int i = 0; i < 100; i++) { |
| final long pow = ArithmeticUtils.pow(base, i); |
| Assert.assertEquals("i: " + i, i % 2 == 0 ? 1 : -1, pow); |
| } |
| } |
| |
| @Test |
| public void testPowOneLong() { |
| final long base = 1; |
| for (int i = 0; i < 100; i++) { |
| final long pow = ArithmeticUtils.pow(base, i); |
| Assert.assertEquals("i: " + i, 1, pow); |
| } |
| } |
| |
| @Test |
| public void testIsPowerOfTwo() { |
| final int n = 1025; |
| final boolean[] expected = new boolean[n]; |
| Arrays.fill(expected, false); |
| for (int i = 1; i < expected.length; i *= 2) { |
| expected[i] = true; |
| } |
| for (int i = 0; i < expected.length; i++) { |
| final boolean actual = ArithmeticUtils.isPowerOfTwo(i); |
| Assert.assertTrue(Integer.toString(i), actual == expected[i]); |
| } |
| } |
| |
| private void testAddAndCheckLongFailure(long a, long b) { |
| try { |
| ArithmeticUtils.addAndCheck(a, b); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| // success |
| } |
| } |
| |
| private void testMulAndCheckLongFailure(long a, long b) { |
| try { |
| ArithmeticUtils.mulAndCheck(a, b); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| // success |
| } |
| } |
| |
| private void testSubAndCheckLongFailure(long a, long b) { |
| try { |
| ArithmeticUtils.subAndCheck(a, b); |
| Assert.fail("Expecting ArithmeticException"); |
| } catch (ArithmeticException ex) { |
| // success |
| } |
| } |
| |
| /** |
| * Testing helper method. |
| * @return an array of int numbers containing corner cases:<ul> |
| * <li>values near the beginning of int range,</li> |
| * <li>values near the end of int range,</li> |
| * <li>values near zero</li> |
| * <li>and some randomly distributed values.</li> |
| * </ul> |
| */ |
| private static int[] getIntSpecialCases() { |
| int ints[] = new int[100]; |
| int i = 0; |
| ints[i++] = Integer.MAX_VALUE; |
| ints[i++] = Integer.MAX_VALUE - 1; |
| ints[i++] = 100; |
| ints[i++] = 101; |
| ints[i++] = 102; |
| ints[i++] = 300; |
| ints[i++] = 567; |
| for (int j = 0; j < 20; j++) { |
| ints[i++] = j; |
| } |
| for (int j = i - 1; j >= 0; j--) { |
| ints[i++] = ints[j] > 0 ? -ints[j] : Integer.MIN_VALUE; |
| } |
| java.util.Random r = new java.util.Random(System.nanoTime()); |
| for (; i < ints.length;) { |
| ints[i++] = r.nextInt(); |
| } |
| return ints; |
| } |
| |
| /** |
| * Testing helper method. |
| * @return an array of long numbers containing corner cases:<ul> |
| * <li>values near the beginning of long range,</li> |
| * <li>values near the end of long range,</li> |
| * <li>values near the beginning of int range,</li> |
| * <li>values near the end of int range,</li> |
| * <li>values near zero</li> |
| * <li>and some randomly distributed values.</li> |
| * </ul> |
| */ |
| private static long[] getLongSpecialCases() { |
| long longs[] = new long[100]; |
| int i = 0; |
| longs[i++] = Long.MAX_VALUE; |
| longs[i++] = Long.MAX_VALUE - 1L; |
| longs[i++] = (long) Integer.MAX_VALUE + 1L; |
| longs[i++] = Integer.MAX_VALUE; |
| longs[i++] = Integer.MAX_VALUE - 1; |
| longs[i++] = 100L; |
| longs[i++] = 101L; |
| longs[i++] = 102L; |
| longs[i++] = 300L; |
| longs[i++] = 567L; |
| for (int j = 0; j < 20; j++) { |
| longs[i++] = j; |
| } |
| for (int j = i - 1; j >= 0; j--) { |
| longs[i++] = longs[j] > 0L ? -longs[j] : Long.MIN_VALUE; |
| } |
| java.util.Random r = new java.util.Random(System.nanoTime()); |
| for (; i < longs.length;) { |
| longs[i++] = r.nextLong(); |
| } |
| return longs; |
| } |
| |
| private static long toUnsignedLong(int number) { |
| return number < 0 ? 0x100000000L + (long)number : (long)number; |
| } |
| |
| private static int remainderUnsignedExpected(int dividend, int divisor) { |
| return (int)remainderUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor)); |
| } |
| |
| private static int divideUnsignedExpected(int dividend, int divisor) { |
| return (int)divideUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor)); |
| } |
| |
| private static BigInteger toUnsignedBigInteger(long number) { |
| return number < 0L ? BigInteger.ONE.shiftLeft(64).add(BigInteger.valueOf(number)) : BigInteger.valueOf(number); |
| } |
| |
| private static long remainderUnsignedExpected(long dividend, long divisor) { |
| return toUnsignedBigInteger(dividend).remainder(toUnsignedBigInteger(divisor)).longValue(); |
| } |
| |
| private static long divideUnsignedExpected(long dividend, long divisor) { |
| return toUnsignedBigInteger(dividend).divide(toUnsignedBigInteger(divisor)).longValue(); |
| } |
| |
| @Test() |
| public void testRemainderUnsignedInt() { |
| Assert.assertEquals(36, ArithmeticUtils.remainderUnsigned(-2147479015, 63)); |
| Assert.assertEquals(6, ArithmeticUtils.remainderUnsigned(-2147479015, 25)); |
| } |
| |
| @Test() |
| public void testRemainderUnsignedIntSpecialCases() { |
| int ints[] = getIntSpecialCases(); |
| for (int dividend : ints) { |
| for (int divisor : ints) { |
| if (divisor == 0) { |
| Assertions.assertThrows(ArithmeticException.class, |
| () -> ArithmeticUtils.remainderUnsigned(dividend, divisor) |
| ); |
| } else { |
| Assert.assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor)); |
| } |
| } |
| } |
| } |
| |
| @Test() |
| public void testRemainderUnsignedLong() { |
| Assert.assertEquals(48L, ArithmeticUtils.remainderUnsigned(-2147479015L, 63L)); |
| } |
| |
| @Test |
| public void testRemainderUnsignedLongSpecialCases() { |
| long longs[] = getLongSpecialCases(); |
| for (long dividend : longs) { |
| for (long divisor : longs) { |
| if (divisor == 0L) { |
| try { |
| ArithmeticUtils.remainderUnsigned(dividend, divisor); |
| Assert.fail("Should have failed with ArithmeticException: division by zero"); |
| } catch (ArithmeticException e) { |
| // Success. |
| } |
| } else { |
| Assert.assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor)); |
| } |
| } |
| } |
| } |
| |
| @Test() |
| public void testDivideUnsignedInt() { |
| Assert.assertEquals(34087115, ArithmeticUtils.divideUnsigned(-2147479015, 63)); |
| Assert.assertEquals(85899531, ArithmeticUtils.divideUnsigned(-2147479015, 25)); |
| Assert.assertEquals(2147483646, ArithmeticUtils.divideUnsigned(-3, 2)); |
| Assert.assertEquals(330382098, ArithmeticUtils.divideUnsigned(-16, 13)); |
| Assert.assertEquals(306783377, ArithmeticUtils.divideUnsigned(-16, 14)); |
| Assert.assertEquals(2, ArithmeticUtils.divideUnsigned(-1, 2147483647)); |
| Assert.assertEquals(2, ArithmeticUtils.divideUnsigned(-2, 2147483647)); |
| Assert.assertEquals(1, ArithmeticUtils.divideUnsigned(-3, 2147483647)); |
| Assert.assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483647)); |
| Assert.assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483646)); |
| } |
| |
| @Test() |
| public void testDivideUnsignedIntSpecialCases() { |
| int ints[] = getIntSpecialCases(); |
| for (int dividend : ints) { |
| for (int divisor : ints) { |
| if (divisor == 0) { |
| Assertions.assertThrows(ArithmeticException.class, |
| () -> ArithmeticUtils.divideUnsigned(dividend, divisor) |
| ); |
| } else { |
| Assert.assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor)); |
| } |
| } |
| } |
| } |
| |
| @Test() |
| public void testDivideUnsignedLong() { |
| Assert.assertEquals(292805461453366231L, ArithmeticUtils.divideUnsigned(-2147479015L, 63L)); |
| } |
| |
| @Test() |
| public void testDivideUnsignedLongSpecialCases() { |
| long longs[] = getLongSpecialCases(); |
| for (long dividend : longs) { |
| for (long divisor : longs) { |
| if (divisor == 0L) { |
| Assertions.assertThrows(ArithmeticException.class, |
| () -> ArithmeticUtils.divideUnsigned(dividend, divisor) |
| ); |
| } else { |
| Assert.assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor)); |
| } |
| } |
| } |
| } |
| } |