changeset 30415:e22183b892c6

maint: merge stable to default.
author Markus Mützel <markus.muetzel@gmx.de>
date Thu, 02 Dec 2021 14:47:40 +0100
parents 1fda8d2229d7 (current diff) 391b35ef8b24 (diff)
children 9f4442cccedf
files
diffstat 1 files changed, 17 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/specfun/nchoosek.m	Wed Dec 01 21:49:21 2021 +0100
+++ b/scripts/specfun/nchoosek.m	Thu Dec 02 14:47:40 2021 +0100
@@ -121,11 +121,11 @@
     ## 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/2) .* (k-1:-1:(k+1)/2) / 2, k];
+      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;
+      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
 
     ## Remove common factors from numerator and denominator
@@ -140,9 +140,13 @@
       numer = numer(numer > 1);
     until (isempty (denom))
 
-    C = prod (numer);
-    if (C > flintmax)
-      warning ("nchoosek: possible loss of precision");
+    C = prod (numer, "native");
+    if (isfloat (C) && C > flintmax (C))
+      warning ("Octave:nchoosek:large-output-float", ...
+               "nchoosek: possible loss of precision");
+    elseif (isinteger (C) && C == intmax (C))
+      warning ("Octave:nchoosek:large-output-integer", ...
+               "nchoosek: result may have saturated at intmax");
     endif
   elseif (k == 0)
     C = v(zeros (1, 0));  # Return 1x0 object for Matlab compatibility
@@ -269,6 +273,11 @@
 %! assert (isstruct (x));
 %! assert (fieldnames (x), {"a"; "b"});
 
+%!test <61565>
+%! x = nchoosek (uint8 (10), uint8 (5));
+%! assert (x, uint8 (252));
+%! assert (class (x), "uint8");
+
 ## Test input validation
 %!error <Invalid call> nchoosek ()
 %!error <Invalid call> nchoosek (1)
@@ -282,3 +291,4 @@
 %!error <N must be a non-negative integer .= K> nchoosek (-100, 45)
 %!error <N must be a non-negative integer .= K> nchoosek (100.5, 45)
 %!warning <possible loss of precision> nchoosek (100, 45);
+%!warning <result .* saturated> nchoosek (uint64 (80), uint64 (40));