changeset 17261:533c980b5796

maint: Merge away extra head.
author Rik <rik@octave.org>
date Thu, 15 Aug 2013 22:11:22 -0700
parents a654c1eccd29 (diff) 92effb035b97 (current diff)
children 12e5fa85f1bb
files
diffstat 11 files changed, 324 insertions(+), 164 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/mk_doc_cache.m	Thu Aug 15 19:39:55 2013 -0400
+++ b/doc/interpreter/mk_doc_cache.m	Thu Aug 15 22:11:22 2013 -0700
@@ -24,7 +24,7 @@
 docstrings_files = args(2:end);
 
 ## Special character used as break between DOCSTRINGS
-doc_delim = char (0x1e);
+doc_delim = char (0x1d);
 
 ## Read the contents of all the DOCSTRINGS files into TEXT.
 ## It is more efficient to fork to shell for makeinfo only once on large data
--- a/doc/interpreter/munge-texi.pl	Thu Aug 15 19:39:55 2013 -0400
+++ b/doc/interpreter/munge-texi.pl	Thu Aug 15 22:11:22 2013 -0700
@@ -6,7 +6,7 @@
 $top_srcdir = shift (@ARGV);
 
 # Constant patterns
-$doc_delim = qr/^\x{1e}/;
+$doc_delim = qr/^\x{1d}/;
 $tex_delim = qr/\Q-*- texinfo -*-\E/;
 $comment_line = qr/^\s*(?:$|#)/;
 # Pre-declare hash size for efficiency
--- a/doc/interpreter/stmt.txi	Thu Aug 15 19:39:55 2013 -0400
+++ b/doc/interpreter/stmt.txi	Thu Aug 15 22:11:22 2013 -0700
@@ -860,40 +860,46 @@
 In the Octave language, most statements end with a newline character and
 you must tell Octave to ignore the newline character in order to
 continue a statement from one line to the next.  Lines that end with the
-characters @code{...} or @code{\} are joined with the following line
-before they are divided into tokens by Octave's parser.  For example,
-the lines
+characters @code{...} are joined with the following line before they are
+divided into tokens by Octave's parser.  For example, the lines
 
 @example
 @group
 x = long_variable_name ...
-    + longer_variable_name \
+    + longer_variable_name ...
     - 42
 @end group
 @end example
 
 @noindent
-form a single statement.  The backslash character on the second line
-above is interpreted as a continuation character, @emph{not} as a division
-operator.
+form a single statement.
 
-For continuation lines that do not occur inside string constants,
-whitespace and comments may appear between the continuation marker and
-the newline character.  For example, the statement
+Any text between the continuation marker and the newline character is
+ignored.  For example, the statement
 
 @example
 @group
-x = long_variable_name ...     # comment one
-    + longer_variable_name \   # comment two
-    - 42                       # last comment
+x = long_variable_name ...    # comment one
+    + longer_variable_name ...comment two
+    - 42                      # last comment
 @end group
 @end example
 
 @noindent
-is equivalent to the one shown above.  Inside string constants, the
-continuation marker must appear at the end of the line just before the
-newline character.
+is equivalent to the one shown above.
+
+Inside double-quoted string constants, the character @code{\} has to be
+used as continuation marker.  The @code{\} must appear at the end of the
+line just before the newline character:
 
+@example
+@group
+s = "This text starts in the first line \
+and is continued in the second line."
+@end group
+@end example
+
+@noindent
 Input that occurs inside parentheses can be continued to the next line
 without having to use a continuation marker.  For example, it is
 possible to write statements like
--- a/libinterp/corefcn/help.cc	Thu Aug 15 19:39:55 2013 -0400
+++ b/libinterp/corefcn/help.cc	Thu Aug 15 22:11:22 2013 -0700
@@ -967,7 +967,7 @@
   if (file)
     {
       // Ignore header;
-      file.ignore (1000, 0x1e);
+      file.ignore (1000, 0x1d);
 
       if (file.gcount () == 1000)
         {
@@ -988,7 +988,7 @@
 
       while (! file.eof ())
         {
-          file.getline (buf, bufsize, 0x1e);
+          file.getline (buf, bufsize, 0x1d);
 
           std::string tmp (buf);
 
--- a/libinterp/corefcn/rand.cc	Thu Aug 15 19:39:55 2013 -0400
+++ b/libinterp/corefcn/rand.cc	Thu Aug 15 22:11:22 2013 -0700
@@ -533,6 +533,19 @@
 %! endif
 */
 
+/*
+%!# Test out-of-range values as rand() seeds.  See oct-rand.cc: double2uint32().
+%!function v = __rand_sample__ (initval)
+%!  rand ("state", initval);
+%!  v = rand (1, 6);
+%!endfunction
+%!
+%!assert (__rand_sample__ (0), __rand_sample__ (2^32))
+%!assert (__rand_sample__ (-2), __rand_sample__ (2^32-2))
+%!assert (__rand_sample__ (Inf), __rand_sample__ (NaN))
+%!assert (! isequal (__rand_sample__ (-1), __rand_sample__ (-2)))
+*/
+
 static std::string current_distribution = octave_rand::distribution ();
 
 DEFUN (randn, args, ,
--- a/libinterp/gendoc.pl	Thu Aug 15 19:39:55 2013 -0400
+++ b/libinterp/gendoc.pl	Thu Aug 15 22:11:22 2013 -0700
@@ -64,7 +64,7 @@
   foreach $i (0 .. $#func_list)
   {
     $func = $func_list[$i];
-    print "\x{1e}$func\n";
+    print "\x{1d}$func\n";
     print "\@c $func $src_fname\n";
     print $docstr[$i],"\n";
   }
--- a/liboctave/numeric/oct-rand.cc	Thu Aug 15 19:39:55 2013 -0400
+++ b/liboctave/numeric/oct-rand.cc	Thu Aug 15 22:11:22 2013 -0700
@@ -663,6 +663,30 @@
   return retval;
 }
 
+// Guarantee reproducible conversion of negative initialization values to
+// random number algorithm.  Note that Matlab employs slightly different rules.
+// 1) Seed saturates at 2^32-1 for any value larger than that.
+// 2) NaN, Inf are translated to 2^32-1.
+// 3) -Inf is translated to 0.
+static uint32_t
+double2uint32 (double d)
+{
+  uint32_t u;
+  static const double TWOUP32 = std::numeric_limits<uint32_t>::max() + 1.0;
+
+  if (! xfinite (d))
+    u = 0;
+  else
+    {
+      d = fmod (d, TWOUP32);
+      if (d < 0)
+        d += TWOUP32;
+      u = static_cast<uint32_t> (d);
+    }
+
+  return u;
+}
+
 void
 octave_rand::set_internal_state (const ColumnVector& s)
 {
@@ -672,7 +696,7 @@
   OCTAVE_LOCAL_BUFFER (uint32_t, tmp, MT_N + 1);
 
   for (octave_idx_type i = 0; i < n; i++)
-    tmp[i] = static_cast<uint32_t> (s.elem (i));
+    tmp[i] = double2uint32 (s.elem (i));
 
   if (len == MT_N + 1 && tmp[MT_N] <= MT_N && tmp[MT_N] > 0)
     oct_set_state (tmp);
--- a/scripts/mkdoc.pl	Thu Aug 15 19:39:55 2013 -0400
+++ b/scripts/mkdoc.pl	Thu Aug 15 22:11:22 2013 -0700
@@ -52,7 +52,7 @@
   @help_txt = gethelp ($fcn, $full_fname);
   next MFILE if ($help_txt[0] eq "");
 
-  print "\x{1e}$fcn\n";
+  print "\x{1d}$fcn\n";
   print "\@c $fcn scripts/$m_fname\n";
 
   foreach $_ (@help_txt)
--- a/scripts/plot/contour.m	Thu Aug 15 19:39:55 2013 -0400
+++ b/scripts/plot/contour.m	Thu Aug 15 22:11:22 2013 -0700
@@ -91,7 +91,7 @@
 %! [x, y, z] = peaks ();
 %! contour (x, y, z);
 %! title ('contour() plot of peaks() function');
-%! title ({'contour() plot (isolines of constant Z)'; 'Z = peaks()');
+%! title ({'contour() plot (isolines of constant Z)'; 'Z = peaks()'});
 
 %!demo
 %! clf;
@@ -100,7 +100,7 @@
 %! [X, Y] = pol2cart (theta, r);
 %! Z = sin (2*theta) .* (1-r);
 %! contour (X, Y, abs (Z), 10);
-%! title ({'contour() plot'; 'polar fcn Z = sin (2*theta) * (1-r)'});
+%! title ({'contour() plot'; 'polar fcn: Z = sin (2*theta) * (1-r)'});
 
 %!test
 %! hf = figure ("visible", "off");
--- a/scripts/plot/contourf.m	Thu Aug 15 19:39:55 2013 -0400
+++ b/scripts/plot/contourf.m	Thu Aug 15 22:11:22 2013 -0700
@@ -92,7 +92,7 @@
 %! colormap ('default');
 %! [x, y, z] = peaks (50);
 %! contourf (x, y, z, -7:9);
-%! title ({'contourf() plot (filled contour lines)'; 'Z = peaks()');
+%! title ({'contourf() plot (filled contour lines)'; 'Z = peaks()'});
 
 %!demo
 %! clf;
@@ -101,7 +101,7 @@
 %! [X, Y] = pol2cart (theta, r);
 %! Z = sin (2*theta) .* (1-r);
 %! contourf (X, Y, abs (Z), 10);
-%! title ({'contourf() plot'; 'polar fcn Z = sin (2*theta) * (1-r)'});
+%! title ({'contourf() plot'; 'polar fcn: Z = sin (2*theta) * (1-r)'});
 
 %!demo
 %! clf;
--- a/scripts/testfun/assert.m	Thu Aug 15 19:39:55 2013 -0400
+++ b/scripts/testfun/assert.m	Thu Aug 15 22:11:22 2013 -0700
@@ -77,6 +77,7 @@
 
   if (nargin == 1 || (nargin > 1 && islogical (cond) && ischar (varargin{1})))
     if ((! isnumeric (cond) && ! islogical (cond)) || ! all (cond(:)))
+      call_depth--;
       if (nargin == 1)
         ## Perhaps, say which elements failed?
         error ("assert %s failed", in);
@@ -100,18 +101,15 @@
 
     if (ischar (expected))
       if (! ischar (cond))
-        err.index{end+1} = "[]";
+        err.index{end+1} = ".";
         err.expected{end+1} = expected;
         if (isnumeric (cond))
           err.observed{end+1} = num2str (cond);
           err.reason{end+1} = "Expected string, but observed number";
-        elseif (iscell (cond))
-          err.observed{end+1} = "{}";
-          err.reason{end+1} = "Expected string, but observed cell";
         else
-          err.observed{end+1} = "[]";
-          err.reason{end+1} = "Expected string, but observed struct";
-        end
+          err.observed{end+1} = "O";
+          err.reason{end+1} = ["Expected string, but observed " class(cond)];
+        endif
       elseif (! strcmp (cond, expected))
         err.index{end+1} = "[]";
         err.observed{end+1} = cond;
@@ -120,11 +118,17 @@
       endif
 
     elseif (iscell (expected))
-      if (! iscell (cond) || any (size (cond) != size (expected)))
-        err.index{end+1} = "{}";
+      if (! iscell (cond))
+        err.index{end+1} = ".";
         err.observed{end+1} = "O";
         err.expected{end+1} = "E";
-        err.reason{end+1} = "Cell sizes don't match";
+        err.reason{end+1} = ["Expected cell, but observed " class(cond)];
+      elseif (ndims (cond) != ndims (expected)
+              || any (size (cond) != size (expected)))
+        err.index{end+1} = ".";
+        err.observed{end+1} = ["O(" sprintf("%dx", size(cond))(1:end-1) ")"];
+        err.expected{end+1} = ["E(" sprintf("%dx", size(expected))(1:end-1) ")"];
+        err.reason{end+1} = "Dimensions don't match";
       else
         try
           ## Recursively compare cell arrays
@@ -140,11 +144,18 @@
       endif
 
     elseif (isstruct (expected))
-      if (! isstruct (cond) || any (size (cond) != size (expected))
-          || rows (fieldnames (cond)) != rows (fieldnames (expected)))
-        err.index{end+1} = "{}";
+      if (! isstruct (cond))
+        err.index{end+1} = ".";
         err.observed{end+1} = "O";
         err.expected{end+1} = "E";
+        err.reason{end+1} = ["Expected struct, but observed " class(cond)];
+      elseif (ndims (cond) != ndims (expected)
+              || any (size (cond) != size (expected))
+              || rows (fieldnames (cond)) != rows (fieldnames (expected)))
+
+        err.index{end+1} = ".";
+        err.observed{end+1} = ["O(" sprintf("%dx", size(cond))(1:end-1) ")"];
+        err.expected{end+1} = ["E(" sprintf("%dx", size(expected))(1:end-1) ")"];
         err.reason{end+1} = "Structure sizes don't match";
       else
         try
@@ -219,57 +230,63 @@
         B = expected;
 
         ## Check exceptional values.
-        erridx = find (  isna (real (A)) != isna (real (B))
-                       | isna (imag (A)) != isna (imag (B)));
+        errvec = (  isna (real (A)) != isna (real (B))
+                  | isna (imag (A)) != isna (imag (B)));
+        erridx = find (errvec);
         if (! isempty (erridx))
-          err.index(end+1:end + length (erridx)) = ...
-              ind2tuple (size (A), erridx);
-          err.observed(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (A(erridx) (:))));
-          err.expected(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (B(erridx) (:))));
-          err.reason(end+1:end + length (erridx)) = ...
-              cellstr (repmat ("'NA' mismatch", length (erridx), 1));
+          err.index(end+1:end+length (erridx)) = ...
+            ind2tuple (size (A), erridx);
+          err.observed(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (A(erridx) (:))));
+          err.expected(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (B(erridx) (:))));
+          err.reason(end+1:end+length (erridx)) = ...
+            repmat ({"'NA' mismatch"}, length (erridx), 1);
         endif
+        errseen = errvec;
 
-        erridx = find (  isnan (real (A)) != isnan (real (B))
-                       | isnan (imag (A)) != isnan (imag (B)));
+        errvec = (  isnan (real (A)) != isnan (real (B))
+                  | isnan (imag (A)) != isnan (imag (B)));
+        erridx = find (errvec & !errseen);
         if (! isempty (erridx))
-          err.index(end+1:end + length (erridx)) = ...
-              ind2tuple (size (A), erridx);
-          err.observed(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (A(erridx) (:))));
-          err.expected(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (B(erridx) (:))));
-          err.reason(end+1:end + length (erridx)) = ...
-              cellstr (repmat ("'NaN' mismatch", length (erridx), 1));
+          err.index(end+1:end+length (erridx)) = ...
+            ind2tuple (size (A), erridx);
+          err.observed(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (A(erridx) (:))));
+          err.expected(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (B(erridx) (:))));
+          err.reason(end+1:end+length (erridx)) = ...
+            repmat ({"'NaN' mismatch"}, length (erridx), 1);
         endif
