changeset 30938:9c7822f4fc9c stable

nchoosek.m: Restore fast path code for floating point inputs (bug #62319). * nchoosek.m: Restore fast path code for floating point inputs, but only use it if neither N nor K are of integer class.
author Rik <rik@octave.org>
date Sat, 16 Apr 2022 12:43:24 -0700
parents 670eb988dd6a
children 5d410755481e fe898ae23e0e
files scripts/specfun/nchoosek.m
diffstat 1 files changed, 17 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/specfun/nchoosek.m	Fri Apr 15 14:46:23 2022 -0400
+++ b/scripts/specfun/nchoosek.m	Sat Apr 16 12:43:24 2022 -0700
@@ -115,8 +115,23 @@
     ## Steps: 1) Make a list of integers for numerator and denominator,
     ## 2) filter out common factors, 3) multiply what remains.
     k = min (k, v-k);
-    numer = (v-k+1):v;
-    denom = (1:k);
+
+    if (isinteger (v) || isinteger (k))
+      numer = (v-k+1):v;
+      denom = (1:k);
+    else
+      ## For a ~25% performance boost, multiply values pairwise so there
+      ## are fewer elements in do/until loop which is the slow part.
+      ## Since Odd*Even is guaranteed to be Even, also take out a factor
+      ## of 2 from numerator and denominator.
+      if (rem (k, 2))  # k is odd
+        numer = [((v-k+1:v-(k+1)/2) .* (v-1:-1:v-(k-1)/2)) / 2, v];
+        denom = [((1:(k-1)/2) .* (k-1:-1:(k+1)/2)) / 2, k];
+      else             # k is even
+        numer = ((v-k+1:v-k/2) .* (v:-1:v-k/2+1)) / 2;
+        denom = ((1:k/2) .* (k:-1:k/2+1)) / 2;
+      endif
+    endif
 
     ## Remove common factors from numerator and denominator
     do