Mercurial > octave
changeset 31917:655e757c7522
isuniform.m: New function.
* NEWS.9.md: Announce new function
* scripts/general/isuniform.m: New function.
* scripts/general/module.mk: Add isuniform.m to build system.
* numbers.txi: Add DOCSTRING to manual.
author | Rik <rik@octave.org> |
---|---|
date | Wed, 22 Mar 2023 12:00:05 -0700 |
parents | b35cd94027b0 |
children | e67b7b85670b |
files | doc/interpreter/numbers.txi etc/NEWS.9.md scripts/general/isuniform.m scripts/general/module.mk |
diffstat | 4 files changed, 134 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/interpreter/numbers.txi Tue Mar 21 17:38:55 2023 -0700 +++ b/doc/interpreter/numbers.txi Wed Mar 22 12:00:05 2023 -0700 @@ -871,6 +871,8 @@ @DOCSTRING(isprime) +@DOCSTRING(isuniform) + If instead of knowing properties of variables, you wish to know which variables are defined and to gather other information about the workspace itself, @pxref{Status of Variables}.
--- a/etc/NEWS.9.md Tue Mar 21 17:38:55 2023 -0700 +++ b/etc/NEWS.9.md Wed Mar 22 12:00:05 2023 -0700 @@ -42,6 +42,7 @@ ### Alphabetical list of new functions added in Octave 9 +* `isuniform` * `tensorprod` ### Deprecated functions, properties, and operators @@ -111,7 +112,7 @@ removed. Delete unnecessary trailing whitespace. - For plot functions, the use of numbers to select line colors in - shorthand formats was an undocumented feature was removed from Octave 9. + shorthand formats was an undocumented feature that was removed in Octave 9. - The environment variable used by `mkoctfile` for linker flags is now `LDFLAGS` rather than `LFLAGS`. `LFLAGS` was deprecated in Octave 6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/general/isuniform.m Wed Mar 22 12:00:05 2023 -0700 @@ -0,0 +1,129 @@ +######################################################################## +## +## Copyright (C) 2023 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{tf} =} isuniform (@var{v}) +## @deftypefnx {} {[@var{tf}, @var{delta}] =} isuniform (@var{v}) +## Return true if the real vector @var{v} is uniformly spaced and false +## otherwise. +## +## A vector is uniform if the mean difference (@var{delta}) between all +## elements is the same to within a tolerance of +## @w{@code{4 * eps (max (abs (@var{v})))}}. +## +## The optional output @var{delta} is the uniform difference between elements. +## If the vector is not uniform then @var{delta} is @code{NaN}. @var{delta} +## is of the same class as @var{v} for floating point inputs and of class +## double for integer, logical, and character inputs. +## +## Programming Notes: The output is always false for the special cases of an +## empty input or a scalar input. If any element is @code{NaN} then the output +## is false. If @var{delta} is smaller than the calculated relative tolerance +## then an absolute tolerance of @code{eps} is used. +## +## @seealso{linspace, colon} +## @end deftypefn + +function [tf, delta] = isuniform (v) + + if (nargin != 1) + print_usage (); + endif + + if (! (isreal (v) && (isvector (v) || isempty (v)))) + error ("isuniform: V must be a real vector"); + endif + + if (! isfloat (v)) + v = double (v); # char, logical, integer inputs converted to double + endif + + ## Handle special corner cases + if (isempty (v) || isscalar (v)) + tf = false; + delta = NaN (class (v)); + return; + endif + + ## Compare mean delta to individual deltas with a tolerance + d = diff (v, 1); + delta = mean (d); + if (isnan (delta)) + tf = false; + else + tol = 4 * eps (max (abs (v))); + if (delta < tol) + ## Switch to absolute tolerance for very small delta + tol = eps (class (v)); + endif + tf = ! any (abs (d - delta) > tol); + if (! tf) + delta = NaN (class (v)); + endif + endif + +endfunction + + +%!assert (isuniform ([]), false) # empty input +%!assert (isuniform (zeros (1,2,0,4)), false) # empty input +%!assert (isuniform (1), false) # scalar input +%!assert (isuniform (1:5), true) +%!assert (isuniform (int8 (1:3:10)), true) +%!assert (isuniform ([false false false]), true) +%!assert (isuniform (['A', 'C', 'E']), true) + +## Test return class of step +%!test +%! [tf, delta] = isuniform (single (10:-1.5:1)); +%! assert (tf, true); +%! assert (delta, single (-1.5)); +%! [tf, delta] = isuniform (single ([1 2 5 6])); +%! assert (tf, false); +%! assert (delta, single (NaN)); + +%!test +%! [tf, delta] = isuniform (int8 (1:3:15)); +%! assert (tf, true); +%! assert (delta, double (3)); +%! [tf, delta] = isuniform (int8 ([1 2 5 6])); +%! assert (tf, false); +%! assert (delta, double (NaN)); + +## Test for small delta smaller than tolerance +%!test +%! v = 1:eps:(1+8*eps); +%! [tf, delta] = isuniform (v); +%! assert (tf, true); +%! assert (delta, eps); +%! v(3) -= 2*eps; +%! [tf, delta] = isuniform (v); +%! assert (tf, false); +%! assert (delta, NaN); + +## test input validation +%!error <Invalid call> isuniform () +%!error <V must be a real vector> isuniform (magic (3)) +%!error <V must be a real vector> isuniform ({1, 2, 3})