+        errseen |= errvec;
 
-        erridx = find (((isinf (real (A)) | isinf (real (B))) ...
-                         & real (A) != real (B)) ...
-                       | ((isinf (imag (A)) | isinf (imag (B)))
-                         & imag (A) != imag (B)));
+        errvec =   ((isinf (real (A)) | isinf (real (B))) ...
+                    & (real (A) != real (B)))             ...
+                 | ((isinf (imag (A)) | isinf (imag (B))) ...
+                    & (imag (A) != imag (B)));
+        erridx = find (errvec & !errseen);
         if (! isempty (erridx))
-          err.index(end+1:end + length (erridx)) = ...
-              ind2tuple (size (A), erridx);
-          err.observed(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (A(erridx) (:))));
-          err.expected(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (B(erridx) (:))));
-          err.reason(end+1:end + length (erridx)) = ...
-              cellstr (repmat ("'Inf' mismatch", length (erridx), 1));
+          err.index(end+1:end+length (erridx)) = ...
+            ind2tuple (size (A), erridx);
+          err.observed(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (A(erridx) (:))));
+          err.expected(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (B(erridx) (:))));
+          err.reason(end+1:end+length (erridx)) = ...
+            repmat ({"'Inf' mismatch"}, length (erridx), 1);
         endif
