changeset 31379:84fa33608593

normalize.m: Use bsxfun rather than broadcasting (bug #55765) * normalize.m: Replace broadcasting with bsxfun for in "range" option and primary calculation. Add FIXME note that it can revert to broadcasting when sparse and diagonal matrix types no longer produce errors. Add BISTs for sparse and diagonal input handling and xtests for preserving sparseness.
author Nicholas R. Jankowski <jankowski.nicholas@gmail.com>
date Mon, 31 Oct 2022 16:25:46 -0400
parents 8dc9508b8364
children 980059c3b129
files scripts/statistics/normalize.m
diffstat 1 files changed, 36 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/statistics/normalize.m	Mon Oct 31 19:27:17 2022 +0100
+++ b/scripts/statistics/normalize.m	Mon Oct 31 16:25:46 2022 -0400
@@ -389,7 +389,10 @@
           case "robust"
             ## center/median to zero and MAD = 1
             c = median (x, dim);
-            s = median (abs (x - c), dim);
+            ## FIXME: Use bsxfun, rather than broadcasting, until broadcasting
+            ##        supports diagonal and sparse matrices (Bugs #41441, #35787).
+            s = median (abs (bsxfun (@minus, x , c)), dim);
+            ## s = median (abs (x - c), dim);   # Automatic broadcasting
         endswitch
 
       case "norm"
@@ -444,7 +447,11 @@
   endif
 
   ## Divide by scale factor.  If scale = 0, divide by zero = Inf, which is OK.
-  z = (x - c) ./ s;
+
+  ## FIXME: Use bsxfun, rather than broadcasting, until broadcasting
+  ##        supports diagonal and sparse matrices (Bugs #41441, #35787).
+  z = bsxfun (@rdivide, bsxfun (@minus, x , c), s);
+  ## z = (x - c) ./ s;  # Automatic broadcasting
 
 endfunction
 
@@ -610,6 +617,33 @@
 %! [z, c, s] = normalize (Inf);
 %! assert ({z, c, s}, {NaN, Inf, NaN});
 
+## Test sparse and diagonal inputs
+%!test
+%! [z, c, s] = normalize (eye (2));
+%! assert (z, (sqrt(2)/2)*[1, -1; -1, 1], eps);
+%! assert (c, [0.5, 0.5], eps);
+%! assert (s, (sqrt(2)/2)*[1, 1], eps);
+%!test
+%! [z, c, s] = normalize (sparse (eye (2)));
+%! assert (full (z), (sqrt(2)/2)*[1, -1; -1, 1], eps);
+%! assert (full (c), [0.5, 0.5], eps);
+%! assert (full (s), (sqrt(2)/2)*[1, 1], eps);
+%!test
+%! [z, c, s] = normalize (sparse (magic (3)), "zscore", "robust");
+%! assert (full (z), [4 -1 0; -1 0 1; 0 1 -4], eps);
+%! assert (full (c), [4, 5, 6], eps);
+%! assert (full (s), [1, 4, 1], eps);
+%!test <55765>
+%! [z, c, s] = normalize (sparse (eye(2)));
+%! assert (issparse (z));
+%! assert (issparse (c));
+%! assert (issparse (s));
+%!test <55765>
+%! [z, c, s] = normalize (sparse (magic (3)), "zscore", "robust");
+%! assert (issparse (z));
+%! assert (issparse (c));
+%! assert (issparse (s));
+
 ## Matlab ignores NaNs, operating as if the vector had one less element, then
 ## returns the result retaining the NaN in the solution.
 %!assert <50571> (normalize ([1 2 NaN], 2), [-1, 1, NaN]*sqrt(2)/2)