changeset 3196:3ac3e8edc258

[project @ 1998-10-28 23:04:39 by jwe]
author jwe
date Wed, 28 Oct 1998 23:11:11 +0000
parents 7a5a5da64756
children a998db745232
files NEWS doc/interpreter/basics.texi doc/interpreter/linalg.texi kpathsea/ChangeLog kpathsea/kdefault.c liboctave/ChangeLog liboctave/pathsearch.cc liboctave/pathsearch.h scripts/ChangeLog src/ChangeLog src/ov-list.cc src/ov-list.h src/ov-typeinfo.cc src/ov-typeinfo.h src/ov.cc
diffstat 15 files changed, 437 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,21 @@
 Summary of changes for version 2.1.x:
 ------------------------------------
 
+  * The built-in variable argv is now a list of strings instead of a
+    string vector.
+
+  * The value of LOADPATH set by the environment variable
+    OCTAVE_PATH, the -p or --path command line options, or on the
+    command line is no longer modified to include the default path.
+    Instead it is left as specified.  Its default value is now ":",
+    which tells Octave to search the default path, and the new
+    built-in variable DEFAULT_LOADPATH contains the default list of
+    directories to search.  
+
+  * The function file_in_path no longer does any special processing of
+    its PATH argument.  To search LOADPATH for files, it is now
+    generally better to use the new function file_in_loadpath.
+
   * If fread is given a skip parameter, the skip is performed after
     the read instead of before (for compatibility with Matlab).
 
--- a/doc/interpreter/basics.texi
+++ b/doc/interpreter/basics.texi
@@ -198,7 +198,7 @@
 @end example
 
 @noindent
-@code{argv} would be a string vector with the elements
+@code{argv} would be a list of strings with the elements
 @code{--no-line-editing} and @code{--silent}.
 
 If you write an executable Octave script, @code{argv} will contain the
@@ -229,7 +229,7 @@
 @example
 printf ("%s", program_name);
 for i = 1:nargin
-  printf (" %s", argv(i,:));
+  printf (" %s", argv(i));
 endfor
 printf ("\n");
 @end example
--- a/doc/interpreter/linalg.texi
+++ b/doc/interpreter/linalg.texi
@@ -380,6 +380,102 @@
 @code{span (a)}.
 @end deftypefn
 
+
+@deftypefn {Function File} {@var{lambda} =} qz (@var{a}, @var{b})
+Generalized eigenvalue problem @math{A x = s B x},
+@var{QZ} decomposition.  Three ways to call:
+@enumerate
+@item @code{lambda = qz(A,B)}
+
+Computes the generalized eigenvalues @var{lambda} of @math{(A - sB)}.
+
+@item @code{[AA, BB, Q, Z @{, V, W, lambda@}] = qz (A, B)}
+
+Computes qz decomposition, generalized eigenvectors, and 
+        generalized eigenvalues of @math{(A - sB)}
+@example
+@group
+        A V = B V diag(lambda)
+        W' A = diag(lambda) W' B
+        AA = Q'*A*Z, BB = Q'*B*Z  with Q, Z orthogonal (unitary)= I
+@end group
+@end example
+
+@item @code{[AA,BB,Z@{,lambda@}] = qz(A,B,opt)}
+
+As in form [2], but allows ordering of generalized eigenpairs
+        for (e.g.) solution of discrete time algebraic Riccati equations.
+        Form 3 is not available for complex matrices and does not compute
+        the generalized eigenvectors V, W, nor the orthogonal matrix Q.
+@table @var
+@item opt
+ for ordering eigenvalues of the GEP pencil.  The leading  block
+             of the revised pencil contains all eigenvalues that satisfy:
+@table @code
+@item "N"
+ = unordered (default) 
+
+@item "S"
+= small: leading block has all |lambda| <=1 
+
+@item "B"
+ = big: leading block has all |lambda >= 1 
+
+@item "-"
+ = negative real part: leading  block has all eigenvalues
+                  in the open left half-plant
+
+@item "+"
+ = nonnegative real part:  leading block has all eigenvalues
+                  in the closed right half-plane
+@end  table
+@end table
+@end enumerate
+
+Note: qz performs permutation balancing, but not scaling (see balance).
+      Order of output arguments was selected for compatibility with MATLAB
+
+See also: balance, dare, eig, schur
+@end deftypefn
+
+@deftypefn {Function File} {[@var{aa}, @var{bb}, @var{q}, @var{z}] =} qzhess (@var{a}, @var{b})
+Compute the Hessenberg-triangular decomposition of the matrix pencil
+@code{(@var{a}, @var{b})}, returning
+@code{@var{aa} = @var{q} * @var{a} * @var{z}}, 
+@code{@var{bb} = @var{q} * @var{b} * @var{z}}, with @var{q} and @var{z}
+orthogonal.  For example,
+
+@example
+@group
+[aa, bb, q, z] = qzhess ([1, 2; 3, 4], [5, 6; 7, 8])
+     @result{} aa = [ -3.02244, -4.41741;  0.92998,  0.69749 ]
+     @result{} bb = [ -8.60233, -9.99730;  0.00000, -0.23250 ]
+     @result{}  q = [ -0.58124, -0.81373; -0.81373,  0.58124 ]
+     @result{}  z = [ 1, 0; 0, 1 ]
+@end group
+@end example
+
+The Hessenberg-triangular decomposition is the first step in
+Moler and Stewart's QZ decomposition algorithm.
+
+Algorithm taken from Golub and Van Loan, @cite{Matrix Computations, 2nd
+edition}.
+@end deftypefn
+
+@deftypefn {Loadable Function} {} qzval (@var{a}, @var{b})
+Compute generalized eigenvalues of the matrix pencil 
+@iftex
+@tex
+$a - \lambda b$.
+@end tex
+@end iftex
+@ifinfo
+@code{@var{a} - lambda @var{b}}.
+@end ifinfo
+
+The arguments @var{a} and @var{b} must be real matrices.
+@end deftypefn
+
 @deftypefn {Loadable Function} {@var{s} =} schur (@var{a})
 @deftypefnx {Loadable Function} {[@var{u}, @var{s}] =} schur (@var{a}, @var{opt})
 @cindex Schur decomposition
