Hi all,

I've increased support for cell arrays in octave 2.1.31.  Now you can
assign to, extend and delete from cell arrays.  Assignments must be
from cell arrays, which means you must wrap an octave value in {}
before assigning.  For dereferencing, I've overloaded the nth function
from the list type.

Both cell arrays and lists should use the {} dereferencing
operator.  Support for this will be non-trivial.  The parser must be
extended to distinguish {} indexing from [] indexing which is easy
enough, but then every context in which they are interpreted must be
extended to accept multi-valued rvalues.  This is done already in
function calls with all_va_args (see pt-arg-list.cc), but this must be
extended to all other contexts which make sense with a dereferenced
list.

Dereferencing can also be used for lvalues in Matlab.  In this case,
you do not have wrap the value in {} before assigning, but you need to
use {} as the indexing operator.  This will require even more work to
support.  

While implementing assignment, I noticed that =[] is an operator in
Matlab.  That is, "x(i)=[];" deletes the ith element of x, but "y=[];
x(i)=y;" gives a non-conformant arguments error.  Putting deletion in
the parse.y and separating assignment from deletion would make the code
in liboctave somewhat cleaner, and fix a hack that I needed to implement
cell array deletion.

Summary of changes:

Array.h, Array.cc, Array2.cc, Array-s.cc, Array-i.cc, Array-d.cc,
Array-ch.cc, Array-C.cc, Array-b.cc 
	When you extend cell arrays by assignment, the missing values must
	be filled with [] rather than 0.  I invented a template function
	T& assign_fill_element(Array<T>&) which returns a constant with
	which to fill the missing array elements.  The template defaults
	to T(0), but you can override the template with your own function
	but not instantiating the assign_fill_element function for your type.

Cell.h Cell.cc
	Cells now inherit directly from Array2.

ov.cc
	Register octave_cell

ov-list.cc
	Extend nth to dereference cell arrays as well as lists

op-cell.cc
	Copied from op-m-m.cc, then trimmed heavily

ov-cell.cc, ov-cell.h
	Use 'matrix' rather than 'cell_val' so that the code looks more
	like the matrix code (and hopefully easier to support).
	Use matrix assignment code more or less directly.

parse.y
	Treat the empty cell array as an empty cell array rather than
	an empty matrix.

NOTES: 
	copy OPERATORS/op-m-m.cc to OPERATORS/op-cell.cc before applying patch

	the patch will probably not apply without displacements since I did
	the changes on top of other patches I submitted recently.

Enjoy!

Paul Kienzle
pkienzle@kienzle.powernet.co.uk

*** src/Cell.cc	2000/10/05 12:32:11	1.1
--- src/Cell.cc	2000/10/19 12:04:08
*************** Software Foundation, 59 Temple Place - S
*** 30,49 ****
  
  #include "Cell.h"
  
- octave_allocator
- Cell::allocator (sizeof (Cell));
  
! Cell
! Cell::index (idx_vector& i) const
! {
!   return Cell (data.index (i));
! }
  
