comparison scripts/statistics/normalize.m @ 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 d727bda73574
children fd29c7a50a78
comparison
equal deleted inserted replaced
31378:8dc9508b8364 31379:84fa33608593
387 case "std" 387 case "std"
388 [s, c] = std (x, [], dim); 388 [s, c] = std (x, [], dim);
389 case "robust" 389 case "robust"
390 ## center/median to zero and MAD = 1 390 ## center/median to zero and MAD = 1
391 c = median (x, dim); 391 c = median (x, dim);
392 s = median (abs (x - c), dim); 392 ## FIXME: Use bsxfun, rather than broadcasting, until broadcasting
393 ## supports diagonal and sparse matrices (Bugs #41441, #35787).
394 s = median (abs (bsxfun (@minus, x , c)), dim);
395 ## s = median (abs (x - c), dim); # Automatic broadcasting
393 endswitch 396 endswitch
394 397
395 case "norm" 398 case "norm"
396 switch (methodoption) 399 switch (methodoption)
397 case 1 400 case 1
442 endswitch 445 endswitch
443 446
444 endif 447 endif
445 448
446 ## Divide by scale factor. If scale = 0, divide by zero = Inf, which is OK. 449 ## Divide by scale factor. If scale = 0, divide by zero = Inf, which is OK.
447 z = (x - c) ./ s; 450
451 ## FIXME: Use bsxfun, rather than broadcasting, until broadcasting
452 ## supports diagonal and sparse matrices (Bugs #41441, #35787).
453 z = bsxfun (@rdivide, bsxfun (@minus, x , c), s);
454 ## z = (x - c) ./ s; # Automatic broadcasting
448 455
449 endfunction 456 endfunction
450 457
451 function c = process_center_option (x, dim, center_option) 458 function c = process_center_option (x, dim, center_option)
452 459
608 %! [z, c, s] = normalize ([1 2 Inf], 2); 615 %! [z, c, s] = normalize ([1 2 Inf], 2);
609 %! assert ({z, c, s}, {[NaN, NaN, NaN], Inf, NaN}); 616 %! assert ({z, c, s}, {[NaN, NaN, NaN], Inf, NaN});
610 %! [z, c, s] = normalize (Inf); 617 %! [z, c, s] = normalize (Inf);
611 %! assert ({z, c, s}, {NaN, Inf, NaN}); 618 %! assert ({z, c, s}, {NaN, Inf, NaN});
612 619
620 ## Test sparse and diagonal inputs
621 %!test
622 %! [z, c, s] = normalize (eye (2));
623 %! assert (z, (sqrt(2)/2)*[1, -1; -1, 1], eps);
624 %! assert (c, [0.5, 0.5], eps);
625 %! assert (s, (sqrt(2)/2)*[1, 1], eps);
626 %!test
627 %! [z, c, s] = normalize (sparse (eye (2)));
628 %! assert (full (z), (sqrt(2)/2)*[1, -1; -1, 1], eps);
629 %! assert (full (c), [0.5, 0.5], eps);
630 %! assert (full (s), (sqrt(2)/2)*[1, 1], eps);
631 %!test
632 %! [z, c, s] = normalize (sparse (magic (3)), "zscore", "robust");
633 %! assert (full (z), [4 -1 0; -1 0 1; 0 1 -4], eps);
634 %! assert (full (c), [4, 5, 6], eps);
635 %! assert (full (s), [1, 4, 1], eps);
636 %!test <55765>
637 %! [z, c, s] = normalize (sparse (eye(2)));
638 %! assert (issparse (z));
639 %! assert (issparse (c));
640 %! assert (issparse (s));
641 %!test <55765>
642 %! [z, c, s] = normalize (sparse (magic (3)), "zscore", "robust");
643 %! assert (issparse (z));
644 %! assert (issparse (c));
645 %! assert (issparse (s));
646
613 ## Matlab ignores NaNs, operating as if the vector had one less element, then 647 ## Matlab ignores NaNs, operating as if the vector had one less element, then
614 ## returns the result retaining the NaN in the solution. 648 ## returns the result retaining the NaN in the solution.
615 %!assert <50571> (normalize ([1 2 NaN], 2), [-1, 1, NaN]*sqrt(2)/2) 649 %!assert <50571> (normalize ([1 2 NaN], 2), [-1, 1, NaN]*sqrt(2)/2)
616 %!assert <50571> (normalize ([1 2 NaN; 1 2 3], 2), [[-1 1 NaN]*sqrt(2)/2; -1 0 1], eps) 650 %!assert <50571> (normalize ([1 2 NaN; 1 2 3], 2), [[-1 1 NaN]*sqrt(2)/2; -1 0 1], eps)
617 651