NUMBERS-150: Fix Fraction.pow and BigFraction.pow

Modified to:

- correctly handle Integer.MIN_VALUE as the argument.
- throw an ArithmeticException when zero is raised to a negative power.

Squashed commit of the following:

commit 0fd1da5bdb92bf31b7dd4ec3981924c5f68dbef4
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 04:36:46 2020 +0800

    fix checkstyles

commit 4c2aa76d0f4425e55eccd23e4a40a19eb9834a31
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 04:34:54 2020 +0800

    apply suggestions

commit 0fc3a52c4d3789b18795392223e6add522843a0a
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 04:27:42 2020 +0800

    apply suggestions

commit 1481998f24c49bf8f20123703037a6fbefe6b9af
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 04:24:58 2020 +0800

    apply suggestions

commit 44678423889201f2c60ac024e132593336033bc9
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:28:58 2020 +0800

    fix checkstyles

commit 708414cdb8046c442360469f294b77729f5d345c
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:27:43 2020 +0800

    change as suggested

commit 5b9c91aaae49f7b2d8d331b2d8947bd1b684151e
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:24:56 2020 +0800

    change as suggested

commit 12142b608c3776e498fd17d66d51f4a7bc48e8f8
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:23:57 2020 +0800

    change as suggested

commit 3f10f12e3f9bb79edb835682cefeeea5ccf6a7ca
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:22:13 2020 +0800

    change as suggested

commit d01b5b8f509c5c9641798d57e4de1434cbac9688
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:20:50 2020 +0800

    change as suggested

commit 6f23df0d9fe789faff07406482108810b0eaf8b4
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:16:33 2020 +0800

    change as suggested

commit 3646e00ce9c17a81ca3a64ffe103974c44b33995
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:15:10 2020 +0800

    change as suggested

commit 3d4bc49f704ee0784ccdc96ab61edeb3720dbff3
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:13:29 2020 +0800

    change as suggested

commit 267df9448e14d28451e9d2ad88783f4bc32b635b
Author: XenoAmess <xenoamess@gmail.com>
Date:   Wed Aug 26 03:12:04 2020 +0800

    change as suggested

commit ba0d39ba532f36e62417b277641932fe46f6af23
Author: XenoAmess <xenoamess@gmail.com>
Date:   Tue Aug 25 21:26:27 2020 +0800

    [NUMBERS-150] fix bug in Fraction.pow and BigFraction.pow