! Cell
! Cell::index (idx_vector& i, idx_vector& j) const
  {
!   return Cell (data.index (i, j));
  }
  
  /*
  ;;; Local Variables: ***
--- 30,56 ----
  
  #include "Cell.h"
  
  
! #include "Array.h"
! #include "Array.cc"
! 
! template class Array<octave_value>;
! 
! template int assign (Array<octave_value>&, const Array<octave_value>&);
  
! #include "Array2.h"
! #include "Array2.cc"
! 
! octave_value& assign_fill_element(Array<octave_value>& lhs) 
  {
!   static octave_value foo(Matrix(0,0));
! 
!   return foo; 
  }
+ 
+ template class Array2<octave_value>;
+ 
+ template int assign (Array2<octave_value>&, const Array2<octave_value>&);
  
  /*
  ;;; Local Variables: ***
*** src/ov.cc	2000/10/05 12:32:11	1.1
--- src/ov.cc	2000/11/04 23:08:26
*************** install_types (void)
*** 1537,1542 ****
--- 1535,1541 ----
    octave_struct::register_type ();
    octave_file::register_type ();
    octave_list::register_type ();
+   octave_cell::register_type ();
    octave_all_va_args::register_type ();
    octave_magic_colon::register_type ();
    octave_builtin::register_type ();
*** src/ov-cell.cc	2000/10/05 12:32:11	1.1
--- src/ov-cell.cc	2000/10/23 09:10:27
*************** Software Foundation, 59 Temple Place - S
*** 36,41 ****
--- 36,42 ----
  #include "defun.h"
  #include "error.h"
  #include "ov-cell.h"
+ #include "ov-re-mat.h"
  #include "oct-obj.h"
  #include "unwind-prot.h"
  #include "utils.h"
*************** octave_cell::do_index_op (const octave_v
*** 58,64 ****
  	idx_vector i = idx (0).index_vector ();
  	idx_vector j = idx (1).index_vector ();
  
! 	retval = cell_val.index (i, j);
        }
        break;
  
--- 59,65 ----
  	idx_vector i = idx (0).index_vector ();
  	idx_vector j = idx (1).index_vector ();
  
! 	retval = Cell (matrix.index (i, j));
        }
        break;
  
*************** octave_cell::do_index_op (const octave_v
*** 66,77 ****
        {
  	idx_vector i = idx (0).index_vector ();
  
! 	retval = cell_val.index (i);
        }
        break;
  
      default:
        {
  	std::string n = type_name ();
  
  	error ("invalid number of indices (%d) for %s value",
--- 67,79 ----
        {
  	idx_vector i = idx (0).index_vector ();
  
! 	retval = Cell (matrix.index (i));
        }
        break;
  
      default:
        {
+ 
  	std::string n = type_name ();
  
  	error ("invalid number of indices (%d) for %s value",
*************** octave_cell::do_index_op (const octave_v
*** 83,110 ****
    return retval;
  }
  
  void
! octave_cell::assign (const octave_value_list& idx, const octave_value& rhs)
  {
! #if 0
!   if (idx.length () == 1)
      {
!       int i = idx(0).int_value (true);
  
!       if (! error_state)
! 	{
! 	  int n = lst.length ();
  
! 	  if (i > 0 && (Vresize_on_range_error || i <= n))
! 	    lst(i-1) = 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");
  #endif
  }
  
--- 85,149 ----
    return retval;
  }
  
+ #if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)
+ extern void assign (Array2<octave_value>&, const Array2<octave_value>&);
+ #endif
+ 
  void
! octave_cell::assign (const octave_value_list& idx, const Cell& rhs)
  {
!   int len = idx.length ();
!   
! 
!   switch (len)
      {
!     case 2:
!       {
! 	idx_vector i = idx (0).index_vector ();
! 	idx_vector j = idx (1).index_vector ();
  
! 	matrix.set_index (i);
! 	matrix.set_index (j);
! 
! 	::assign (matrix, rhs);
!       }
!       break;
  
!     case 1:
!       {
! 	idx_vector i = idx (0).index_vector ();
! 
! 	matrix.set_index (i);
! 
! 	::assign (matrix, rhs);
!       }
!       break;
! 
!     default:
!       error ("invalid number of indices (%d) for indexed cell assignment",
! 	     len);
      }
+ }
+ 
+ 
+ void
+ octave_cell::assign (const octave_value_list& idx, const octave_value& rhs)
+ {
+   // XXX FIX ME XXX
+   // For compatibility, need to be able to delete cells by assigning
+   // them from [].  This will have nasty interactions with auto
+   // conversion between octave values and Cell(1,1), so don't do it.
+   // The proper solution is to make a new postfix operator =[], which 
+   // means delete the indexed elements.  This won't break compatibility
+   // since "y=[]; x(idx)=y;" gives an error in Matlab, but it may
+   // break some existing octave code.
+ #if 1
+   if (rhs.is_real_matrix() && rhs.rows() == 0 && rhs.columns() == 0)
+     assign(idx, Cell(0,0,rhs));
    else
!     error ("use {v} to assign v to a cell");
! #else
!   assign(idx, Cell(1,1,rhs));
  #endif
  }
  
*************** octave_cell::print_raw (std::ostream& os
*** 119,126 ****
  {
    unwind_protect::begin_frame ("octave_cell_print");
  
!   int nr = cell_val.rows ();
!   int nc = cell_val.columns();
  
    if (nr > 0 && nc > 0)
      {
--- 158,165 ----
  {
    unwind_protect::begin_frame ("octave_cell_print");
  
!   int nr = matrix.rows ();
!   int nc = matrix.columns();
  
    if (nr > 0 && nc > 0)
      {
*************** octave_cell::print_raw (std::ostream& os
*** 138,144 ****
  	      buf << "[" << i+1 << "," << j+1 << "]" << std::ends;
  	      const char *nm = buf.str ();
  
! 	      octave_value val = cell_val(i,j);
  
  	      val.print_with_name (os, nm);
  
--- 177,183 ----
  	      buf << "[" << i+1 << "," << j+1 << "]" << std::ends;
  	      const char *nm = buf.str ();
  
! 	      octave_value val = matrix(i,j);
  
  	      val.print_with_name (os, nm);
  
*** src/ov-list.cc	2000/10/05 12:32:11	1.1
--- src/ov-list.cc	2000/10/23 11:12:48
*************** Software Foundation, 59 Temple Place - S
*** 37,42 ****
--- 37,43 ----
  #include "error.h"
  #include "ov-list.h"
  #include "unwind-prot.h"
+ #include "Cell.h"
  
  DEFINE_OCTAVE_ALLOCATOR (octave_list);
  
*************** DEFUN (nth, args, ,
*** 157,190 ****
    "-*- texinfo -*-\n\
  @deftypefn {Built-in Function} {} nth (@var{list}, @var{n})\n\
  Return the @var{n}-th element of @var{list}.\n\
  @end deftypefn")
  {
    octave_value retval;
! 
!   if (args.length () == 2)
      {
        octave_value_list lst = args(0).list_value ();
! 
        if (! error_state)
  	{
! 	  int n = args(1).int_value (true);
! 
! 	  if (! error_state)
! 	    {
! 	      if (n > 0 && n <= lst.length ())
! 		retval = lst(n-1);
! 	      else
! 		error ("nth: index = %d out of range", n);
! 	    }
  	  else
! 	    error ("nth: second argument must be an integer");
  	}
        else
! 	error ("nth: first argument must be a list");
      }
    else
!     print_usage ("nth");
! 
    return retval;
  }
  
--- 158,239 ----
    "-*- texinfo -*-\n\
  @deftypefn {Built-in Function} {} nth (@var{list}, @var{n})\n\
  Return the @var{n}-th element of @var{list}.\n\
+ @deftypefnx {Built-in Function} {} nth (@var{cell}, @var{i}, @var{j})\n\
+ Return the @var{i,j}-th element of @var{cell}.\n\
  @end deftypefn")
  {
    octave_value retval;
!   int i=-1,j=-1;
!   
!   if (args.length() < 2 
!       || (args(0).is_list() && args.length() > 2)
!       || args.length() > 3)
!     {
!       print_usage ("nth");
!       return retval;
!     }
!   
!   i = args(1).int_value (true);
!   if (error_state || i < 1)
!     {
!       error ("nth: second argument must be a positive integer");
!       return retval;
!     }
!   
!   if (args.length() == 3) 
!     {
!       j = args(2).int_value (true);
!       if (error_state || j < 1)
! 	{
! 	  error ("nth: third argument must be a positive integer");
! 	  return retval;
! 	}
!     }
!   
!   if (args(0).is_list ())
      {
        octave_value_list lst = args(0).list_value ();
!       
        if (! error_state)
  	{
! 	  if (i <= lst.length ())
! 	    retval = lst(i-1);
  	  else
! 	    error ("nth: index = %d out of range", i);
  	}
        else
! 	error ("nth: list value error");
      }
    else
!     {
!       Cell cell = args(0).cell_value ();
!       
!       if (! error_state)
! 	{
! 	  int nr = cell.rows();
! 	  int nc = cell.columns();
! 	  
! 	  if (j == -1) 
! 	    if (nr == 1)
! 	      if (i <= nc)
! 		retval = cell(0,i-1);
! 	      else
! 		error ("nth: index = %d out of range", i);
! 	    else if (nc == 1)
! 	      if (i <= nr)
! 		retval = cell(i-1,0);
! 	      else
! 		error ("nth: index = %d out of range", i);
! 	    else
! 	      error ("nth: single index not valid for 2-D cell array");
! 	  else if (i <= nr && j <= nc)
! 	    retval = cell(i-1, j-1);
! 	  else
! 	    error ("nth: index = %d,%d out of range", i, j);
! 	}
!       else
! 	error ("nth: first argument must be a list or cell");
!     }
    return retval;
  }
  
*** src/Cell.h	2000/10/05 12:32:11	1.1
--- src/Cell.h	2000/10/09 10:16:06
*************** Software Foundation, 59 Temple Place - S
*** 30,92 ****
  #include <string>
  
  #include "Array2.h"
- #include "oct-alloc.h"
- #include "str-vec.h"
  
  #include "ov.h"
  
! class
! Cell
  {
  public:
  
!   Cell (void)
!     : data () { }
  
    Cell (int n, int m, const octave_value& val = octave_value ())
!     : data (n, m, val) { }
  
!   Cell (const Array2<octave_value>& c)
!     : data (c) { }
  
!   Cell (const Cell& c)
!     : data (c.data) { }
! 
!   void *operator new (size_t size)
!     { return allocator.alloc (size); }
! 
!   void operator delete (void *p, size_t size)
!     { allocator.free (p, size); }
  
    Cell& operator = (const Cell& c)
      {
!       if (this != &c)
! 	data = c.data;
! 
        return *this;
      }
  
!   int rows (void) const { return data.rows (); }
! 
!   int columns (void) const { return data.columns (); }
! 
!   octave_value& operator () (int i, int j) { return elem (i, j); }
! 
!   octave_value operator () (int i, int j) const { return elem (i, j); }
! 
!   octave_value& elem (int i, int j) { return data.elem (i, j); }
! 
!   octave_value elem (int i, int j) const { return data.elem (i, j); }
! 
!   Cell index (idx_vector& i) const;
! 
!   Cell index (idx_vector& i, idx_vector& j) const;
! 
! private:
  
!   static octave_allocator allocator;
  
-   Array2<octave_value> data;
  };
  
  #endif
--- 30,65 ----
  #include <string>
  
  #include "Array2.h"
  
  #include "ov.h"
  
! class Cell : public Array2<octave_value>
  {
  public:
  
!   Cell (void) : Array2<octave_value> () { }
  
    Cell (int n, int m, const octave_value& val = octave_value ())
!     : Array2<octave_value> (n, m, val) { }
  
!   Cell (const Cell& c) : Array2<octave_value> (c) { }
  
!   Cell (const Array2<octave_value>& c) : Array2<octave_value> (c) { }
  
    Cell& operator = (const Cell& c)
      {
!       Array2<octave_value>::operator = (c);
        return *this;
      }
  
!   Cell& insert (const Array2<octave_value>& a, int r, int c)
!   {
!     Array2<octave_value>::insert (a, r, c);
!     return *this;
!   }
  
!   Cell transpose (void) const { return Array2<octave_value>::transpose (); }
  
  };
  
  #endif
*** src/ov-cell.h	2000/10/05 12:32:11	1.1
--- src/ov-cell.h	2000/10/19 12:28:30
*************** public:
*** 56,66 ****
    octave_cell (void)
      : octave_base_value () { }
  
!   octave_cell (const Cell& c)
!     : octave_base_value (), cell_val (c) { }
  
!   octave_cell (const octave_cell& c)
!     : octave_base_value (), cell_val (c.cell_val) { }
  
    ~octave_cell (void) { }
  
--- 56,66 ----
    octave_cell (void)
      : octave_base_value () { }
  
!   octave_cell (const Cell& m)
!     : octave_base_value (), matrix (m) { }
  
!   octave_cell (const octave_cell& m)
!     : octave_base_value (), matrix (m.matrix) { }
  
    ~octave_cell (void) { }
  
*************** public:
*** 68,80 ****
  
    octave_value do_index_op (const octave_value_list& idx);
  
    void assign (const octave_value_list& idx, const octave_value& rhs);
  
    bool is_defined (void) const { return true; }
  
    bool is_constant (void) const { return true; }
  
!   Cell cell_value (void) const { return cell_val; }
  
    void print (std::ostream& os, bool pr_as_read_syntax = false) const;
  
--- 68,94 ----
  
    octave_value do_index_op (const octave_value_list& idx);
  
+   int rows (void) const { return matrix.rows (); }
+   int columns (void) const { return matrix.columns (); }
+ 
+   int length (void) const
+   {
+     int r = rows ();
+     int c = columns ();
+ 
+     return (r == 0 || c == 0) ? 0 : ((r > c) ? r : c);
+   }
+ 
+   void assign (const octave_value_list& idx, const Cell& rhs);
    void assign (const octave_value_list& idx, const octave_value& rhs);
  
    bool is_defined (void) const { return true; }
  
    bool is_constant (void) const { return true; }
  
!   bool is_cell (void) const { return true; }
! 
!   Cell cell_value (void) const { return matrix; }
  
    void print (std::ostream& os, bool pr_as_read_syntax = false) const;
  
*************** public:
*** 84,90 ****
  
  private:
  
!   Cell cell_val;
  
    DECLARE_OCTAVE_ALLOCATOR
  
--- 98,104 ----
  
  private:
  
!   Cell matrix;
  
    DECLARE_OCTAVE_ALLOCATOR
  
*** src/parse.y	2000/10/05 12:33:31	1.1
--- src/parse.y	2000/10/26 12:20:02
*************** Software Foundation, 59 Temple Place - S
*** 40,45 ****
--- 40,46 ----
  
  #include <strstream.h>
  
+ #include "Cell.h"
  #include "Matrix.h"
  #include "cmd-edit.h"
  #include "cmd-hist.h"
*************** matrix_rows1	: cell_or_matrix_row
*** 603,611 ****
  		;
  
  cell		: '{' '}'
! 		  { $$ = new tree_constant (octave_value (Matrix ())); }
  		| '{' ';' '}'
! 		  { $$ = new tree_constant (octave_value (Matrix ())); }
  		| '{' cell_rows '}'
  		  { $$ = finish_cell ($2); }
  		;
--- 610,618 ----
  		;
  
  cell		: '{' '}'
! 		  { $$ = new tree_constant (octave_value (Cell ())); }
  		| '{' ';' '}'
! 		  { $$ = new tree_constant (octave_value (Cell ())); }
  		| '{' cell_rows '}'
  		  { $$ = finish_cell ($2); }
  		;
*** src/OPERATORS/op-cell.cc	2000/10/10 12:44:55	1.1
--- src/OPERATORS/op-cell.cc	2000/10/23 11:58:11
*************** Software Foundation, 59 Temple Place - S
*** 30,131 ****
  
  #include "gripes.h"
  #include "ov.h"
! #include "ov-re-mat.h"
  #include "ov-typeinfo.h"
  #include "ops.h"
- #include "xdiv.h"
- #include "xpow.h"
  
  // matrix unary ops.
  
! DEFUNOP_OP (not, matrix, !)
! DEFUNOP_OP (uminus, matrix, -)
! 
! DEFUNOP (transpose, matrix)
  {
!   CAST_UNOP_ARG (const octave_matrix&);
  
!   return octave_value (v.matrix_value().transpose ());
  }
  
! DEFNCUNOP_METHOD (incr, matrix, increment)
! DEFNCUNOP_METHOD (decr, matrix, decrement)
! 
! // matrix by matrix ops.
! 
! DEFBINOP_OP (add, matrix, matrix, +)
! DEFBINOP_OP (sub, matrix, matrix, -)
! DEFBINOP_OP (mul, matrix, matrix, *)
! 
! DEFBINOP (div, matrix, matrix)
  {
!   CAST_BINOP_ARGS (const octave_matrix&, const octave_matrix&);
! 
!   return xdiv (v1.matrix_value (), v2.matrix_value ());
  }
  
- DEFBINOPX (pow, matrix, matrix)
- {
-   error ("can't do A ^ B for A and B both matrices");
-   return octave_value ();
- }
- 
- DEFBINOP_FN (ldiv, matrix, matrix, xleftdiv)
- 
- DEFBINOP_FN (lt, matrix, matrix, mx_el_lt)
- DEFBINOP_FN (le, matrix, matrix, mx_el_le)
- DEFBINOP_FN (eq, matrix, matrix, mx_el_eq)
- DEFBINOP_FN (ge, matrix, matrix, mx_el_ge)
- DEFBINOP_FN (gt, matrix, matrix, mx_el_gt)
- DEFBINOP_FN (ne, matrix, matrix, mx_el_ne)
- 
- DEFBINOP_FN (el_mul, matrix, matrix, product)
- DEFBINOP_FN (el_div, matrix, matrix, quotient)
- DEFBINOP_FN (el_pow, matrix, matrix, elem_xpow)
- 
- DEFBINOP (el_ldiv, matrix, matrix)
- {
-   CAST_BINOP_ARGS (const octave_matrix&, const octave_matrix&);
- 
-   return octave_value (quotient (v2.matrix_value (), v1.matrix_value ()));
- }
- 
- DEFBINOP_FN (el_and, matrix, matrix, mx_el_and)
- DEFBINOP_FN (el_or, matrix, matrix, mx_el_or)
- 
- DEFASSIGNOP_FN (assign, matrix, matrix, assign)
- 
  void
! install_m_m_ops (void)
  {
!   INSTALL_UNOP (op_not, octave_matrix, not);
!   INSTALL_UNOP (op_uminus, octave_matrix, uminus);
!   INSTALL_UNOP (op_transpose, octave_matrix, transpose);
!   INSTALL_UNOP (op_hermitian, octave_matrix, transpose);
! 
!   INSTALL_NCUNOP (op_incr, octave_matrix, incr);
!   INSTALL_NCUNOP (op_decr, octave_matrix, decr);
! 
!   INSTALL_BINOP (op_add, octave_matrix, octave_matrix, add);
!   INSTALL_BINOP (op_sub, octave_matrix, octave_matrix, sub);
!   INSTALL_BINOP (op_mul, octave_matrix, octave_matrix, mul);
!   INSTALL_BINOP (op_div, octave_matrix, octave_matrix, div);
!   INSTALL_BINOP (op_pow, octave_matrix, octave_matrix, pow);
!   INSTALL_BINOP (op_ldiv, octave_matrix, octave_matrix, ldiv);
!   INSTALL_BINOP (op_lt, octave_matrix, octave_matrix, lt);
!   INSTALL_BINOP (op_le, octave_matrix, octave_matrix, le);
!   INSTALL_BINOP (op_eq, octave_matrix, octave_matrix, eq);
!   INSTALL_BINOP (op_ge, octave_matrix, octave_matrix, ge);
!   INSTALL_BINOP (op_gt, octave_matrix, octave_matrix, gt);
!   INSTALL_BINOP (op_ne, octave_matrix, octave_matrix, ne);
!   INSTALL_BINOP (op_el_mul, octave_matrix, octave_matrix, el_mul);
!   INSTALL_BINOP (op_el_div, octave_matrix, octave_matrix, el_div);
!   INSTALL_BINOP (op_el_pow, octave_matrix, octave_matrix, el_pow);
!   INSTALL_BINOP (op_el_ldiv, octave_matrix, octave_matrix, el_ldiv);
!   INSTALL_BINOP (op_el_and, octave_matrix, octave_matrix, el_and);
!   INSTALL_BINOP (op_el_or, octave_matrix, octave_matrix, el_or);
  
!   INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_matrix, assign);
  }
  
  /*
--- 30,66 ----
  
  #include "gripes.h"
  #include "ov.h"
! #include "ov-cell.h"
  #include "ov-typeinfo.h"
  #include "ops.h"
  
  // matrix unary ops.
  
! DEFUNOP (transpose, cell)
  {
!   CAST_UNOP_ARG (const octave_cell&);
  
!   return octave_value (v.cell_value().transpose ());
  }
  
! DEFASSIGNOP_FN (assign, cell, cell, assign)
! DEFASSIGNANYOP_FN (assignany, cell, assign);
! CONVDECLX (cell_conv)
  {
!   return new octave_cell();
  }
  
  void
! install_cell_ops (void)
  {
!   INSTALL_UNOP (op_transpose, octave_cell, transpose);
!   INSTALL_UNOP (op_hermitian, octave_cell, transpose);
! 
!   INSTALL_ASSIGNOP (op_asn_eq, octave_cell, octave_cell, assign);
!   INSTALL_ASSIGNANYOP (op_asn_eq, octave_cell, assignany);
  
!   INSTALL_ASSIGNCONV (octave_base_value, octave_cell, octave_cell);
!   INSTALL_WIDENOP (octave_base_value, octave_cell, cell_conv);
  }
  
  /*
*** liboctave/Array-b.cc	2000/10/05 09:33:32	1.1
--- liboctave/Array-b.cc	2000/10/19 11:56:48
*************** Software Foundation, 59 Temple Place - S
*** 31,36 ****
--- 31,37 ----
  
  template class Array<bool>;
  
+ template bool& assign_fill_element(Array<bool>&);
  template int assign (Array<bool>&, const Array<bool>&);
  
  #include "Array2.h"
*** liboctave/Array-C.cc	2000/10/05 09:33:32	1.1
--- liboctave/Array-C.cc	2000/10/19 11:54:42
*************** Software Foundation, 59 Temple Place - S
*** 33,38 ****
--- 33,39 ----
  
  template class Array<Complex>;
  
+ template Complex& assign_fill_element(Array<Complex>&);
  template int assign (Array<Complex>&, const Array<Complex>&);
  template int assign (Array<Complex>&, const Array<double>&);
  template int assign (Array<Complex>&, const Array<int>&);
*** liboctave/Array-ch.cc	2000/10/05 09:33:32	1.1
--- liboctave/Array-ch.cc	2000/10/19 11:54:50
*************** Software Foundation, 59 Temple Place - S
*** 31,36 ****
--- 31,37 ----
  
  template class Array<char>;
  
+ template char& assign_fill_element(Array<char>&);
  template int assign (Array<char>&, const Array<char>&);
  
  #include "Array2.h"
*** liboctave/Array-d.cc	2000/10/05 09:33:32	1.1
--- liboctave/Array-d.cc	2000/10/19 11:55:22
*************** Software Foundation, 59 Temple Place - S
*** 31,36 ****
--- 31,37 ----
  
  template class Array<double>;
  
+ template double& assign_fill_element(Array<double>&);
  template int assign (Array<double>&, const Array<double>&);
  template int assign (Array<double>&, const Array<int>&);
  template int assign (Array<double>&, const Array<short>&);
*** liboctave/Array-i.cc	2000/10/05 09:33:32	1.1
--- liboctave/Array-i.cc	2000/10/19 11:54:31
*************** Software Foundation, 59 Temple Place - S
*** 31,36 ****
--- 31,37 ----
  
  template class Array<int>;
  
+ template int& assign_fill_element(Array<int>&);
  template int assign (Array<int>&, const Array<int>&);
  template int assign (Array<int>&, const Array<short>&);
  template int assign (Array<int>&, const Array<char>&);
*** liboctave/Array-s.cc	2000/10/05 09:33:32	1.1
--- liboctave/Array-s.cc	2000/10/19 11:57:39
*************** Software Foundation, 59 Temple Place - S
*** 31,36 ****
--- 31,37 ----
  
  template class Array<short>;
  
+ template short& assign_fill_element(Array<short>&);
  template int assign (Array<short>&, const Array<short>&);
  template int assign (Array<short>&, const Array<char>&);
  
*** liboctave/Array2-idx.h	2000/10/05 09:33:32	1.1
--- liboctave/Array2-idx.h	2000/10/18 23:29:56
*************** Array2<T>::maybe_delete_elements (idx_ve
*** 487,493 ****
  	  int new_nr = max_row_idx > lhs_nr ? max_row_idx : lhs_nr; \
  	  int new_nc = max_col_idx > lhs_nc ? max_col_idx : lhs_nc; \
   \
! 	  lhs.resize (new_nr, new_nc, 0.0); \
  	} \
      } \
    while (0)
--- 497,503 ----
  	  int new_nr = max_row_idx > lhs_nr ? max_row_idx : lhs_nr; \
  	  int new_nc = max_col_idx > lhs_nc ? max_col_idx : lhs_nc; \
   \
! 	  lhs.resize (new_nr, new_nc, assign_fill_element(lhs)); \
  	} \
      } \
    while (0)
*** liboctave/Array.h	2000/10/05 09:33:32	1.1
--- liboctave/Array.h	2000/10/18 23:19:45
*************** public:
*** 250,255 ****
--- 250,259 ----
  #endif
  };
  
+ template <class T>
+ T&
+ assign_fill_element (Array<T>& lhs);
+ 
  template <class LT, class RT>
  int
  assign (Array<LT>& lhs, const Array<RT>& rhs);
*** liboctave/Array-idx.h	2000/10/05 09:33:32	1.1
--- liboctave/Array-idx.h	2000/10/18 23:19:31
*************** Array<T>::maybe_delete_elements (idx_vec
*** 172,177 ****
--- 172,185 ----
      }
  }
  
+ template <class T>
+ T& assign_fill_element(Array<T>& lhs)
+ { 
+   static T foo(0);
+ 
+   return foo;
+ }
+ 
  // ??? FIXME ??? -- this does not handle assignment of empty vectors
  // to delete elements.  Should it?
  
*************** assign (Array<LT>& lhs, const Array<RT>&
*** 196,202 ****
  	{
  	  int max_idx = lhs_idx.max () + 1;
  	  if (max_idx > lhs_len)
! 	    lhs.resize (max_idx, 0.0);
  	}
  
        if (rhs_len == n)
--- 204,210 ----
  	{
  	  int max_idx = lhs_idx.max () + 1;
  	  if (max_idx > lhs_len)
! 	    lhs.resize (max_idx, assign_fill_element(lhs));
  	}
  
        if (rhs_len == n)
