diff scripts/general/private/__isequal__.m @ 9899:9f25290a35e8

more private function and subfunction changes
author John W. Eaton <jwe@octave.org>
date Tue, 01 Dec 2009 22:40:37 -0500
parents scripts/general/__isequal__.m@6f1ea8241c99
children 14d5fee02b3b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/private/__isequal__.m	Tue Dec 01 22:40:37 2009 -0500
@@ -0,0 +1,183 @@
+## Copyright (C) 2000, 2005, 2006, 2007, 2009 Paul Kienzle
+##
+## 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
+## <http://www.gnu.org/licenses/>.
+
+## Undocumented internal function.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} __isequal__ (@var{nans_compare_equal}, @var{x1}, @var{x2}, @dots{})
+## Undocumented internal function.
+## @end deftypefn
+
+## Return true if @var{x1}, @var{x2}, @dots{} are all equal and
+## @var{nans_compare_equal} evaluates to false.
+##
+## If @var{nans_compare_equal} evaluates to true, then assume NaN == NaN.
+
+## Modified by: William Poetra Yoga Hadisoeseno
+
+## Algorithm:
+##
+## 1. Determine the class of x
+## 2. If x is of the struct, cell, list or char class, for each
+##    argument after x, determine whether it has the same class
+##    and size as x.
+##    Otherwise, for each argument after x, verify that it is not
+##    of the struct, cell, list or char class, and that it has
+##    the same size as x.
+## 3. For each argument after x, compare it for equality with x:
+##    a. struct     compare each member by name, not by order (recursive)
+##    b. cell/list  compare each member by order (recursive)
+##    c. char       compare each member with strcmp
+##    d. <other>    compare each nonzero member, and assume NaN == NaN
+##                  if nans_compare_equal is nonzero.
+
+function t = __isequal__ (nans_compare_equal, x, varargin)
+
+  if (nargin < 3)
+    print_usage ();
+  endif
+
+  l_v = nargin - 2;
+
+  ## Generic tests.
+
+  ## Give an error for a list (that will make the code simpler and lists
+  ## are deprecated anyway.
+  if (islist (x))
+    error ("__isequal__: list objects are deprecated and cannot be tested for equality here; use cell arrays instead");
+  endif
+
+  ## All arguments must either be of the same class or they must be
+  ## numeric values.
+  t = (all (strcmp (class(x),
+		   cellfun (@class, varargin, "UniformOutput", false)))
+       || ((isnumeric (x) || islogical (x))
+	   && all ((cellfun (@isnumeric, varargin) | cellfun (@islogical, varargin)))));
+
+  if (t)
+    ## Test that everything has the same number of dimensions.
+    s_x = size (x);
+    s_v = cellfun (@size, varargin, "UniformOutput", false);
+    t = all (length (s_x) == cellfun (@length, s_v));
+  endif
+
+  if (t)
+    ## Test that everything is the same size since it has the same
+    ## dimensionality.
+    l_x = length (s_x);
+    s_v = reshape ([s_v{:}], length (s_x), []);
+    idx = 0;
+    while (t && idx < l_x)
+      idx++;
+      t = all (s_x(idx) == s_v(idx, :));
+    endwhile
+  endif
+
+  if (t)
+    ## Check individual classes.
+    if (isstruct (x))
+      ## Test the number of fields.
+      fn_x = fieldnames (x);
+      l_fn_x = length (fn_x);
+      fn_v = cellfun (@fieldnames, varargin, "UniformOutput", false);
+      t = all (l_fn_x == cellfun (@length, fn_v));
+
+      ## Test that all the names are equal.
+      idx = 0;
+      s_fn_x = sort (fn_x);
+      while (t && idx < l_v)
+	idx++;
+	## We'll allow the fieldnames to be in a different order.
+	t = all (strcmp (s_fn_x, sort (fn_v{idx})));
+      endwhile
+
+      idx = 0;
+      while (t && idx < l_fn_x)
+	## Test that all field values are equal.
+	idx++;
+	args = {nans_compare_equal, {x.(fn_x{idx})}};
+	for argn = 1:l_v
+	  args{argn+2} = {varargin{argn}.(fn_x{idx})};
+	endfor
+	## Minimize function calls by calling for all the arguments at
+	## once.
+        t = __isequal__ (args{:});
+      endwhile
+
+    elseif (iscell (x))
+      ## Check that each element of a cell is equal.
+      l_x = numel (x);
+      idx = 0;
+      while (t && idx < l_x)
+	idx++;
+	args = {nans_compare_equal, x{idx}};
+	for p = 1:l_v
+	  args{p+2} = varargin{p}{idx};
+	endfor
+        t = __isequal__ (args{:});
+      endwhile
+
+    elseif (ischar (x))
+
+      ## Sizes are equal already, so we can just make everything into a
+      ## row and test the rows.
+      for i = 1:l_v
+	strings{i} = reshape (varargin{i}, 1, []);
+      endfor
+      t = all (strcmp (reshape (x, 1, []), strings));
+
+    else
+      ## Check the numeric types.
+
+      if (issparse (x))
+	f_x = spfind (x);
+      else
+	f_x = find (x);
+      endif
+      l_f_x = length (f_x);
+      x = x(f_x);
+      for argn = 1:l_v
+	y = varargin{argn};
+	if (issparse (y))
+          f_y = spfind (y);
+	else
+          f_y = find (y);
+	endif
+
+	t = (l_f_x == length (f_y)) && all (f_x == f_y);
+	if (!t)
+          return;
+	endif
+
+	y = y(f_y);
+	m = (x == y);
+	t = all (m);
+
+	if (!t)
+          if (nans_compare_equal)
+            t = isnan (x(!m)) && isnan (y(!m));
+          else
+            return;
+          endif
+	endif
+      endfor
+
+    endif
+  endif
+
+endfunction