# HG changeset patch
# User Nicholas R. Jankowski <jankowskin@asme.org>
# Date 1633708519 14400
#      Fri Oct 08 11:55:19 2021 -0400
# Node ID d8f8e8cd05c64601cd4f8e801cd3cba6e15931e7
# Parent  aaee7b170cb1449131efdea9f4ec18c61c63e85d
Add functions sumsqr, sumabs, meansqr, meanabs (patch #10119)

* /scripts/statistics/sumsqr.m, sumabs.m, meansqr.m, meanabs.m: new functions
* /scripts/statistics/module.mk: update with new files
* NEWS: update with new function information, compatibility notes

diff -r aaee7b170cb1 -r d8f8e8cd05c6 NEWS
--- a/NEWS	Thu Sep 23 12:19:54 2021 -0700
+++ b/NEWS	Fri Oct 08 11:55:19 2021 -0400
@@ -237,6 +237,11 @@
 compatibility the `print_struct_array_contents` internal variable is set
 to true.
 
+- A Matlab-compatible implementations of the functions `meansqr` and `sumsqr`
+have been added.  Octave's similarly named `meansq` and `sumsq` functions have
+sufficiently different input and output handling behavior that they have been
+kept unchanged for backward compatibilty.
+
 ### Alphabetical list of new functions added in Octave 7
 
 * `cospi`
@@ -249,12 +254,16 @@
 * `listfonts`
 * `matlab.net.base64decode`
 * `matlab.net.base64encode`
+* `meanabs`
+* `meansqr`
 * `memory`
 * `ordqz`
 * `rng`
 * `sinpi`
 * `startsWith`
 * `streamribbon`
+* `sumabs`
+* `sumsqr`
 * `turbo`
 * `uniquetol`
 * `xtickangle`
diff -r aaee7b170cb1 -r d8f8e8cd05c6 scripts/statistics/meanabs.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/statistics/meanabs.m	Fri Oct 08 11:55:19 2021 -0400
@@ -0,0 +1,142 @@
+########################################################################
+##
+## Copyright (C) 1998-2021 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{m} =} meanabs (@var{x})
+## @deftypefnx {} {[@var{m}, @var{n}] =} meanabs (@var{x})
+##
+## Compute the magnitude each element of the array or cell input @var{x} and
+## return the mean of the result as a scalar output @var{m}.  @var{x} may
+## consist of numeric, char, logical, or complex values, and cells may contain
+## mixed types.  Non-finite (Inf, NaN, NA) values are ignored for the
+## calculation.  If requested, the optional output argument @var{n} will contain
+## the number of finite elements in @var{x} used to calculate @var{m}.
+##
+## @example
+## @group
+## a = [1 2 Inf -3];
+## [m, n] = meanabs (@var{a})
+## @result{}
+##    m =
+##        2
+##    n =
+##         3
+## @end group
+## @end example
+## @seealso{mean, abs, meansq, meansqr, sumsqr, sumabs}
+## @end deftypefn
+
+function [m, n] = meanabs (x)
+
+  if ((nargin != 1) || (!any (nargout == [0 1 2])))
+    print_usage ();
+  endif
+
+  if (isnumeric (x) || islogical (x) || ischar (x))
+
+    ## abs first to convert any char to numeric, output column vector
+    x = abs (x(:));
+
+  elseif strcmp (class (x), "cell")
+    ## input validation: check contents after cell flattened
+
+    ## output 1 column cell array with 1 column array cell contents to avoid
+    ## problems with mismatched cell content sizes
+    x = flatten_to_column_cell (x);
+
+    ##check flattened content types
+    if ! all(cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x))
+      bad_cells = ! cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x);
+      bad_class = find (bad_cells, 1, "first");
+      error ("meanabs: MEANABS not defined for cell arrays containing type %s", class (x{bad_class}));
+    endif
+
+    ## convert any chars to numeric with @abs, then revert to array.
+    x = cell2mat (cellfun (@abs, x, "UniformOutput", false));
+
+  else
+    error ("meanabs: MEANABS not defined for type %s", class (x));
+  endif
+
+  ## convert to single column input and exclude non-finite (NaN,Inf, NA)
+  x = x(isfinite (x));
+
+  n = numel (x);
+
+  if n == 0
+    m = 0;
+  else
+    m = mean(x);
+  endif
+
+endfunction
+
+function C = flatten_to_column_cell (C)
+  ## recursively flatten cell of any depth into a n x 1 cell array.
+  if iscell (C)
+    C = cellfun (@flatten_to_column_cell, C, 'UniformOutput', false);
+    C = vertcat (C{:});
+  else
+    C = {C(:)};
+  endif
+endfunction
+
+
+%!assert (meanabs (2), 2)
+%!assert (class (meanabs (single (2))), "single")
+%!assert (class (meanabs ({single(2)})), "single")
+%!assert (meanabs (3+4i), 5)
+%!assert (meanabs ([1, 2, -3]), 2)
+%!assert (meanabs ([1, 2, -3]'), 2)
+%!assert (meanabs (magic (2)-2), 1)
+%!assert (meanabs ({magic(2)-2}), 1)
+%!assert (meanabs ('test'), 112)
+%!assert (meanabs (cat (3, magic(2)-2, magic(2)-2)), 1)
+%!assert (meanabs ([3+4i, 5-12i; 9+12i, 8+15i]), 12.5, 10*eps)
+%!assert (meanabs ({[3+4i, 5-12i; 9+12i, 8+15i]}), 12.5, 10*eps)
+
+##test mixed inputs
+%!assert (meanabs ([{[{1}, {-2}]},{[3; -4]'}]), 2.5, 10*eps)
+%!assert (meanabs ({1, -2, [3, -4]', 'test'}), 57.25, 10*eps)
+%!assert (meanabs ([{1}, {[{-2, {[3, -4], [5, -6]}, -7}]}]), 4, 10*eps)
+
+## test nonfinite inputs
+%!assert (meanabs ([]), 0)
+%!assert (meanabs (Inf), 0)
+%!assert (meanabs ([Inf, NA, NaN]), 0)
+%!assert (meanabs ([Inf, NA, NaN, -1]), 1)
+
+%!test
+%! a = [{'test'}, {[{2, -7}]}, Inf];
+%! [m, n] = meanabs (a);
+%! assert (m, 457/6)
+%! assert (n, 6)
+
+## Test input validation
+%!error meanabs ()
+%!error meanabs (1, 2)
+%!error [a, b, c] = meanabs (1, 2)
+%!error <MEANABS not defined for type> meanabs (struct("a",1))
+%!error <MEANABS not defined for cell arrays containing type> meanabs ({1, struct("a",1)})
diff -r aaee7b170cb1 -r d8f8e8cd05c6 scripts/statistics/meansqr.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/statistics/meansqr.m	Fri Oct 08 11:55:19 2021 -0400
@@ -0,0 +1,141 @@
+########################################################################
+##
+## Copyright (C) 1998-2021 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{m} =} meansqr (@var{x})
+## @deftypefnx {} {[@var{m}, @var{n}] =} meansqr (@var{x})
+##
+## Square each element of the array or cell input @var{x} and return the mean of
+## the result as a scalar output @var{m}.  @var{x} may consist of numeric, char,
+## logical, or complex values, and cells may contain mixed types.  Non-finite
+## (Inf, NaN, NA) values are ignored for the calculation.  If requested, the
+## optional output argument @var{n} will contain the number of finite elements
+## in @var{x} used to calculate @var{m}.
+##
+## @example
+## @group
+## a = [1 2 Inf 3];
+## [m, n] = meansqr (@var{a})
+## @result{}
+##    m =
+##        4.6667
+##    n =
+##         3
+## @end group
+## @end example
+## @seealso{mean, meanabs, meansq, sumsqr, sumabs}
+## @end deftypefn
+
+function [m, n] = meansqr (x)
+
+  if ((nargin != 1) || (!any (nargout == [0 1 2])))
+    print_usage ();
+  endif
+
+  if (isnumeric (x) || islogical (x) || ischar (x))
+
+    ## square first to convert any char to numeric, output column vector
+    x = x(:).^2;
+
+  elseif strcmp (class (x), "cell")
+    ## input validation: check contents after cell flattened
+
+    ## output 1 column cell array with 1 column array cell contents to avoid
+    ## problems with mismatched cell content sizes
+    x = flatten_to_column_cell (x);
+
+    ##check flattened content types
+    if ! all(cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x))
+      bad_cells = ! cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x);
+      bad_class = find (bad_cells, 1, "first");
+      error ("meansqr: MEANSQR not defined for cell arrays containing type %s", class (x{bad_class}));
+    endif
+
+    ## convert any chars to numeric with @power, then revert to array.
+    x = cell2mat (cellfun (@power, x, {2}, "UniformOutput", false));
+
+  else
+    error ("meansqr: MEANSQR not defined for type %s", class (x));
+  endif
+
+  ## convert to single column input and exclude non-finite (NaN,Inf, NA)
+  x = x(isfinite (x));
+
+  n = numel (x);
+
+  if n == 0
+    m = 0;
+  else
+    m = mean (x);
+  endif
+
+endfunction
+
+function C = flatten_to_column_cell (C)
+  ## recursively flatten cell of any depth into a n x 1 cell array.
+  if iscell (C)
+    C = cellfun (@flatten_to_column_cell, C, 'UniformOutput', false);
+    C = vertcat (C{:});
+  else
+    C = {C(:)};
+  endif
+endfunction
+
+%!assert (meansqr (2), 4)
+%!assert (class (meansqr (single (2))), "single")
+%!assert (class (meansqr ({single(2)})), "single")
+%!assert (meansqr (2+3i), -5+12i)
+%!assert (meansqr ([1, 2, 4]), 7)
+%!assert (meansqr ([1, 2, 4]'), 7)
+%!assert (meansqr (magic (2)), 7.5, 10*eps)
+%!assert (meansqr ({magic(2)}), 7.5, 10*eps)
+%!assert (meansqr ('foo'), 11682)
+%!assert (meansqr (cat (3, magic(2), magic(2))), 7.5, 10*eps)
+%!assert (meansqr ([1+i, 2-i; 3+2i, 4-2i]), 5-1.5i, 10*eps)
+%!assert (meansqr ({[1+i, 2-i; 3+2i, 4-2i]}), 5-1.5i, 10*eps)
+
+##test mixed inputs
+%!assert (meansqr ([{[{1}, {2}]},{[3; 4]'}]), 7.5, 10*eps)
+%!assert (meansqr ({1, 2, [3, 4]', 'test'}), 6296)
+%!assert (meansqr ([{1}, {[{2, {[3, 4], [5, 6]}, 7}]}]), 20)
+
+## test nonfinite inputs
+%!assert (meansqr ([]), 0)
+%!assert (meansqr (Inf), 0)
+%!assert (meansqr ([Inf, NA, NaN]), 0)
+%!assert (meansqr ([Inf, NA, NaN, 1]), 1)
+
+%!test
+%! a = [{'a'}, {[{2, 7}]}, Inf];
+%! [m, n] = meansqr (a);
+%! assert (m, 3154)
+%! assert (n, 3)
+
+## Test input validation
+%!error meansqr ()
+%!error meansqr (1, 2)
+%!error [a, b, c] = meansqr (1, 2)
+%!error <MEANSQR not defined for type> meansqr (struct("a",1))
+%!error <MEANSQR not defined for cell arrays containing type> meansqr ({1, struct("a",1)})
diff -r aaee7b170cb1 -r d8f8e8cd05c6 scripts/statistics/module.mk
--- a/scripts/statistics/module.mk	Thu Sep 23 12:19:54 2021 -0700
+++ b/scripts/statistics/module.mk	Fri Oct 08 11:55:19 2021 -0400
@@ -21,7 +21,9 @@
   %reldir%/kurtosis.m \
   %reldir%/mad.m \
   %reldir%/mean.m \
+  %reldir%/meanabs.m \
   %reldir%/meansq.m \
+  %reldir%/meansqr.m \
   %reldir%/median.m \
   %reldir%/mode.m \
   %reldir%/moment.m \
@@ -42,6 +44,8 @@
   %reldir%/runlength.m \
   %reldir%/skewness.m \
   %reldir%/spearman.m \
+  %reldir%/sumsqr.m \
+  %reldir%/sumabs.m \
   %reldir%/statistics.m \
   %reldir%/std.m \
   %reldir%/var.m \
diff -r aaee7b170cb1 -r d8f8e8cd05c6 scripts/statistics/sumabs.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/statistics/sumabs.m	Fri Oct 08 11:55:19 2021 -0400
@@ -0,0 +1,142 @@
+########################################################################
+##
+## Copyright (C) 1998-2021 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{s} =} sumabs (@var{x})
+## @deftypefnx {} {[@var{s}, @var{n}] =} sumabs (@var{x})
+##
+## Compute the magnitude each element of the array or cell input @var{x} and
+## return the sum of the result as a scalar output @var{s}.  @var{x} may consist
+## of numeric, char, logical, or complex values, and cells may contain mixed
+## types.  Non-finite (Inf, NaN, NA) values are ignored for the calculation.  If
+## requested, the optional output argument @var{n} will contain the number of
+## finite elements in @var{x} used to calculate @var{s}.
+##
+## @example
+## @group
+## a = [1 2 Inf -3];
+## [s, n] = sumabs (@var{a})
+## @result{}
+##    s =
+##        6
+##    n =
+##         3
+## @end group
+## @end example
+## @seealso{sum, abs, sumsqr, meanabs, meansq, meansqr}
+## @end deftypefn
+
+function [s, n] = sumabs (x)
+
+  if ((nargin != 1) || (!any (nargout == [0 1 2])))
+    print_usage ();
+  endif
+
+  if (isnumeric (x) || islogical (x) || ischar (x))
+
+    ## abs first to convert any char to numeric, output column vector
+    x = abs (x(:));
+
+  elseif strcmp (class (x), "cell")
+    ## input validation: check contents after cell flattened
+
+    ## output 1 column cell array with 1 column array cell contents to avoid
+    ## problems with mismatched cell content sizes
+    x = flatten_to_column_cell (x);
+
+    ##check flattened content types
+    if ! all(cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x))
+      bad_cells = ! cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x);
+      bad_class = find (bad_cells, 1, "first");
+      error ("sumabs: SUMABS not defined for cell arrays containing type %s", class (x{bad_class}));
+    endif
+
+    ## convert any chars to numeric with @abs, then revert to array.
+    x = cell2mat (cellfun (@abs, x, "UniformOutput", false));
+
+  else
+    error ("sumabs: SUMABS not defined for type %s", class (x));
+  endif
+
+  ## convert to single column input and exclude non-finite (NaN,Inf, NA)
+  x = x(isfinite (x));
+
+  n = numel (x);
+
+  if n == 0
+    s = 0;
+  else
+    s = sum (x);
+  endif
+
+endfunction
+
+function C = flatten_to_column_cell (C)
+  ## recursively flatten cell of any depth into a n x 1 cell array.
+  if iscell (C)
+    C = cellfun (@flatten_to_column_cell, C, 'UniformOutput', false);
+    C = vertcat (C{:});
+  else
+    C = {C(:)};
+  endif
+endfunction
+
+
+%!assert (sumabs (2), 2)
+%!assert (class (sumabs (single (2))), "single")
+%!assert (class (sumabs ({single(2)})), "single")
+%!assert (sumabs (3+4i), 5)
+%!assert (sumabs ([1, 2, -3]), 6)
+%!assert (sumabs ([1, 2, -3]'), 6)
+%!assert (sumabs (magic (2)-2), 4)
+%!assert (sumabs ({magic(2)-2}), 4)
+%!assert (sumabs ('test'), 448)
+%!assert (sumabs (cat (3, magic(2)-2, magic(2)-2)), 8)
+%!assert (sumabs ([3+4i, 5-12i; 9+12i, 8+15i]), 50)
+%!assert (sumabs ({[3+4i, 5-12i; 9+12i, 8+15i]}), 50)
+
+##test mixed inputs
+%!assert (sumabs ([{[{1}, {-2}]},{[3; -4]'}]), 10)
+%!assert (sumabs ({1, -2, [3, -4]', 'test'}), 458)
+%!assert (sumabs ([{1}, {[{-2, {[3, -4], [5, -6]}, -7}]}]), 28)
+
+## test nonfinite inputs
+%!assert (sumabs ([]), 0)
+%!assert (sumabs (Inf), 0)
+%!assert (sumabs ([Inf, NA, NaN]), 0)
+%!assert (sumabs ([Inf, NA, NaN, -1]), 1)
+
+%!test
+%! a = [{'test'}, {[{2, -7}]}, Inf];
+%! [s, n] = sumabs (a);
+%! assert (s, 457)
+%! assert (n, 6)
+
+## Test input validation
+%!error sumabs ()
+%!error sumabs (1, 2)
+%!error [a, b, c] = sumabs (1, 2)
+%!error <SUMABS not defined for type> sumabs (struct("a",1))
+%!error <SUMABS not defined for cell arrays containing type> sumabs ({1, struct("a",1)})
diff -r aaee7b170cb1 -r d8f8e8cd05c6 scripts/statistics/sumsqr.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/statistics/sumsqr.m	Fri Oct 08 11:55:19 2021 -0400
@@ -0,0 +1,141 @@
+########################################################################
+##
+## Copyright (C) 1998-2021 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{s} =} sumsqr (@var{x})
+## @deftypefnx {} {[@var{s}, @var{n}] =} sumsqr (@var{x})
+##
+## Square each element of the array or cell input @var{x} and return the sum of
+## the result as a scalar output @var{s}.  @var{x} may consist of numeric, char,
+## logical, or complex values, and cells may contain mixed types.  Non-finite
+## (Inf, NaN, NA) values are ignored for the calculation.  If requested, the
+## optional output argument @var{n} will contain the number of finite elements
+## in @var{x} used to calculate @var{s}.
+##
+## @example
+## @group
+## a = [1 2 Inf -3];
+## [s, n] = sumsqr (@var{a})
+## @result{}
+##    s =
+##        14
+##    n =
+##         3
+## @end group
+## @end example
+## @seealso{sum, sumsq, sumabs, meansqr, meansq, meanabs}
+## @end deftypefn
+
+function [s, n] = sumsqr (x)
+
+  if ((nargin != 1) || (!any (nargout == [0 1 2])))
+    print_usage ();
+  endif
+
+  if (isnumeric (x) || islogical (x) || ischar (x))
+
+    ## square first to convert any char to numeric, output column vector
+    x = x(:).^2;
+
+  elseif strcmp (class (x), "cell")
+    ## input validation: check contents after cell flattened
+
+    ## output 1 column cell array with 1 column array cell contents to avoid
+    ## problems with mismatched cell content sizes
+    x = flatten_to_column_cell (x);
+
+    ##check flattened content types
+    if ! all(cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x))
+      bad_cells = ! cellfun (@(C) isnumeric (C) || islogical (C) || ischar (C), x);
+      bad_class = find (bad_cells, 1, "first");
+      error ("sumsqr: SUMSQR not defined for cell arrays containing type %s", class (x{bad_class}));
+    endif
+
+    ## convert any chars to numeric with @power, then revert to array.
+    x = cell2mat (cellfun (@power, x, {2}, "UniformOutput", false));
+
+  else
+    error ("sumsqr: SUMSQR not defined for type %s", class (x));
+  endif
+
+  ## convert to single column input and exclude non-finite (NaN,Inf, NA)
+  x = x(isfinite (x));
+
+  n = numel (x);
+
+  if n == 0
+    s = 0;
+  else
+    s = sum (x);
+  endif
+
+endfunction
+
+function C = flatten_to_column_cell (C)
+  ## recursively flatten cell of any depth into a n x 1 cell array.
+  if iscell (C)
+    C = cellfun (@flatten_to_column_cell, C, 'UniformOutput', false);
+    C = vertcat (C{:});
+  else
+    C = {C(:)};
+  endif
+endfunction
+
+%!assert (sumsqr (2), 4)
+%!assert (class (sumsqr (single (2))), "single")
+%!assert (class (sumsqr ({single(2)})), "single")
+%!assert (sumsqr (2+3i), -5+12i)
+%!assert (sumsqr ([1, 2, 3]), 14)
+%!assert (sumsqr ([1, 2, 3]'), 14)
+%!assert (sumsqr (magic (2)), 30)
+%!assert (sumsqr ({magic(2)}), 30)
+%!assert (sumsqr ('test'), 50338)
+%!assert (sumsqr (cat (3, magic(2), magic(2))), 60)
+%!assert (sumsqr ([1+i, 2-i; 3+2i, 4-2i]), 20-6i)
+%!assert (sumsqr ({[1+i, 2-i; 3+2i, 4-2i]}), 20-6i)
+
+##test mixed inputs
+%!assert (sumsqr ([{[{1}, {2}]},{[3; 4]'}]), 30)
+%!assert (sumsqr ({1, 2, [3, 4]', 'test'}), 50368)
+%!assert (sumsqr ([{1}, {[{2, {[3, 4], [5, 6]}, 7}]}]), 140)
+
+## test nonfinite inputs
+%!assert (sumsqr ([]), 0)
+%!assert (sumsqr (Inf), 0)
+%!assert (sumsqr ([Inf, NA, NaN]), 0)
+%!assert (sumsqr ([Inf, NA, NaN, 1]), 1)
+
+%!test
+%! a = [{'test'}, {[{2, 7}]}, Inf];
+%! [s, n] = sumsqr (a);
+%! assert (s, 50391)
+%! assert (n, 6)
+
+## Test input validation
+%!error sumsqr ()
+%!error sumsqr (1, 2)
+%!error [a, b, c] = sumsqr (1, 2)
+%!error <SUMSQR not defined for type> sumsqr (struct("a",1))
+%!error <SUMSQR not defined for cell arrays containing type> sumsqr ({1, struct("a",1)})
