This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
The following commit(s) were added to refs/heads/master by this push:
new 6ba410f NUMBERS-178: Add Factorial.doubleValue(int)
6ba410f is described below
commit 6ba410f24a351d47bc137daa9f0e8528ca0aea69
Author: Alex Herbert <[email protected]>
AuthorDate: Sat Dec 4 00:52:12 2021 +0000
NUMBERS-178: Add Factorial.doubleValue(int)
Deprecate the FactorialDouble class.
---
.../commons/numbers/combinatorics/Factorial.java | 200 +++++++++++++++++++-
.../numbers/combinatorics/FactorialDouble.java | 210 ++-------------------
.../numbers/combinatorics/FactorialDoubleTest.java | 26 +--
.../numbers/combinatorics/FactorialTest.java | 58 ++++--
src/changes/changes.xml | 6 +-
5 files changed, 263 insertions(+), 237 deletions(-)
diff --git
a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Factorial.java
b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Factorial.java
index 553652d..7a47070 100644
---
a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Factorial.java
+++
b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Factorial.java
@@ -23,7 +23,7 @@ package org.apache.commons.numbers.combinatorics;
public final class Factorial {
/** All long-representable factorials. */
- static final long[] FACTORIALS = new long[] {
+ static final long[] FACTORIALS = {
1L, 1L, 2L,
6L, 24L, 120L,
720L, 5040L, 40320L,
@@ -33,6 +33,181 @@ public final class Factorial {
6402373705728000L, 121645100408832000L, 2432902008176640000L
};
+ /** All factorials that can be represented as a double (values up to
170!). */
+ private static final double[] DOUBLE_FACTORIALS = {
+ 1,
+ 1,
+ 2,
+ 6,
+ 24,
+ 120,
+ 720,
+ 5040,
+ 40320,
+ 362880,
+ 3628800,
+ 3.99168E7,
+ 4.790016E8,
+ 6.2270208E9,
+ 8.71782912E10,
+ 1.307674368E12,
+ 2.0922789888E13,
+ 3.55687428096E14,
+ 6.402373705728E15,
+ 1.21645100408832E17,
+ 2.43290200817664E18,
+ 5.109094217170944E19,
+ 1.1240007277776077E21,
+ 2.585201673888498E22,
+ 6.204484017332394E23,
+ 1.5511210043330986E25,
+ 4.0329146112660565E26,
+ 1.0888869450418352E28,
+ 3.0488834461171387E29,
+ 8.841761993739702E30,
+ 2.6525285981219107E32,
+ 8.222838654177922E33,
+ 2.631308369336935E35,
+ 8.683317618811886E36,
+ 2.9523279903960416E38,
+ 1.0333147966386145E40,
+ 3.7199332678990125E41,
+ 1.3763753091226346E43,
+ 5.230226174666011E44,
+ 2.0397882081197444E46,
+ 8.159152832478977E47,
+ 3.345252661316381E49,
+ 1.40500611775288E51,
+ 6.041526306337383E52,
+ 2.658271574788449E54,
+ 1.1962222086548019E56,
+ 5.502622159812089E57,
+ 2.5862324151116818E59,
+ 1.2413915592536073E61,
+ 6.082818640342675E62,
+ 3.0414093201713376E64,
+ 1.5511187532873822E66,
+ 8.065817517094388E67,
+ 4.2748832840600255E69,
+ 2.308436973392414E71,
+ 1.2696403353658276E73,
+ 7.109985878048635E74,
+ 4.0526919504877214E76,
+ 2.3505613312828785E78,
+ 1.3868311854568984E80,
+ 8.32098711274139E81,
+ 5.075802138772248E83,
+ 3.146997326038794E85,
+ 1.98260831540444E87,
+ 1.2688693218588417E89,
+ 8.247650592082472E90,
+ 5.443449390774431E92,
+ 3.647111091818868E94,
+ 2.4800355424368305E96,
+ 1.711224524281413E98,
+ 1.1978571669969892E100,
+ 8.504785885678623E101,
+ 6.1234458376886085E103,
+ 4.4701154615126844E105,
+ 3.307885441519386E107,
+ 2.48091408113954E109,
+ 1.8854947016660504E111,
+ 1.4518309202828587E113,
+ 1.1324281178206297E115,
+ 8.946182130782976E116,
+ 7.156945704626381E118,
+ 5.797126020747368E120,
+ 4.753643337012842E122,
+ 3.945523969720659E124,
+ 3.314240134565353E126,
+ 2.81710411438055E128,
+ 2.4227095383672734E130,
+ 2.107757298379528E132,
+ 1.8548264225739844E134,
+ 1.650795516090846E136,
+ 1.4857159644817615E138,
+ 1.352001527678403E140,
+ 1.2438414054641308E142,
+ 1.1567725070816416E144,
+ 1.087366156656743E146,
+ 1.032997848823906E148,
+ 9.916779348709496E149,
+ 9.619275968248212E151,
+ 9.426890448883248E153,
+ 9.332621544394415E155,
+ 9.332621544394415E157,
+ 9.42594775983836E159,
+ 9.614466715035127E161,
+ 9.90290071648618E163,
+ 1.0299016745145628E166,
+ 1.081396758240291E168,
+ 1.1462805637347084E170,
+ 1.226520203196138E172,
+ 1.324641819451829E174,
+ 1.4438595832024937E176,
+ 1.588245541522743E178,
+ 1.7629525510902446E180,
+ 1.974506857221074E182,
+ 2.2311927486598138E184,
+ 2.5435597334721877E186,
+ 2.925093693493016E188,
+ 3.393108684451898E190,
+ 3.969937160808721E192,
+ 4.684525849754291E194,
+ 5.574585761207606E196,
+ 6.689502913449127E198,
+ 8.094298525273444E200,
+ 9.875044200833601E202,
+ 1.214630436702533E205,
+ 1.506141741511141E207,
+ 1.882677176888926E209,
+ 2.372173242880047E211,
+ 3.0126600184576594E213,
+ 3.856204823625804E215,
+ 4.974504222477287E217,
+ 6.466855489220474E219,
+ 8.47158069087882E221,
+ 1.1182486511960043E224,
+ 1.4872707060906857E226,
+ 1.9929427461615188E228,
+ 2.6904727073180504E230,
+ 3.659042881952549E232,
+ 5.012888748274992E234,
+ 6.917786472619489E236,
+ 9.615723196941089E238,
+ 1.3462012475717526E241,
+ 1.898143759076171E243,
+ 2.695364137888163E245,
+ 3.854370717180073E247,
+ 5.5502938327393044E249,
+ 8.047926057471992E251,
+ 1.1749972043909107E254,
+ 1.727245890454639E256,
+ 2.5563239178728654E258,
+ 3.80892263763057E260,
+ 5.713383956445855E262,
+ 8.62720977423324E264,
+ 1.3113358856834524E267,
+ 2.0063439050956823E269,
+ 3.0897696138473508E271,
+ 4.789142901463394E273,
+ 7.471062926282894E275,
+ 1.1729568794264145E278,
+ 1.853271869493735E280,
+ 2.9467022724950384E282,
+ 4.7147236359920616E284,
+ 7.590705053947219E286,
+ 1.2296942187394494E289,
+ 2.0044015765453026E291,
+ 3.287218585534296E293,
+ 5.423910666131589E295,
+ 9.003691705778438E297,
+ 1.503616514864999E300,
+ 2.5260757449731984E302,
+ 4.269068009004705E304,
+ 7.257415615307999E306
+ };
+
/** Private constructor. */
private Factorial() {
// intentionally empty.
@@ -56,4 +231,27 @@ public final class Factorial {
return FACTORIALS[n];
}
+
+ /**
+ * Computes the factorial of {@code n}.
+ *
+ * <p>The result should be small enough to fit into a {@code double}: The
+ * largest {@code n} for which {@code n!} does not exceed
+ * {@code Double.MAX_VALUE} is 170. {@code Double.POSITIVE_INFINITY} is
+ * returned for {@code n > 170}.
+ *
+ * @param n Argument.
+ * @return {@code n!}
+ * @throws IllegalArgumentException if {@code n < 0}.
+ * @since 1.1
+ */
+ public static double doubleValue(int n) {
+ if (n < 0) {
+ throw new CombinatoricsException(CombinatoricsException.NEGATIVE,
n);
+ }
+ if (n < DOUBLE_FACTORIALS.length) {
+ return DOUBLE_FACTORIALS[n];
+ }
+ return Double.POSITIVE_INFINITY;
+ }
}
diff --git
a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/FactorialDouble.java
b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/FactorialDouble.java
index 6b0baf0..e39589a 100644
---
a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/FactorialDouble.java
+++
b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/FactorialDouble.java
@@ -18,185 +18,12 @@
package org.apache.commons.numbers.combinatorics;
/**
- * Class for computing the natural logarithm of the
- * <a href="http://mathworld.wolfram.com/Factorial.html">factorial of a
number</a>.
+ * @deprecated Since 1.1 this functionality has been replaced with {@link
Factorial#doubleValue(int)}.
+ *
+ * <a href="http://mathworld.wolfram.com/Factorial.html">Factorial of a
number</a>.
*/
+@Deprecated
public final class FactorialDouble {
- /** All factorials that can be represented as a double (values up to
170!). */
- private static final double[] FACTORIAL = {
- 1,
- 1,
- 2,
- 6,
- 24,
- 120,
- 720,
- 5040,
- 40320,
- 362880,
- 3628800,
- 3.99168E7,
- 4.790016E8,
- 6.2270208E9,
- 8.71782912E10,
- 1.307674368E12,
- 2.0922789888E13,
- 3.55687428096E14,
- 6.402373705728E15,
- 1.21645100408832E17,
- 2.43290200817664E18,
- 5.109094217170944E19,
- 1.1240007277776077E21,
- 2.585201673888498E22,
- 6.204484017332394E23,
- 1.5511210043330986E25,
- 4.0329146112660565E26,
- 1.0888869450418352E28,
- 3.0488834461171387E29,
- 8.841761993739702E30,
- 2.6525285981219107E32,
- 8.222838654177922E33,
- 2.631308369336935E35,
- 8.683317618811886E36,
- 2.9523279903960416E38,
- 1.0333147966386145E40,
- 3.7199332678990125E41,
- 1.3763753091226346E43,
- 5.230226174666011E44,
- 2.0397882081197444E46,
- 8.159152832478977E47,
- 3.345252661316381E49,
- 1.40500611775288E51,
- 6.041526306337383E52,
- 2.658271574788449E54,
- 1.1962222086548019E56,
- 5.502622159812089E57,
- 2.5862324151116818E59,
- 1.2413915592536073E61,
- 6.082818640342675E62,
- 3.0414093201713376E64,
- 1.5511187532873822E66,
- 8.065817517094388E67,
- 4.2748832840600255E69,
- 2.308436973392414E71,
- 1.2696403353658276E73,
- 7.109985878048635E74,
- 4.0526919504877214E76,
- 2.3505613312828785E78,
- 1.3868311854568984E80,
- 8.32098711274139E81,
- 5.075802138772248E83,
- 3.146997326038794E85,
- 1.98260831540444E87,
- 1.2688693218588417E89,
- 8.247650592082472E90,
- 5.443449390774431E92,
- 3.647111091818868E94,
- 2.4800355424368305E96,
- 1.711224524281413E98,
- 1.1978571669969892E100,
- 8.504785885678623E101,
- 6.1234458376886085E103,
- 4.4701154615126844E105,
- 3.307885441519386E107,
- 2.48091408113954E109,
- 1.8854947016660504E111,
- 1.4518309202828587E113,
- 1.1324281178206297E115,
- 8.946182130782976E116,
- 7.156945704626381E118,
- 5.797126020747368E120,
- 4.753643337012842E122,
- 3.945523969720659E124,
- 3.314240134565353E126,
- 2.81710411438055E128,
- 2.4227095383672734E130,
- 2.107757298379528E132,
- 1.8548264225739844E134,
- 1.650795516090846E136,
- 1.4857159644817615E138,
- 1.352001527678403E140,
- 1.2438414054641308E142,
- 1.1567725070816416E144,
- 1.087366156656743E146,
- 1.032997848823906E148,
- 9.916779348709496E149,
- 9.619275968248212E151,
- 9.426890448883248E153,
- 9.332621544394415E155,
- 9.332621544394415E157,
- 9.42594775983836E159,
- 9.614466715035127E161,
- 9.90290071648618E163,
- 1.0299016745145628E166,
- 1.081396758240291E168,
- 1.1462805637347084E170,
- 1.226520203196138E172,
- 1.324641819451829E174,
- 1.4438595832024937E176,
- 1.588245541522743E178,
- 1.7629525510902446E180,
- 1.974506857221074E182,
- 2.2311927486598138E184,
- 2.5435597334721877E186,
- 2.925093693493016E188,
- 3.393108684451898E190,
- 3.969937160808721E192,
- 4.684525849754291E194,
- 5.574585761207606E196,
- 6.689502913449127E198,
- 8.094298525273444E200,
- 9.875044200833601E202,
- 1.214630436702533E205,
- 1.506141741511141E207,
- 1.882677176888926E209,
- 2.372173242880047E211,
- 3.0126600184576594E213,
- 3.856204823625804E215,
- 4.974504222477287E217,
- 6.466855489220474E219,
- 8.47158069087882E221,
- 1.1182486511960043E224,
- 1.4872707060906857E226,
- 1.9929427461615188E228,
- 2.6904727073180504E230,
- 3.659042881952549E232,
- 5.012888748274992E234,
- 6.917786472619489E236,
- 9.615723196941089E238,
- 1.3462012475717526E241,
- 1.898143759076171E243,
- 2.695364137888163E245,
- 3.854370717180073E247,
- 5.5502938327393044E249,
- 8.047926057471992E251,
- 1.1749972043909107E254,
- 1.727245890454639E256,
- 2.5563239178728654E258,
- 3.80892263763057E260,
- 5.713383956445855E262,
- 8.62720977423324E264,
- 1.3113358856834524E267,
- 2.0063439050956823E269,
- 3.0897696138473508E271,
- 4.789142901463394E273,
- 7.471062926282894E275,
- 1.1729568794264145E278,
- 1.853271869493735E280,
- 2.9467022724950384E282,
- 4.7147236359920616E284,
- 7.590705053947219E286,
- 1.2296942187394494E289,
- 2.0044015765453026E291,
- 3.287218585534296E293,
- 5.423910666131589E295,
- 9.003691705778438E297,
- 1.503616514864999E300,
- 2.5260757449731984E302,
- 4.269068009004705E304,
- 7.257415615307999E306
- };
-
/** Single instance. */
private static final FactorialDouble INSTANCE = new FactorialDouble();
@@ -204,18 +31,21 @@ public final class FactorialDouble {
private FactorialDouble() {}
/**
- * Creates an instance.
+ * @deprecated Since 1.1 this functionality has been replaced with {@link
Factorial#doubleValue(int)}.
+ *
+ * <p>This class no longer supports a cache. This method returns a
reference to a single instance.
+ *
* @return instance
*/
+ @Deprecated
public static FactorialDouble create() {
return INSTANCE;
}
/**
- * @deprecated Since 1.1 the cache size argument is ignored. Use {@link
#create()} to obtain an instance.
+ * @deprecated Since 1.1 this functionality has been replaced with {@link
Factorial#doubleValue(int)}.
*
- * <p>As of Numbers 1.1 all representable factorials up to {@code n=170}
are tabulated.
- * This method returns a reference to the same object.
+ * <p>This class no longer supports a cache. This method returns a
reference to the same object.
*
* @param cacheSize Ignored.
* @return instance
@@ -226,24 +56,16 @@ public final class FactorialDouble {
}
/**
- * Computes the factorial of {@code n}.
- * The result should be small enough to fit into a {@code double}: The
- * largest {@code n} for which {@code n!} does not exceed
- * {@code Double.MAX_VALUE} is 170. {@code Double.POSITIVE_INFINITY} is
- * returned for {@code n > 170}.
+ * @deprecated Since 1.1 this functionality has been replaced with {@link
Factorial#doubleValue(int)}.
+ *
+ * <p>The result of calling this method is the same as calling the {@link
Factorial#doubleValue(int)}.
*
* @param n Argument.
* @return {@code n!}
* @throws IllegalArgumentException if {@code n < 0}.
*/
- // Note: This must remain an instance method for binary compatibility
+ @Deprecated
public double value(int n) {
- if (n < 0) {
- throw new CombinatoricsException(CombinatoricsException.NEGATIVE,
n);
- }
- if (n < FACTORIAL.length) {
- return FACTORIAL[n];
- }
- return Double.POSITIVE_INFINITY;
+ return Factorial.doubleValue(n);
}
}
diff --git
a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java
b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java
index 23bc7b4..2437d44 100644
---
a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java
+++
b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialDoubleTest.java
@@ -16,23 +16,18 @@
*/
package org.apache.commons.numbers.combinatorics;
-import java.math.BigInteger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* Test cases for the {@link FactorialDouble} class.
*/
+@SuppressWarnings("deprecation")
class FactorialDoubleTest {
/** The largest representable factorial (n=170). */
private static final int MAX_N = 170;
@Test
- void testFactorialZero() {
- Assertions.assertEquals(1, FactorialDouble.create().value(0), "0!");
- }
-
- @Test
void testNonPositiveArgument() {
Assertions.assertThrows(IllegalArgumentException.class,
() -> FactorialDouble.create().value(-1)
@@ -42,21 +37,11 @@ class FactorialDoubleTest {
@Test
void testFactorials() {
final FactorialDouble f = FactorialDouble.create();
- // Start at 0!
- BigInteger value = BigInteger.ONE;
- for (int n = 1; n <= MAX_N; n++) {
- // n! = (n-1)! * n
- value = value.multiply(BigInteger.valueOf(n));
- Assertions.assertEquals(value.doubleValue(), f.value(n));
+ for (int n = 0; n <= MAX_N; n++) {
+ Assertions.assertEquals(Factorial.doubleValue(n), f.value(n));
}
- }
-
- @Test
- void testFactorialDoubleTooLarge() {
- final FactorialDouble f = FactorialDouble.create();
- // Long avoids overflow to negative
- for (long n = MAX_N + 1; n < Integer.MAX_VALUE; n *= 2) {
- Assertions.assertEquals(Double.POSITIVE_INFINITY, f.value((int)
n));
+ for (final int n : new int[] {MAX_N + 1, 678, Integer.MAX_VALUE}) {
+ Assertions.assertEquals(Factorial.doubleValue(n), f.value(n));
}
}
@@ -65,7 +50,6 @@ class FactorialDoubleTest {
* This method was deprecated since 1.1.
* It now allows calling the method with an invalid cache size.
*/
- @SuppressWarnings("deprecation")
@Test
void testWithCacheReturnsThis() {
final FactorialDouble f = FactorialDouble.create();
diff --git
a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialTest.java
b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialTest.java
index 689739d..4e549c8 100644
---
a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialTest.java
+++
b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/FactorialTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.commons.numbers.combinatorics;
+import java.math.BigInteger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -23,40 +24,61 @@ import org.junit.jupiter.api.Test;
* Test cases for the {@link Factorial} class.
*/
class FactorialTest {
+ /** The largest representable factorial using a long (n=20). */
+ private static final int MAX_N_LONG = 20;
+ /** The largest representable factorial using a double (n=170). */
+ private static final int MAX_N_DOUBLE = 170;
+
@Test
void testFactorialZero() {
Assertions.assertEquals(1, Factorial.value(0), "0!");
+ Assertions.assertEquals(1.0, Factorial.doubleValue(0), "0!");
}
@Test
- void testFactorial() {
- for (int i = 1; i < 21; i++) {
- Assertions.assertEquals(factorial(i), Factorial.value(i), i + "!");
- }
- }
-
- @Test
- void testPrecondition1() {
+ void testFactorialNonPositiveArgument() {
Assertions.assertThrows(IllegalArgumentException.class,
() -> Factorial.value(-1)
);
+ Assertions.assertThrows(IllegalArgumentException.class,
+ () -> Factorial.doubleValue(-1)
+ );
}
@Test
- void testPrecondition2() {
+ void testFactorialArgumentTooLarge() {
Assertions.assertThrows(IllegalArgumentException.class,
- () -> Factorial.value(21)
+ () -> Factorial.value(MAX_N_LONG + 1)
);
}
- /**
- * Direct multiplication implementation.
- */
- private long factorial(int n) {
- long result = 1;
- for (int i = 2; i <= n; i++) {
- result *= i;
+ @Test
+ void testFactorialDoubleValueArgumentTooLarge() {
+ // Long avoids overflow to negative
+ for (long n = MAX_N_DOUBLE + 1; n < Integer.MAX_VALUE; n *= 2) {
+ Assertions.assertEquals(Double.POSITIVE_INFINITY,
Factorial.doubleValue((int) n));
+ }
+ }
+
+ @Test
+ void testFactorial() {
+ // Start at 0!
+ long value = 1;
+ for (int n = 1; n <= MAX_N_LONG; n++) {
+ // n! = (n-1)! * n
+ value *= n;
+ Assertions.assertEquals(value, Factorial.value(n));
+ }
+ }
+
+ @Test
+ void testFactorialDoubleValue() {
+ // Start at 0!
+ BigInteger value = BigInteger.ONE;
+ for (int n = 1; n <= MAX_N_DOUBLE; n++) {
+ // n! = (n-1)! * n
+ value = value.multiply(BigInteger.valueOf(n));
+ Assertions.assertEquals(value.doubleValue(),
Factorial.doubleValue(n));
}
- return result;
}
}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index a0fc286..4b7d6e7 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -73,9 +73,9 @@ N.B. the Performance testing module requires Java 9+.
">
<action dev="aherbert" type="update" issue="NUMBERS-178">
- "FactorialDouble": Tabulate all representable factorials. This change
deprecates the
- caching of iteratively computed values with exact 64-bit double
representations of
- n! up to n=170.
+ "Factorial/FactorialDouble": Tabulate all factorials with exact 64-bit
double
+ representations of n! up to n=170. This change deprecates the
FactorialDouble
+ class and removes obsolete caching functionality.
</action>
<action dev="aherbert" type="update" issue="NUMBERS-176">
"ContinuedFraction": Update to use a shared implementation with
GeneralizedContinuedFraction.