@@ -784,44 +880,6 @@
 @end example
 @end deftypefn
 
-@deftypefn {Function File} {[@var{aa}, @var{bb}, @var{q}, @var{z}] =} qzhess (@var{a}, @var{b})
-Compute the Hessenberg-triangular decomposition of the matrix pencil
-@code{(@var{a}, @var{b})}, returning
-@code{@var{aa} = @var{q} * @var{a} * @var{z}}, 
-@code{@var{bb} = @var{q} * @var{b} * @var{z}}, with @var{q} and @var{z}
-orthogonal.  For example,
-
-@example
-@group
-[aa, bb, q, z] = qzhess ([1, 2; 3, 4], [5, 6; 7, 8])
-     @result{} aa = [ -3.02244, -4.41741;  0.92998,  0.69749 ]
-     @result{} bb = [ -8.60233, -9.99730;  0.00000, -0.23250 ]
-     @result{}  q = [ -0.58124, -0.81373; -0.81373,  0.58124 ]
-     @result{}  z = [ 1, 0; 0, 1 ]
-@end group
-@end example
-
-The Hessenberg-triangular decomposition is the first step in
-Moler and Stewart's QZ decomposition algorithm.
-
-Algorithm taken from Golub and Van Loan, @cite{Matrix Computations, 2nd
-edition}.
-@end deftypefn
-
-@deftypefn {Loadable Function} {} qzval (@var{a}, @var{b})
-Compute generalized eigenvalues of the matrix pencil 
-@iftex
-@tex
-$a - \lambda b$.
-@end tex
-@end iftex
-@ifinfo
-@code{@var{a} - lambda @var{b}}.
-@end ifinfo
-
-The arguments @var{a} and @var{b} must be real matrices.
-@end deftypefn
-
 @deftypefn {Loadable Function} {@var{x} =} syl (@var{a}, @var{b}, @var{c})
 Solve the Sylvester equation
 @iftex
--- a/kpathsea/ChangeLog
+++ b/kpathsea/ChangeLog
@@ -1,3 +1,8 @@
+Fri Oct 23 22:05:46 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* kdefault.c (kpse_expand_default): Always return newly allocated
+	storage.
+
 Fri Sep 25 13:28:54 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* elt-dirs.c (kpse_clear_dir_cache): New function.
--- a/kpathsea/kdefault.c
+++ b/kpathsea/kdefault.c
@@ -38,12 +38,12 @@
   assert (fallback);
   
   if (path == NULL)
