From 2fd39d6e0c51ca29f1b82be8ba29f8efcebdddfd Mon Sep 17 00:00:00 2001 From: Yujing Date: Tue, 15 Oct 2024 22:46:12 +1100 Subject: [PATCH] #7430 implemented multiFactorial --- .../google/common/math/BigIntegerMath.java | 26 ++++++++++++++++++- guava/src/com/google/common/math/IntMath.java | 24 +++++++++++++++++ .../src/com/google/common/math/LongMath.java | 25 +++++++++++++++++- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/guava/src/com/google/common/math/BigIntegerMath.java b/guava/src/com/google/common/math/BigIntegerMath.java index 5f7ce6b57577..17417a4747d4 100644 --- a/guava/src/com/google/common/math/BigIntegerMath.java +++ b/guava/src/com/google/common/math/BigIntegerMath.java @@ -520,6 +520,30 @@ public static BigInteger binomial(int n, int k) { static boolean fitsInLong(BigInteger x) { return x.bitLength() <= Long.SIZE - 1; } - + /** + * Returns multifactorial of n with step size BigInteger k. + * This is used for large values of n. + * + * @param n the number to compute the multifactorial of. Must be non-negative. + * @param k the step size. Must be positive. + * @return the multifactorial of n with step size k. If none-zero n is less than k then return n, else return one. + * @throws IllegalArgumentException if n is negative or if k is less than 1. + */ + public static BigInteger multiFactorial(int n, int k) { + if (n < 0) { + throw new IllegalArgumentException("n cannot be negative!"); + } + if (k < 1) { + throw new IllegalArgumentException("k must be positive!"); + } + if (n <= k) { + return n == 0 ? BigInteger.ONE : BigInteger.valueOf(n); + } + BigInteger result = BigInteger.valueOf(n); + for (int i = n - k; i > 1; i -= k) { + result = result.multiply(BigInteger.valueOf(i)); + } + return result; + } private BigIntegerMath() {} } diff --git a/guava/src/com/google/common/math/IntMath.java b/guava/src/com/google/common/math/IntMath.java index 7ab7765cf840..c5f1b08a2209 100644 --- a/guava/src/com/google/common/math/IntMath.java +++ b/guava/src/com/google/common/math/IntMath.java @@ -721,6 +721,30 @@ public static int mean(int x, int y) { public static boolean isPrime(int n) { return LongMath.isPrime(n); } + /** + * Returns multifactorial of Int n with step size k. + * + * @param n the number to compute. Must be non-negative. + * @param k the step size for the multifactorial. Must be positive. + * @return the multifactorial of n with step size k. If none-zero n is less than k then return n, else return 1. + * @throws IllegalArgumentException if n is negative or if k is less than 1. + */ + public static int multiFactorial(int n, int k) { + if (n < 0) { + throw new IllegalArgumentException("n cannot be negative!"); + } + if (k < 1) { + throw new IllegalArgumentException("k must be positive!"); + } + if (n <= k) { + return n == 0 ? 1 : n; + } + int result = n; + for (int i = n - k; i > 1; i -= k) { + result *= i; + } + return result; + } private IntMath() {} } diff --git a/guava/src/com/google/common/math/LongMath.java b/guava/src/com/google/common/math/LongMath.java index 16e0248d99e4..790526969c58 100644 --- a/guava/src/com/google/common/math/LongMath.java +++ b/guava/src/com/google/common/math/LongMath.java @@ -1345,6 +1345,29 @@ public static double roundToDouble(long x, RoundingMode mode) { } throw new AssertionError("impossible"); } - + /** + * Returns multifactorial of int n with step size k. + * + * @param n the number to compute. Must be non-negative. + * @param k the step size must be positive. + * @return the long type multifactorial of n with step size k. If none-zero n is less than k then return (long) n, else return 1L. + * @throws IllegalArgumentException if n is negative or if k is less than 1. + */ + public static long multiFactorial(int n, int k) { + if (n < 0) { + throw new IllegalArgumentException("n cannot be negative!"); + } + if (k < 1) { + throw new IllegalArgumentException("k must be positive!"); + } + if (n <= k) { + return n == 0 ? 1L : (long)n; + } + long result = n; + for (long i = n - k; i > 1; i -= k) { + result *= i; + } + return result; + } private LongMath() {} }