Merge branch 'refine_ArithmeticUtils_pow' of https://github.com/XenoAmess/commons-numbers into XenoAmess-refine_ArithmeticUtils_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
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 07f1a6a..9c2aa6e 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -50,6 +50,30 @@
<title>Apache Commons Numbers Release Notes</title>
</properties>
<body>
+ <release version="1.0-beta2" date="TBD" description="
+This is a beta release of Apache Commons Numbers. No guarantees are
+made regarding the stability of the API or compatibility with future
+releases.
+
+Apache Commons Numbers 1.0-beta1 contains the following library modules:
+ commons-numbers-angle (requires Java 8+)
+ commons-numbers-arrays (requires Java 8+)
+ commons-numbers-combinatorics (requires Java 8+)
+ commons-numbers-complex (requires Java 8+)
+ commons-numbers-core (requires Java 8+)
+ commons-numbers-field (requires Java 8+)
+ commons-numbers-fraction (requires Java 8+)
+ commons-numbers-gamma (requires Java 8+)
+ commons-numbers-primes (requires Java 8+)
+ commons-numbers-quaternion (requires Java 8+)
+ commons-numbers-rootfinder (requires Java 8+)
+">
+ <action dev="aherbert" type="fix" issue="NUMBERS-150" due-to="Jin Xu">
+ "Fraction/BigFraction": Fixed pow(int) to handle Integer.MIN_VALUE and throw
+ ArithmeticException for negative exponents to a fraction of zero.
+ </action>
+ </release>
+
<release version="1.0-beta1" date="2020-04-08" description="
This is a beta release of Apache Commons Numbers. No guarantees are
made regarding the stability of the API or compatibility with future