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.fraction;
18  
19  import java.math.BigDecimal;
20  import java.math.BigInteger;
21  import java.math.RoundingMode;
22  import java.util.Arrays;
23  import org.apache.commons.numbers.core.TestUtils;
24  
25  import org.junit.jupiter.api.Assertions;
26  import org.junit.jupiter.api.Test;
27  
28  /**
29   * Tests for {@link BigFraction}.
30   */
31  class BigFractionTest {
32  
33      /** The zero representation with positive denominator. */
34      private static final BigFraction ZERO_P = BigFraction.of(0, 1);
35      /** The zero representation with negative denominator. */
36      private static final BigFraction ZERO_N = BigFraction.of(0, -1);
37  
38      private static void assertFraction(int expectedNumerator, int expectedDenominator, BigFraction actual) {
39          Assertions.assertEquals(expectedNumerator, actual.getNumeratorAsInt());
40          Assertions.assertEquals(expectedDenominator, actual.getDenominatorAsInt());
41          Assertions.assertEquals(
42              Integer.signum(expectedNumerator) * Integer.signum(expectedDenominator),
43              actual.signum());
44      }
45  
46      private static void assertFraction(long expectedNumerator, long expectedDenominator, BigFraction actual) {
47          Assertions.assertEquals(expectedNumerator, actual.getNumeratorAsLong());
48          Assertions.assertEquals(expectedDenominator, actual.getDenominatorAsLong());
49          Assertions.assertEquals(
50              Long.signum(expectedNumerator) * Long.signum(expectedDenominator),
51              actual.signum());
52      }
53  
54      private static void assertFraction(BigInteger expectedNumerator, BigInteger expectedDenominator, BigFraction actual) {
55          Assertions.assertEquals(expectedNumerator, actual.getNumerator());
56          Assertions.assertEquals(expectedDenominator, actual.getDenominator());
57          Assertions.assertEquals(
58              expectedNumerator.signum() * expectedDenominator.signum(),
59              actual.signum());
60      }
61  
62      private static void assertDoubleValue(double expected, BigInteger numerator, BigInteger denominator) {
63          final BigFraction f = BigFraction.of(numerator, denominator);
64          Assertions.assertEquals(expected, f.doubleValue());
65      }
66  
67      private static void assertDoubleValue(double expected, long numerator, long denominator) {
68          assertDoubleValue(expected, BigInteger.valueOf(numerator), BigInteger.valueOf(denominator));
69      }
70  
71      @Test
72      void testConstructor() {
73          for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.numDenConstructorTestCases()) {
74              assertFraction(
75                      testCase.expectedNumerator,
76                      testCase.expectedDenominator,
77                      BigFraction.of(testCase.operandNumerator, testCase.operandDenominator)
78              );
79          }
80  
81          // Long/BigInteger arguments
82          assertFraction(0, 1, BigFraction.of(0L, 2L));
83          assertFraction(1L, 1, BigFraction.of(1L));
84          assertFraction(11, 1, BigFraction.of(11L));
85          assertFraction(11, 1, BigFraction.of(new BigInteger("11")));
86  
87          // Divide by zero
88          Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.of(BigInteger.ONE, BigInteger.ZERO));
89  
90          // Null pointers
91          Assertions.assertThrows(NullPointerException.class, () -> BigFraction.of(null, BigInteger.ONE));
92          Assertions.assertThrows(NullPointerException.class, () -> BigFraction.of(BigInteger.ONE, null));
93          Assertions.assertThrows(NullPointerException.class, () -> BigFraction.of(null));
94  
95          Assertions.assertThrows(ArithmeticException.class,
96              () -> BigFraction.from(2.0 * Integer.MAX_VALUE, 1.0e-5, 100000));
97      }
98  
99      @Test
100     void testConstructorZero() {
101         Assertions.assertSame(BigFraction.ZERO, BigFraction.from(0.0));
102         Assertions.assertSame(BigFraction.ZERO, BigFraction.from(0.0, 1e-10, 100));
103         Assertions.assertSame(BigFraction.ZERO, BigFraction.from(0.0, 100));
104         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(0));
105         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(0L));
106         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(BigInteger.ZERO));
107         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(0, 1));
108         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(0, -1));
109         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(0L, 1L));
110         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(0L, -1L));
111         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(BigInteger.ZERO, BigInteger.ONE));
112         Assertions.assertSame(BigFraction.ZERO, BigFraction.of(BigInteger.ZERO, BigInteger.ONE.negate()));
113     }
114 
115     // MATH-179
116     @Test
117     void testDoubleConstructor() {
118         for (final CommonTestCases.DoubleToFractionTestCase testCase : CommonTestCases.doubleConstructorTestCases()) {
119             assertFraction(
120                     testCase.expectedNumerator,
121                     testCase.expectedDenominator,
122                     BigFraction.from(testCase.operand, 1.0e-5, 100)
123             );
124         }
125 
126         // Cases with different exact results from Fraction
127         assertFraction(6004799503160661L, 18014398509481984L, BigFraction.from(1.0 / 3.0));
128         assertFraction(6124895493223875L, 36028797018963968L, BigFraction.from(17.0 / 100.0));
129         assertFraction(1784551352345559L, 562949953421312L, BigFraction.from(317.0 / 100.0));
130         assertFraction(-6004799503160661L, 18014398509481984L, BigFraction.from(-1.0 / 3.0));
131         assertFraction(-6124895493223875L, 36028797018963968L, BigFraction.from(17.0 / -100.0));
132         assertFraction(-1784551352345559L, 562949953421312L, BigFraction.from(-317.0 / 100.0));
133 
134         // Extreme double values
135         Assertions.assertEquals(1L, BigFraction.from(Double.MAX_VALUE).getDenominatorAsLong());
136         Assertions.assertEquals(1L, BigFraction.from(Double.longBitsToDouble(0x0010000000000000L)).getNumeratorAsLong());
137         assertFraction(BigInteger.ONE, BigInteger.ONE.shiftLeft(1074), BigFraction.from(Double.MIN_VALUE));
138 
139         // Check exact round-trip of double
140         Assertions.assertEquals(0.00000000000001, BigFraction.from(0.00000000000001).doubleValue());
141         Assertions.assertEquals(0.40000000000001, BigFraction.from(0.40000000000001).doubleValue());
142         Assertions.assertEquals(15.0000000000001, BigFraction.from(15.0000000000001).doubleValue());
143         // Check the representation
144         assertFraction(3602879701896487L, 9007199254740992L, BigFraction.from(0.40000000000001));
145         assertFraction(1055531162664967L, 70368744177664L, BigFraction.from(15.0000000000001));
146     }
147 
148     // MATH-181
149     // NUMBERS-147
150     @Test
151     void testDoubleConstructorWithMaxDenominator() {
152         for (final CommonTestCases.DoubleToFractionTestCase testCase : CommonTestCases.doubleMaxDenomConstructorTestCases()) {
153             assertFraction(
154                     testCase.expectedNumerator,
155                     testCase.expectedDenominator,
156                     BigFraction.from(testCase.operand, testCase.maxDenominator)
157             );
158         }
159 
160         // Cases with different exact results from Fraction
161         final long pow31 = 1L << 31;
162         assertFraction(pow31, 1, BigFraction.from(Integer.MIN_VALUE * -1.0, 2));
163         assertFraction(pow31, 3, BigFraction.from(Integer.MIN_VALUE / -3.0, 10));
164         assertFraction(-1, pow31, BigFraction.from(1.0 / Integer.MIN_VALUE, Integer.MIN_VALUE));
165         assertFraction(1, pow31, BigFraction.from(-1.0 / Integer.MIN_VALUE, Integer.MIN_VALUE));
166 
167         Assertions.assertThrows(IllegalArgumentException.class, () -> BigFraction.from(1.0, 0));
168     }
169 
170     @Test
171     void testDoubleConstructorThrows() {
172         final double eps = 1e-5;
173         final int maxIterations = Integer.MAX_VALUE;
174         final int maxDenominator = Integer.MAX_VALUE;
175         for (final double value : new double[] {Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}) {
176             Assertions.assertThrows(IllegalArgumentException.class, () -> BigFraction.from(value));
177             Assertions.assertThrows(IllegalArgumentException.class, () -> BigFraction.from(value, eps, maxIterations));
178             Assertions.assertThrows(IllegalArgumentException.class, () -> BigFraction.from(value, maxDenominator));
179         }
180         Assertions.assertThrows(IllegalArgumentException.class, () -> BigFraction.from(1.0, Double.NaN, maxIterations));
181         Assertions.assertThrows(IllegalArgumentException.class, () -> BigFraction.from(1.0, -1.0, maxIterations));
182         Assertions.assertThrows(IllegalArgumentException.class, () -> BigFraction.from(1.0, eps, 0));
183         // Test a zero epsilon is allowed
184         assertFraction(1, 1, BigFraction.from(1.0, 0, maxIterations));
185     }
186 
187     @Test
188     void testDoubleConstructorGoldenRatioThrows() {
189         // the golden ratio is notoriously a difficult number for continuous fraction
190         Assertions.assertThrows(FractionException.class,
191             () -> BigFraction.from((1 + Math.sqrt(5)) / 2, 1.0e-12, 25)
192         );
193     }
194 
195     // MATH-1029
196     @Test
197     void testDoubleConstructorWithMaxDenominatorOverFlow() {
198         Assertions.assertThrows(ArithmeticException.class,
199             () -> BigFraction.from(1e10, 1000)
200         );
201         Assertions.assertThrows(ArithmeticException.class,
202             () -> BigFraction.from(-1e10, 1000)
203         );
204     }
205 
206     @Test
207     void testDoubleConstructorOverflow() {
208         assertDoubleConstructorOverflow(0.75000000001455192);
209         assertDoubleConstructorOverflow(1.0e10);
210         assertDoubleConstructorOverflow(-1.0e10);
211         assertDoubleConstructorOverflow(-43979.60679604749);
212     }
213 
214     private void assertDoubleConstructorOverflow(final double a) {
215         Assertions.assertThrows(ArithmeticException.class,
216             () -> BigFraction.from(a, 1.0e-12, 1000)
217         );
218     }
219 
220     @Test
221     void testDoubleConstructorWithEpsilonLimit() {
222         assertFraction(2, 5, BigFraction.from(0.4, 1.0e-5, 100));
223 
224         assertFraction(3, 5,      BigFraction.from(0.6152, 0.02, 100));
225         assertFraction(8, 13,     BigFraction.from(0.6152, 1.0e-3, 100));
226         assertFraction(251, 408,  BigFraction.from(0.6152, 1.0e-4, 100));
227         assertFraction(251, 408,  BigFraction.from(0.6152, 1.0e-5, 100));
228         assertFraction(510, 829,  BigFraction.from(0.6152, 1.0e-6, 100));
229         assertFraction(769, 1250, BigFraction.from(0.6152, 1.0e-7, 100));
230     }
231 
232     @Test
233     void testCompareTo() {
234         final BigFraction a = BigFraction.of(1, 2);
235         final BigFraction b = BigFraction.of(1, 3);
236         final BigFraction c = BigFraction.of(1, 2);
237         final BigFraction d = BigFraction.of(-1, 2);
238         final BigFraction e = BigFraction.of(1, -2);
239         final BigFraction f = BigFraction.of(-1, -2);
240         final BigFraction g = BigFraction.of(-1, Integer.MIN_VALUE);
241 
242         Assertions.assertEquals(0, a.compareTo(a));
243         Assertions.assertEquals(0, a.compareTo(c));
244         Assertions.assertEquals(1, a.compareTo(b));
245         Assertions.assertEquals(-1, b.compareTo(a));
246         Assertions.assertEquals(-1, d.compareTo(a));
247         Assertions.assertEquals(1, a.compareTo(d));
248         Assertions.assertEquals(-1, e.compareTo(a));
249         Assertions.assertEquals(1, a.compareTo(e));
250         Assertions.assertEquals(0, d.compareTo(e));
251         Assertions.assertEquals(0, a.compareTo(f));
252         Assertions.assertEquals(0, f.compareTo(a));
253         Assertions.assertEquals(1, f.compareTo(e));
254         Assertions.assertEquals(-1, e.compareTo(f));
255         Assertions.assertEquals(-1, g.compareTo(a));
256         Assertions.assertEquals(-1, g.compareTo(f));
257         Assertions.assertEquals(1, a.compareTo(g));
258         Assertions.assertEquals(-1, d.compareTo(g));
259 
260         Assertions.assertEquals(0, BigFraction.of(0, 3).compareTo(BigFraction.of(0, -2)));
261 
262         // these two values are different approximations of PI
263         // the first  one is approximately PI - 3.07e-18
264         // the second one is approximately PI + 1.936e-17
265         final BigFraction pi1 = BigFraction.of(1068966896, 340262731);
266         final BigFraction pi2 = BigFraction.of(411557987, 131002976);
267         Assertions.assertEquals(-1, pi1.compareTo(pi2));
268         Assertions.assertEquals(1, pi2.compareTo(pi1));
269         Assertions.assertEquals(0.0, pi1.doubleValue() - pi2.doubleValue(), 1.0e-20);
270 
271         Assertions.assertEquals(0, ZERO_P.compareTo(ZERO_N));
272     }
273 
274     @Test
275     void testDoubleValue() {
276         assertDoubleValue(0.5, 1, 2);
277         assertDoubleValue(-0.5, -1, 2);
278         assertDoubleValue(-0.5, 1, -2);
279         assertDoubleValue(0.5, -1, -2);
280         assertDoubleValue(1.0 / 3.0, 1, 3);
281 
282         Assertions.assertEquals(0.0, BigFraction.ZERO.doubleValue());
283         Assertions.assertEquals(0.0, ZERO_P.doubleValue());
284         Assertions.assertEquals(0.0, ZERO_N.doubleValue());
285 
286         // NUMBERS-120
287         assertDoubleValue(
288                 2d - 0x1P-52,
289                 1L << 54,
290                 (1L << 53) + 1L
291         );
292 
293         assertDoubleValue(
294                 2d,
295                 (1L << 54) - 1L,
296                 1L << 53
297         );
298         assertDoubleValue(
299                 1d,
300                 (1L << 53) + 1L,
301                 1L << 53
302         );
303     }
304 
305     @Test
306     void testDoubleValueForSubnormalNumbers() {
307         assertDoubleValue(
308                 //Double.MIN_VALUE * 2/3
309                 Double.MIN_VALUE,
310                 BigInteger.ONE,
311                 BigInteger.ONE.shiftLeft(1073).multiply(BigInteger.valueOf(3L))
312         );
313 
314         assertDoubleValue(
315                 Double.MIN_VALUE,
316                 BigInteger.ONE,
317                 BigInteger.ONE.shiftLeft(1074)
318         );
319         assertDoubleValue(
320                 Double.MIN_VALUE * 2,
321                 BigInteger.valueOf(2),
322                 BigInteger.ONE.shiftLeft(1074)
323         );
324         assertDoubleValue(
325                 Double.MIN_VALUE * 3,
326                 BigInteger.valueOf(3),
327                 BigInteger.ONE.shiftLeft(1074)
328         );
329 
330         assertDoubleValue(
331                 Double.MIN_NORMAL - Double.MIN_VALUE,
332                 BigInteger.ONE.shiftLeft(52).subtract(BigInteger.ONE),
333                 BigInteger.ONE.shiftLeft(1074)
334         );
335         assertDoubleValue(
336                 Double.MIN_NORMAL - 2 * Double.MIN_VALUE,
337                 BigInteger.ONE.shiftLeft(52).subtract(BigInteger.valueOf(2)),
338                 BigInteger.ONE.shiftLeft(1074)
339         );
340 
341         //this number is smaller than Double.MIN_NORMAL, but should round up to it
342         assertDoubleValue(
343                 Double.MIN_NORMAL,
344                 BigInteger.ONE.shiftLeft(53).subtract(BigInteger.ONE),
345                 BigInteger.ONE.shiftLeft(1075)
346         );
347     }
348 
349     @Test
350     void testDoubleValueForInfinities() {
351         //the smallest integer that rounds up to Double.POSITIVE_INFINITY
352         final BigInteger minInf = BigInteger.ONE
353                 .shiftLeft(1024)
354                 .subtract(BigInteger.ONE.shiftLeft(970));
355 
356         assertDoubleValue(
357                 Double.NEGATIVE_INFINITY,
358                 minInf.negate(),
359                 BigInteger.ONE
360         );
361         assertDoubleValue(
362                 Double.POSITIVE_INFINITY,
363                 minInf,
364                 BigInteger.ONE
365         );
366     }
367 
368     // MATH-744
369     @Test
370     void testDoubleValueForLargeNumeratorAndDenominator() {
371         final BigInteger pow400 = BigInteger.TEN.pow(400);
372         final BigInteger pow401 = BigInteger.TEN.pow(401);
373         final BigInteger two = new BigInteger("2");
374         final BigFraction large = BigFraction.of(pow401.add(BigInteger.ONE),
375                                                  pow400.multiply(two));
376 
377         Assertions.assertEquals(5, large.doubleValue(), 1e-15);
378     }
379 
380     // MATH-744
381     @Test
382     void testFloatValueForLargeNumeratorAndDenominator() {
383         final BigInteger pow400 = BigInteger.TEN.pow(400);
384         final BigInteger pow401 = BigInteger.TEN.pow(401);
385         final BigInteger two = new BigInteger("2");
386         final BigFraction large = BigFraction.of(pow401.add(BigInteger.ONE),
387                                                  pow400.multiply(two));
388 
389         Assertions.assertEquals(5, large.floatValue(), 1e-15);
390     }
391 
392     @Test
393     void testDoubleValueForLargeNumeratorAndSmallDenominator() {
394         // NUMBERS-15
395         final BigInteger pow300 = BigInteger.TEN.pow(300);
396         final BigInteger pow330 = BigInteger.TEN.pow(330);
397         final BigFraction large = BigFraction.of(pow330.add(BigInteger.ONE),
398                                                  pow300);
399 
400         Assertions.assertEquals(1e30, large.doubleValue(), 1e-15);
401 
402         // NUMBERS-120
403         assertDoubleValue(
404                 5.992310449541053E307,
405                 BigInteger.ONE
406                         .shiftLeft(1024)
407                         .subtract(BigInteger.ONE.shiftLeft(970))
408                         .add(BigInteger.ONE),
409                 BigInteger.valueOf(3)
410         );
411 
412         assertDoubleValue(
413                 Double.MAX_VALUE,
414                 BigInteger.ONE
415                         .shiftLeft(1025)
416                         .subtract(BigInteger.ONE.shiftLeft(972))
417                         .subtract(BigInteger.ONE),
418                 BigInteger.valueOf(2)
419         );
420     }
421 
422     // NUMBERS-15
423     @Test
424     void testFloatValueForLargeNumeratorAndSmallDenominator() {
425         final BigInteger pow30 = BigInteger.TEN.pow(30);
426         final BigInteger pow40 = BigInteger.TEN.pow(40);
427         final BigFraction large = BigFraction.of(pow40.add(BigInteger.ONE),
428                                                  pow30);
429 
430         Assertions.assertEquals(1e10f, large.floatValue(), 1e-15);
431     }
432 
433     @Test
434     void testFloatValue() {
435         Assertions.assertEquals(0.5f, BigFraction.of(1, 2).floatValue());
436         Assertions.assertEquals(0.5f, BigFraction.of(-1, -2).floatValue());
437         Assertions.assertEquals(-0.5f, BigFraction.of(-1, 2).floatValue());
438         Assertions.assertEquals(-0.5f, BigFraction.of(1, -2).floatValue());
439 
440         final float e = 1f / 3f;
441         Assertions.assertEquals(e, BigFraction.of(1, 3).floatValue());
442         Assertions.assertEquals(e, BigFraction.of(-1, -3).floatValue());
443         Assertions.assertEquals(-e, BigFraction.of(-1, 3).floatValue());
444         Assertions.assertEquals(-e, BigFraction.of(1, -3).floatValue());
445 
446         Assertions.assertEquals(0.0f, ZERO_P.floatValue());
447         Assertions.assertEquals(0.0f, ZERO_N.floatValue());
448     }
449 
450     @Test
451     void testIntValue() {
452         Assertions.assertEquals(0, BigFraction.of(1, 2).intValue());
453         Assertions.assertEquals(0, BigFraction.of(-1, -2).intValue());
454         Assertions.assertEquals(0, BigFraction.of(-1, 2).intValue());
455         Assertions.assertEquals(0, BigFraction.of(1, -2).intValue());
456 
457         Assertions.assertEquals(1, BigFraction.of(3, 2).intValue());
458         Assertions.assertEquals(1, BigFraction.of(-3, -2).intValue());
459         Assertions.assertEquals(-1, BigFraction.of(-3, 2).intValue());
460         Assertions.assertEquals(-1, BigFraction.of(3, -2).intValue());
461 
462         Assertions.assertEquals(0, ZERO_P.intValue());
463         Assertions.assertEquals(0, ZERO_N.intValue());
464     }
465 
466     @Test
467     void testLongValue() {
468         Assertions.assertEquals(0L, BigFraction.of(1, 2).longValue());
469         Assertions.assertEquals(0L, BigFraction.of(-1, -2).longValue());
470         Assertions.assertEquals(0L, BigFraction.of(-1, 2).longValue());
471         Assertions.assertEquals(0L, BigFraction.of(1, -2).longValue());
472 
473         Assertions.assertEquals(1L, BigFraction.of(3, 2).longValue());
474         Assertions.assertEquals(1L, BigFraction.of(-3, -2).longValue());
475         Assertions.assertEquals(-1L, BigFraction.of(-3, 2).longValue());
476         Assertions.assertEquals(-1L, BigFraction.of(3, -2).longValue());
477 
478         Assertions.assertEquals(0, ZERO_P.longValue());
479         Assertions.assertEquals(0, ZERO_N.longValue());
480     }
481 
482     @Test
483     void testBigDecimalValue() {
484         Assertions.assertEquals(new BigDecimal(0.5), BigFraction.of(1, 2).bigDecimalValue());
485         Assertions.assertEquals(new BigDecimal("0.0003"), BigFraction.of(3, 10000).bigDecimalValue());
486         Assertions.assertEquals(new BigDecimal("0"), BigFraction.of(1, 3).bigDecimalValue(RoundingMode.DOWN));
487         Assertions.assertEquals(new BigDecimal("0.333"), BigFraction.of(1, 3).bigDecimalValue(3, RoundingMode.DOWN));
488     }
489 
490     @Test
491     void testAbs() {
492         for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.absTestCases()) {
493             final BigFraction f = BigFraction.of(testCase.operandNumerator, testCase.operandDenominator);
494             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f.abs());
495         }
496     }
497 
498     @Test
499     void testReciprocal() {
500         for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.reciprocalTestCases()) {
501             final BigFraction f = BigFraction.of(testCase.operandNumerator, testCase.operandDenominator);
502             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f.reciprocal());
503         }
504 
505         final BigFraction f = BigFraction.of(0, 3);
506         Assertions.assertThrows(ArithmeticException.class, f::reciprocal);
507     }
508 
509     @Test
510     void testNegate() {
511         for (final CommonTestCases.UnaryOperatorTestCase testCase : CommonTestCases.negateTestCases()) {
512             final BigFraction f = BigFraction.of(testCase.operandNumerator, testCase.operandDenominator);
513             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f.negate());
514         }
515     }
516 
517     @Test
518     void testAdd() {
519         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.addFractionTestCases()) {
520             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
521             final BigFraction f2 = BigFraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
522             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.add(f2));
523         }
524         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.addIntTestCases()) {
525             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
526             final int i2 = testCase.secondOperand;
527             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.add(i2));
528             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.add((long) i2));
529             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.add(BigInteger.valueOf(i2)));
530         }
531 
532         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.add((BigFraction) null));
533         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.add((BigInteger) null));
534 
535         // Special cases
536         final BigFraction f2 = BigFraction.of(1, 2);
537         assertFraction(1, 2, f2.add(BigInteger.ZERO));
538         assertFraction(12, 1, BigFraction.ZERO.add(BigInteger.valueOf(12)));
539     }
540 
541     @Test
542     void testDivide() {
543         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.divideByFractionTestCases()) {
544             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
545             final BigFraction f2 = BigFraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
546             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.divide(f2));
547         }
548         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.divideByIntTestCases()) {
549             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
550             final int i2 = testCase.secondOperand;
551             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.divide(i2));
552             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.divide((long) i2));
553             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.divide(BigInteger.valueOf(i2)));
554         }
555 
556         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.divide((BigFraction) null));
557         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.divide((BigInteger) null));
558 
559         Assertions.assertThrows(FractionException.class, () -> BigFraction.of(1, 2).divide(BigFraction.ZERO));
560         Assertions.assertThrows(FractionException.class, () -> BigFraction.of(1, 2).divide(0));
561         Assertions.assertThrows(FractionException.class, () -> BigFraction.of(1, 2).divide(0L));
562         Assertions.assertThrows(FractionException.class, () -> BigFraction.of(1, 2).divide(BigInteger.ZERO));
563 
564         // Special cases
565         final BigFraction f1 = BigFraction.of(Integer.MIN_VALUE, Integer.MAX_VALUE);
566         assertFraction(-1, -Integer.MAX_VALUE, f1.divide(Integer.MIN_VALUE));
567         assertFraction(-1, -Integer.MAX_VALUE, f1.divide((long) Integer.MIN_VALUE));
568         assertFraction(-1, -Integer.MAX_VALUE, f1.divide(BigInteger.valueOf(Integer.MIN_VALUE)));
569     }
570 
571     @Test
572     void testMultiply() {
573         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.multiplyByFractionTestCases()) {
574             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
575             final BigFraction f2 = BigFraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
576             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.multiply(f2));
577         }
578         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.multiplyByIntTestCases()) {
579             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
580             final int i2 = testCase.secondOperand;
581             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.multiply(i2));
582             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.multiply((long) i2));
583             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.multiply(BigInteger.valueOf(i2)));
584         }
585 
586         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.multiply((BigFraction) null));
587         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.multiply((BigInteger) null));
588     }
589 
590     @Test
591     void testPow() {
592         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.powTestCases()) {
593             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
594             final int exponent = testCase.secondOperand;
595             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.pow(exponent));
596         }
597 
598         // Note: BigInteger magnitude is limited to 2^Integer.MAX_VALUE exclusive
599         // in the reference implementation (up to at least JDK 14).
600         Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.of(2).pow(Integer.MAX_VALUE));
601         Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.of(1, 2).pow(Integer.MAX_VALUE));
602         Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.of(2).pow(-Integer.MAX_VALUE));
603         Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.of(1, 2).pow(-Integer.MAX_VALUE));
604     }
605 
606     @Test
607     void testSubtract() {
608         for (final CommonTestCases.BinaryOperatorTestCase testCase : CommonTestCases.subtractFractionTestCases()) {
609             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
610             final BigFraction f2 = BigFraction.of(testCase.secondOperandNumerator, testCase.secondOperandDenominator);
611             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.subtract(f2));
612         }
613         for (final CommonTestCases.BinaryIntOperatorTestCase testCase : CommonTestCases.subtractIntTestCases()) {
614             final BigFraction f1 = BigFraction.of(testCase.firstOperandNumerator, testCase.firstOperandDenominator);
615             final int i2 = testCase.secondOperand;
616             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.subtract(i2));
617             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.subtract((long) i2));
618             assertFraction(testCase.expectedNumerator, testCase.expectedDenominator, f1.subtract(BigInteger.valueOf(i2)));
619         }
620 
621         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.subtract((BigFraction) null));
622         Assertions.assertThrows(NullPointerException.class, () -> BigFraction.ONE.subtract((BigInteger) null));
623     }
624 
625     @Test
626     void testEqualsAndHashCode() {
627         final BigFraction zero = BigFraction.of(0, 1);
628         Assertions.assertEquals(zero, zero);
629         Assertions.assertNotEquals(zero, null);
630         Assertions.assertNotEquals(zero, new Object());
631         Assertions.assertNotEquals(zero, Double.valueOf(0));
632 
633         // Equal to same rational number
634         final BigFraction zero2 = BigFraction.of(0, 2);
635         assertEqualAndHashCodeEqual(zero, zero2);
636 
637         // Not equal to different rational number
638         final BigFraction one = BigFraction.of(1, 1);
639         Assertions.assertNotEquals(zero, one);
640         Assertions.assertNotEquals(one, zero);
641 
642         // Test using different representations of the same fraction
643         // (Denominators are primes)
644         for (final int[] f : new int[][] {{1, 1}, {2, 3}, {6826, 15373}, {1373, 103813}, {0, 3}}) {
645             final int num = f[0];
646             final int den = f[1];
647             BigFraction f1 = BigFraction.of(-num, den);
648             BigFraction f2 = BigFraction.of(num, -den);
649             assertEqualAndHashCodeEqual(f1, f2);
650             assertEqualAndHashCodeEqual(f2, f1);
651             f1 = BigFraction.of(num, den);
652             f2 = BigFraction.of(-num, -den);
653             assertEqualAndHashCodeEqual(f1, f2);
654             assertEqualAndHashCodeEqual(f2, f1);
655         }
656 
657         // Same numerator or denominator as 1/1
658         final BigFraction half = BigFraction.of(1, 2);
659         final BigFraction two = BigFraction.of(2, 1);
660         Assertions.assertNotEquals(one, half);
661         Assertions.assertNotEquals(one, two);
662     }
663 
664     /**
665      * Assert the two fractions are equal. The contract of {@link Object#hashCode()} requires
666      * that the hash code must also be equal.
667      *
668      * <p>Ideally this method should not be called with the same instance for both arguments.
669      * It is intended to be used to test different objects that are equal have the same hash code.
670      * However the same object may be constructed for different arguments using factory
671      * constructors, e.g. zero.
672      *
673      * @param f1 Fraction 1.
674      * @param f2 Fraction 2.
675      */
676     private static void assertEqualAndHashCodeEqual(BigFraction f1, BigFraction f2) {
677         Assertions.assertEquals(f1, f2);
678         Assertions.assertEquals(f1.hashCode(), f2.hashCode(), "Equal fractions have different hashCode");
679         // Check the computation matches the result of Arrays.hashCode and the signum.
680         // This is not mandated but is a recommendation.
681         final int expected = f1.signum() *
682                              Arrays.hashCode(new Object[] {f1.getNumerator().abs(),
683                                                            f1.getDenominator().abs()});
684         Assertions.assertEquals(expected, f1.hashCode(), "Hashcode not equal to using Arrays.hashCode");
685     }
686 
687     @Test
688     void testAdditiveNeutral() {
689         Assertions.assertEquals(BigFraction.ZERO, BigFraction.ONE.zero());
690     }
691 
692     @Test
693     void testMultiplicativeNeutral() {
694         Assertions.assertEquals(BigFraction.ONE, BigFraction.ZERO.one());
695     }
696 
697     @Test
698     void testSerial() {
699         final BigFraction[] fractions = {
700             BigFraction.of(3, 4), BigFraction.ONE, BigFraction.ZERO,
701             BigFraction.of(17), BigFraction.from(Math.PI, 1000),
702             BigFraction.of(-5, 2)
703         };
704         for (final BigFraction fraction : fractions) {
705             Assertions.assertEquals(fraction,
706                                     TestUtils.serializeAndRecover(fraction));
707         }
708     }
709 
710     @Test
711     void testToString() {
712         Assertions.assertEquals("0", BigFraction.of(0, 3).toString());
713         Assertions.assertEquals("0", BigFraction.of(0, -3).toString());
714         Assertions.assertEquals("3", BigFraction.of(6, 2).toString());
715         Assertions.assertEquals("2 / 3", BigFraction.of(18, 27).toString());
716         Assertions.assertEquals("-10 / 11", BigFraction.of(-10, 11).toString());
717         Assertions.assertEquals("10 / -11", BigFraction.of(10, -11).toString());
718     }
719 
720     @Test
721     void testParse() {
722         final String[] validExpressions = new String[] {
723             "1 / 2",
724             "-1 / 2",
725             "1 / -2",
726             "-1 / -2",
727             "01 / 2",
728             "01 / 02",
729             "-01 / 02",
730             "01 / -02",
731             "15 / 16",
732             "-2 / 3",
733             "8 / 7",
734             "5",
735             "-3",
736             "-3",
737             "2147,483,647 / 2,147,483,648", //over largest int value
738             "9,223,372,036,854,775,807 / 9,223,372,036,854,775,808" //over largest long value
739         };
740         final BigFraction[] fractions = {
741                 BigFraction.of(1, 2),
742                 BigFraction.of(-1, 2),
743                 BigFraction.of(1, -2),
744                 BigFraction.of(-1, -2),
745                 BigFraction.of(1, 2),
746                 BigFraction.of(1, 2),
747                 BigFraction.of(-1, 2),
748                 BigFraction.of(1, -2),
749                 BigFraction.of(15, 16),
750                 BigFraction.of(-2, 3),
751                 BigFraction.of(8, 7),
752                 BigFraction.of(5, 1),
753                 BigFraction.of(-3, 1),
754                 BigFraction.of(3, -1),
755                 BigFraction.of(2147483647, 2147483648L),
756                 BigFraction.of(new BigInteger("9223372036854775807"),
757                                new BigInteger("9223372036854775808"))
758         };
759         int inc = 0;
760         for (final BigFraction fraction: fractions) {
761             Assertions.assertEquals(fraction,
762                                     BigFraction.parse(validExpressions[inc]));
763             inc++;
764         }
765 
766         Assertions.assertThrows(NumberFormatException.class, () -> BigFraction.parse("1 // 2"));
767         Assertions.assertThrows(NumberFormatException.class, () -> BigFraction.parse("1 / z"));
768         Assertions.assertThrows(NumberFormatException.class, () -> BigFraction.parse("1 / --2"));
769         Assertions.assertThrows(NumberFormatException.class, () -> BigFraction.parse("x"));
770     }
771 
772     @Test
773     void testMath340() {
774         final BigFraction fractionA = BigFraction.from(0.00131);
775         final BigFraction fractionB = BigFraction.from(.37).reciprocal();
776         final BigFraction errorResult = fractionA.multiply(fractionB);
777         final BigFraction correctResult = BigFraction.of(fractionA.getNumerator().multiply(fractionB.getNumerator()),
778                                                    fractionA.getDenominator().multiply(fractionB.getDenominator()));
779         Assertions.assertEquals(correctResult, errorResult);
780     }
781 
782     @Test
783     void testNumbers150() {
784         // zero to negative powers should throw an exception
785         Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.ZERO.pow(-1));
786         Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.ZERO.pow(Integer.MIN_VALUE));
787 
788         // shall overflow
789         final BigFraction f2 = BigFraction.of(2);
790         Assertions.assertThrows(ArithmeticException.class, () -> f2.pow(Integer.MIN_VALUE));
791         final BigFraction f12 = BigFraction.of(1, 2);
792         Assertions.assertThrows(ArithmeticException.class, () -> f12.pow(Integer.MIN_VALUE));
793     }
794 }