public static long value()

in commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/BinomialCoefficient.java [61:116]


    public static long value(int n, int k) {
        final int m = checkBinomial(n, k);

        if (m == 0) {
            return 1;
        }
        if (m == 1) {
            return n;
        }

        // We use the formulae:
        // (n choose m) = n! / (n-m)! / m!
        // (n choose m) = ((n-m+1)*...*n) / (1*...*m)
        // which can be written
        // (n choose m) = (n-1 choose m-1) * n / m
        long result = 1;
        if (n <= SMALL_N) {
            // For n <= 61, the naive implementation cannot overflow.
            int i = n - m + 1;
            for (int j = 1; j <= m; j++) {
                result = result * i / j;
                i++;
            }
        } else if (n <= LIMIT_N) {
            // For n > 61 but n <= 66, the result cannot overflow,
            // but we must take care not to overflow intermediate values.
            int i = n - m + 1;
            for (int j = 1; j <= m; j++) {
                // We know that (result * i) is divisible by j,
                // but (result * i) may overflow, so we split j:
                // Filter out the gcd, d, so j/d and i/d are integer.
                // result is divisible by (j/d) because (j/d)
                // is relative prime to (i/d) and is a divisor of
                // result * (i/d).
                final long d = ArithmeticUtils.gcd(i, j);
                result = (result / (j / d)) * (i / d);
                ++i;
            }
        } else {
            if (m > MAX_M) {
                throw new ArithmeticException(n + " choose " + k);
            }

            // For n > 66, a result overflow might occur, so we check
            // the multiplication, taking care to not overflow
            // unnecessary.
            int i = n - m + 1;
            for (int j = 1; j <= m; j++) {
                final long d = ArithmeticUtils.gcd(i, j);
                result = Math.multiplyExact(result / (j / d), i / d);
                ++i;
            }
        }

        return result;
    }