changeset 29311:2d26113ddf57

uniquetol.m: Update documentation and BIST tests (bug #59850). * uniquetol.m: Update documentation and BIST tests (bug #59850).
author Rik <rik@octave.org>
date Fri, 22 Jan 2021 11:45:59 -0800
parents 0fb5ba41a12a
children 875d799ab0b3
files scripts/set/uniquetol.m
diffstat 1 files changed, 65 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/set/uniquetol.m	Fri Jan 22 17:13:01 2021 +0100
+++ b/scripts/set/uniquetol.m	Fri Jan 22 11:45:59 2021 -0800
@@ -30,54 +30,68 @@
 ## @deftypefnx {} {[@var{c}, @var{ia}, @var{ic}] =} uniquetol (@dots{})
 ## Return the unique elements of @var{A} within tolerance @var{tol}.
 ##
-## Two values, @var{x} and @var{y}, are within tolerance if
+## Two values, @var{x} and @var{y}, are within relative tolerance if
 ## @code{abs (@var{x} - @var{y}) <= @var{tol} * max (abs (@var{A}(:)))}.
 ##
-## If it is unspecified, the default tolerance is 1e-12 for double precision
-## input or 1e-6 for single precision input, respectively.
-##
-## The input input @var{A} must be a floating point type (double or single).
+## The input @var{A} must be a floating point type (double or single).
 ##
-## The output @var{C} is a row vector if the input @var{A} is a row vector.
-## For all other cases, a column vector is returned.
+## If @var{tol} is unspecified, the default tolerance is 1e-12 for double
+## precision input or 1e-6 for single precision input.
 ##
-## @var{IA} and @var{IC} are column index vectors such that
-## @code{@var{C} = @var{A}(@var{IA})} and @code{@var{A} = @var{C}(@var{IC})}.
-##
-## Additionally, the function can be called with the following optional
-## property value pairs. Property value pairs must be passed after the other
-## input arguments:
+## The function may also be called with the following optional property/value
+## pairs.  Property/value pairs must be passed after other input arguments:
 ##
 ## @table @asis
-## @item @qcode{"ByRows"}, @code{true}
-## The function returns the unique rows of @var{A}.
+## @item @qcode{"ByRows"} (default: @code{false})
+## When true, return the unique rows of @var{A}.  @var{A} must be a 2-D array
+## to use this option.  For rows, the criteria for uniqueness is changed to
+## @code{all (abs (@var{x} - @var{y}) <= @var{tol}*max (abs (@var{A}),[],1))}
+## which compares each column component of a row against a column-specific
+## tolerance.
 ##
-## @item @qcode{"DataScale"}, @var{DS}
+## @item @qcode{"DataScale"}
 ## The tolerance test is changed to
-## @code{abs (@var{x}-@var{y}) <= @var{tol}*@var{DS}} where @var{DS} is a scalar
-## unless the property @qcode{"ByRows"} is set to @code{true}.  In that case,
-## @var{DS} can be a scalar or a vector with a length equal to the number of
-## rows in @var{A}.  Using a value of 1.0 for @var{DS} will change the
-## tolerance from a relative one to an absolute tolerance.
+## @code{abs (@var{x} - @var{y}) <= @var{tol}*@var{DS}} where @var{DS} is a
+## scalar unless the property @qcode{"ByRows"} is true.  In that case, @var{DS}
+## can either be a scalar or a vector with a length equal to the number of
+## columns in @var{A}.  Using a value of @code{1.0} for @var{DS} will change
+## the tolerance from a relative one to an absolute tolerance.  Using a value
+## of @code{Inf} will disable testing.
 ##
-## @item @qcode{"OutputAllIndices"}, @code{true}
-## @var{IA} is a cell array that contains the indices for all elements in
-## @var{A} that are within tolerance of a value in @var{C}. That is, each cell
-## in @var{IA} corresponds to a value in @var{C}, and the values in each cell
-## correspond to locations in @var{A}.
+## @item @qcode{"OutputAllIndices"} (default: @code{false})
+## When true, @var{ia} is a cell array (not a vector) that contains the indices
+## for @emph{all} elements in @var{A} that are within tolerance of a value in
+## @var{C}.  That is, each cell in @var{ia} corresponds to a single unique
+## value in @var{C}, and the values in each cell correspond to locations in
+## @var{A}.
 ## @end table
 ##
-## Example:
+## The output @var{c} is a row vector if the input @var{A} is a row vector.
+## For all other cases, a column vector is returned.
+##
+## The optional output @var{ia} is a column index vector such that
+## @code{@var{c} = @var{A}(@var{ia})}.  If the @qcode{"ByRows"} property is
+## true the condition is @code{@var{c} = @var{A}(@var{ia}, :)}.  If the
+## @qcode{"OutputAllIndices"} property is true then the values
+## @code{@var{A}(@var{ia}{i})} are all within tolerance of the unique value
+## @code{@var{c}(@var{i}).
+##
+## The optional output @var{ic} is a column index vector such that
+## @code{@var{A} = @var{c}(@var{ic})} when @var{A} is a vector.  When @var{A}
+## is a matrix, @code{@var{A}(:) = @var{c}(@var{ic})}.  If the @qcode{"ByRows"}
+## property is true then @code{@var{A} = @var{c}(@var{ic},:)}.
+##
+## Example: small round-off errors require @code{uniquetol}, not @code{unique}
 ##
 ## @example
 ## @group
-## x = (1:6)*pi;
-## y = 10.^log10 (x);
+## x = [1:5];
+## ## Inverse_Function (Function (x)) should return exactly x
+## y = exp (log (x));
+## D = unique ([x, y])
+## @result{} [1.0000   2.0000   3.0000   3.0000   4.0000   5.0000   5.0000]
 ## C = uniquetol ([x, y])
-## @result{} [3.1416, 6.2832, 9.4248, 12.5664, 15.7080, 18.8496]
-## D = unique ([x, y])
-## @result{} [3.1416, 6.2832, 9.4248, 12.5664, 12.5664, 15.7080,
-## 18.8496, 18.8496]
+## @result{} [1   2   3   4   5]
 ## @end group
 ## @end example
 ##
@@ -207,8 +221,8 @@
 endfunction
 
 
-%!assert (uniquetol ([1 1 2; 1 2 1; 1 1 2]), [1;2])
-%!assert (uniquetol ([1 1 2; 1 0 1; 1 1 2], 1e-12, "byrows", true),
+%!assert (uniquetol ([1 1 2; 1 2 1; 1 1 2+10*eps]), [1;2])
+%!assert (uniquetol ([1 1 2; 1 0 1; 1 1 2+10*eps], "byrows", true),
 %!        [1 1 2; 1 0 1])
 %!assert (uniquetol ([]), [])
 %!assert (uniquetol ([1]), [1])
@@ -218,30 +232,31 @@
 %!assert (uniquetol ([1; 2]), [1; 2])
 %!xtest <59850>
 %! ## FIXME: Matlab returns only one unique value for Inf.
-%! assert (uniquetol ([1, NaN, Inf, NaN, Inf]), [1, Inf, NaN, NaN]);
+%! assert (uniquetol ([-Inf, 1, NaN, Inf, NaN, Inf]), [-Inf, 1, Inf, NaN, NaN]);
 %!xtest <59850>
 %! ## FIXME: Matlab returns empty column vectors.
 %! ##        Do we want to bother with that?
 %! assert (uniquetol (zeros (1,0)), zeros (0,1));
-%!assert (uniquetol (zeros (1,0), 1e-12, "byrows", true), zeros (1,0))
-%!assert (uniquetol ([1,2,2,3,2,4], 1e-12, "byrows", true), [1,2,2,3,2,4])
+%!assert (uniquetol (zeros (1,0), "byrows", true), zeros (1,0))
+%!assert (uniquetol ([1,2,2,3,2,4], "byrows", true), [1,2,2,3,2,4])
 %!assert (uniquetol ([1,2,2,3,2,4]), [1,2,3,4])
-%!assert (uniquetol ([1,2,2,3,2,4].', 1e-12, "byrows", true), [1;2;3;4])
+%!assert (uniquetol ([1,2,2,3,2,4].', "byrows", true), [1;2;3;4])
 %!assert (uniquetol (sparse ([2,0;2,0])), sparse ([2;0]))
 %!assert (uniquetol (sparse ([1,2;2,3])), sparse ([1;2;3]))
-%!assert (uniquetol ([1,2,2,3,2,4]', 1e-12, "byrows", true), [1;2;3;4])
-%!assert (uniquetol (single ([1,2,2,3,2,4]), 1e-12, "byrows", true),
+%!assert (uniquetol (single ([1,2,2,3,2,4]), "byrows", true),
 %!        single ([1,2,2,3,2,4]))
 %!assert (uniquetol (single ([1,2,2,3,2,4])), single ([1,2,3,4]))
-%!assert (uniquetol (single ([1,2,2,3,2,4].'), 1e-12, "byrows", true),
+%!assert (uniquetol (single ([1,2,2,3,2,4].'), "byrows", true),
 %!        single ([1;2;3;4]))
 
+## Test index vector return arguments
 %!test
 %! [c, ia, ic] = uniquetol ([1,1,2,3,3,3,4]);
 %! assert (c, [1,2,3,4]);
 %! assert (ia, [1;3;4;7]);
 %! assert (ic, [1;1;2;3;3;3;4]);
 
+## Test index vector return arguments with "ByRows"
 %!test
 %! A = [2, 3, 4; 2, 3, 4];
 %! [c, ia, ic] = uniquetol (A, "byrows", true);
@@ -251,17 +266,23 @@
 
 %!test
 %! x = (2:7)'*pi;
-%! y = exp (1).^log (x);
+%! y = exp (log (x));
 %! C = uniquetol ([x; y]);
 %! assert (C, x);
 
 ## Test "ByRows" Property
 %!test
 %! A = [0.06, 0.21, 0.38; 0.38, 0.21, 0.39; 0.54, 0.56, 0.41; 0.46, 0.52, 0.95];
-%! B = log (exp (1).^A);
+%! B = log (exp (A));
 %! C = uniquetol ([A; B], "ByRows", true);
 %! assert (C, A);
 
+## Test "DataScale" Property
+%!test
+%! x = 10^11;
+%! C = uniquetol ([x, exp(log(x))], 1e-6, "DataScale", 1);
+%! assert (C, [x, exp(log(x))]);
+
 ## Test "OutputAllIndices" Property
 %!test
 %! A = [.1 .2 .3 10];
@@ -270,12 +291,6 @@
 %! assert (ia, {(1:3)', 4});
 %! assert (ic, [1; 1; 1; 2]);
 
-## Test "DataScale" Property
-%!test
-%! x = 10^11;
-%! C = uniquetol ([x, exp(log(x))], 1e-6, "DataScale", 1);
-%! assert (C, [x, exp(log(x))]);
-
 ## Test input validation
 %!error <Invalid call> uniquetol ()
 %!error <A must be a double or single precision array> uniquetol (int8 (1))