Mercurial > octave
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