-    expansion = (string) fallback;
+    expansion = xstrdup (fallback);
 
   /* Solitary or leading :?  */
   else if (IS_ENV_SEP (*path))
     {
-      expansion = path[1] == 0 ? (string) fallback : concat (fallback, path);
+      expansion = path[1] == 0 ? xstrdup (fallback) : concat (fallback, path);
     }
 
   /* Sorry about the assignment in the middle of the expression, but
@@ -60,7 +60,7 @@
       const_string loc;
 
       /* What we'll return if we find none.  */
-      expansion = (string) path;
+      expansion = xstrdup (path);
 
       for (loc = path; *loc && expansion == path; loc++)
         {
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,10 @@
+Fri Oct 23 21:46:20 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* pathsearch.h (dir_path::default_path): New data member.
+	* pathsearch.cc (dir_path::init): Use it.
+
+	* Makefile.in: Avoid optmization when compiling lo-ieee.cc.
+
 Fri Oct 16 01:08:30 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* chMatrix.cc (charMatrix::extract): New function.
--- a/liboctave/pathsearch.cc
+++ b/liboctave/pathsearch.cc
@@ -39,6 +39,8 @@
 // or otherwise cause trouble...
 #define string kpse_string
 
+#include <kpathsea/default.h>
+#include <kpathsea/expand.h>
 #include <kpathsea/pathsearch.h>
 #include <kpathsea/progname.h>
 
@@ -161,11 +163,24 @@
 
   kpse_clear_dir_cache ();
 
-  char *tmp = kpse_path_expand (p_orig.c_str ());
-  if (tmp)
+  char *t1 = 0;
+
+  if (p_default.empty ())
+    t1 = kpse_path_expand (p_orig.c_str ());
+  else
     {
-      p = tmp;
-      free (tmp);
+      char *t2 = kpse_expand_default (p_orig.c_str (), p_default.c_str ());
+
+      t1 = kpse_path_expand (t2);
+
+      if (t2)
+	free (t2);
+    }
+
+  if (t1)
+    {
+      p = t1;
+      free (t1);
     }
   else
     p = string ();
--- a/liboctave/pathsearch.h
+++ b/liboctave/pathsearch.h
@@ -32,20 +32,22 @@
 {
 public:
 
-  dir_path (const string& s = string ())
-    : p_orig (s), initialized (false)
+  dir_path (const string& s = string (), const string& d = string ())
+    : p_orig (s), p_default (d), initialized (false)
     {
       if (! p_orig.empty ())
 	init ();
     }
 
   dir_path (const dir_path& dp)
-    : p_orig (dp.p_orig), initialized (dp.initialized), p (dp.p), pv (dp.pv)
+    : p_orig (dp.p_orig), p_default (dp.p_default),
+      initialized (dp.initialized), p (dp.p), pv (dp.pv)
   { }
 
   dir_path& operator = (const dir_path& dp)
     {
       p_orig = dp.p_orig;
+      p_default = dp.p_default;
       initialized = dp.initialized;
       p = dp.p;
       pv = dp.pv;
@@ -82,11 +84,15 @@
   // The colon separated list that we were given.
   string p_orig;
 
+  // The default path.  If specified, replaces leading, trailing, or
+  // doubled colons in p_orig.
+  string p_default;
+
   // TRUE means we've unpacked p.
   bool initialized;
 
   // A version of the colon separate list on which we have performed
-  // tilde and variable expansion.
+  // tilde, variable, and possibly default path expansion.
   string p;
 
   // The elements of the list.
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,3 +1,7 @@
+Wed Oct 28 11:51:14 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* general/length.m: Delete.
+
 Fri Oct 23 00:21:55 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* configure.in: Add finance/Makefile, statistics/base/Makefile,
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,85 @@
+Wed Oct 28 11:01:37 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* OPERATORS/op-list.cc: New file.
+	* Makefile.in (OP_XSRC): Add it to the list.
+
+	* ov-list.cc (octave_list::assign): New function.
+
+	* ov-typeinfo.h (octave_value_typeinfo::assignany_ops):
+	New data member.
+	* ov-typeinfo.cc (octave_value_info::register_assignany_op,
+	octave_value_info::do_register_assignany_op,
+	octave_value_info::lookup_assignany_op,
+	octave_value_info::do_lookup_assignany_op):
+	New functions.
+	* ov.cc (octave_value::try_assignment (octave_value::assign_op,
+	const octave_value_list&, const octave_value&)): If no assignment
+	operator for particular RHS type exists, try finding one for
+	generic octave_value as RHS type.
+	* ops.h (DEFASSIGNANYOP_FN): New macro.
+
+	* ov-list.cc (Fsplice): New function.
+	* oct-obj.cc (octave_value_list::splice): New function.
+
+	* ov.cc (Vresize_on_range_error): No longer static.
+	* ov.h (Vresize_on_range_error): Provide extern declaration.
+
+	* oct-procbuf.cc (symbols_of_oct_procbuf): Don't declare static.
+
+	* data.cc (Flength): New function.
+	* ov.h (octave_value::length): New virtual function.
+	* ov-base.cc (octave_base_value::length): New function.
+	(octave_base_value::rows, octave_base_value::columns): Move
+	definitions here, from ov-base.h.  Don't return -1.  Instead,
+	gripe about wrong argument type.
+	* ov-bool-mat.h (octave_bool_matrix::length): New function.
+	* ov-bool.h (octave_bool::length): Ditto.
+	* ov-ch-mat.h (octave_char_matrix::length): Ditto.
+	* ov-complex.h (octave_complex::length): Ditto.
+	* ov-cx-mat.h (octave_complex_matrix::length): Ditto.
+	* ov-list.h (octave_list::length): Ditto.
+	* ov-range.h (octave_range::length): Ditto.
+	* ov-re-mat.h (octave_matrix::length): Ditto.
+	* ov-scalar.h (octave_scalar::length): Ditto.
+
+Tue Oct 27 22:19:24 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* ov-list.cc (octave_list::print_raw): Handle case of empty list.
+	(octave_list::print_name_tag): Likewise.	
+
+	* octave.cc (intern_argv): Built-in variable argv is now a list of
+	strings instead of a string vector.
+	Always bind argv, making it an empty list if there are no args.
+
+Mon Oct 26 08:41:46 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* xdiv.cc (mx_leftdiv_conform): Explicitly declare args to be
+	passed as references to const objects.  Fix explicit instantiation
+	requests to match.
+	(mx_div_conform): Likewise.
+
+	* pt-unop.h (tree_prefix_expression): Reorder constructor args to
+	put those with default values last.
+	(tree_postfix_expression): Likewise.
+	* parse.y: Change all callers.	
+
 Fri Oct 23 12:07:32 1998  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	* utils.cc (Ffile_in_loadpath): New function.
+
+	* defaults.cc (Vload_path, Vdefault_load_path): Now static.
+
+	* help.cc (simple_help): Use Vload_path_dir_path here instead of
+	trying to reconstruct it from Vload_path.
+	* fn-cache.cc (octave_fcn_file_name_cache::do_list): Likewise.
+	(octave_fcn_file_name_cache::update): Likewise.
+
+	* defaults.cc (octave_loadpath): Construct Vload_path_dir_path
+	using Vdefault_load_path.
+	(set_default_path): Likewise.
+
+	* defaults.h, defaults.cc (maybe_add_default_load_path): Delete.
+
 	* defaults.cc (Vdefault_load_path): New static variable.
 	(set_default_path): Set it.
 	(maybe_add_default_load_path): Use it.
--- a/src/ov-list.cc
+++ b/src/ov-list.cc
@@ -80,6 +80,34 @@
 }
 
 void
+octave_list::assign (const octave_value_list& idx, const octave_value& rhs)
+{
+  if (idx.length () == 1)
+    {
+      double d = idx(0).double_value ();
+
+      if (! error_state)
+	{
+	  if (D_NINT (d) == d)
+	    {
+	      int n = lst.length ();
+
+	      int i = static_cast<int> (d);
+
+	      if (i > 0 && (Vresize_on_range_error || i <= n))
+		lst(i) = rhs;
+	      else
+		error ("list index = %d out of range", i);
+	    }
+	  else
+	    error ("list index must be an integer");
+	}
+    }
+  else
+    error ("lists may only be indexed by a single scalar");
+}
+
+void
 octave_list::print (ostream& os, bool) const
 {
   print_raw (os);
@@ -90,31 +118,37 @@
 {
   unwind_protect::begin_frame ("octave_list_print");
 
-  indent (os);
-  os << "(";
-  newline (os);
-
-  increment_indent_level ();
-
   int n = lst.length ();
 
-  for (int i = 0; i < n; i++)
+  if (n > 0)
     {
-      ostrstream buf;
-      buf << "[" << i+1 << "]" << ends;
-      const char *nm = buf.str ();
+      indent (os);
+      os << "(";
+      newline (os);
+
+      increment_indent_level ();
 
-      octave_value val = lst(i);
+      for (int i = 0; i < n; i++)
+	{
+	  ostrstream buf;
+	  buf << "[" << i+1 << "]" << ends;
+	  const char *nm = buf.str ();
 
-      val.print_with_name (os, nm);
+	  octave_value val = lst(i);
 
-      delete [] nm;
-    }
+	  val.print_with_name (os, nm);
+
+	  delete [] nm;
+	}
 
-  decrement_indent_level ();
+      decrement_indent_level ();
 
-  indent (os);
-  os << ")";
+      indent (os);
+      os << ")";
+    }
+  else
+    os << "()";
+
   newline (os);
 
   unwind_protect::run_frame ("octave_list_print");
@@ -124,8 +158,13 @@
 octave_list::print_name_tag (ostream& os, const string& name) const
 {
   indent (os);
-  os << name << " =";
-  newline (os);
+  if (lst.length () == 0)
+    os << name << " = ";
+  else
+    {
+      os << name << " =";
+      newline (os);
+    }
   return false;
 }
 
@@ -186,6 +225,82 @@
   return retval;
 }
 
+DEFUN (splice, args, ,
+  "splice (LIST_1, OFFSET, LENGTH, LIST_2)\n\
+splice (LIST_1, OFFSET, LENGTH, LIST_2)\n\
+splice (LIST_1, OFFSET, LENGTH)\n\
+splice (LIST_1, OFFSET)\n\
+\n\
+Replace LENGTH elements of LIST_1 beginning at OFFSET with the
+contents of LIST_2 (if any).  If LENGTH is omitted, ")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 1 && nargin < 5)
+    {
+      octave_value_list list_1 = args(0).list_value ();
+
+      if (! error_state)
+	{
+	  double d_offset = args(1).double_value ();
+
+	  if (! error_state)
+	    {
+	      if (D_NINT (d_offset) == d_offset)
+		{
+		  int offset = static_cast<int> (d_offset) - 1;
+
+		  int length = 0;
+
+		  if (nargin < 3)
+		    length = list_1.length () - offset;
+		  else
+		    {
+		      double d_length = args(2).double_value ();
+
+		      if (error_state)
+			return retval;
+		      else
+			{
+			  if (D_NINT (d_length) == d_length)
+			    length = static_cast<int> (d_length);
+			  else
+			    error ("splice: LENGTH must be an integer");
+			}
+		    }
+
+		  octave_value_list list_2;
+
+		  if (nargin == 4)
+		    {
+		      list_2 = args(3).list_value ();
+
+		      if (error_state)
+			{
+			  error ("splice: fourth argument must be a list");
+			  return retval;
+			}
+		    }
+
+		  retval = list_1.splice (offset, length, list_2);
+		}
+	      else
+		error ("splice: OFFSET must be an integer");
+	    }
+	  else
+	    error ("splice: OFFSET must be an integer");
+	}
+      else
+	error ("splice: first argument must be a list");      
+    }
+  else
+    print_usage ("splice");
+
+  return retval;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/ov-list.h
+++ b/src/ov-list.h
@@ -72,6 +72,10 @@
 
   octave_value do_index_op (const octave_value_list& idx);
 
+  void assign (const octave_value_list& idx, const octave_value& rhs);
+
+  int length (void) const { return lst.length (); }
+
   bool is_defined (void) const { return true; }
 
   bool is_constant (void) const { return true; }
--- a/src/ov-typeinfo.cc
+++ b/src/ov-typeinfo.cc
@@ -98,6 +98,14 @@
 }
 
 bool
+octave_value_typeinfo::register_assignany_op (octave_value::assign_op op,
+					       int t_lhs, assign_op_fcn f)
+{
+  return (instance_ok ())
+    ? instance->do_register_assignany_op (op, t_lhs, f) : -1;
+}
+
+bool
 octave_value_typeinfo::register_pref_assign_conv (int t_lhs, int t_rhs,
 						  int t_result) 
 {
@@ -136,6 +144,9 @@
       assign_ops.resize (static_cast<int> (octave_value::num_assign_ops),
 			 len, len, static_cast<assign_op_fcn> (0));
 
+      assignany_ops.resize (static_cast<int> (octave_value::num_assign_ops),
+			    len, static_cast<assign_op_fcn> (0));
+
       pref_assign_conv.resize (len, len, -1);
 
       widening_ops.resize (len, len, static_cast<type_conv_fcn> (0));
@@ -169,6 +180,15 @@
 }
 
 bool
+octave_value_typeinfo::do_register_assignany_op (octave_value::assign_op op,
+						  int t_lhs, assign_op_fcn f)
+{
+  assignany_ops.checkelem (static_cast<int> (op), t_lhs) = f;
+
+  return false;
+}
+
+bool
 octave_value_typeinfo::do_register_pref_assign_conv (int t_lhs, int t_rhs,
 						     int t_result) 
 {
@@ -202,6 +222,13 @@
   return assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs);
 }
 
+assign_op_fcn
+octave_value_typeinfo::do_lookup_assignany_op (octave_value::assign_op op,
+					       int t_lhs)
+{
+  return assignany_ops.checkelem (static_cast<int> (op), t_lhs);
+}
+
 int
 octave_value_typeinfo::do_lookup_pref_assign_conv (int t_lhs, int t_rhs)
 {
--- a/src/ov-typeinfo.h
+++ b/src/ov-typeinfo.h
@@ -52,6 +52,9 @@
   static bool register_assign_op (octave_value::assign_op, int, int,
 				  assign_op_fcn);
 
+  static bool register_assignany_op (octave_value::assign_op, int,
+				     assign_op_fcn);
+
   static bool register_pref_assign_conv (int, int, int);
 
   static bool register_widening_op (int, int, type_conv_fcn);
@@ -68,6 +71,12 @@
     return instance->do_lookup_assign_op (op, t_lhs, t_rhs);
   }
 
+  static assign_op_fcn
+  lookup_assignany_op (octave_value::assign_op op, int t_lhs)
+  {
+    return instance->do_lookup_assignany_op (op, t_lhs);
+  }
+
   static int
   lookup_pref_assign_conv (int t_lhs, int t_rhs)
   {
@@ -93,6 +102,8 @@
 		  init_tab_sz, (binary_op_fcn) 0),
       assign_ops (octave_value::num_assign_ops, init_tab_sz,
 		  init_tab_sz, (assign_op_fcn) 0),
+      assignany_ops (octave_value::num_assign_ops, init_tab_sz,
+		     (assign_op_fcn) 0),
       pref_assign_conv (init_tab_sz, init_tab_sz, -1),
       widening_ops (init_tab_sz, init_tab_sz, (type_conv_fcn) 0)  { }
 
@@ -110,6 +121,8 @@
 
   Array3<assign_op_fcn> assign_ops;
 
+  Array2<assign_op_fcn> assignany_ops;
+
   Array2<int> pref_assign_conv;
 
   Array2<type_conv_fcn> widening_ops;
@@ -122,6 +135,9 @@
   bool do_register_assign_op (octave_value::assign_op, int, int,
 			      assign_op_fcn);
 
+  bool do_register_assignany_op (octave_value::assign_op, int,
+				 assign_op_fcn);
+
   bool do_register_pref_assign_conv (int, int, int);
 
   bool do_register_widening_op (int, int, type_conv_fcn);
@@ -132,6 +148,9 @@
   assign_op_fcn
   do_lookup_assign_op (octave_value::assign_op, int, int);
 
+  assign_op_fcn
+  do_lookup_assignany_op (octave_value::assign_op, int);
+
   int do_lookup_pref_assign_conv (int, int);
 
   type_conv_fcn do_lookup_widening_op (int, int);
--- a/src/ov.cc
+++ b/src/ov.cc
@@ -115,7 +115,7 @@
 
 // If TRUE, resize matrices when performing and indexed assignment and
 // the indices are outside the current bounds.
-static bool Vresize_on_range_error;
+bool Vresize_on_range_error;
 
 // XXX FIXME XXX
 
@@ -846,6 +846,17 @@
 
       retval = (! error_state);
     }
+  else
+    {
+      f = octave_value_typeinfo::lookup_assignany_op (op, t_lhs);
+
+      if (f)
+	{
+	  f (*rep, idx, rhs);
+
+	  retval = (! error_state);
+	}
+    }
 
   return retval;
 }