Example usage for org.apache.commons.math3.exception.util LocalizedFormats ARGUMENT_OUTSIDE_DOMAIN

List of usage examples for org.apache.commons.math3.exception.util LocalizedFormats ARGUMENT_OUTSIDE_DOMAIN

Introduction

In this page you can find the example usage for org.apache.commons.math3.exception.util LocalizedFormats ARGUMENT_OUTSIDE_DOMAIN.

Prototype

LocalizedFormats ARGUMENT_OUTSIDE_DOMAIN

To view the source code for org.apache.commons.math3.exception.util LocalizedFormats ARGUMENT_OUTSIDE_DOMAIN.

Click Source Link

Usage

From source file:org.gitools.analysis.groupcomparison.format.math33Preview.CombinatoricsUtils.java

/**
 * Returns the <a/*w ww  .  ja v  a 2 s .  com*/
 * href="http://mathworld.wolfram.com/StirlingNumberoftheSecondKind.html">
 * Stirling number of the second kind</a>, "{@code S(n, k)}", the number of
 * ways of partitioning an {@code n}-element set into {@code k} non-empty
 * subsets.
 * <p>
 * The preconditions are {@code 0 <= k <= n } (otherwise
 * {@code NotPositiveException} is thrown)
 * </p>
 *
 * @param n the size of the set
 * @param k the number of non-empty subsets
 * @return {@code S(n, k)}
 * @throws NotPositiveException      if {@code k < 0}.
 * @throws NumberIsTooLargeException if {@code k > n}.
 * @throws MathArithmeticException   if some overflow happens, typically for n exceeding 25 and
 *                                   k between 20 and n-2 (S(n,n-1) is handled specifically and does not overflow)
 * @since 3.1
 */
public static long stirlingS2(final int n, final int k)
        throws NotPositiveException, NumberIsTooLargeException, MathArithmeticException {
    if (k < 0) {
        throw new NotPositiveException(k);
    }
    if (k > n) {
        throw new NumberIsTooLargeException(k, n, true);
    }

    long[][] stirlingS2 = STIRLING_S2.get();

    if (stirlingS2 == null) {
        // the cache has never been initialized, compute the first numbers
        // by direct recurrence relation

        // as S(26,9) = 11201516780955125625 is larger than Long.MAX_VALUE
        // we must stop computation at row 26
        final int maxIndex = 26;
        stirlingS2 = new long[maxIndex][];
        stirlingS2[0] = new long[] { 1l };
        for (int i = 1; i < stirlingS2.length; ++i) {
            stirlingS2[i] = new long[i + 1];
            stirlingS2[i][0] = 0;
            stirlingS2[i][1] = 1;
            stirlingS2[i][i] = 1;
            for (int j = 2; j < i; ++j) {
                stirlingS2[i][j] = j * stirlingS2[i - 1][j] + stirlingS2[i - 1][j - 1];
            }
        }

        // atomically save the cache
        STIRLING_S2.compareAndSet(null, stirlingS2);

    }

    if (n < stirlingS2.length) {
        // the number is in the small cache
        return stirlingS2[n][k];
    } else {
        // use explicit formula to compute the number without caching it
        if (k == 0) {
            return 0;
        } else if (k == 1 || k == n) {
            return 1;
        } else if (k == 2) {
            return (1l << (n - 1)) - 1l;
        } else if (k == n - 1) {
            return binomialCoefficient(n, 2);
        } else {
            // definition formula: note that this may trigger some overflow
            long sum = 0;
            long sign = ((k & 0x1) == 0) ? 1 : -1;
            for (int j = 1; j <= k; ++j) {
                sign = -sign;
                sum += sign * binomialCoefficient(k, j) * ArithmeticUtils.pow(j, n);
                if (sum < 0) {
                    // there was an overflow somewhere
                    throw new MathArithmeticException(LocalizedFormats.ARGUMENT_OUTSIDE_DOMAIN, n, 0,
                            stirlingS2.length - 1);
                }
            }
            return sum / factorial(k);
        }
    }

}