changeset 21540:ffb4770ba079

Make median preserve discrete types (bug #47515). * median.m: Replace mean by "native" sum (or max for logical), and avoid assigning NaN to non-float types. * data.cc (Fnth_element): Allow type bool, treated as an integer.
author Lachlan Andrew <lachlanbis@gmail.com>
date Thu, 24 Mar 2016 13:35:40 +1100
parents 212bafe8413a
children 38c0c1f5cf57
files libinterp/corefcn/data.cc scripts/statistics/base/median.m
diffstat 2 files changed, 18 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/data.cc	Fri Mar 25 16:37:52 2016 -0700
+++ b/libinterp/corefcn/data.cc	Thu Mar 24 13:35:40 2016 +1100
@@ -6929,6 +6929,7 @@
           MAKE_INT_BRANCH (uint16);
           MAKE_INT_BRANCH (uint32);
           MAKE_INT_BRANCH (uint64);
+          MAKE_INT_BRANCH (bool);
 #undef MAKE_INT_BRANCH
         default:
           if (argx.is_cellstr ())
--- a/scripts/statistics/base/median.m	Fri Mar 25 16:37:52 2016 -0700
+++ b/scripts/statistics/base/median.m	Thu Mar 24 13:35:40 2016 +1100
@@ -41,6 +41,9 @@
 ## @end example
 ##
 ## @end ifnottex
+## If @var{x} is of a discrete type such as integer or logical, then
+## the case of even N rounds up (or toward @qcode{true}).
+##
 ## If @var{x} is a matrix, compute the median value for each column and
 ## return them in a row vector.
 ##
@@ -80,10 +83,15 @@
   if (mod (n, 2) == 1)
     retval = nth_element (x, k, dim);
   else
-    retval = mean (nth_element (x, k:k+1, dim), dim);
+    retval = sum (nth_element (x, k:k+1, dim), dim, "native") / 2;
+    if (islogical (x))
+      retval = logical (retval);
+    endif
   endif
   ## Inject NaNs where needed, to be consistent with Matlab.
-  retval(any (isnan (x), dim)) = NaN;
+  if (isfloat (x))
+    retval(any (isnan (x), dim)) = NaN;
+  endif
 
 endfunction
 
@@ -113,6 +121,13 @@
 %!assert (median (a, 4), x(:, :, :, 3))
 %!assert (median (b, 3), (y(:, :, 3, :) + y(:, :, 4, :))/2)
 
+## Test non-floating point types
+%!assert (median ([true, false]), true);
+%!assert (median (uint8 ([1, 3])), uint8 (2));
+%!assert (median (int8 ([1, 3, 4])), int8 (3));
+%!assert (median (single ([1, 3, 4])), single (3));
+%!assert (median (single ([1, 3, NaN])), single (NaN));
+
 ## Test input validation
 %!error median ()
 %!error median (1, 2, 3)