# HG changeset patch # User Rik # Date 1606881291 28800 # Node ID ee39aef7c4173deda7a8fd610fb0abfc1b1db33a # Parent c45cf1fd51b832ddbb97ae7b6d98c3a567b23059 vecnorm.m: Overhaul function. * vecnorm.m: Rewrite documentation. Add input validation for A and reduce number of ! operators required for validating P input. Use isindex to simplify validating DIM input. Add comment about why special case for P being a multiple of 2 is used. Add additional special case of a real matrix where P==2 for 75% speed improvement. Add BIST tests for new input validation and modify existing tests to pass with new modified error messages. diff -r c45cf1fd51b8 -r ee39aef7c417 scripts/linear-algebra/vecnorm.m --- a/scripts/linear-algebra/vecnorm.m Tue Dec 01 14:59:32 2020 -0800 +++ b/scripts/linear-algebra/vecnorm.m Tue Dec 01 19:54:51 2020 -0800 @@ -27,7 +27,8 @@ ## @deftypefn {} {@var{n} =} vecnorm (@var{A}) ## @deftypefnx {} {@var{n} =} vecnorm (@var{A}, @var{p}) ## @deftypefnx {} {@var{n} =} vecnorm (@var{A}, @var{p}, @var{dim}) -## Return the p-norm of the elements of @var{A} along dimension @var{dim}. +## Return the vector p-norm of the elements of array @var{A} along dimension +## @var{dim}. ## ## The p-norm of a vector is defined as ## @@ -41,10 +42,14 @@ ## @end example ## ## @end ifnottex -## If @var{p} is omitted it defaults to 2 (Euclidean norm). @var{p} can be -## @code{Inf} (absolute value of largest element). +## The input @var{p} must be a positive scalar. If omitted it defaults to 2 +## (Euclidean norm or distance). Other special values of @var{p} are 1 +## (Manhattan norm, sum of absolute values) and @code{Inf} (absolute value of +## largest element). ## -## If @var{dim} is omitted the first non-singleton dimension is used. +## The input @var{dim} specifies the dimension of the array on which the +## function operates and must be a positive integer. If omitted the first +## non-singleton dimension is used. ## ## @seealso{norm} ## @end deftypefn @@ -55,16 +60,19 @@ print_usage (); endif - if (! isscalar (p) || ! isreal (p) || (p <= 0)) + if (! isnumeric (A)) + error ("vecnorm: A must be numeric"); + endif + + if (! (isscalar (p) && isreal (p) && p > 0)) error ("vecnorm: P must be positive real scalar or Inf"); endif - sz = size (A); - if (nargin <= 2) + if (nargin < 3) ## Find the first non-singleton dimension. - (dim = find (sz > 1, 1)) || (dim = 1); - elseif (! (isscalar (dim) && dim == fix (dim) && dim > 0)) - error ("vecnorm: DIM must be an integer and a valid dimension"); + (dim = find (size (A) > 1, 1)) || (dim = 1); + elseif (! (isscalar (dim) && isindex (dim))) + error ("vecnorm: DIM must be a positive integer"); endif ## Calculate norm using the value of p to accelerate special cases @@ -80,7 +88,13 @@ otherwise if (rem (p,2) == 0) - n = (sum ((real (A).^2 + imag (A).^2) .^ (p/2), dim)) .^ (1 / p); + ## Even index such as 2,4,6 are specifically accelerated in math + ## libraries. Beyond 6, it doesn't matter which method is used. + if (iscomplex (A)) + n = (sum ((real (A).^2 + imag (A).^2) .^ (p/2), dim)) .^ (1 / p); + else + n = (sum (A.^2 .^ (p/2), dim)) .^ (1 / p); + endif else n = (sum (abs (A) .^ p, dim)) .^ (1 / p); endif @@ -112,11 +126,12 @@ ## Test input validation %!error vecnorm () +%!error vecnorm ({1}) %!error

vecnorm (1, [1 2]) %!error

vecnorm (1, i) %!error

vecnorm (1, -1) %!error

vecnorm (1, 0) -%!error vecnorm (1, 2, [1 2]) -%!error vecnorm (1, 2, [1 2]) -%!error vecnorm (1, 2, 0) -%!error vecnorm (1, 2, -1) +%!error vecnorm (1, 2, [1 2]) +%!error vecnorm (1, 2, -1) +%!error vecnorm (1, 2, 0) +%!error vecnorm (1, 2, 1.5)