diff liboctave/Array.cc @ 4517:b4449b1193ac

[project @ 2003-09-20 02:06:06 by jwe]
author jwe
date Sat, 20 Sep 2003 02:06:07 +0000
parents 508238e65af7
children 382cb0ed8c14
line wrap: on
line diff
--- a/liboctave/Array.cc
+++ b/liboctave/Array.cc
@@ -34,7 +34,8 @@
 #include <iostream>
 
 #include "Array.h"
-#include "Array-idx.h"
+#include "Array-flags.h"
+#include "Range.h"
 #include "idx-vector.h"
 #include "lo-error.h"
 
@@ -225,29 +226,6 @@
   return retval;
 }
 
-#if 0
-
-template <class T>
-int
-Array<T>::compute_index (int i, int j) const
-{
-  int retval = -1;
-
-  int n = dimensions.length ();
-
-  if (n == 2)
-    retval = j*dimensions(0)+i;
-  else if (n == 1 && j == 0)
-    retval = i;
-  else
-    (*current_liboctave_error_handler)
-      ("Array<T>::compute_index: invalid ra_idxing operation");
-
-  return retval;
-}
-
-#endif
-
 template <class T>
 T
 Array<T>::range_error (const char *fcn, int n) const
@@ -767,35 +745,6 @@
 }
 
 template <class T>
