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