From 35d2b1f235bb8bed8d4ab0a1586eb9f342b286e5 Mon Sep 17 00:00:00 2001 From: John Michael Hall Date: Fri, 3 Jun 2022 20:33:02 -0400 Subject: [PATCH] Support const for binomial --- source/mir/combinatorics/package.d | 35 ++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/source/mir/combinatorics/package.d b/source/mir/combinatorics/package.d index 3f9e9895..8c8a3201 100644 --- a/source/mir/combinatorics/package.d +++ b/source/mir/combinatorics/package.d @@ -85,45 +85,49 @@ Params: Returns: Binomial coefficient */ -R binomial(R = ulong, T)(T n, T k) +R binomial(R = ulong, T)(const T n, const T k) if (isArithmetic!(R, T) && ((is(typeof(T.min < 0)) && is(typeof(T.init & 1))) || !is(typeof(T.min < 0))) ) { R result = 1; enum hasMinProperty = is(typeof(T.min < 0)); + + T n2 = n; + T k2 = k; + // only add negative support if possible static if ((hasMinProperty && T.min < 0) || !hasMinProperty) { - if (n < 0) + if (n2 < 0) { - if (k >= 0) + if (k2 >= 0) { - return (k & 1 ? -1 : 1) * binomial!(R, T)(-n + k-1, k); + return (k2 & 1 ? -1 : 1) * binomial!(R, T)(-n2 + k2 - 1, k2); } - else if (k <= n) + else if (k2 <= n2) { - return ((n-k) & 1 ? -1 : 1) * binomial!(R, T)(-k-1, n-k); + return ((n2 - k2) & 1 ? -1 : 1) * binomial!(R, T)(-k2 - 1, n2 - k2); } } - if (k < 0) + if (k2 < 0) { result = 0; return result; } } - if (k > n) + if (k2 > n2) { result = 0; return result; } - if (k > n - k) + if (k2 > n2 - k2) { - k = n - k; + k2 = n2 - k2; } // make a copy of n (could be a custom type) - for (T i = 1, m = n; i <= k; i++, m--) + for (T i = 1, m = n2; i <= k2; i++, m--) { // check whether an overflow can happen // hasMember!(Result, "max") doesn't work with dmd2.068 and ldc 0.17 @@ -189,6 +193,15 @@ version(mir_test) unittest assert(binomial!BigInt(-5, -7) == 15); } +version(mir_test) +@safe pure nothrow @nogc +unittest +{ + const size_t n = 5; + const size_t k = 2; + assert(binomial(n, k) == 10); +} + /** Creates a projection of a generalized `Collection` range for the numeric case case starting from `0` onto a custom `range` of any type.