Returns Long, not Int: a combinatorial index can be astronomically larger than n/k themselves, and silently truncating it is a real bug, not a contrived edge case -- e.g. C(229,5) = 5,022,337,545 truncates to 727,370,249 via Int, well within a realistic point-cloud size. Long matches ripser.cpp's own int64_t/long long for this exact purpose and is dramatically cheaper than BigInt, which matters since this backs Ordering[Simplex[Int]]'s comparator, consulted on every SortedMap/PriorityQueue operation during reduction. Long is not infinite either, so this still asserts on overflow rather than repeating the same class of bug one order of magnitude further out.
Returns Long, not Int: a combinatorial index can be astronomically larger than n/k themselves, and silently truncating it is a real bug, not a contrived edge case -- e.g. C(229,5) = 5,022,337,545 truncates to 727,370,249 via Int, well within a realistic point-cloud size. Long matches ripser.cpp's own int64_t/long long for this exact purpose and is dramatically cheaper than BigInt, which matters since this backs Ordering[Simplex[Int]]'s comparator, consulted on every SortedMap/PriorityQueue operation during reduction. Long is not infinite either, so this still asserts on overflow rather than repeating the same class of bug one order of magnitude further out.
Delegates to commons.numbers.combinatorics.BinomialCoefficient.value, a long-only, GCD-guarded-for-large-n algorithm. n < 0 || k < 0 || n < k are special-cased to 0 BEFORE delegating: BinomialCoefficient.value throws IllegalArgumentException for those inputs instead, which would be a real behavior change for callers relying on the old "returns 0 outside the valid range" contract (cofacetIteratorWithVertex's own iA/iB bookkeeping does hit k > n-shaped calls at the boundary of its sweep). Overflow (ArithmeticException) is caught and re-thrown as the same IllegalArgumentException-with-message shape require used to produce.