diff --git a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
index a172d44..bc71783 100644
--- a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
+++ b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
@@ -966,23 +966,36 @@
      */
     @Override
     public BigFraction pow(final int exponent) {
+        if (exponent == 1) {
+            return this;
+        }
         if (exponent == 0) {
             return ONE;
         }
         if (isZero()) {
+            if (exponent < 0) {
+                throw new FractionException(FractionException.ERROR_ZERO_DENOMINATOR);
+            }
             return ZERO;
         }
-
+        if (exponent > 0) {
+            return new BigFraction(numerator.pow(exponent),
+                                   denominator.pow(exponent));
+        }
+        if (exponent == -1) {
+            return this.reciprocal();
+        }
+        if (exponent == Integer.MIN_VALUE) {
+            // MIN_VALUE can't be negated
+            return new BigFraction(denominator.pow(Integer.MAX_VALUE).multiply(denominator),
+                                   numerator.pow(Integer.MAX_VALUE).multiply(numerator));
+        }
         // Note: Raise the BigIntegers to the power and then reduce.
         // The supported range for BigInteger is currently
         // +/-2^(Integer.MAX_VALUE) exclusive thus larger
         // exponents (long, BigInteger) are currently not supported.
-        if (exponent < 0) {
-            return new BigFraction(denominator.pow(-exponent),
-                                   numerator.pow(-exponent));
-        }
-        return new BigFraction(numerator.pow(exponent),
-                               denominator.pow(exponent));
+        return new BigFraction(denominator.pow(-exponent),
+                               numerator.pow(-exponent));
     }
 
     /**
diff --git a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java
index f1bc542..2afe738 100644
--- a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java
+++ b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/Fraction.java
@@ -775,19 +775,32 @@
      */
     @Override
     public Fraction pow(final int exponent) {
+        if (exponent == 1) {
+            return this;
+        }
         if (exponent == 0) {
             return ONE;
         }
         if (isZero()) {
+            if (exponent < 0) {
+                throw new FractionException(FractionException.ERROR_ZERO_DENOMINATOR);
+            }
             return ZERO;
         }
-
-        if (exponent < 0) {
-            return new Fraction(ArithmeticUtils.pow(denominator, -exponent),
-                                ArithmeticUtils.pow(numerator,   -exponent));
+        if (exponent > 0) {
+            return new Fraction(ArithmeticUtils.pow(numerator, exponent),
+                                ArithmeticUtils.pow(denominator, exponent));
         }
-        return new Fraction(ArithmeticUtils.pow(numerator,   exponent),
-                            ArithmeticUtils.pow(denominator, exponent));
+        if (exponent == -1) {
+            return this.reciprocal();
+        }
+        if (exponent == Integer.MIN_VALUE) {
+            // MIN_VALUE can't be negated
+            return new Fraction(ArithmeticUtils.pow(denominator, Integer.MAX_VALUE) * denominator,
+                                ArithmeticUtils.pow(numerator, Integer.MAX_VALUE) * numerator);
+        }
+        return new Fraction(ArithmeticUtils.pow(denominator, -exponent),
+                            ArithmeticUtils.pow(numerator, -exponent));
     }
 
     /**
diff --git a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java
index 5ded68e..f6c147f 100644
--- a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java
+++ b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/BigFractionTest.java
@@ -778,4 +778,15 @@
                                                    fractionA.getDenominator().multiply(fractionB.getDenominator()));
         Assertions.assertEquals(correctResult, errorResult);
     }
+
+    @Test
+    void testNumbers150() {
+        // zero to negative powers should throw an exception
+        Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.ZERO.pow(-1));
+        Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.ZERO.pow(Integer.MIN_VALUE));
+
+        // shall overflow
+        Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.of(2).pow(Integer.MIN_VALUE));
+        Assertions.assertThrows(ArithmeticException.class, () -> BigFraction.of(1, 2).pow(Integer.MIN_VALUE));
+    }
 }
diff --git a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/CommonTestCases.java b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/CommonTestCases.java
index d6e58dc..621d02a 100644
--- a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/CommonTestCases.java
+++ b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/CommonTestCases.java
@@ -570,6 +570,10 @@
         testCases.add(new BinaryIntOperatorTestCase(0, 1, Integer.MAX_VALUE, 0, 1));
         testCases.add(new BinaryIntOperatorTestCase(0, -1, Integer.MAX_VALUE, 0, 1));
 
+        testCases.add(new BinaryIntOperatorTestCase(1, 1, Integer.MIN_VALUE, 1, 1));
+        testCases.add(new BinaryIntOperatorTestCase(1, -1, Integer.MIN_VALUE, 1, 1));
+        testCases.add(new BinaryIntOperatorTestCase(-1, 1, Integer.MIN_VALUE, 1, 1));
+        testCases.add(new BinaryIntOperatorTestCase(-1, -1, Integer.MIN_VALUE, 1, 1));
         return testCases;
     }
 
diff --git a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/FractionTest.java b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/FractionTest.java
index 1a2a1b6..8b5506d 100644
--- a/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/FractionTest.java
+++ b/commons-numbers-fraction/src/test/java/org/apache/commons/numbers/fraction/FractionTest.java
@@ -622,6 +622,17 @@
         assertFraction(1, Integer.MAX_VALUE, b.divide(2));
     }
 
+    @Test
+    void testNumbers150() {
+        // zero to negative powers should throw an exception
+        Assertions.assertThrows(ArithmeticException.class, () -> Fraction.ZERO.pow(-1));
+        Assertions.assertThrows(ArithmeticException.class, () -> Fraction.ZERO.pow(Integer.MIN_VALUE));
+
+        // shall overflow
+        Assertions.assertThrows(ArithmeticException.class, () -> Fraction.of(2).pow(Integer.MIN_VALUE));
+        Assertions.assertThrows(ArithmeticException.class, () -> Fraction.of(1, 2).pow(Integer.MIN_VALUE));
+    }
+
     /**
      * Defines test cases that cause overflow in {@link Fraction#add(Fraction)}.
      * @return a list of test cases