changeset 31370:80bd450892b2 stable

var.m: Use bsxfun rather than broadcasting with vector weighting (bug #63291) * var.m: Replace broadcasting with bsxfun for var calculation in vector weighting codepath. 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. * etc/NEWS.7.md: Note bugfix for sparse and diagonal inputs under Improvements and fixes.
author Nicholas R. Jankowski <jankowski.nicholas@gmail.com>
date Sun, 30 Oct 2022 23:42:04 -0400
parents 9e7a7e6f54bc
children c549b2401c38 da3ac42a143d
files etc/NEWS.7.md scripts/statistics/var.m
diffstat 2 files changed, 16 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS.7.md	Wed Oct 26 19:11:04 2022 +0200
+++ b/etc/NEWS.7.md	Sun Oct 30 23:42:04 2022 -0400
@@ -23,6 +23,7 @@
 - Fix incorrect `lambda` outputs for `lsqnonneg` and `pqpnonneg` (bug #63178).
 - `addtodate.m`: Fix wrong month returned when subtracting a month from some end-of-month dates (bug #60671).
 - `var.m`: Fix some Inf and NaN inputs returning 0 instead of NaN (bug #63203)
+- `var.m`: Fix automatic broadcasting error for sparse and diagonal matrix inputs with vector weighting (bug #63291).
 - `legend.m`: Fix error with `contour` plot containing `clabel`s (bug #63262).
 - `dec2bin.m`: Fix input validation (bug #63089).
 - `glpk.m`: Avoid using `isfinite` on potentially sparse input.
--- a/scripts/statistics/var.m	Wed Oct 26 19:11:04 2022 +0200
+++ b/scripts/statistics/var.m	Sun Oct 30 23:42:04 2022 -0400
@@ -216,8 +216,13 @@
             w = reshape (w, newdims);
           endif
           den = sum (w);
-          mu = sum (w .* x, dim) ./ sum (w);
-          retval = sum (w .* ((x - mu) .^ 2), dim) / den;
+          ## FIXME: Use bsxfun, rather than broadcasting, until broadcasting
+          ##        supports diagonal and sparse matrices (Bugs #41441, #35787).
+          mu = sum (bsxfun (@times, w , x), dim) ./ sum (w);
+          retval = sum (bsxfun (@times, w, ...
+                                bsxfun (@minus, x, mu) .^ 2), dim) / den;
+          ## mu = sum (w .* x, dim) ./ sum (w); # automatic broadcasting
+          ## retval = sum (w .* ((x - mu) .^ 2), dim) / den;
         endif
       endif
     endif
@@ -288,6 +293,14 @@
 %!assert <*63203> (var ([1, 3, NaN; 3, 5, Inf]), [2, 2, NaN])
 %!assert <*63203> (var ([1, 3, Inf; 3, 5, NaN]), [2, 2, NaN]);
 
+## Test sparse/diagonal inputs
+%!assert <*63291> (var (2 * eye (2)), [2, 2])
+%!assert <*63291> (var (4 * eye (2), [1, 3]), [3, 3])
+%!assert <*63291> (full (var (sparse (2 * eye (2)))), [2, 2])
+%!assert <*63291> (full (var (sparse (4 * eye (2)), [1, 3])), [3, 3])
+%!assert <63291> (issparse (var (sparse (2 * eye (2)))))
+%!assert <63291> (issparse (var (sparse (4 * eye (2)), [1, 3])))
+
 ## Test input validation
 %!error <Invalid call> var ()
 %!error <X must be a numeric> var (['A'; 'B'])