View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.util;
23  
24  import org.hipparchus.exception.MathIllegalArgumentException;
25  import org.hipparchus.exception.MathRuntimeException;
26  import org.hipparchus.random.RandomDataGenerator;
27  import org.junit.jupiter.api.Test;
28  import org.junit.jupiter.api.Timeout;
29  
30  import java.math.BigInteger;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.concurrent.TimeUnit;
34  
35  import static org.junit.jupiter.api.Assertions.assertEquals;
36  import static org.junit.jupiter.api.Assertions.assertThrows;
37  import static org.junit.jupiter.api.Assertions.assertTrue;
38  import static org.junit.jupiter.api.Assertions.fail;
39  
40  /**
41   * Test cases for the {@link ArithmeticUtils} class.
42   */
43  class ArithmeticUtilsTest {
44  
45      @Test
46      void testAddAndCheck() {
47          int big = Integer.MAX_VALUE;
48          int bigNeg = Integer.MIN_VALUE;
49          assertEquals(big, ArithmeticUtils.addAndCheck(big, 0));
50          try {
51              ArithmeticUtils.addAndCheck(big, 1);
52              fail("Expecting MathRuntimeException");
53          } catch (MathRuntimeException ex) {
54          }
55          try {
56              ArithmeticUtils.addAndCheck(bigNeg, -1);
57              fail("Expecting MathRuntimeException");
58          } catch (MathRuntimeException ex) {
59          }
60      }
61  
62      @Test
63      void testAddAndCheckLong() {
64          long max = Long.MAX_VALUE;
65          long min = Long.MIN_VALUE;
66          assertEquals(max, ArithmeticUtils.addAndCheck(max, 0L));
67          assertEquals(min, ArithmeticUtils.addAndCheck(min, 0L));
68          assertEquals(max, ArithmeticUtils.addAndCheck(0L, max));
69          assertEquals(min, ArithmeticUtils.addAndCheck(0L, min));
70          assertEquals(1, ArithmeticUtils.addAndCheck(-1L, 2L));
71          assertEquals(1, ArithmeticUtils.addAndCheck(2L, -1L));
72          assertEquals(-3, ArithmeticUtils.addAndCheck(-2L, -1L));
73          assertEquals(min, ArithmeticUtils.addAndCheck(min + 1, -1L));
74          assertEquals(-1, ArithmeticUtils.addAndCheck(min, max));
75          testAddAndCheckLongFailure(max, 1L);
76          testAddAndCheckLongFailure(min, -1L);
77          testAddAndCheckLongFailure(1L, max);
78          testAddAndCheckLongFailure(-1L, min);
79          testAddAndCheckLongFailure(max, max);
80          testAddAndCheckLongFailure(min, min);
81      }
82  
83      @Test
84      void testGcd() {
85          int a = 30;
86          int b = 50;
87          int c = 77;
88  
89          assertEquals(0, ArithmeticUtils.gcd(0, 0));
90  
91          assertEquals(b, ArithmeticUtils.gcd(0, b));
92          assertEquals(a, ArithmeticUtils.gcd(a, 0));
93          assertEquals(b, ArithmeticUtils.gcd(0, -b));
94          assertEquals(a, ArithmeticUtils.gcd(-a, 0));
95  
96          assertEquals(10, ArithmeticUtils.gcd(a, b));
97          assertEquals(10, ArithmeticUtils.gcd(-a, b));
98          assertEquals(10, ArithmeticUtils.gcd(a, -b));
99          assertEquals(10, ArithmeticUtils.gcd(-a, -b));
100 
101         assertEquals(1, ArithmeticUtils.gcd(a, c));
102         assertEquals(1, ArithmeticUtils.gcd(-a, c));
103         assertEquals(1, ArithmeticUtils.gcd(a, -c));
104         assertEquals(1, ArithmeticUtils.gcd(-a, -c));
105 
106         assertEquals(3 * (1<<15), ArithmeticUtils.gcd(3 * (1<<20), 9 * (1<<15)));
107 
108         assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(Integer.MAX_VALUE, 0));
109         assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(-Integer.MAX_VALUE, 0));
110         assertEquals(1<<30, ArithmeticUtils.gcd(1<<30, -Integer.MIN_VALUE));
111         try {
112             // gcd(Integer.MIN_VALUE, 0) > Integer.MAX_VALUE
113             ArithmeticUtils.gcd(Integer.MIN_VALUE, 0);
114             fail("expecting MathRuntimeException");
115         } catch (MathRuntimeException expected) {
116             // expected
117         }
118         try {
119             // gcd(0, Integer.MIN_VALUE) > Integer.MAX_VALUE
120             ArithmeticUtils.gcd(0, Integer.MIN_VALUE);
121             fail("expecting MathRuntimeException");
122         } catch (MathRuntimeException expected) {
123             // expected
124         }
125         try {
126             // gcd(Integer.MIN_VALUE, Integer.MIN_VALUE) > Integer.MAX_VALUE
127             ArithmeticUtils.gcd(Integer.MIN_VALUE, Integer.MIN_VALUE);
128             fail("expecting MathRuntimeException");
129         } catch (MathRuntimeException expected) {
130             // expected
131         }
132     }
133 
134     @Test
135     void testGcdConsistency() {
136         int[] primeList = {19, 23, 53, 67, 73, 79, 101, 103, 111, 131};
137         ArrayList<Integer> primes = new ArrayList<Integer>();
138         for (int i = 0; i < primeList.length; i++) {
139             primes.add(Integer.valueOf(primeList[i]));
140         }
141         RandomDataGenerator randomData = new RandomDataGenerator();
142         for (int i = 0; i < 20; i++) {
143             Object[] sample = randomData.nextSample(primes, 4);
144             int p1 = ((Integer) sample[0]).intValue();
145             int p2 = ((Integer) sample[1]).intValue();
146             int p3 = ((Integer) sample[2]).intValue();
147             int p4 = ((Integer) sample[3]).intValue();
148             int i1 = p1 * p2 * p3;
149             int i2 = p1 * p2 * p4;
150             int gcd = p1 * p2;
151             assertEquals(gcd, ArithmeticUtils.gcd(i1, i2));
152             long l1 = i1;
153             long l2 = i2;
154             assertEquals(gcd, ArithmeticUtils.gcd(l1, l2));
155         }
156     }
157 
158     @Test
159     void testGcdLong(){
160         long a = 30;
161         long b = 50;
162         long c = 77;
163 
164         assertEquals(0, ArithmeticUtils.gcd(0L, 0));
165 
166         assertEquals(b, ArithmeticUtils.gcd(0, b));
167         assertEquals(a, ArithmeticUtils.gcd(a, 0));
168         assertEquals(b, ArithmeticUtils.gcd(0, -b));
169         assertEquals(a, ArithmeticUtils.gcd(-a, 0));
170 
171         assertEquals(10, ArithmeticUtils.gcd(a, b));
172         assertEquals(10, ArithmeticUtils.gcd(-a, b));
173         assertEquals(10, ArithmeticUtils.gcd(a, -b));
174         assertEquals(10, ArithmeticUtils.gcd(-a, -b));
175 
176         assertEquals(1, ArithmeticUtils.gcd(a, c));
177         assertEquals(1, ArithmeticUtils.gcd(-a, c));
178         assertEquals(1, ArithmeticUtils.gcd(a, -c));
179         assertEquals(1, ArithmeticUtils.gcd(-a, -c));
180 
181         assertEquals(3L * (1L<<45), ArithmeticUtils.gcd(3L * (1L<<50), 9L * (1L<<45)));
182 
183         assertEquals(1L<<45, ArithmeticUtils.gcd(1L<<45, Long.MIN_VALUE));
184 
185         assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(Long.MAX_VALUE, 0L));
186         assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(-Long.MAX_VALUE, 0L));
187         assertEquals(1, ArithmeticUtils.gcd(60247241209L, 153092023L));
188         try {
189             // gcd(Long.MIN_VALUE, 0) > Long.MAX_VALUE
190             ArithmeticUtils.gcd(Long.MIN_VALUE, 0);
191             fail("expecting MathRuntimeException");
192         } catch (MathRuntimeException expected) {
193             // expected
194         }
195         try {
196             // gcd(0, Long.MIN_VALUE) > Long.MAX_VALUE
197             ArithmeticUtils.gcd(0, Long.MIN_VALUE);
198             fail("expecting MathRuntimeException");
199         } catch (MathRuntimeException expected) {
200             // expected
201         }
202         try {
203             // gcd(Long.MIN_VALUE, Long.MIN_VALUE) > Long.MAX_VALUE
204             ArithmeticUtils.gcd(Long.MIN_VALUE, Long.MIN_VALUE);
205             fail("expecting MathRuntimeException");
206         } catch (MathRuntimeException expected) {
207             // expected
208         }
209     }
210 
211 
212     @Test
213     void testLcm() {
214         int a = 30;
215         int b = 50;
216         int c = 77;
217 
218         assertEquals(0, ArithmeticUtils.lcm(0, b));
219         assertEquals(0, ArithmeticUtils.lcm(a, 0));
220         assertEquals(b, ArithmeticUtils.lcm(1, b));
221         assertEquals(a, ArithmeticUtils.lcm(a, 1));
222         assertEquals(150, ArithmeticUtils.lcm(a, b));
223         assertEquals(150, ArithmeticUtils.lcm(-a, b));
224         assertEquals(150, ArithmeticUtils.lcm(a, -b));
225         assertEquals(150, ArithmeticUtils.lcm(-a, -b));
226         assertEquals(2310, ArithmeticUtils.lcm(a, c));
227 
228         // Assert that no intermediate value overflows:
229         // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b)
230         assertEquals((1<<20)*15, ArithmeticUtils.lcm((1<<20)*3, (1<<20)*5));
231 
232         // Special case
233         assertEquals(0, ArithmeticUtils.lcm(0, 0));
234 
235         try {
236             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
237             ArithmeticUtils.lcm(Integer.MIN_VALUE, 1);
238             fail("Expecting MathRuntimeException");
239         } catch (MathRuntimeException expected) {
240             // expected
241         }
242 
243         try {
244             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
245             ArithmeticUtils.lcm(Integer.MIN_VALUE, 1<<20);
246             fail("Expecting MathRuntimeException");
247         } catch (MathRuntimeException expected) {
248             // expected
249         }
250 
251         try {
252             ArithmeticUtils.lcm(Integer.MAX_VALUE, Integer.MAX_VALUE - 1);
253             fail("Expecting MathRuntimeException");
254         } catch (MathRuntimeException expected) {
255             // expected
256         }
257     }
258 
259     @Test
260     void testLcmLong() {
261         long a = 30;
262         long b = 50;
263         long c = 77;
264 
265         assertEquals(0, ArithmeticUtils.lcm(0, b));
266         assertEquals(0, ArithmeticUtils.lcm(a, 0));
267         assertEquals(b, ArithmeticUtils.lcm(1, b));
268         assertEquals(a, ArithmeticUtils.lcm(a, 1));
269         assertEquals(150, ArithmeticUtils.lcm(a, b));
270         assertEquals(150, ArithmeticUtils.lcm(-a, b));
271         assertEquals(150, ArithmeticUtils.lcm(a, -b));
272         assertEquals(150, ArithmeticUtils.lcm(-a, -b));
273         assertEquals(2310, ArithmeticUtils.lcm(a, c));
274 
275         assertEquals(Long.MAX_VALUE, ArithmeticUtils.lcm(60247241209L, 153092023L));
276 
277         // Assert that no intermediate value overflows:
278         // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b)
279         assertEquals((1L<<50)*15, ArithmeticUtils.lcm((1L<<45)*3, (1L<<50)*5));
280 
281         // Special case
282         assertEquals(0L, ArithmeticUtils.lcm(0L, 0L));
283 
284         try {
285             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
286             ArithmeticUtils.lcm(Long.MIN_VALUE, 1);
287             fail("Expecting MathRuntimeException");
288         } catch (MathRuntimeException expected) {
289             // expected
290         }
291 
292         try {
293             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
294             ArithmeticUtils.lcm(Long.MIN_VALUE, 1<<20);
295             fail("Expecting MathRuntimeException");
296         } catch (MathRuntimeException expected) {
297             // expected
298         }
299 
300         assertEquals((long) Integer.MAX_VALUE * (Integer.MAX_VALUE - 1),
301             ArithmeticUtils.lcm((long)Integer.MAX_VALUE, Integer.MAX_VALUE - 1));
302         try {
303             ArithmeticUtils.lcm(Long.MAX_VALUE, Long.MAX_VALUE - 1);
304             fail("Expecting MathRuntimeException");
305         } catch (MathRuntimeException expected) {
306             // expected
307         }
308     }
309 
310     @Test
311     void testMulAndCheck() {
312         int big = Integer.MAX_VALUE;
313         int bigNeg = Integer.MIN_VALUE;
314         assertEquals(big, ArithmeticUtils.mulAndCheck(big, 1));
315         try {
316             ArithmeticUtils.mulAndCheck(big, 2);
317             fail("Expecting MathRuntimeException");
318         } catch (MathRuntimeException ex) {
319         }
320         try {
321             ArithmeticUtils.mulAndCheck(bigNeg, 2);
322             fail("Expecting MathRuntimeException");
323         } catch (MathRuntimeException ex) {
324         }
325     }
326 
327     @Test
328     void testMulAndCheckLong() {
329         long max = Long.MAX_VALUE;
330         long min = Long.MIN_VALUE;
331         assertEquals(max, ArithmeticUtils.mulAndCheck(max, 1L));
332         assertEquals(min, ArithmeticUtils.mulAndCheck(min, 1L));
333         assertEquals(0L, ArithmeticUtils.mulAndCheck(max, 0L));
334         assertEquals(0L, ArithmeticUtils.mulAndCheck(min, 0L));
335         assertEquals(max, ArithmeticUtils.mulAndCheck(1L, max));
336         assertEquals(min, ArithmeticUtils.mulAndCheck(1L, min));
337         assertEquals(0L, ArithmeticUtils.mulAndCheck(0L, max));
338         assertEquals(0L, ArithmeticUtils.mulAndCheck(0L, min));
339         assertEquals(1L, ArithmeticUtils.mulAndCheck(-1L, -1L));
340         assertEquals(min, ArithmeticUtils.mulAndCheck(min / 2, 2));
341         testMulAndCheckLongFailure(max, 2L);
342         testMulAndCheckLongFailure(2L, max);
343         testMulAndCheckLongFailure(min, 2L);
344         testMulAndCheckLongFailure(2L, min);
345         testMulAndCheckLongFailure(min, -1L);
346         testMulAndCheckLongFailure(-1L, min);
347     }
348 
349     @Test
350     void testSubAndCheck() {
351         int big = Integer.MAX_VALUE;
352         int bigNeg = Integer.MIN_VALUE;
353         assertEquals(big, ArithmeticUtils.subAndCheck(big, 0));
354         assertEquals(bigNeg + 1, ArithmeticUtils.subAndCheck(bigNeg, -1));
355         assertEquals(-1, ArithmeticUtils.subAndCheck(bigNeg, -big));
356         try {
357             ArithmeticUtils.subAndCheck(big, -1);
358             fail("Expecting MathRuntimeException");
359         } catch (MathRuntimeException ex) {
360         }
361         try {
362             ArithmeticUtils.subAndCheck(bigNeg, 1);
363             fail("Expecting MathRuntimeException");
364         } catch (MathRuntimeException ex) {
365         }
366     }
367 
368     @Test
369     void testSubAndCheckErrorMessage() {
370         int big = Integer.MAX_VALUE;
371         try {
372             ArithmeticUtils.subAndCheck(big, -1);
373             fail("Expecting MathRuntimeException");
374         } catch (MathRuntimeException ex) {
375             assertTrue(ex.getMessage().length() > 1);
376         }
377     }
378 
379     @Test
380     void testSubAndCheckLong() {
381         long max = Long.MAX_VALUE;
382         long min = Long.MIN_VALUE;
383         assertEquals(max, ArithmeticUtils.subAndCheck(max, 0));
384         assertEquals(min, ArithmeticUtils.subAndCheck(min, 0));
385         assertEquals(-max, ArithmeticUtils.subAndCheck(0, max));
386         assertEquals(min + 1, ArithmeticUtils.subAndCheck(min, -1));
387         // min == -1-max
388         assertEquals(-1, ArithmeticUtils.subAndCheck(-max - 1, -max));
389         assertEquals(max, ArithmeticUtils.subAndCheck(-1, -1 - max));
390         testSubAndCheckLongFailure(0L, min);
391         testSubAndCheckLongFailure(max, -1L);
392         testSubAndCheckLongFailure(min, 1L);
393     }
394 
395     @Test
396     void testPow() {
397 
398         assertEquals(1801088541, ArithmeticUtils.pow(21, 7));
399         assertEquals(1, ArithmeticUtils.pow(21, 0));
400         try {
401             ArithmeticUtils.pow(21, -7);
402             fail("Expecting MathIllegalArgumentException");
403         } catch (MathIllegalArgumentException e) {
404             // expected behavior
405         }
406 
407         assertEquals(1801088541, ArithmeticUtils.pow(21, 7));
408         assertEquals(1, ArithmeticUtils.pow(21, 0));
409         try {
410             ArithmeticUtils.pow(21, -7);
411             fail("Expecting MathIllegalArgumentException");
412         } catch (MathIllegalArgumentException e) {
413             // expected behavior
414         }
415 
416         assertEquals(1801088541L, ArithmeticUtils.pow(21L, 7));
417         assertEquals(1L, ArithmeticUtils.pow(21L, 0));
418         try {
419             ArithmeticUtils.pow(21L, -7);
420             fail("Expecting MathIllegalArgumentException");
421         } catch (MathIllegalArgumentException e) {
422             // expected behavior
423         }
424 
425         BigInteger twentyOne = BigInteger.valueOf(21L);
426         assertEquals(BigInteger.valueOf(1801088541L), ArithmeticUtils.pow(twentyOne, 7));
427         assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0));
428         try {
429             ArithmeticUtils.pow(twentyOne, -7);
430             fail("Expecting MathIllegalArgumentException");
431         } catch (MathIllegalArgumentException e) {
432             // expected behavior
433         }
434 
435         assertEquals(BigInteger.valueOf(1801088541L), ArithmeticUtils.pow(twentyOne,
436                                                                                  7L));
437         assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0L));
438         try {
439             ArithmeticUtils.pow(twentyOne, -7L);
440             fail("Expecting MathIllegalArgumentException");
441         } catch (MathIllegalArgumentException e) {
442             // expected behavior
443         }
444 
445         assertEquals(BigInteger.valueOf(1801088541L), ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(
446                         7L)));
447         assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, BigInteger.ZERO));
448         try {
449             ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(-7L));
450             fail("Expecting MathIllegalArgumentException");
451         } catch (MathIllegalArgumentException e) {
452             // expected behavior
453         }
454 
455         BigInteger bigOne =
456             new BigInteger("1543786922199448028351389769265814882661837148" +
457                            "4763915343722775611762713982220306372888519211" +
458                            "560905579993523402015636025177602059044911261");
459         assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103));
460         assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103L));
461         assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(
462                         103L)));
463 
464     }
465 
466     @Test
467     void testPowIntOverflow() {
468         assertThrows(MathRuntimeException.class, () -> {
469             ArithmeticUtils.pow(21, 8);
470         });
471     }
472 
473     @Test
474     void testPowInt() {
475         final int base = 21;
476 
477         assertEquals(85766121L,
478                             ArithmeticUtils.pow(base, 6));
479         assertEquals(1801088541L,
480                             ArithmeticUtils.pow(base, 7));
481     }
482 
483     @Test
484     void testPowNegativeIntOverflow() {
485         assertThrows(MathRuntimeException.class, () -> {
486             ArithmeticUtils.pow(-21, 8);
487         });
488     }
489 
490     @Test
491     void testPowNegativeInt() {
492         final int base = -21;
493 
494         assertEquals(85766121,
495                             ArithmeticUtils.pow(base, 6));
496         assertEquals(-1801088541,
497                             ArithmeticUtils.pow(base, 7));
498     }
499 
500     @Test
501     void testPowMinusOneInt() {
502         final int base = -1;
503         for (int i = 0; i < 100; i++) {
504             final int pow = ArithmeticUtils.pow(base, i);
505             assertEquals(i % 2 == 0 ? 1 : -1, pow, "i: " + i);
506         }
507     }
508 
509     @Test
510     void testPowOneInt() {
511         final int base = 1;
512         for (int i = 0; i < 100; i++) {
513             final int pow = ArithmeticUtils.pow(base, i);
514             assertEquals(1, pow, "i: " + i);
515         }
516     }
517 
518     @Test
519     void testPowLongOverflow() {
520         assertThrows(MathRuntimeException.class, () -> {
521             ArithmeticUtils.pow(21, 15);
522         });
523     }
524 
525     @Test
526     void testPowLong() {
527         final long base = 21;
528 
529         assertEquals(154472377739119461L,
530                             ArithmeticUtils.pow(base, 13));
531         assertEquals(3243919932521508681L,
532                             ArithmeticUtils.pow(base, 14));
533     }
534 
535     @Test
536     void testPowNegativeLongOverflow() {
537         assertThrows(MathRuntimeException.class, () -> {
538             ArithmeticUtils.pow(-21L, 15);
539         });
540     }
541 
542     @Test
543     void testPowNegativeLong() {
544         final long base = -21;
545 
546         assertEquals(-154472377739119461L,
547                             ArithmeticUtils.pow(base, 13));
548         assertEquals(3243919932521508681L,
549                             ArithmeticUtils.pow(base, 14));
550     }
551 
552     @Test
553     void testPowMinusOneLong() {
554         final long base = -1;
555         for (int i = 0; i < 100; i++) {
556             final long pow = ArithmeticUtils.pow(base, i);
557             assertEquals(i % 2 == 0 ? 1 : -1, pow, "i: " + i);
558         }
559     }
560 
561     @Test
562     void testPowOneLong() {
563         final long base = 1;
564         for (int i = 0; i < 100; i++) {
565             final long pow = ArithmeticUtils.pow(base, i);
566             assertEquals(1, pow, "i: " + i);
567         }
568     }
569 
570     @Test
571     void testIsPowerOfTwo() {
572         final int n = 1025;
573         final boolean[] expected = new boolean[n];
574         Arrays.fill(expected, false);
575         for (int i = 1; i < expected.length; i *= 2) {
576             expected[i] = true;
577         }
578         for (int i = 0; i < expected.length; i++) {
579             final boolean actual = ArithmeticUtils.isPowerOfTwo(i);
580             assertEquals(actual, expected[i], Integer.toString(i));
581         }
582     }
583 
584     private void testAddAndCheckLongFailure(long a, long b) {
585         try {
586             ArithmeticUtils.addAndCheck(a, b);
587             fail("Expecting MathRuntimeException");
588         } catch (MathRuntimeException ex) {
589             // success
590         }
591     }
592 
593     private void testMulAndCheckLongFailure(long a, long b) {
594         try {
595             ArithmeticUtils.mulAndCheck(a, b);
596             fail("Expecting MathRuntimeException");
597         } catch (MathRuntimeException ex) {
598             // success
599         }
600     }
601 
602     private void testSubAndCheckLongFailure(long a, long b) {
603         try {
604             ArithmeticUtils.subAndCheck(a, b);
605             fail("Expecting MathRuntimeException");
606         } catch (MathRuntimeException ex) {
607             // success
608         }
609     }
610 
611     /**
612      * Testing helper method.
613      * @return an array of int numbers containing corner cases:<ul>
614      * <li>values near the beginning of int range,</li>
615      * <li>values near the end of int range,</li>
616      * <li>values near zero</li>
617      * <li>and some randomly distributed values.</li>
618      * </ul>
619      */
620     private static int[] getIntSpecialCases() {
621         int[] ints = new int[100];
622         int i = 0;
623         ints[i++] = Integer.MAX_VALUE;
624         ints[i++] = Integer.MAX_VALUE - 1;
625         ints[i++] = 100;
626         ints[i++] = 101;
627         ints[i++] = 102;
628         ints[i++] = 300;
629         ints[i++] = 567;
630         for (int j = 0; j < 20; j++) {
631             ints[i++] = j;
632         }
633         for (int j = i - 1; j >= 0; j--) {
634             ints[i++] = ints[j] > 0 ? -ints[j] : Integer.MIN_VALUE;
635         }
636         java.util.Random r = new java.util.Random(System.nanoTime());
637         while (i < ints.length) {
638             ints[i++] = r.nextInt();
639         }
640         return ints;
641     }
642 
643     /**
644      * Testing helper method.
645      * @return an array of long numbers containing corner cases:<ul>
646      * <li>values near the beginning of long range,</li>
647      * <li>values near the end of long range,</li>
648      * <li>values near the beginning of int range,</li>
649      * <li>values near the end of int range,</li>
650      * <li>values near zero</li>
651      * <li>and some randomly distributed values.</li>
652      * </ul>
653      */
654     private static long[] getLongSpecialCases() {
655         long[] longs = new long[100];
656         int i = 0;
657         longs[i++] = Long.MAX_VALUE;
658         longs[i++] = Long.MAX_VALUE - 1L;
659         longs[i++] = (long) Integer.MAX_VALUE + 1L;
660         longs[i++] = Integer.MAX_VALUE;
661         longs[i++] = Integer.MAX_VALUE - 1;
662         longs[i++] = 100L;
663         longs[i++] = 101L;
664         longs[i++] = 102L;
665         longs[i++] = 300L;
666         longs[i++] = 567L;
667         for (int j = 0; j < 20; j++) {
668             longs[i++] = j;
669         }
670         for (int j = i - 1; j >= 0; j--) {
671             longs[i++] = longs[j] > 0L ? -longs[j] : Long.MIN_VALUE;
672         }
673         java.util.Random r = new java.util.Random(System.nanoTime());
674         while (i < longs.length) {
675             longs[i++] = r.nextLong();
676         }
677         return longs;
678     }
679 
680     private static long toUnsignedLong(int number) {
681         return number < 0 ? 0x100000000L + (long)number : (long)number;
682     }
683 
684     private static int remainderUnsignedExpected(int dividend, int divisor) {
685         return (int)remainderUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor));
686     }
687 
688     private static int divideUnsignedExpected(int dividend, int divisor) {
689         return (int)divideUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor));
690     }
691 
692     private static BigInteger toUnsignedBigInteger(long number) {
693         return number < 0L ? BigInteger.ONE.shiftLeft(64).add(BigInteger.valueOf(number)) : BigInteger.valueOf(number);
694     }
695 
696     private static long remainderUnsignedExpected(long dividend, long divisor) {
697         return toUnsignedBigInteger(dividend).remainder(toUnsignedBigInteger(divisor)).longValue();
698     }
699 
700     private static long divideUnsignedExpected(long dividend, long divisor) {
701         return toUnsignedBigInteger(dividend).divide(toUnsignedBigInteger(divisor)).longValue();
702     }
703 
704     @Test
705     @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
706     void testRemainderUnsignedInt() {
707         assertEquals(36, ArithmeticUtils.remainderUnsigned(-2147479015, 63));
708         assertEquals(6, ArithmeticUtils.remainderUnsigned(-2147479015, 25));
709     }
710 
711     @Test
712     @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
713     void testRemainderUnsignedIntSpecialCases() {
714         int[] ints = getIntSpecialCases();
715         for (int dividend : ints) {
716             for (int divisor : ints) {
717                 if (divisor == 0) {
718                     try {
719                         ArithmeticUtils.remainderUnsigned(dividend, divisor);
720                         fail("Should have failed with ArithmeticException: division by zero");
721                     } catch (ArithmeticException e) {
722                         // Success.
723                     }
724                 } else {
725                     assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor));
726                 }
727             }
728         }
729     }
730 
731     @Test
732     @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
733     void testRemainderUnsignedLong() {
734         assertEquals(48L, ArithmeticUtils.remainderUnsigned(-2147479015L, 63L));
735     }
736 
737     //(timeout=5000L)
738     @Test
739     void testRemainderUnsignedLongSpecialCases() {
740         long[] longs = getLongSpecialCases();
741         for (long dividend : longs) {
742             for (long divisor : longs) {
743                 if (divisor == 0L) {
744                     try {
745                         ArithmeticUtils.remainderUnsigned(dividend, divisor);
746                         fail("Should have failed with ArithmeticException: division by zero");
747                     } catch (ArithmeticException e) {
748                         // Success.
749                     }
750                 } else {
751                     assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor));
752                 }
753             }
754         }
755     }
756 
757     @Test
758     @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
759     void testDivideUnsignedInt() {
760         assertEquals(34087115, ArithmeticUtils.divideUnsigned(-2147479015, 63));
761         assertEquals(85899531, ArithmeticUtils.divideUnsigned(-2147479015, 25));
762         assertEquals(2147483646, ArithmeticUtils.divideUnsigned(-3, 2));
763         assertEquals(330382098, ArithmeticUtils.divideUnsigned(-16, 13));
764         assertEquals(306783377, ArithmeticUtils.divideUnsigned(-16, 14));
765         assertEquals(2, ArithmeticUtils.divideUnsigned(-1, 2147483647));
766         assertEquals(2, ArithmeticUtils.divideUnsigned(-2, 2147483647));
767         assertEquals(1, ArithmeticUtils.divideUnsigned(-3, 2147483647));
768         assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483647));
769         assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483646));
770     }
771 
772     @Test
773     @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
774     void testDivideUnsignedIntSpecialCases() {
775         int[] ints = getIntSpecialCases();
776         for (int dividend : ints) {
777             for (int divisor : ints) {
778                 if (divisor == 0) {
779                     try {
780                         ArithmeticUtils.divideUnsigned(dividend, divisor);
781                         fail("Should have failed with ArithmeticException: division by zero");
782                     } catch (ArithmeticException e) {
783                         // Success.
784                     }
785                 } else {
786                     assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor));
787                 }
788             }
789         }
790     }
791 
792     @Test
793     @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
794     void testDivideUnsignedLong() {
795         assertEquals(292805461453366231L, ArithmeticUtils.divideUnsigned(-2147479015L, 63L));
796     }
797 
798     @Test
799     @Timeout(value = 5000L, unit = TimeUnit.MILLISECONDS)
800     void testDivideUnsignedLongSpecialCases() {
801         long[] longs = getLongSpecialCases();
802         for (long dividend : longs) {
803             for (long divisor : longs) {
804                 if (divisor == 0L) {
805                     try {
806                         ArithmeticUtils.divideUnsigned(dividend, divisor);
807                         fail("Should have failed with ArithmeticException: division by zero");
808                     } catch (ArithmeticException e) {
809                         // Success.
810                     }
811                 } else {
812                     assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor));
813                 }
814             }
815         }
816     }
817 }