-void
-Array<T>::maybe_delete_dims (void)
-{
-  int ndims = dimensions.length ();
-
-  dim_vector new_dims (1, 1);
-
-  bool delete_dims = true;
-
-  for (int i = ndims - 1; i >= 0; i--)
-    {
-      if (delete_dims)
-        {
-          if (dimensions(i) != 1)
-	    {
-	      delete_dims = false;
-
-	      new_dims = dim_vector (i + 1, dimensions(i));
-	    }
-        }
-      else
-	new_dims(i) = dimensions(i);
-    }
-    
-  if (ndims != new_dims.length ())
-    dimensions = new_dims;
-}
-
-template <class T>
 Array<T>
 Array<T>::transpose (void) const
 {
@@ -833,6 +782,1726 @@
 
 template <class T>
 void
+Array<T>::maybe_delete_dims (void)
+{
+  int ndims = dimensions.length ();
+
+  dim_vector new_dims (1, 1);
+
+  bool delete_dims = true;
+
+  for (int i = ndims - 1; i >= 0; i--)
+    {
+      if (delete_dims)
+        {
+          if (dimensions(i) != 1)
+	    {
+	      delete_dims = false;
+
+	      new_dims = dim_vector (i + 1, dimensions(i));
+	    }
+        }
+      else
+	new_dims(i) = dimensions(i);
+    }
+    
+  if (ndims != new_dims.length ())
+    dimensions = new_dims;
+}
+
+template <class T>
+void
+Array<T>::clear_index (void)
+{
+  delete [] idx;
+  idx = 0;
+  idx_count = 0;
+}
+
+template <class T>
+void
+Array<T>::set_index (const idx_vector& idx_arg)
+{
+  int nd = ndims ();
+
+  if (! idx && nd > 0)
+    idx = new idx_vector [nd];
+
+  if (idx_count < nd)
+    {
+      idx[idx_count++] = idx_arg;
+    }
+  else
+    {
+      idx_vector *new_idx = new idx_vector [idx_count+1];
+
+      for (int i = 0; i < idx_count; i++)
+	new_idx[i] = idx[i];
+
+      new_idx[idx_count++] = idx_arg;
+
+      delete [] idx;
+
+      idx = new_idx;
+    }
+}
+
+template <class T>
+void
+Array<T>::maybe_delete_elements (idx_vector& idx_arg)
+{
+  switch (ndims ())
+    {
+    case 1:
+      maybe_delete_elements_1 (idx_arg);
+      break;
+
+    case 2:
+      maybe_delete_elements_2 (idx_arg);
+      break;
+
+    default:
+      (*current_liboctave_error_handler)
+	("Array<T>::maybe_delete_elements: invalid operation");
+      break;
+    }
+}
+
+template <class T>
+void
+Array<T>::maybe_delete_elements_1 (idx_vector& idx_arg)
+{
+  int len = length ();
+
+  if (len == 0)
+    return;
+
+  if (idx_arg.is_colon_equiv (len, 1))
+    resize_no_fill (0);
+  else
+    {
+      int num_to_delete = idx_arg.length (len);
+
+      if (num_to_delete != 0)
+	{
+	  int new_len = len;
+
+	  int iidx = 0;
+
+	  for (int i = 0; i < len; i++)
+	    if (i == idx_arg.elem (iidx))
+	      {
+		iidx++;
+		new_len--;
+
+		if (iidx == num_to_delete)
+		  break;
+	      }
+
+	  if (new_len > 0)
+	    {
+	      T *new_data = new T [new_len];
+
+	      int ii = 0;
+	      iidx = 0;
+	      for (int i = 0; i < len; i++)
+		{
+		  if (iidx < num_to_delete && i == idx_arg.elem (iidx))
+		    iidx++;
+		  else
+		    {
+		      new_data[ii] = elem (i);
+		      ii++;
+		    }
+		}
+
+	      if (--rep->count <= 0)
+		delete rep;
+
+	      rep = new typename Array<T>::ArrayRep (new_data, new_len);
+
+	      dimensions.resize (1);
+	      dimensions(0) = new_len;
+	    }
+	  else
+	    (*current_liboctave_error_handler)
+	      ("A(idx) = []: index out of range");
+	}
+    }
+}
+
+template <class T>
+void
+Array<T>::maybe_delete_elements_2 (idx_vector& idx_arg)
+{
+  int nr = dim1 ();
+  int nc = dim2 ();
+
+  if (nr == 0 && nc == 0)
+    return;
+
+  int n;
+  if (nr == 1)
+    n = nc;
+  else if (nc == 1)
+    n = nr;
+  else
+    {
+      (*current_liboctave_error_handler)
+	("A(idx) = []: expecting A to be row or column vector or scalar");
+
+      return;
+    }
+
+  if (idx_arg.is_colon_equiv (n, 1))
+    {
+      // Either A(:) = [] or A(idx) = [] with idx enumerating all
+      // elements, so we delete all elements and return [](0x0).  To
+      // preserve the orientation of the vector, you have to use
+      // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns).
+
+      resize_no_fill (0, 0);
+      return;
+    }
+
+  idx_arg.sort (true);
+
+  int num_to_delete = idx_arg.length (n);
+
+  if (num_to_delete != 0)
+    {
+      int new_n = n;
+
+      int iidx = 0;
+
+      for (int i = 0; i < n; i++)
+	if (i == idx_arg.elem (iidx))
+	  {
+	    iidx++;
+	    new_n--;
+
+	    if (iidx == num_to_delete)
+	      break;
+	  }
+
+      if (new_n > 0)
+	{
+	  T *new_data = new T [new_n];
+
+	  int ii = 0;
+	  iidx = 0;
+	  for (int i = 0; i < n; i++)
+	    {
+	      if (iidx < num_to_delete && i == idx_arg.elem (iidx))
+		iidx++;
+	      else
+		{
+		  if (nr == 1)
+		    new_data[ii] = elem (0, i);
+		  else
+		    new_data[ii] = elem (i, 0);
+
+		  ii++;
+		}
+	    }
+
+	  if (--(Array<T>::rep)->count <= 0)
+	    delete Array<T>::rep;
+
+	  Array<T>::rep = new typename Array<T>::ArrayRep (new_data, new_n);
+
+	  dimensions.resize (2);
+
+	  if (nr == 1)
+	    {
+	      dimensions(0) = 1;
+	      dimensions(1) = new_n;
+	    }
+	  else
+	    {
+	      dimensions(0) = new_n;
+	      dimensions(1) = 1;
+	    }
+	}
+      else
+	(*current_liboctave_error_handler)
+	  ("A(idx) = []: index out of range");
+    }
+}
+
+template <class T>
+void
+Array<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j)
+{
+  int nr = dim1 ();
+  int nc = dim2 ();
+
+  if (nr == 0 && nc == 0)
+    return;
+
+  if (idx_i.is_colon ())
+    {
+      if (idx_j.is_colon ())
+	{
+	  // A(:,:) -- We are deleting columns and rows, so the result
+	  // is [](0x0).
+
+	  resize_no_fill (0, 0);
+	  return;
+	}
+
+      if (idx_j.is_colon_equiv (nc, 1))
+	{
+	  // A(:,j) -- We are deleting columns by enumerating them,
+	  // If we enumerate all of them, we should have zero columns
+	  // with the same number of rows that we started with.
+
+	  resize_no_fill (nr, 0);
+	  return;
+	}
+    }
+
+  if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1))
+    {
+      // A(i,:) -- We are deleting rows by enumerating them.  If we
+      // enumerate all of them, we should have zero rows with the
+      // same number of columns that we started with.
+
+      resize_no_fill (0, nc);
+      return;
+    }
+
+  if (idx_i.is_colon_equiv (nr, 1))
+    {
+      if (idx_j.is_colon_equiv (nc, 1))
+	resize_no_fill (0, 0);
+      else
+	{
+	  idx_j.sort (true);
+
+	  int num_to_delete = idx_j.length (nc);
+
+	  if (num_to_delete != 0)
+	    {
+	      if (nr == 1 && num_to_delete == nc)
+		resize_no_fill (0, 0);
+	      else
+		{
+		  int new_nc = nc;
+
+		  int iidx = 0;
+
+		  for (int j = 0; j < nc; j++)
+		    if (j == idx_j.elem (iidx))
+		      {
+			iidx++;
+			new_nc--;
+
+			if (iidx == num_to_delete)
+			  break;
+		      }
+
+		  if (new_nc > 0)
+		    {
+		      T *new_data = new T [nr * new_nc];
+
+		      int jj = 0;
+		      iidx = 0;
+		      for (int j = 0; j < nc; j++)
+			{
+			  if (iidx < num_to_delete && j == idx_j.elem (iidx))
+			    iidx++;
+			  else
+			    {
+			      for (int i = 0; i < nr; i++)
+				new_data[nr*jj+i] = elem (i, j);
+			      jj++;
+			    }
+			}
+
+		      if (--(Array<T>::rep)->count <= 0)
+			delete Array<T>::rep;
+
+		      Array<T>::rep = new typename Array<T>::ArrayRep (new_data, nr * new_nc);
+
+		      dimensions.resize (2);
+		      dimensions(1) = new_nc;
+		    }
+		  else
+		    (*current_liboctave_error_handler)
+		      ("A(idx) = []: index out of range");
+		}
+	    }
+	}
+    }
+  else if (idx_j.is_colon_equiv (nc, 1))
+    {
+      if (idx_i.is_colon_equiv (nr, 1))
+	resize_no_fill (0, 0);
+      else
+	{
+	  idx_i.sort (true);
+
+	  int num_to_delete = idx_i.length (nr);
+
+	  if (num_to_delete != 0)
+	    {
+	      if (nc == 1 && num_to_delete == nr)
+		resize_no_fill (0, 0);
+	      else
+		{
+		  int new_nr = nr;
+
+		  int iidx = 0;
+
+		  for (int i = 0; i < nr; i++)
+		    if (i == idx_i.elem (iidx))
+		      {
+			iidx++;
+			new_nr--;
+
+			if (iidx == num_to_delete)
+			  break;
+		      }
+
+		  if (new_nr > 0)
+		    {
+		      T *new_data = new T [new_nr * nc];
+
+		      int ii = 0;
+		      iidx = 0;
+		      for (int i = 0; i < nr; i++)
+			{
+			  if (iidx < num_to_delete && i == idx_i.elem (iidx))
+			    iidx++;
+			  else
+			    {
+			      for (int j = 0; j < nc; j++)
+				new_data[new_nr*j+ii] = elem (i, j);
+			      ii++;
+			    }
+			}
+
+		      if (--(Array<T>::rep)->count <= 0)
+			delete Array<T>::rep;
+
+		      Array<T>::rep = new typename Array<T>::ArrayRep (new_data, new_nr * nc);
+
+		      dimensions.resize (2);
+		      dimensions(0) = new_nr;
+		    }
+		  else
+		    (*current_liboctave_error_handler)
+		      ("A(idx) = []: index out of range");
+		}
+	    }
+	}
+    }
+}
+
+template <class T>
+void
+Array<T>::maybe_delete_elements (idx_vector&, idx_vector&, idx_vector&)
+{
+  assert (0);
+}
+
+template <class T>
+void
+Array<T>::maybe_delete_elements (Array<idx_vector>& idx, const T& rfv)
+{
+  int n_idx = idx.length ();
+
+  dim_vector lhs_dims = dims ();
+
+  dim_vector idx_is_colon;
+  idx_is_colon.resize (n_idx);
+
+  dim_vector idx_is_colon_equiv;
+  idx_is_colon_equiv.resize (n_idx);
+
+  // Initialization of colon arrays.
+
+  for (int i = 0; i < n_idx; i++)
+    {
+      idx_is_colon_equiv(i) = idx(i).is_colon_equiv (lhs_dims(i), 1);
+
+      idx_is_colon(i) = idx(i).is_colon ();
+    }
+
+  if (all_ones (idx_is_colon) || all_ones (idx_is_colon_equiv))
+    {
+      // A(:,:,:) -- we are deleting elements in all dimensions, so
+      // the result is [](0x0x0).
+
+      dim_vector zeros;
+      zeros.resize (n_idx);
+
+      for (int i = 0; i < n_idx; i++)
+	zeros(i) = 0;
+
+      resize (zeros, rfv);
+    }
+
+  else if (num_ones (idx_is_colon) == n_idx - 1
+	   && num_ones (idx_is_colon_equiv) == n_idx)
+    {
+      // A(:,:,j) -- we are deleting elements in one dimension by
+      // enumerating them.
+      //
+      // If we enumerate all of the elements, we should have zero
+      // elements in that dimension with the same number of elements
+      // in the other dimensions that we started with.
+
+      dim_vector temp_dims;
+      temp_dims.resize (n_idx);
+
+      for (int i = 0; i < n_idx; i++)
+	{
+	  if (idx_is_colon (i))
+	    temp_dims (i) =  lhs_dims (i);
+	  else
+	    temp_dims (i) = 0;
+	}
+
+      resize (temp_dims);
+    }
+  else if (num_ones (idx_is_colon) == n_idx - 1)
+    {
+      // We have colons in all indices except for one.
+      // This index tells us which slice to delete
+
+      int non_col = 0;
+
+      // Find the non-colon column.
+
+      for (int i = 0; i < n_idx; i++)
+	{
+	  if (! idx_is_colon (i))
+	    non_col = i;
+	}
+
+      // The length of the non-colon dimension.
+
+      int non_col_dim = lhs_dims (non_col);
+
+      idx(non_col).sort (true);
+
+      int num_to_delete = idx(non_col).length (lhs_dims (non_col));
+
+      if (num_to_delete > 0)
+	{
+	  int temp = num_ones(lhs_dims);
+
+	  if (non_col_dim == 1)
+	    temp--;
+
+	  if (temp == n_idx - 1 && num_to_delete == non_col_dim)
+	    {
+	      // We have A with (1x1x4), where A(1,:,1:4)
+	      // Delete all (0x0x0)
+
+	      dim_vector zero_dims (n_idx, 0);
+
+	      resize (zero_dims, rfv);
+	    }
+	  else
+	    {
+	      // New length of non-colon dimension
+	      // (calculated in the next for loop)
+
+	      int new_dim = non_col_dim;
+
+	      int iidx = 0;
+
+	      for (int j = 0; j < non_col_dim; j++)
+		if (j == idx(non_col).elem (iidx))
+		  {
+		    iidx++;
+
+		    new_dim--;
+
+		    if (iidx == num_to_delete)
+		      break;
+		  }
+
+	      // Creating the new nd array after deletions.
+
+	      if (new_dim > 0)
+		{
+		  // Calculate number of elements in new array.
+
+		  int num_new_elem=1;
+
+		  for (int i = 0; i < n_idx; i++)
+		    {
+		      if (i == non_col)
+			num_new_elem *= new_dim;
+
+		      else
+			num_new_elem *= lhs_dims(i);
+		    }
+
+		  T *new_data = new T [num_new_elem];
+		  
+		  Array<int> result_idx (lhs_dims.length (), 0);
+
+		  dim_vector lhs_inc;
+		  lhs_inc.resize (lhs_dims.length ());
+
+		  for (int i = 0; i < lhs_dims.length (); i++)
+		    lhs_inc(i) = lhs_dims(i) + 1;
+
+		  dim_vector new_lhs_dim = lhs_dims;
+
+		  new_lhs_dim(non_col) = new_dim;
+
+		  int num_elem = 1;
+
+		  int numidx = 0;
+
+		  int n = length ();
+
+		  for (int i =0; i < lhs_dims.length (); i++)
+		    if (i != non_col)
+		      num_elem *= lhs_dims (i);
+
+		  num_elem *= idx(non_col).capacity ();
+
+		  for (int i = 0; i < n; i++)
+		    {
+		      if (numidx < num_elem
+			  && is_in (result_idx(non_col), idx(non_col)))
+			numidx++;
+
+		      else
+			{
+			  Array<int> temp_result_idx = result_idx;
+
+			  int num_lgt
+			    = how_many_lgt (result_idx(non_col), idx(non_col));
+
+			  temp_result_idx(non_col) -= num_lgt;
+
+			  int kidx
+			    = ::compute_index (temp_result_idx, new_lhs_dim);
+
+			  new_data[kidx] = elem (result_idx);
+			}
+
+		      increment_index (result_idx, lhs_dims);
+		    }
+
+		  if (--rep->count <= 0)
+		    delete rep;
+
+		  rep = new typename Array<T>::ArrayRep (new_data,
+							 num_new_elem);
+
+		  dimensions = new_lhs_dim;
+	    	}
+	    }
+	}
+    }
+  else if (num_ones(idx_is_colon) < n_idx)
+    {
+      (*current_liboctave_error_handler)
+	("A null assignment can have only one non-colon index.");
+    }
+}
+
+template <class T>
+Array<T>
+Array<T>::value (void)
+{
+  Array<T> retval;
+
+  int n_idx = index_count ();
+
+  if (n_idx == 2)
+    {
+      idx_vector *tmp = get_idx ();
+
+      idx_vector idx_i = tmp[0];
+      idx_vector idx_j = tmp[1];
+
+      retval = index (idx_i, idx_j);
+    }
+  else if (n_idx == 1)
+    {
+      retval = index (idx[0]);
+    }
+  else
+    (*current_liboctave_error_handler)
+      ("Array<T>::value: invalid number of indices specified");
+
+  clear_index ();
+
+  return retval;
+}
+
+template <class T>
+Array<T>
+Array<T>::index (idx_vector& idx_arg, int resize_ok, const T& rfv) const
+{
+  Array<T> retval;
+
+  switch (ndims ())
+    {
+    case 1:
+      retval = index1 (idx_arg, resize_ok, rfv);
+      break;
+
+    case 2:
+      retval = index2 (idx_arg, resize_ok, rfv);
+      break;
+
+    default:
+      {
+	Array<idx_vector> tmp (1, idx_arg);
+
+	retval = index (tmp, resize_ok, rfv);
+      }
+      break;
+    }
+
+  return retval;
+}
+
+template <class T>
+Array<T>
+Array<T>::index1 (idx_vector& idx_arg, int resize_ok, const T& rfv) const
+{
+  Array<T> retval;
+
+  int len = length ();
+
+  int n = idx_arg.freeze (len, "vector", resize_ok);
+
+  if (idx_arg)
+    {
+      if (idx_arg.is_colon_equiv (len))
+	{
+	  retval = *this;
+	}
+      else if (n == 0)
+	{
+	  retval.resize_no_fill (0);
+	}
+      else if (len == 1 && n > 1
+	       && idx_arg.one_zero_only ()
+	       && idx_arg.ones_count () == n)
+	{
+	  retval.resize (n, elem (0));
+	}
+      else
+	{
+	  retval.resize_no_fill (n);
+
+	  for (int i = 0; i < n; i++)
+	    {
+	      int ii = idx_arg.elem (i);
+	      if (ii >= len)
+		retval.elem (i) = rfv;
+	      else
+		retval.elem (i) = elem (ii);
+	    }
+	}
+    }
+
+  // idx_vector::freeze() printed an error message for us.
+
+  return retval;
+}
+
+template <class T>
+Array<T>
+Array<T>::index2 (idx_vector& idx_arg, int resize_ok, const T& rfv) const
+{
+  Array<T> retval;
+
+  int nr = dim1 ();
+  int nc = dim2 ();
+
+  int orig_len = nr * nc;
+
+  int idx_orig_rows = idx_arg.orig_rows ();
+  int idx_orig_columns = idx_arg.orig_columns ();
+
+  if (idx_arg.is_colon ())
+    {
+      // Fast magic colon processing.
+
+      int result_nr = nr * nc;
+      int result_nc = 1;
+
+      retval = Array<T> (*this, dim_vector (result_nr, result_nc));
+    }
+  else if (nr == 1 && nc == 1)
+    {
+      Array<T> tmp = Array<T>::index1 (idx_arg, resize_ok);
+
+      if (tmp.length () != 0)
+	retval = Array<T> (tmp, dim_vector (idx_orig_rows, idx_orig_columns));
+      else
+	retval = Array<T> (tmp, dim_vector (0, 0));
+    }
+  else if (nr == 1 || nc == 1)
+    {
+      // If indexing a vector with a matrix, return value has same
+      // shape as the index.  Otherwise, it has same orientation as
+      // indexed object.
+
+      Array<T> tmp = index1 (idx_arg, resize_ok);
+
+      int len = tmp.length ();
+
+      if (len == 0)
+	{
+	  if (idx_orig_rows == 0 || idx_orig_columns == 0)
+	    retval = Array<T> (dim_vector (idx_orig_rows, idx_orig_columns));
+	  else if (nr == 1)
+	    retval = Array<T> (dim_vector (1, 0));
+	  else
+	    retval = Array<T> (dim_vector (0, 1));
+	}
+      else
+	{
+	  if (idx_orig_rows == 1 || idx_orig_columns == 1)
+	    {
+	      if (nr == 1)
+		retval = Array<T> (tmp, dim_vector (1, len));
+	      else
+		retval = Array<T> (tmp, dim_vector (len, 1));
+	    }
+	  else
+	    retval = Array<T> (tmp, dim_vector (idx_orig_rows, idx_orig_columns));
+	}
+    }
+  else
+    {
+      if (liboctave_wfi_flag
+	  && ! (idx_arg.one_zero_only ()
+		&& idx_orig_rows == nr
+		&& idx_orig_columns == nc))
+	(*current_liboctave_warning_handler) ("single index used for matrix");
+
+      // This code is only for indexing matrices.  The vector
+      // cases are handled above.
+
+      idx_arg.freeze (nr * nc, "matrix", resize_ok);
+
+      if (idx_arg)
+	{
+	  int result_nr = idx_orig_rows;
+	  int result_nc = idx_orig_columns;
+
+	  if (idx_arg.one_zero_only ())
+	    {
+	      result_nr = idx_arg.ones_count ();
+	      result_nc = (result_nr > 0 ? 1 : 0);
+	    }
+
+	  retval.resize_no_fill (result_nr, result_nc);
+
+	  int k = 0;
+	  for (int j = 0; j < result_nc; j++)
+	    {
+	      for (int i = 0; i < result_nr; i++)
+		{
+		  int ii = idx_arg.elem (k++);
+		  if (ii >= orig_len)
+		    retval.elem (i, j) = rfv;
+		  else
+		    {
+		      int fr = ii % nr;
+		      int fc = (ii - fr) / nr;
+		      retval.elem (i, j) = elem (fr, fc);
+		    }
+		}
+	    }
+	}
+      // idx_vector::freeze() printed an error message for us.
+    }
+
+  return retval;
+}
+
+template <class T>
+Array<T>
+Array<T>::index (idx_vector& idx_i, idx_vector& idx_j, int resize_ok,
+		 const T& rfv) const
+{
+  Array<T> retval;
+
+  int nr = dim1 ();
+  int nc = dim2 ();
+
+  int n = idx_i.freeze (nr, "row", resize_ok);
+  int m = idx_j.freeze (nc, "column", resize_ok);
+
+  if (idx_i && idx_j)
+    {
+      if (idx_i.orig_empty () || idx_j.orig_empty () || n == 0 || m == 0)
+	{
+	  retval.resize_no_fill (n, m);
+	}
+      else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc))
+	{
+	  retval = *this;
+	}
+      else
+	{
+	  retval.resize_no_fill (n, m);
+
+	  for (int j = 0; j < m; j++)
+	    {
+	      int jj = idx_j.elem (j);
+	      for (int i = 0; i < n; i++)
+		{
+		  int ii = idx_i.elem (i);
+		  if (ii >= nr || jj >= nc)
+		    retval.elem (i, j) = rfv;
+		  else
+		    retval.elem (i, j) = elem (ii, jj);
+		}
+	    }
+	}
+    }
+
+  // idx_vector::freeze() printed an error message for us.
+
+  return retval;
+}
+
+#include "ArrayN-inline.h"
+
+template <class T>
+Array<T>
+Array<T>::index (Array<idx_vector>& ra_idx, int resize_ok, const T& rfv) const
+{
+  Array<T> retval;
+
+  int n_idx = ra_idx.length ();
+
+  int n_dims = dimensions.length ();
+
+  if (n_idx == n_dims)
+    {
+      dim_vector frozen_lengths = freeze (ra_idx, dimensions, resize_ok);
+
+      if (frozen_lengths.length () == n_dims)
+	{
+	  if (all_ok (ra_idx))
+	    {
+	      if (any_orig_empty (ra_idx))
+		{
+		  retval.resize (frozen_lengths);
+		}
+	      else if (any_zero_len (frozen_lengths))
+		{
+		  dim_vector new_size = get_zero_len_size (frozen_lengths,
+							   dimensions);
+
+		  retval.resize (new_size);
+		}
+	      else if (all_colon_equiv (ra_idx, frozen_lengths))
+		{
+		  retval = *this;
+		}
+	      else
+		{
+		  (*current_liboctave_error_handler) ("not implemented");
+#if 0
+		  retval.resize (frozen_lengths);
+
+		  int n = Array<T>::get_size (frozen_lengths);
+
+		  dim_vector result_idx (n_dims, 0);
+
+		  for (int i = 0; i < n; i++)
+		    {
+		      dim_vector elt_idx = get_elt_idx (result_idx);
+
+		      if (elt_idx > orig_len)
+			retval.elem (result_idx) = rfv;
+		      else
+			retval.elem (result_idx) = elem (elt_idx);
+
+		      increment_index (result_idx, frozen_lengths);
+		    }
+#endif
+		}
+	    }
+	  // idx_vector::freeze() printed an error message for us.
+	}
+    }
+  else if (n_idx == 1)
+    {
+      if (ra_idx(0).is_colon ())
+	{
+	  // Fast magic colon processing.
+
+	  int result_nr = Array<int>::get_size (dimensions);
+	  int result_nc = 1;
+
+	  retval = Array<T> (*this, dim_vector (result_nr, result_nc));
+	}
+      else
+	(*current_liboctave_error_handler) ("not implemented");
+    }
+  else
+    (*current_liboctave_error_handler)
+      ("invalid number of dimensions for N-dimensional array index");
+
+  return retval;
+}
+
+// XXX FIXME XXX -- this is a mess.
+
+template <class LT, class RT>
+int
+assign (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv)
+{
+  int retval = 0;
+
+  switch (lhs.ndims ())
+    {
+    case 0:
+      {
+	if (lhs.index_count () < 3)
+	  {
+	    // kluge...
+	    lhs.resize_no_fill (0, 0);
+	    retval = assign2 (lhs, rhs, rfv);
+	  }
+	else
+	  retval = assignN (lhs, rhs, rfv);
+      }
+      break;
+
+    case 1:
+      {
+	if (lhs.index_count () > 1)
+	  retval = assignN (lhs, rhs, rfv);
+	else
+	  retval = assign1 (lhs, rhs, rfv);
+      }
+      break;
+
+    case 2:
+      {
+	if (lhs.index_count () > 2)
+	  retval = assignN (lhs, rhs, rfv);
+	else
+	  retval = assign2 (lhs, rhs, rfv);
+      }
+      break;
+
+    default:
+      retval = assignN (lhs, rhs, rfv);
+      break;
+    }
+
+  return retval;
+}
+
+template <class LT, class RT>
+int
+assign1 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv)
+{
+  int retval = 1;
+
+  idx_vector *tmp = lhs.get_idx ();
+
+  idx_vector lhs_idx = tmp[0];
+
+  int lhs_len = lhs.length ();
+  int rhs_len = rhs.length ();
+
+  int n = lhs_idx.freeze (lhs_len, "vector", true, liboctave_wrore_flag);
+
+  if (n != 0)
+    {
+      if (rhs_len == n || rhs_len == 1)
+	{
+	  int max_idx = lhs_idx.max () + 1;
+	  if (max_idx > lhs_len)
+	    lhs.resize (max_idx, rfv);
+	}
+
+      if (rhs_len == n)
+	{
+	  for (int i = 0; i < n; i++)
+	    {
+	      int ii = lhs_idx.elem (i);
+	      lhs.elem (ii) = rhs.elem (i);
+	    }
+	}
+      else if (rhs_len == 1)
+	{
+	  RT scalar = rhs.elem (0);
+
+	  for (int i = 0; i < n; i++)
+	    {
+	      int ii = lhs_idx.elem (i);
+	      lhs.elem (ii) = scalar;
+	    }
+	}
+      else
+	{
+	  (*current_liboctave_error_handler)
+	    ("A(I) = X: X must be a scalar or a vector with same length as I");
+
+	  retval = 0;
+	}
+    }
+  else if (lhs_idx.is_colon ())
+    {
+      if (lhs_len == 0)
+	{
+	  lhs.resize_no_fill (rhs_len);
+
+	  for (int i = 0; i < rhs_len; i++)
+	    lhs.elem (i) = rhs.elem (i);
+	}
+      else
+	(*current_liboctave_error_handler)
+	  ("A(:) = X: A must be the same size as X");
+    }
+  else if (! (rhs_len == 1 || rhs_len == 0))
+    {
+      (*current_liboctave_error_handler)
+	("A([]) = X: X must also be an empty matrix or a scalar");
+
+      retval = 0;
+    }
+
+  lhs.clear_index ();
+
+  return retval;
+}
+
+#define MAYBE_RESIZE_LHS \
+  do \
+    { \
+      int max_row_idx = idx_i_is_colon ? rhs_nr : idx_i.max () + 1; \
+      int max_col_idx = idx_j_is_colon ? rhs_nc : idx_j.max () + 1; \
+ \
+      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_and_fill (new_nr, new_nc, rfv); \
+    } \
+  while (0)
+
+template <class LT, class RT>
+int
+assign2 (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv)
+{
+  int retval = 1;
+
+  int n_idx = lhs.index_count ();
+
+  int lhs_nr = lhs.rows ();
+  int lhs_nc = lhs.cols ();
+
+  int rhs_nr = rhs.rows ();
+  int rhs_nc = rhs.cols ();
+
+  idx_vector *tmp = lhs.get_idx ();
+
+  idx_vector idx_i;
+  idx_vector idx_j;
+
+  if (n_idx > 1)
+    idx_j = tmp[1];
+
+  if (n_idx > 0)
+    idx_i = tmp[0];
+
+  if (n_idx == 2)
+    {
+      int n = idx_i.freeze (lhs_nr, "row", true, liboctave_wrore_flag);
+
+      int m = idx_j.freeze (lhs_nc, "column", true, liboctave_wrore_flag);
+
+      int idx_i_is_colon = idx_i.is_colon ();
+      int idx_j_is_colon = idx_j.is_colon ();
+
+      if (idx_i_is_colon)
+	n = lhs_nr > 0 ? lhs_nr : rhs_nr;
+
+      if (idx_j_is_colon)
+	m = lhs_nc > 0 ? lhs_nc : rhs_nc;
+
+      if (idx_i && idx_j)
+	{
+	  if (rhs_nr == 0 && rhs_nc == 0)
+	    {
+	      lhs.maybe_delete_elements (idx_i, idx_j);
+	    }
+	  else
+	    {
+	      if (rhs_nr == 1 && rhs_nc == 1 && n > 0 && m > 0)
+		{
+		  MAYBE_RESIZE_LHS;
+
+		  RT scalar = rhs.elem (0, 0);
+
+		  for (int j = 0; j < m; j++)
+		    {
+		      int jj = idx_j.elem (j);
+		      for (int i = 0; i < n; i++)
+			{
+			  int ii = idx_i.elem (i);
+			  lhs.elem (ii, jj) = scalar;
+			}
+		    }
+		}
+	      else if (n == rhs_nr && m == rhs_nc)
+		{
+		  if (n > 0 && m > 0)
+		    {
+		      MAYBE_RESIZE_LHS;
+
+		      for (int j = 0; j < m; j++)
+			{
+			  int jj = idx_j.elem (j);
+			  for (int i = 0; i < n; i++)
+			    {
+			      int ii = idx_i.elem (i);
+			      lhs.elem (ii, jj) = rhs.elem (i, j);
+			    }
+			}
+		    }
+		}
+	      else if (n == 0 && m == 0)
+		{
+		  if (! ((rhs_nr == 1 && rhs_nc == 1)
+			 || (rhs_nr == 0 && rhs_nc == 0)))
+		    {
+		      (*current_liboctave_error_handler)
+		("A([], []) = X: X must be an empty matrix or a scalar");
+
+		      retval = 0;
+		    }
+		}
+	      else
+		{
+		  (*current_liboctave_error_handler)
+    ("A(I, J) = X: X must be a scalar or the number of elements in I must");
+		  (*current_liboctave_error_handler)
+    ("match the number of rows in X and the number of elements in J must");
+		  (*current_liboctave_error_handler)
+    ("match the number of columns in X");
+
+		  retval = 0;
+		}
+	    }
+	}
+      // idx_vector::freeze() printed an error message for us.
+    }
+  else if (n_idx == 1)
+    {
+      int lhs_is_empty = lhs_nr == 0 || lhs_nc == 0;
+
+      if (lhs_is_empty || (lhs_nr == 1 && lhs_nc == 1))
+	{
+	  int lhs_len = lhs.length ();
+
+	  int n = idx_i.freeze (lhs_len, 0, true, liboctave_wrore_flag);
+
+	  if (idx_i)
+	    {
+	      if (rhs_nr == 0 && rhs_nc == 0)
+		{
+		  if (n != 0 && (lhs_nr != 0 || lhs_nc != 0))
+		    lhs.maybe_delete_elements (idx_i);
+		}
+	      else
+		{
+		  if (liboctave_wfi_flag)
+		    {
+		      if (lhs_is_empty
+			  && idx_i.is_colon ()
+			  && ! (rhs_nr == 1 || rhs_nc == 1))
+			{
+			  (*current_liboctave_warning_handler)
+			    ("A(:) = X: X is not a vector or scalar");
+			}
+		      else
+			{
+			  int idx_nr = idx_i.orig_rows ();
+			  int idx_nc = idx_i.orig_columns ();
+
+			  if (! (rhs_nr == idx_nr && rhs_nc == idx_nc))
+			    (*current_liboctave_warning_handler)
+			      ("A(I) = X: X does not have same shape as I");
+			}
+		    }
+
+		  if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv))
+		    {
+		      int len = lhs.length ();
+
+		      if (len > 0)
+			{
+			  // The following behavior is much simplified
+			  // over previous versions of Octave.  It
+			  // seems to be compatible with Matlab.
+
+			  lhs.dimensions = dim_vector (1, lhs.length ());
+			}
+		      else
+			lhs.dimensions = dim_vector (0, 0);
+		    }
+		  else
+		    retval = 0;
+		}
+	    }
+	  // idx_vector::freeze() printed an error message for us.
+	}
+      else if (lhs_nr == 1)
+	{
+	  idx_i.freeze (lhs_nc, "vector", true, liboctave_wrore_flag);
+
+	  if (idx_i)
+	    {
+	      if (rhs_nr == 0 && rhs_nc == 0)
+		lhs.maybe_delete_elements (idx_i);
+	      else
+		{
+		  if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv))
+		    lhs.dimensions = dim_vector (1, lhs.length ());
+		  else
+		    retval = 0;
+		}
+	    }
+	  // idx_vector::freeze() printed an error message for us.
+	}
+      else if (lhs_nc == 1)
+	{
+	  idx_i.freeze (lhs_nr, "vector", true, liboctave_wrore_flag);
+
+	  if (idx_i)
+	    {
+	      if (rhs_nr == 0 && rhs_nc == 0)
+		lhs.maybe_delete_elements (idx_i);
+	      else
+		{
+		  if (assign1 ((Array<LT>&) lhs, (Array<RT>&) rhs, rfv))
+		    lhs.dimensions = dim_vector (lhs.length (), 1);
+		  else
+		    retval = 0;
+		}
+	    }
+	  // idx_vector::freeze() printed an error message for us.
+	}
+      else
+	{
+	  if (liboctave_wfi_flag
+	      && ! (idx_i.is_colon ()
+		    || (idx_i.one_zero_only ()
+			&& idx_i.orig_rows () == lhs_nr
+			&& idx_i.orig_columns () == lhs_nc)))
+	    (*current_liboctave_warning_handler)
+	      ("single index used for matrix");
+
+	  int len = idx_i.freeze (lhs_nr * lhs_nc, "matrix");
+
+	  if (idx_i)
+	    {
+	      if (len == 0)
+		{
+		  if (! ((rhs_nr == 1 && rhs_nc == 1)
+			 || (rhs_nr == 0 && rhs_nc == 0)))
+		    (*current_liboctave_error_handler)
+		      ("A([]) = X: X must be an empty matrix or scalar");
+		}
+	      else if (len == rhs_nr * rhs_nc)
+		{
+		  int k = 0;
+		  for (int j = 0; j < rhs_nc; j++)
+		    {
+		      for (int i = 0; i < rhs_nr; i++)
+			{
+			  int ii = idx_i.elem (k++);
+			  int fr = ii % lhs_nr;
+			  int fc = (ii - fr) / lhs_nr;
+			  lhs.elem (fr, fc) = rhs.elem (i, j);
+			}
+		    }
+		}
+	      else if (rhs_nr == 1 && rhs_nc == 1 && len <= lhs_nr * lhs_nc)
+		{
+		  RT scalar = rhs.elem (0, 0);
+
+		  for (int i = 0; i < len; i++)
+		    {
+		      int ii = idx_i.elem (i);
+		      int fr = ii % lhs_nr;
+		      int fc = (ii - fr) / lhs_nr;
+		      lhs.elem (fr, fc) = scalar;
+		    }
+		}
+	      else
+		{
+		  (*current_liboctave_error_handler)
+      ("A(I) = X: X must be a scalar or a matrix with the same size as I");
+
+		  retval = 0;
+		}
+	    }
+	  // idx_vector::freeze() printed an error message for us.
+	}
+    }
+  else
+    {
+      (*current_liboctave_error_handler)
+	("invalid number of indices for matrix expression");
+
+      retval = 0;
+    }
+
+  lhs.clear_index ();
+
+  return retval;
+}
+
+#define MAYBE_RESIZE_ND_DIMS \
+  do \
+    { \
+      if (n_idx >= lhs_dims.length () && ! rhs_is_empty) \
+	{ \
+	  Array<int> max_idx (n_idx); \
+	  dim_vector new_idx; \
+          new_idx.resize (n_idx); \
+ \
+	  for (int i = 0; i < n_idx; i++) \
+	    { \
+	      if (lhs_dims.length () == 0 || i >= lhs_dims.length ()) \
+		new_idx(i) = idx(i).max () + 1; \
+	      else \
+		{ \
+		  if (i < rhs_dims.length ()) \
+		    max_idx(i) = idx(i).is_colon () ? rhs_dims(i) : idx(i).max () + 1; \
+		  else \
+		    max_idx(i) = idx(i).max () + 1; \
+ \
+		  new_idx(i) = max_idx(i) > lhs_dims(i) ? max_idx(i) : lhs_dims(i); \
+		} \
+            } \
+ \
+	  lhs.resize (new_idx, rfv); \
+	  lhs_dims = lhs.dims ();  \
+        } \
+    } \
+  while (0)
+
+template <class LT, class RT>
+int
+assignN (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv)
+{
+  int retval = 1;
+
+  int n_idx = lhs.index_count ();
+
+  dim_vector lhs_dims = lhs.dims ();
+  dim_vector rhs_dims = rhs.dims ();
+
+  idx_vector *tmp = lhs.get_idx ();
+
+  Array<idx_vector> idx = conv_to_array (tmp, n_idx);
+
+  // This needs to be defined before MAYBE_RESIZE_ND_DIMS.
+
+  bool rhs_is_empty = rhs_dims.length () == 0 ? true : any_zero_len (rhs_dims);
+
+  // Maybe expand to more dimensions.
+
+  MAYBE_RESIZE_ND_DIMS;
+
+  Array<int> idx_is_colon (n_idx, 0);
+  Array<int> idx_is_colon_equiv (n_idx, 0);
+
+  for (int i = 0; i < n_idx; i++)
+    {
+      idx_is_colon_equiv(i) = idx(i).is_colon_equiv (lhs_dims(i), 1);
+
+      idx_is_colon(i) = idx(i).is_colon ();
+    }
+
+  int resize_ok = 1;
+
+  dim_vector frozen_len;
+
+  if (n_idx == lhs_dims.length ())
+    frozen_len = freeze (idx, lhs_dims, resize_ok);
+
+  bool rhs_is_scalar = is_scalar (rhs_dims);
+
+  bool idx_is_empty = any_zero_len (frozen_len);
+
+  if (rhs_is_empty)
+    {
+      lhs.maybe_delete_elements (idx, rfv);
+    }
+  else if (rhs_is_scalar)
+    {
+      if (n_idx == 0)
+	(*current_liboctave_error_handler)
+	  ("number of indices is zero.");
+
+      else if (n_idx < lhs_dims.length ())
+	{
+	  // Number of indices is less than dimensions.
+
+	  if (any_ones (idx_is_colon)|| any_ones (idx_is_colon_equiv))
+	    {
+	      (*current_liboctave_error_handler)
+		("number of indices is less than number of dimensions, one or more indices are colons.");
+	    }
+	  else
+	    {
+	      // Fewer indices than dimensions, no colons.
+
+	      bool resize = false;
+
+	      // Subtract one since the last idx do not tell us
+	      // anything about dimensionality.
+
+	      for (int i = 0; i < idx.length () - 1; i++)
+		{
+		  // Subtract one since idx counts from 0 while dims
+		  // count from 1.
+
+		  if (idx(i).elem (0) + 1 > lhs_dims(i))
+		    resize = true;
+		}
+
+	      if (resize)
+		{
+		  dim_vector new_dims;
+		  new_dims.resize (lhs_dims.length ());
+
+		  for (int i = 0; i < lhs_dims.length (); i++)
+		    {
+		      if (i < idx.length () - 1
+			  && idx(i).elem (0) + 1 > lhs_dims(i))
+			new_dims(i) = idx(i).elem (0)+1;
+		      else
+			new_dims(i) = lhs_dims(i);
+		    }
+
+		  lhs.resize (new_dims, rfv);
+
+		  lhs_dims = lhs.dims ();
+		}
+
+	      Array<int> one_arg_temp (1, 0);
+
+	      RT scalar = rhs.elem (one_arg_temp);
+
+	      Array<int> int_arr = conv_to_int_array (idx);
+
+	      int numelem = get_scalar_idx (int_arr, lhs_dims);
+
+	      if (numelem > lhs.length () || numelem < 0)
+		(*current_liboctave_error_handler)
+		  ("attempt to grow array along ambiguous dimension.");
+	      else
+		lhs.Array<LT>::checkelem (numelem) = scalar;
+	    }
+	}
+      else
+	{
+	  // Scalar to matrix assignment with as many indices as lhs
+	  // dimensions.
+
+	  int n = Array<LT>::get_size (frozen_len);
+
+	  Array<int> result_idx (lhs_dims.length (), 0);
+
+	  Array<int> elt_idx;
+
+	  RT scalar = rhs.elem (0);
+
+	  for (int i = 0; i < n; i++)
+	    {
+	      elt_idx = get_elt_idx (idx, result_idx);
+
+	      dim_vector lhs_inc;
+	      lhs_inc.resize (lhs_dims.length ());
+
+	      for (int i = 0; i < lhs_dims.length (); i++)
+		lhs_inc(i) = lhs_dims(i) + 1;
+
+	      if (index_in_bounds(elt_idx, lhs_inc))
+		lhs.checkelem (elt_idx) = scalar;
+	      else
+		lhs.checkelem (elt_idx) = rfv;
+
+	      increment_index (result_idx, frozen_len);
+	    }
+	}
+    }
+  else if (rhs_dims.length () >= 2)
+    {
+      // RHS is matrix or higher dimension.
+
+      // Subtracting number of dimensions of length 1 will catch
+      // cases where: A(2,1,2)=3  A(:,1,:)=[2,3;4,5]
+
+      if (rhs_dims.length () != num_ones(idx_is_colon_equiv) - num_ones(lhs_dims))
+	{
+	  (*current_liboctave_error_handler)
+	    ("dimensions do not match in matrix assignment.");
+	}
+      else
+	{
+	  bool dim_ok(true);
+
+	  int jj = 0;
+
+	  // Check that RHS dimensions are the same length as the
+	  // corresponding LHS dimensions.
+
+	  for (int j = 0; j < idx_is_colon.length (); j++)
+	    {
+	      if (idx_is_colon(j) || idx_is_colon_equiv(j))
+		{
+		  if (rhs_dims(jj) < lhs_dims(j))
+		    {
+		      dim_ok = false;
+
+		      break;
+		    }
+
+		  jj++;
+		}
+	    }
+
+	  if (! dim_ok)
+	    (*current_liboctave_error_handler)
+	      ("subscripted assignment dimension mismatch.");
+	  else
+	    {
+	      dim_vector new_dims;
+	      new_dims.resize (n_idx);
+
+	      bool resize = false;
+
+	      int ii = 0;
+
+	      // Update idx vectors.
+
+	      for (int i = 0; i < n_idx; i++)
+		{
+		  if (idx(i).is_colon ())
+		    {
+		      // Add appropriate idx_vector to idx(i) since
+		      // index with : contains no indexes.
+
+		      frozen_len(i) = lhs_dims(i) > rhs_dims(ii) ? lhs_dims(i) : rhs_dims(ii);
+
+		      new_dims(i) = lhs_dims(i) > rhs_dims(ii) ? lhs_dims(i) : rhs_dims(ii);
+
+		      ii++;
+
+		      Range idxrange (1, frozen_len(i), 1);
+
+		      idx_vector idxv (idxrange);
+
+		      idx(i) = idxv;
+		    }
+		  else
+		    {
+		      new_dims(i) = lhs_dims(i) > idx(i).max () + 1 ? lhs_dims(i) : idx(i).max () + 1;
+
+		      if (frozen_len(i) > 1)
+			ii++;
+		    }
+		  if (new_dims(i) != lhs_dims(i))
+		    resize = true;
+		}
+
+	      // Resize LHS if dimensions have changed.
+
+	      if (resize)
+		{
+		  lhs.resize (new_dims, rfv);
+
+		  lhs_dims = lhs.dims ();
+		}
+
+	      // Number of elements which need to be set.
+
+	      int n = Array<LT>::get_size (frozen_len);
+
+	      Array<int> result_idx (lhs_dims.length (), 0);
+	      Array<int> elt_idx;
+
+	      Array<int> result_rhs_idx (rhs_dims.length (), 0);
+
+	      dim_vector frozen_rhs;
+	      frozen_rhs.resize (rhs_dims.length());
+
+	      for (int i = 0; i < rhs_dims.length (); i++)
+		frozen_rhs(i) = rhs_dims(i);
+
+	      dim_vector lhs_inc;
+	      lhs_inc.resize (lhs_dims.length ());
+
+	      for (int i = 0; i < lhs_dims.length (); i++)
+		lhs_inc(i) = lhs_dims(i) + 1;
+
+	      for (int i = 0; i < n; i++)
+		{
+		  elt_idx = get_elt_idx (idx, result_idx);
+
+		  if (index_in_bounds (elt_idx, lhs_inc))
+		    {
+		      int s = compute_index (result_rhs_idx,rhs_dims);
+
+		      lhs.checkelem (elt_idx) = rhs.elem (s);
+
+		      increment_index (result_rhs_idx, frozen_rhs);
+		    }
+		  else
+		    lhs.checkelem (elt_idx) = rfv;
+
+		  increment_index (result_idx, frozen_len);
+		}
+	    }
+	}
+    }
+  else if (idx_is_empty)
+    {
+      // Assignment to matrix with at least one empty index.
+
+      if (! rhs_is_empty || ! rhs_is_scalar)
+	{
+	  (*current_liboctave_error_handler)
+	    ("A([], []) = X: X must be an empty matrix or a scalar");
+
+	  retval = 0;
+	}
+    }
+  else if (lhs_dims.length () != rhs_dims.length ())
+    {
+      (*current_liboctave_error_handler)
+	("A(I) = X: X must be a scalar or a matrix with the same size as I");
+      retval = 0;
+    }
+
+  lhs.clear_index ();
+
+  return retval;
+}
+
+template <class T>
+void
 Array<T>::print_info (std::ostream& os, const std::string& prefix) const
 {
   os << prefix << "rep address: " << rep << "\n"