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    *      http://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  package org.apache.commons.numbers.core;
18  
19  import java.util.Arrays;
20  import java.math.BigInteger;
21  import java.util.Collections;
22  
23  import org.junit.jupiter.api.Assertions;
24  import org.junit.jupiter.api.Test;
25  
26  /**
27   * Test cases for the {@link ArithmeticUtils} class.
28   *
29   */
30  class ArithmeticUtilsTest {
31  
32      @Test
33      void testGcd() {
34          int a = 30;
35          int b = 50;
36          int c = 77;
37  
38          Assertions.assertEquals(0, ArithmeticUtils.gcd(0, 0));
39  
40          Assertions.assertEquals(b, ArithmeticUtils.gcd(0, b));
41          Assertions.assertEquals(a, ArithmeticUtils.gcd(a, 0));
42          Assertions.assertEquals(b, ArithmeticUtils.gcd(0, -b));
43          Assertions.assertEquals(a, ArithmeticUtils.gcd(-a, 0));
44  
45          Assertions.assertEquals(10, ArithmeticUtils.gcd(a, b));
46          Assertions.assertEquals(10, ArithmeticUtils.gcd(-a, b));
47          Assertions.assertEquals(10, ArithmeticUtils.gcd(a, -b));
48          Assertions.assertEquals(10, ArithmeticUtils.gcd(-a, -b));
49  
50          Assertions.assertEquals(1, ArithmeticUtils.gcd(a, c));
51          Assertions.assertEquals(1, ArithmeticUtils.gcd(-a, c));
52          Assertions.assertEquals(1, ArithmeticUtils.gcd(a, -c));
53          Assertions.assertEquals(1, ArithmeticUtils.gcd(-a, -c));
54  
55          Assertions.assertEquals(3 * (1 << 15), ArithmeticUtils.gcd(3 * (1 << 20), 9 * (1 << 15)));
56  
57          Assertions.assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(Integer.MAX_VALUE, 0));
58          Assertions.assertEquals(Integer.MAX_VALUE, ArithmeticUtils.gcd(-Integer.MAX_VALUE, 0));
59          Assertions.assertEquals(1 << 30, ArithmeticUtils.gcd(1 << 30, -Integer.MIN_VALUE));
60          try {
61              // gcd(Integer.MIN_VALUE, 0) > Integer.MAX_VALUE
62              ArithmeticUtils.gcd(Integer.MIN_VALUE, 0);
63              Assertions.fail("expecting ArithmeticException");
64          } catch (ArithmeticException expected) {
65              // expected
66          }
67          try {
68              // gcd(0, Integer.MIN_VALUE) > Integer.MAX_VALUE
69              ArithmeticUtils.gcd(0, Integer.MIN_VALUE);
70              Assertions.fail("expecting ArithmeticException");
71          } catch (ArithmeticException expected) {
72              // expected
73          }
74          try {
75              // gcd(Integer.MIN_VALUE, Integer.MIN_VALUE) > Integer.MAX_VALUE
76              ArithmeticUtils.gcd(Integer.MIN_VALUE, Integer.MIN_VALUE);
77              Assertions.fail("expecting ArithmeticException");
78          } catch (ArithmeticException expected) {
79              // expected
80          }
81      }
82  
83      @Test
84      void testGcdConsistency() {
85          // Use Integer to prevent varargs vs array issue with Arrays.asList
86          Integer[] primeList = {19, 23, 53, 67, 73, 79, 101, 103, 111, 131};
87  
88          for (int i = 0; i < 20; i++) {
89              Collections.shuffle(Arrays.asList(primeList));
90              int p1 = primeList[0];
91              int p2 = primeList[1];
92              int p3 = primeList[2];
93              int p4 = primeList[3];
94              int i1 = p1 * p2 * p3;
95              int i2 = p1 * p2 * p4;
96              int gcd = p1 * p2;
97              Assertions.assertEquals(gcd, ArithmeticUtils.gcd(i1, i2));
98              long l1 = i1;
99              long l2 = i2;
100             Assertions.assertEquals(gcd, ArithmeticUtils.gcd(l1, l2));
101         }
102     }
103 
104     @Test
105     void  testGcdLong() {
106         long a = 30;
107         long b = 50;
108         long c = 77;
109 
110         Assertions.assertEquals(0, ArithmeticUtils.gcd(0L, 0));
111 
112         Assertions.assertEquals(b, ArithmeticUtils.gcd(0, b));
113         Assertions.assertEquals(a, ArithmeticUtils.gcd(a, 0));
114         Assertions.assertEquals(b, ArithmeticUtils.gcd(0, -b));
115         Assertions.assertEquals(a, ArithmeticUtils.gcd(-a, 0));
116 
117         Assertions.assertEquals(10, ArithmeticUtils.gcd(a, b));
118         Assertions.assertEquals(10, ArithmeticUtils.gcd(-a, b));
119         Assertions.assertEquals(10, ArithmeticUtils.gcd(a, -b));
120         Assertions.assertEquals(10, ArithmeticUtils.gcd(-a, -b));
121 
122         Assertions.assertEquals(1, ArithmeticUtils.gcd(a, c));
123         Assertions.assertEquals(1, ArithmeticUtils.gcd(-a, c));
124         Assertions.assertEquals(1, ArithmeticUtils.gcd(a, -c));
125         Assertions.assertEquals(1, ArithmeticUtils.gcd(-a, -c));
126 
127         Assertions.assertEquals(3L * (1L << 45), ArithmeticUtils.gcd(3L * (1L << 50), 9L * (1L << 45)));
128 
129         Assertions.assertEquals(1L << 45, ArithmeticUtils.gcd(1L << 45, Long.MIN_VALUE));
130 
131         Assertions.assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(Long.MAX_VALUE, 0L));
132         Assertions.assertEquals(Long.MAX_VALUE, ArithmeticUtils.gcd(-Long.MAX_VALUE, 0L));
133         Assertions.assertEquals(1, ArithmeticUtils.gcd(60247241209L, 153092023L));
134         try {
135             // gcd(Long.MIN_VALUE, 0) > Long.MAX_VALUE
136             ArithmeticUtils.gcd(Long.MIN_VALUE, 0);
137             Assertions.fail("expecting ArithmeticException");
138         } catch (ArithmeticException expected) {
139             // expected
140         }
141         try {
142             // gcd(0, Long.MIN_VALUE) > Long.MAX_VALUE
143             ArithmeticUtils.gcd(0, Long.MIN_VALUE);
144             Assertions.fail("expecting ArithmeticException");
145         } catch (ArithmeticException expected) {
146             // expected
147         }
148         try {
149             // gcd(Long.MIN_VALUE, Long.MIN_VALUE) > Long.MAX_VALUE
150             ArithmeticUtils.gcd(Long.MIN_VALUE, Long.MIN_VALUE);
151             Assertions.fail("expecting ArithmeticException");
152         } catch (ArithmeticException expected) {
153             // expected
154         }
155     }
156 
157     @Test
158     void testLcm() {
159         int a = 30;
160         int b = 50;
161         int c = 77;
162 
163         Assertions.assertEquals(0, ArithmeticUtils.lcm(0, b));
164         Assertions.assertEquals(0, ArithmeticUtils.lcm(a, 0));
165         Assertions.assertEquals(b, ArithmeticUtils.lcm(1, b));
166         Assertions.assertEquals(a, ArithmeticUtils.lcm(a, 1));
167         Assertions.assertEquals(150, ArithmeticUtils.lcm(a, b));
168         Assertions.assertEquals(150, ArithmeticUtils.lcm(-a, b));
169         Assertions.assertEquals(150, ArithmeticUtils.lcm(a, -b));
170         Assertions.assertEquals(150, ArithmeticUtils.lcm(-a, -b));
171         Assertions.assertEquals(2310, ArithmeticUtils.lcm(a, c));
172 
173         // Assert that no intermediate value overflows:
174         // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b)
175         Assertions.assertEquals((1 << 20) * 15, ArithmeticUtils.lcm((1 << 20) * 3, (1 << 20) * 5));
176 
177         // Special case
178         Assertions.assertEquals(0, ArithmeticUtils.lcm(0, 0));
179 
180         try {
181             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
182             ArithmeticUtils.lcm(Integer.MIN_VALUE, 1);
183             Assertions.fail("Expecting ArithmeticException");
184         } catch (ArithmeticException expected) {
185             // expected
186         }
187 
188         try {
189             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
190             ArithmeticUtils.lcm(Integer.MIN_VALUE, 1 << 20);
191             Assertions.fail("Expecting ArithmeticException");
192         } catch (ArithmeticException expected) {
193             // expected
194         }
195 
196         try {
197             ArithmeticUtils.lcm(Integer.MAX_VALUE, Integer.MAX_VALUE - 1);
198             Assertions.fail("Expecting ArithmeticException");
199         } catch (ArithmeticException expected) {
200             // expected
201         }
202     }
203 
204     @Test
205     void testLcmLong() {
206         long a = 30;
207         long b = 50;
208         long c = 77;
209 
210         Assertions.assertEquals(0, ArithmeticUtils.lcm(0, b));
211         Assertions.assertEquals(0, ArithmeticUtils.lcm(a, 0));
212         Assertions.assertEquals(b, ArithmeticUtils.lcm(1, b));
213         Assertions.assertEquals(a, ArithmeticUtils.lcm(a, 1));
214         Assertions.assertEquals(150, ArithmeticUtils.lcm(a, b));
215         Assertions.assertEquals(150, ArithmeticUtils.lcm(-a, b));
216         Assertions.assertEquals(150, ArithmeticUtils.lcm(a, -b));
217         Assertions.assertEquals(150, ArithmeticUtils.lcm(-a, -b));
218         Assertions.assertEquals(2310, ArithmeticUtils.lcm(a, c));
219 
220         Assertions.assertEquals(Long.MAX_VALUE, ArithmeticUtils.lcm(60247241209L, 153092023L));
221 
222         // Assert that no intermediate value overflows:
223         // The naive implementation of lcm(a,b) would be (a*b)/gcd(a,b)
224         Assertions.assertEquals((1L << 50) * 15, ArithmeticUtils.lcm((1L << 45) * 3, (1L << 50) * 5));
225 
226         // Special case
227         Assertions.assertEquals(0L, ArithmeticUtils.lcm(0L, 0L));
228 
229         try {
230             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
231             ArithmeticUtils.lcm(Long.MIN_VALUE, 1);
232             Assertions.fail("Expecting ArithmeticException");
233         } catch (ArithmeticException expected) {
234             // expected
235         }
236 
237         try {
238             // lcm == abs(MIN_VALUE) cannot be represented as a nonnegative int
239             ArithmeticUtils.lcm(Long.MIN_VALUE, 1 << 20);
240             Assertions.fail("Expecting ArithmeticException");
241         } catch (ArithmeticException expected) {
242             // expected
243         }
244 
245         Assertions.assertEquals((long) Integer.MAX_VALUE * (Integer.MAX_VALUE - 1),
246             ArithmeticUtils.lcm((long)Integer.MAX_VALUE, Integer.MAX_VALUE - 1));
247         try {
248             ArithmeticUtils.lcm(Long.MAX_VALUE, Long.MAX_VALUE - 1);
249             Assertions.fail("Expecting ArithmeticException");
250         } catch (ArithmeticException expected) {
251             // expected
252         }
253     }
254 
255     @Test
256     void testPow() {
257 
258         Assertions.assertEquals(1801088541, ArithmeticUtils.pow(21, 7));
259         Assertions.assertEquals(1, ArithmeticUtils.pow(21, 0));
260         try {
261             ArithmeticUtils.pow(21, -7);
262             Assertions.fail("Expecting IllegalArgumentException");
263         } catch (IllegalArgumentException e) {
264             // expected behavior
265         }
266 
267         Assertions.assertEquals(1801088541, ArithmeticUtils.pow(21, 7));
268         Assertions.assertEquals(1, ArithmeticUtils.pow(21, 0));
269         try {
270             ArithmeticUtils.pow(21, -7);
271             Assertions.fail("Expecting IllegalArgumentException");
272         } catch (IllegalArgumentException e) {
273             // expected behavior
274         }
275 
276         Assertions.assertEquals(1801088541L, ArithmeticUtils.pow(21L, 7));
277         Assertions.assertEquals(1L, ArithmeticUtils.pow(21L, 0));
278         try {
279             ArithmeticUtils.pow(21L, -7);
280             Assertions.fail("Expecting IllegalArgumentException");
281         } catch (IllegalArgumentException e) {
282             // expected behavior
283         }
284 
285         BigInteger twentyOne = BigInteger.valueOf(21L);
286         Assertions.assertEquals(BigInteger.valueOf(1801088541L), ArithmeticUtils.pow(twentyOne, 7));
287         Assertions.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0));
288         try {
289             ArithmeticUtils.pow(twentyOne, -7);
290             Assertions.fail("Expecting IllegalArgumentException");
291         } catch (IllegalArgumentException e) {
292             // expected behavior
293         }
294 
295         Assertions.assertEquals(BigInteger.valueOf(1801088541L), ArithmeticUtils.pow(twentyOne, 7L));
296         Assertions.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, 0L));
297         try {
298             ArithmeticUtils.pow(twentyOne, -7L);
299             Assertions.fail("Expecting IllegalArgumentException");
300         } catch (IllegalArgumentException e) {
301             // expected behavior
302         }
303 
304         Assertions.assertEquals(BigInteger.valueOf(1801088541L), ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(7L)));
305         Assertions.assertEquals(BigInteger.ONE, ArithmeticUtils.pow(twentyOne, BigInteger.ZERO));
306         Assertions.assertThrows(IllegalArgumentException.class, () ->
307             ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(-7L)));
308 
309         BigInteger bigOne =
310             new BigInteger("1543786922199448028351389769265814882661837148" +
311                            "4763915343722775611762713982220306372888519211" +
312                            "560905579993523402015636025177602059044911261");
313         Assertions.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103));
314         Assertions.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, 103L));
315         Assertions.assertEquals(bigOne, ArithmeticUtils.pow(twentyOne, BigInteger.valueOf(103L)));
316 
317     }
318 
319     @Test
320     void testPowIntOverflow() {
321         Assertions.assertThrows(ArithmeticException.class,
322             () -> ArithmeticUtils.pow(21, 8)
323         );
324     }
325 
326     @Test
327     void testPowInt() {
328         final int base = 21;
329 
330         Assertions.assertEquals(85766121L,
331                             ArithmeticUtils.pow(base, 6));
332         Assertions.assertEquals(1801088541L,
333                             ArithmeticUtils.pow(base, 7));
334     }
335 
336     @Test
337     void testPowNegativeIntOverflow() {
338         Assertions.assertThrows(ArithmeticException.class,
339             () -> ArithmeticUtils.pow(-21, 8)
340         );
341     }
342 
343     @Test
344     void testPowNegativeInt() {
345         final int base = -21;
346 
347         Assertions.assertEquals(85766121,
348                             ArithmeticUtils.pow(base, 6));
349         Assertions.assertEquals(-1801088541,
350                             ArithmeticUtils.pow(base, 7));
351     }
352 
353     @Test
354     void testPowMinusOneInt() {
355         final int base = -1;
356         for (int i = 0; i < 100; i++) {
357             final int pow = ArithmeticUtils.pow(base, i);
358             Assertions.assertEquals(i % 2 == 0 ? 1 : -1, pow, "i: " + i);
359         }
360     }
361 
362     @Test
363     void testPowOneInt() {
364         final int base = 1;
365         for (int i = 0; i < 100; i++) {
366             final int pow = ArithmeticUtils.pow(base, i);
367             Assertions.assertEquals(1, pow, "i: " + i);
368         }
369     }
370 
371     @Test
372     void testPowLongOverflow() {
373         Assertions.assertThrows(ArithmeticException.class,
374             () -> ArithmeticUtils.pow(21, 15)
375         );
376     }
377 
378     @Test
379     void testPowLong() {
380         final long base = 21;
381 
382         Assertions.assertEquals(154472377739119461L,
383                             ArithmeticUtils.pow(base, 13));
384         Assertions.assertEquals(3243919932521508681L,
385                             ArithmeticUtils.pow(base, 14));
386     }
387 
388     @Test
389     void testPowNegativeLongOverflow() {
390         Assertions.assertThrows(ArithmeticException.class,
391             () -> ArithmeticUtils.pow(-21L, 15)
392         );
393     }
394 
395     @Test
396     void testPowNegativeLong() {
397         final long base = -21;
398 
399         Assertions.assertEquals(-154472377739119461L,
400                             ArithmeticUtils.pow(base, 13));
401         Assertions.assertEquals(3243919932521508681L,
402                             ArithmeticUtils.pow(base, 14));
403     }
404 
405     @Test
406     void testPowMinusOneLong() {
407         final long base = -1;
408         for (int i = 0; i < 100; i++) {
409             final long pow = ArithmeticUtils.pow(base, i);
410             Assertions.assertEquals(i % 2 == 0 ? 1 : -1, pow, "i: " + i);
411         }
412     }
413 
414     @Test
415     void testPowOneLong() {
416         final long base = 1;
417         for (int i = 0; i < 100; i++) {
418             final long pow = ArithmeticUtils.pow(base, i);
419             Assertions.assertEquals(1, pow, "i: " + i);
420         }
421     }
422 
423     @Test
424     void testPowEdgeCases() {
425         Assertions.assertEquals(0, ArithmeticUtils.pow(0, 2));
426         Assertions.assertEquals(0L, ArithmeticUtils.pow(0L, 2));
427         Assertions.assertEquals(0, ArithmeticUtils.pow(0, 1));
428         Assertions.assertEquals(0L, ArithmeticUtils.pow(0L, 1));
429         Assertions.assertEquals(1, ArithmeticUtils.pow(0, 0));
430         Assertions.assertEquals(1L, ArithmeticUtils.pow(0L, 0));
431 
432         for (int i = 20; i <= 35; i++) {
433             final int ti = i;
434             Assertions.assertThrows(ArithmeticException.class, () -> ArithmeticUtils.pow(3, ti));
435         }
436         for (int i = 40; i <= 70; i++) {
437             final int ti = i;
438             Assertions.assertThrows(ArithmeticException.class, () -> ArithmeticUtils.pow(3L, ti));
439         }
440     }
441 
442     @Test
443     void testIsPowerOfTwo() {
444         Assertions.assertFalse(ArithmeticUtils.isPowerOfTwo(-1));
445         Assertions.assertFalse(ArithmeticUtils.isPowerOfTwo(Integer.MIN_VALUE));
446 
447         // Small numbers in [0, 1024]
448         final int n = 1025;
449         final boolean[] expected = new boolean[n];
450         Arrays.fill(expected, false);
451         for (int i = 1; i < expected.length; i *= 2) {
452             expected[i] = true;
453         }
454         for (int i = 0; i < expected.length; i++) {
455             final int value = i;
456             final boolean actual = ArithmeticUtils.isPowerOfTwo(value);
457             Assertions.assertEquals(expected[i], actual, () -> Integer.toString(value));
458         }
459 
460         // All powers up to 2^62
461         for (int i = 0; i <= 62; i++) {
462             final long value = 1L << i;
463             Assertions.assertTrue(ArithmeticUtils.isPowerOfTwo(value), () -> Long.toString(value));
464             if (value >= 4) {
465                 Assertions.assertFalse(ArithmeticUtils.isPowerOfTwo(value + 1), () -> Long.toString(value + 1));
466                 Assertions.assertFalse(ArithmeticUtils.isPowerOfTwo(value - 1), () -> Long.toString(value - 1));
467             }
468         }
469     }
470 
471     /**
472      * Testing helper method.
473      * @return an array of int numbers containing corner cases:<ul>
474      * <li>values near the beginning of int range,</li>
475      * <li>values near the end of int range,</li>
476      * <li>values near zero</li>
477      * <li>and some randomly distributed values.</li>
478      * </ul>
479      */
480     private static int[] getIntSpecialCases() {
481         int[] ints = new int[100];
482         int i = 0;
483         ints[i++] = Integer.MAX_VALUE;
484         ints[i++] = Integer.MAX_VALUE - 1;
485         ints[i++] = 100;
486         ints[i++] = 101;
487         ints[i++] = 102;
488         ints[i++] = 300;
489         ints[i++] = 567;
490         for (int j = 0; j < 20; j++) {
491             ints[i++] = j;
492         }
493         for (int j = i - 1; j >= 0; j--) {
494             ints[i++] = ints[j] > 0 ? -ints[j] : Integer.MIN_VALUE;
495         }
496         java.util.Random r = new java.util.Random(System.nanoTime());
497         for (; i < ints.length;) {
498             ints[i++] = r.nextInt();
499         }
500         return ints;
501     }
502 
503     /**
504      * Testing helper method.
505      * @return an array of long numbers containing corner cases:<ul>
506      * <li>values near the beginning of long range,</li>
507      * <li>values near the end of long range,</li>
508      * <li>values near the beginning of int range,</li>
509      * <li>values near the end of int range,</li>
510      * <li>values near zero</li>
511      * <li>and some randomly distributed values.</li>
512      * </ul>
513      */
514     private static long[] getLongSpecialCases() {
515         long[] longs = new long[100];
516         int i = 0;
517         longs[i++] = Long.MAX_VALUE;
518         longs[i++] = Long.MAX_VALUE - 1L;
519         longs[i++] = (long) Integer.MAX_VALUE + 1L;
520         longs[i++] = Integer.MAX_VALUE;
521         longs[i++] = Integer.MAX_VALUE - 1;
522         longs[i++] = 100L;
523         longs[i++] = 101L;
524         longs[i++] = 102L;
525         longs[i++] = 300L;
526         longs[i++] = 567L;
527         for (int j = 0; j < 20; j++) {
528             longs[i++] = j;
529         }
530         for (int j = i - 1; j >= 0; j--) {
531             longs[i++] = longs[j] > 0L ? -longs[j] : Long.MIN_VALUE;
532         }
533         java.util.Random r = new java.util.Random(System.nanoTime());
534         for (; i < longs.length;) {
535             longs[i++] = r.nextLong();
536         }
537         return longs;
538     }
539 
540     private static long toUnsignedLong(int number) {
541         return number < 0 ? 0x100000000L + (long)number : (long)number;
542     }
543 
544     private static int remainderUnsignedExpected(int dividend, int divisor) {
545         return (int)remainderUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor));
546     }
547 
548     private static int divideUnsignedExpected(int dividend, int divisor) {
549         return (int)divideUnsignedExpected(toUnsignedLong(dividend), toUnsignedLong(divisor));
550     }
551 
552     private static BigInteger toUnsignedBigInteger(long number) {
553         return number < 0L ? BigInteger.ONE.shiftLeft(64).add(BigInteger.valueOf(number)) : BigInteger.valueOf(number);
554     }
555 
556     private static long remainderUnsignedExpected(long dividend, long divisor) {
557         return toUnsignedBigInteger(dividend).remainder(toUnsignedBigInteger(divisor)).longValue();
558     }
559 
560     private static long divideUnsignedExpected(long dividend, long divisor) {
561         return toUnsignedBigInteger(dividend).divide(toUnsignedBigInteger(divisor)).longValue();
562     }
563 
564     @Test
565     void testRemainderUnsignedInt() {
566         Assertions.assertEquals(36, ArithmeticUtils.remainderUnsigned(-2147479015, 63));
567         Assertions.assertEquals(6, ArithmeticUtils.remainderUnsigned(-2147479015, 25));
568     }
569 
570     @Test
571     void testRemainderUnsignedIntSpecialCases() {
572         int[] ints = getIntSpecialCases();
573         for (int dividend : ints) {
574             for (int divisor : ints) {
575                 if (divisor == 0) {
576                     Assertions.assertThrows(ArithmeticException.class,
577                         () -> ArithmeticUtils.remainderUnsigned(dividend, divisor)
578                     );
579                 } else {
580                     Assertions.assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor));
581                 }
582             }
583         }
584     }
585 
586     @Test
587     void testRemainderUnsignedLong() {
588         Assertions.assertEquals(48L, ArithmeticUtils.remainderUnsigned(-2147479015L, 63L));
589     }
590 
591     @Test
592     void testRemainderUnsignedLongSpecialCases() {
593         long[] longs = getLongSpecialCases();
594         for (long dividend : longs) {
595             for (long divisor : longs) {
596                 if (divisor == 0L) {
597                     try {
598                         ArithmeticUtils.remainderUnsigned(dividend, divisor);
599                         Assertions.fail("Should have failed with ArithmeticException: division by zero");
600                     } catch (ArithmeticException e) {
601                         // Success.
602                     }
603                 } else {
604                     Assertions.assertEquals(remainderUnsignedExpected(dividend, divisor), ArithmeticUtils.remainderUnsigned(dividend, divisor));
605                 }
606             }
607         }
608     }
609 
610     @Test
611     void testDivideUnsignedInt() {
612         Assertions.assertEquals(34087115, ArithmeticUtils.divideUnsigned(-2147479015, 63));
613         Assertions.assertEquals(85899531, ArithmeticUtils.divideUnsigned(-2147479015, 25));
614         Assertions.assertEquals(2147483646, ArithmeticUtils.divideUnsigned(-3, 2));
615         Assertions.assertEquals(330382098, ArithmeticUtils.divideUnsigned(-16, 13));
616         Assertions.assertEquals(306783377, ArithmeticUtils.divideUnsigned(-16, 14));
617         Assertions.assertEquals(2, ArithmeticUtils.divideUnsigned(-1, 2147483647));
618         Assertions.assertEquals(2, ArithmeticUtils.divideUnsigned(-2, 2147483647));
619         Assertions.assertEquals(1, ArithmeticUtils.divideUnsigned(-3, 2147483647));
620         Assertions.assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483647));
621         Assertions.assertEquals(1, ArithmeticUtils.divideUnsigned(-16, 2147483646));
622     }
623 
624     @Test
625     void testDivideUnsignedIntSpecialCases() {
626         int[] ints = getIntSpecialCases();
627         for (int dividend : ints) {
628             for (int divisor : ints) {
629                 if (divisor == 0) {
630                     Assertions.assertThrows(ArithmeticException.class,
631                         () -> ArithmeticUtils.divideUnsigned(dividend, divisor)
632                     );
633                 } else {
634                     Assertions.assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor));
635                 }
636             }
637         }
638     }
639 
640     @Test
641     void testDivideUnsignedLong() {
642         Assertions.assertEquals(292805461453366231L, ArithmeticUtils.divideUnsigned(-2147479015L, 63L));
643     }
644 
645     @Test
646     void testDivideUnsignedLongSpecialCases() {
647         long[] longs = getLongSpecialCases();
648         for (long dividend : longs) {
649             for (long divisor : longs) {
650                 if (divisor == 0L) {
651                     Assertions.assertThrows(ArithmeticException.class,
652                         () -> ArithmeticUtils.divideUnsigned(dividend, divisor)
653                     );
654                 } else {
655                     Assertions.assertEquals(divideUnsignedExpected(dividend, divisor), ArithmeticUtils.divideUnsigned(dividend, divisor));
656                 }
657             }
658         }
659     }
660 }