+        errseen |= errvec;
 
         ## Check normal values.
         ## Replace exceptional values already checked above by zero.
         A_null_real = real (A);
         B_null_real = real (B);
-        exclude = ! isfinite (A_null_real) & ! isfinite (B_null_real);
+        exclude = errseen | ! isfinite (A_null_real) & ! isfinite (B_null_real);
         A_null_real(exclude) = 0;
         B_null_real(exclude) = 0;
         A_null_imag = imag (A);
         B_null_imag = imag (B);
-        exclude = ! isfinite (A_null_imag) & ! isfinite (B_null_imag);
+        exclude = errseen | ! isfinite (A_null_imag) & ! isfinite (B_null_imag);
         A_null_imag(exclude) = 0;
         B_null_imag(exclude) = 0;
         A_null = complex (A_null_real, A_null_imag);
@@ -283,45 +300,45 @@
         k = (mtol == 0);
         erridx = find ((A_null != B_null) & k);
         if (! isempty (erridx))
-          err.index(end+1:end + length (erridx)) = ...
-              ind2tuple (size (A), erridx);
-          err.observed(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (A(erridx) (:))));
-          err.expected(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (B(erridx) (:))));
-          err.reason(end+1:end + length (erridx)) = ...
-              ostrsplit (deblank (sprintf ("Abs err %g exceeds tol %g\n", ...
-              [abs(A_null(erridx) - B_null(erridx)) mtol(erridx)]')), "\n");
+          err.index(end+1:end+length (erridx)) = ...
+            ind2tuple (size (A), erridx);
+          err.observed(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (A(erridx) (:))));
+          err.expected(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (B(erridx) (:))));
+          err.reason(end+1:end+length (erridx)) = ...
+            ostrsplit (deblank (sprintf ("Abs err %.5g exceeds tol %.5g\n",...
+            [abs(A_null(erridx) - B_null(erridx))(:) mtol(erridx)(:)]')), "\n");
         endif
 
         k = (mtol > 0);
         erridx = find ((abs (A_null - B_null) > mtol) & k);
         if (! isempty (erridx))
-          err.index(end+1:end + length (erridx)) = ...
-              ind2tuple (size (A), erridx);
-          err.observed(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (A(erridx) (:))));
-          err.expected(end+1:end + length (erridx)) = ...
-              strtrim (cellstr (num2str (B(erridx) (:))));
-          err.reason(end+1:end + length (erridx)) = ...
-              ostrsplit (deblank (sprintf ("Abs err %g exceeds tol %g\n", ...
-              [abs(A_null(erridx) - B_null(erridx)) mtol(erridx)]')), "\n");
+          err.index(end+1:end+length (erridx)) = ...
+            ind2tuple (size (A), erridx);
+          err.observed(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (A(erridx) (:))));
+          err.expected(end+1:end+length (erridx)) = ...
+            strtrim (cellstr (num2str (B(erridx) (:))));
+          err.reason(end+1:end+length (erridx)) = ...
+            ostrsplit (deblank (sprintf ("Abs err %.5g exceeds tol %.5g\n",...
+            [abs(A_null(erridx) - B_null(erridx))(:) mtol(erridx)(:)]')), "\n");
         endif
 
         k = (mtol < 0);
-        if (any (k))
+        if (any (k(:)))
           ## Test for absolute error where relative error can't be calculated.
           erridx = find ((B_null == 0) & abs (A_null) > abs (mtol) & k);
           if (! isempty (erridx))
-            err.index(end+1:end + length (erridx)) = ...
-                ind2tuple (size (A), erridx);
-            err.observed(end+1:end + length (erridx)) = ...
-                strtrim (cellstr (num2str (A(erridx) (:))));
-            err.expected(end+1:end + length (erridx)) = ...
-                strtrim (cellstr (num2str (B(erridx) (:))));
-            err.reason(end+1:end + length (erridx)) = ...
-                ostrsplit (deblank (sprintf ("Abs err %g exceeds tol %g\n",
-                [abs(A_null(erridx) - B_null(erridx)) -mtol(erridx)]')), "\n");
+            err.index(end+1:end+length (erridx)) = ...
+              ind2tuple (size (A), erridx);
+            err.observed(end+1:end+length (erridx)) = ...
+              strtrim (cellstr (num2str (A(erridx) (:))));
+            err.expected(end+1:end+length (erridx)) = ...
+              strtrim (cellstr (num2str (B(erridx) (:))));
+            err.reason(end+1:end+length (erridx)) = ...
+              ostrsplit (deblank (sprintf ("Abs err %.5g exceeds tol %.5g\n",
+              [abs(A_null(erridx) - B_null(erridx)) -mtol(erridx)]')), "\n");
           endif
           ## Test for relative error
           Bdiv = Inf (size (B_null));
@@ -329,15 +346,15 @@
           relerr = abs ((A_null - B_null) ./ abs (Bdiv));
           erridx = find ((relerr > abs (mtol)) & k);
           if (! isempty (erridx))
-            err.index(end+1:end + length (erridx)) = ...
-                ind2tuple (size (A), erridx);
-            err.observed(end+1:end + length (erridx)) = ...
-                strtrim (cellstr (num2str (A(erridx) (:))));
-            err.expected(end+1:end + length (erridx)) = ...
-                strtrim (cellstr (num2str (B(erridx) (:))));
-            err.reason(end+1:end + length (erridx)) = ...
-                ostrsplit (deblank (sprintf ("Rel err %g exceeds tol %g\n",
-                [relerr(erridx) -mtol(erridx)]')), "\n");
+            err.index(end+1:end+length (erridx)) = ...
+              ind2tuple (size (A), erridx);
+            err.observed(end+1:end+length (erridx)) = ...
+              strtrim (cellstr (num2str (A(erridx) (:))));
+            err.expected(end+1:end+length (erridx)) = ...
+              strtrim (cellstr (num2str (B(erridx) (:))));
+            err.reason(end+1:end+length (erridx)) = ...
+              ostrsplit (deblank (sprintf ("Rel err %.5g exceeds tol %.5g\n",
+              [relerr(erridx)(:) -mtol(erridx)(:)]')), "\n");
           endif
         endif
       endif
@@ -369,8 +386,8 @@
 ## empty input
 %!assert ([])
 %!assert (zeros (3,0), zeros (3,0))
-%!error assert (zeros (3,0), zeros (0,2))
-%!error assert (zeros (3,0), [])
+%!error <O\(3x0\)\s+E\(0x2\)> assert (zeros (3,0), zeros (0,2))
+%!error <Dimensions don't match> assert (zeros (3,0), [])
 %!error <Dimensions don't match> assert (zeros (2,0,2), zeros (2,0))
 
 ## conditions
@@ -385,85 +402,135 @@
 %!error assert ([1,0;1,1])
 
 ## scalars
-%!error assert (3, [3,3; 3,3])
-%!error assert ([3,3; 3,3], 3)
+%!error <Dimensions don't match> assert (3, [3,3])
+%!error <Dimensions don't match> assert (3, [3,3; 3,3])
+%!error <Dimensions don't match> assert ([3,3; 3,3], 3)
 %!assert (3, 3)
+%!error <Abs err 1 exceeds tol> assert (3, 4)
 %!assert (3+eps, 3, eps)
 %!assert (3, 3+eps, eps)
-%!error assert (3+2*eps, 3, eps)
-%!error assert (3, 3+2*eps, eps)
+%!error <Abs err 4.4409e-16 exceeds tol> assert (3+2*eps, 3, eps)
+%!error <Abs err 4.4409e-16 exceeds tol> assert (3, 3+2*eps, eps)
 
 ## vectors
 %!assert ([1,2,3],[1,2,3]);
 %!assert ([1;2;3],[1;2;3]);
-%!error assert ([2,2,3,3],[1,2,3,4]);
-%!error assert ([6;6;7;7],[5;6;7;8]);
-%!error assert ([1,2,3],[1;2;3]);
-%!error assert ([1,2],[1,2,3]);
-%!error assert ([1;2;3],[1;2]);
-%!assert ([1,2;3,4],[1,2;3,4]);
-%!error assert ([1,4;3,4],[1,2;3,4])
-%!error assert ([1,3;2,4;3,5],[1,2;3,4])
+%!error <Abs err 1 exceeds tol 0> assert ([2,2,3,3],[1,2,3,4]);
+%!error <Abs err 1 exceeds tol 0.5> assert ([2,2,3,3],[1,2,3,4],0.5);
+%!error <Rel err 1 exceeds tol 0.1> assert ([2,2,3,5],[1,2,3,4],-0.1);
+%!error <Abs err 1 exceeds tol 0> assert ([6;6;7;7],[5;6;7;8]);
+%!error <Abs err 1 exceeds tol 0.5> assert ([6;6;7;7],[5;6;7;8],0.5);
+%!error <Rel err .* exceeds tol 0.1> assert ([6;6;7;7],[5;6;7;8],-0.1);
+%!error <Dimensions don't match> assert ([1,2,3],[1;2;3]);
+%!error <Dimensions don't match> assert ([1,2],[1,2,3]);
+%!error <Dimensions don't match> assert ([1;2;3],[1;2]);
 
 ## matrices
-%!test
+%!assert ([1,2;3,4],[1,2;3,4]);
+%!error <\(1,2\)\s+4\s+2> assert ([1,4;3,4],[1,2;3,4])
+%!error <Dimensions don't match> assert ([1,3;2,4;3,5],[1,2;3,4])
+%!test  # 2-D matrix
 %! A = [1 2 3]'*[1,2];
-%! assert (A,A);
+%! assert (A, A);
 %! fail ("assert (A.*(A!=2),A)");
+%!test  # N-D matrix
 %! X = zeros (2,2,3);
 %! Y = X;
-%! Y (1,2,3) = 1;
-%! fail ("assert (X,Y)");
+%! Y(1,2,3) = 1.5;
+%! fail ("assert (X,Y)", "\(1,2,3\).*Abs err 1.5 exceeds tol 0");
 
 ## must give a small tolerance for floating point errors on relative
 %!assert (100+100*eps, 100, -2*eps)
 %!assert (100, 100+100*eps, -2*eps)
-%!error assert (100+300*eps, 100, -2*eps)
-%!error assert (100, 100+300*eps, -2*eps)
-%!error assert (3, [3,3])
-%!error assert (3, 4)
+%!error <Rel err .* exceeds tol> assert (100+300*eps, 100, -2*eps)
+%!error <Rel err .* exceeds tol> assert (100, 100+300*eps, -2*eps)
 
 ## test relative vs. absolute tolerances
-%!test  assert (0.1+eps, 0.1,  2*eps);  # accept absolute
-%!error assert (0.1+eps, 0.1, -2*eps);  # fail relative
-%!test  assert (100+100*eps, 100, -2*eps);  # accept relative
-%!error assert (100+100*eps, 100,  2*eps);  # fail absolute
+%!test  assert (0.1+eps, 0.1,  2*eps);
+%!error <Rel err 2.2204e-15 exceeds tol> assert (0.1+eps, 0.1, -2*eps);
+%!test  assert (100+100*eps, 100, -2*eps);
+%!error <Abs err 2.8422e-14 exceeds tol> assert (100+100*eps, 100,  2*eps);
+
+## Corner case of relative tolerance with 0 divider
+%!error <Abs err 2 exceeds tol 0.1> assert (2, 0, -0.1)
+
+## Extra checking of inputs when tolerance unspecified.
+%!error <Class single != double> assert (single (1), 1)
+%!error <Class uint8 != uint16> assert (uint8 (1), uint16 (1))
+%!error <sparse != non-sparse> assert (sparse([1]), [1])
+%!error <non-sparse != sparse> assert ([1], sparse([1]))
+%!error <complex != real> assert (1+i, 1)
+%!error <real != complex> assert (1, 1+i)
 
 ## exceptional values
 %!assert ([NaN, NA, Inf, -Inf, 1+eps, eps], [NaN, NA, Inf, -Inf, 1, 0], eps)
-%!error assert (NaN, 1)
-%!error assert ([NaN 1], [1 NaN])
-%!error assert (NA, 1)
+
+%!error <'NaN' mismatch> assert (NaN, 1)
+%!error <'NaN' mismatch> assert ([NaN 1], [1 NaN])
+%!test
+%! try
+%!   assert ([NaN 1], [1 NaN]);
+%! catch
+%!   errmsg = lasterr ();
+%!   if (sum (errmsg () == "\n") != 4)
+%!     error ("Too many errors reported for NaN assert");
+%!   elseif (strfind (errmsg, "NA"))
+%!     error ("NA reported for NaN assert");
+%!   elseif (strfind (errmsg, "Abs err NaN exceeds tol 0"))
+%!     error ("Abs err reported for NaN assert");
+%!   endif
+%! end_try_catch
+
+%!error <'NA' mismatch> assert (NA, 1)
 %!error assert ([NA 1]', [1 NA]')
+%!test
+%! try
+%!   assert ([NA 1]', [1 NA]');
+%! catch
+%!   errmsg = lasterr ();
+%!   if (sum (errmsg () == "\n") != 4)
+%!     error ("Too many errors reported for NA assert");
+%!   elseif (strfind (errmsg, "NaN"))
+%!     error ("NaN reported for NA assert");
+%!   elseif (strfind (errmsg, "Abs err NA exceeds tol 0"))
+%!     error ("Abs err reported for NA assert");
+%!   endif
+%! end_try_catch
 %!error assert ([(complex (NA, 1)) (complex (2, NA))], [(complex (NA, 2)) 2])
-%!error assert (-Inf, Inf)
-%!error assert ([-Inf Inf], [Inf -Inf])
-%!error assert (complex (Inf, 0.2), complex (-Inf, 0.2 + 2*eps), eps)
+
+%!error <'Inf' mismatch> assert (-Inf, Inf)
+%!error <'Inf' mismatch> assert ([-Inf Inf], [Inf -Inf])
+%!test
+%! try
+%!   assert (complex (Inf, 0.2), complex (-Inf, 0.2 + 2*eps), eps);
+%! catch
+%!   errmsg = lasterr ();
+%!   if (sum (errmsg () == "\n") != 3)
+%!     error ("Too many errors reported for Inf assert");
+%!   elseif (strfind (errmsg, "Abs err"))
+%!     error ("Abs err reported for Inf assert");
+%!   endif
+%! end_try_catch
+%!error <Abs err> assert (complex (Inf, 0.2), complex (Inf, 0.2 + 2*eps), eps)
 
 ## strings
 %!assert ("dog", "dog")
-%!error assert ("dog", "cat")
-%!error assert ("dog", 3)
-%!error assert (3, "dog")
-%!error assert (cellstr ("dog"), "dog")
-%!error assert (cell2struct ({"dog"; 3}, {"pet", "age"}, 1), "dog");
-
-## structures
-%!shared x,y
-%! x.a = 1; x.b=[2, 2];
-%! y.a = 1; y.b=[2, 2];
-%!assert (x, y)
-%!test y.b=3;
-%!error assert (x, y)
-%!error assert (3, x)
-%!error assert (x, 3)
-%!test
-%! # Empty structures
-%! x = resize (x, 0, 1);
-%! y = resize (y, 0, 1);
-%! assert (x, y);
+%!error <Strings don't match> assert ("dog", "cat")
+%!error <Expected string, but observed number> assert (3, "dog")
+%!error <Class char != double> assert ("dog", [3 3 3])
+%!error <Expected string, but observed cell> assert ({"dog"}, "dog")
+%!error <Expected string, but observed struct> assert (struct ("dog", 3), "dog")
 
 ## cell arrays
+%!error <Expected cell, but observed double> assert (1, {1})
+%!error <Dimensions don't match> assert (cell (1,2,3), cell (3,2,1))
+%!test
+%! x = {{{1}}, 2};  # cell with multiple levels
+%! y = x;
+%! assert (x,y);
+%! y{1}{1}{1} = 3;
+%! fail ("assert (x,y)", "Abs err 2 exceeds tol 0");
+
 %!test
 %! x = {[3], [1,2,3]; 100+100*eps, "dog"};
 %! y = x;
@@ -479,7 +546,39 @@
 %! y = x; y(1,1) = [2];  y(1,2) = [0, 2, 3]; y(2,1) = 101; y(2,2) = "cat";
 %! fail ("assert (x, y)");
 
-## variable tolerance
+## structures
+%!error <Expected struct, but observed double> assert (1, struct ("a", 1))
+%!error <Structure sizes don't match>
+%!  x(1,2,3).a = 1;
+%!  y(1,2).a = 1;
+%!  assert (x,y);
+%!error <Structure sizes don't match>
+%!  x(1,2,3).a = 1;
+%!  y(3,2,2).a = 1;
+%!  assert (x,y);
+%!error <Structure sizes don't match>
+%!  x.a = 1;  x.b = 1;
+%!  y.a = 1;
+%!  assert (x,y);
+%!error <'b' is not an expected field>
+%!  x.b = 1;
+%!  y.a = 1;
+%!  assert (x,y);
+
+%!test
+%! x.a = 1; x.b=[2, 2];
+%! y.a = 1; y.b=[2, 2];
+%! assert (x, y);
+%! y.b=3;
+%! fail ("assert (x, y)");
+%! fail ("assert (3, x)");
+%! fail ("assert (x, 3)");
+%! ## Empty structures
+%! x = resize (x, 0, 1);
+%! y = resize (y, 0, 1);
+%! assert (x, y);
+
+## vector of tolerances
 %!test
 %! x = [-40:0];
 %! y1 = (10.^x).*(10.^x);
@@ -487,6 +586,24 @@
 %! assert (y1, y2, eps (y1));
 %! fail ("assert (y1, y2 + eps*1e-70, eps (y1))");
 
+## Multiple tolerances
+%!test
+%! x = [1 2; 3 4];
+%! y = [0 -1; 1 2];
+%! tol = [-0.1 0; -0.2 0.3];
+%! try
+%!   assert (x, y, tol);
+%! catch
+%!   errmsg = lasterr ();
+%!   if (sum (errmsg () == "\n") != 6)
+%!     error ("Incorrect number of errors reported");
+%!   endif
+%!   assert (!isempty (regexp (errmsg, '\(1,2\).*Abs err 3 exceeds tol 0\>')));
+%!   assert (!isempty (regexp (errmsg, '\(2,2\).*Abs err 2 exceeds tol 0.3')));
+%!   assert (!isempty (regexp (errmsg, '\(1,1\).*Abs err 1 exceeds tol 0.1')));
+%!   assert (!isempty (regexp (errmsg, '\(2,1\).*Rel err 2 exceeds tol 0.2')));
+%! end_try_catch
+
 ## test input validation
 %!error assert ()
 %!error assert (1,2,3,4)