changeset 8679:280fae940bb0

optimize scalar indexing
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 05 Feb 2009 13:58:11 +0100
parents e2b4c19c455c
children a2bcd96b9344
files src/Cell.cc src/Cell.h src/ChangeLog src/OPERATORS/op-cm-cs.cc src/OPERATORS/op-fcm-fcs.cc src/OPERATORS/op-fm-fs.cc src/OPERATORS/op-int.h src/OPERATORS/op-m-s.cc src/oct-map.cc src/oct-map.h src/ov-base-mat.cc src/ov-base-mat.h src/ov-cell.cc src/ov-cell.h src/ov-cx-mat.cc src/ov-cx-mat.h src/ov-flt-cx-mat.cc src/ov-flt-cx-mat.h src/ov-list.cc src/ov-struct.cc src/pt-eval.cc
diffstat 21 files changed, 323 insertions(+), 276 deletions(-) [+]
line wrap: on
line diff
--- a/src/Cell.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/Cell.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -126,7 +126,7 @@
 	idx_vector i = idx_arg(0).index_vector ();
 
 	if (! error_state)
-	  retval = index (i, resize_ok);
+	  retval = ArrayN<octave_value>::index (i, resize_ok);
       }
       break;
 
@@ -139,7 +139,7 @@
 	    idx_vector j = idx_arg(1).index_vector ();
 
 	    if (! error_state)
-	      retval = index (i, j, resize_ok);
+	      retval = ArrayN<octave_value>::index (i, j, resize_ok);
 	  }
       }
       break;
@@ -157,7 +157,7 @@
 	  }
 
 	if (!error_state)
-	  retval = index (iv, resize_ok);
+	  retval = ArrayN<octave_value>::index (iv, resize_ok);
       }
       break;
     }
--- a/src/Cell.h	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/Cell.h	Thu Feb 05 13:58:11 2009 +0100
@@ -73,34 +73,10 @@
 
   Cell index (const octave_value_list& idx, bool resize_ok = false) const;
 
-  Cell index (const idx_vector& i, bool resize_ok = 0,
-	      const octave_value& rfv = resize_fill_value ()) const
-    { return Cell (ArrayN<octave_value>::index (i, resize_ok, rfv)); }
-
-  Cell index (const idx_vector& i, idx_vector& j, bool resize_ok = 0,
-	      const octave_value& rfv = resize_fill_value ()) const
-    { return Cell (ArrayN<octave_value>::index (i, j, resize_ok, rfv)); }
-
-  Cell index (const Array<idx_vector>& ra_idx, bool resize_ok = 0,
-	      const octave_value& rfv = resize_fill_value ()) const
-    { return Cell (ArrayN<octave_value>::index (ra_idx, resize_ok, rfv)); }
-
-  // FIXME -- this seems necessary for
-  // octave_base_mat<Cell>::delete_elements to work, but I don't
-  // understand why.
-  void delete_elements (const Array<idx_vector>& ia)
-    { ArrayN<octave_value>::delete_elements (ia); }
-
   Cell& delete_elements (const octave_value_list& idx);
 
   Cell& assign (const octave_value_list& idx, const Cell& rhs,
-		const octave_value& fill_val = octave_value ());
-
-  // FIXME -- this seems necessary for octave_base_mat<Cell>::assign
-  // to work, but I don't understand why.
-  void assign (const Array<idx_vector>& ia, const Array<octave_value>& rhs,
-               const octave_value& fill_val = octave_value ())
-    { ArrayN<octave_value>::assign (ia, rhs, fill_val); }
+		const octave_value& fill_val = resize_fill_value ());
 
   Cell reshape (const dim_vector& new_dims) const
     { return ArrayN<octave_value>::reshape (new_dims); }
--- a/src/ChangeLog	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ChangeLog	Thu Feb 05 13:58:11 2009 +0100
@@ -1,3 +1,50 @@
+2009-02-05  Jaroslav Hajek  <highegg@gmail.com>
+
+	* ov-base-mat.cc (
+	* ov-base-mat.h
+	* pt-eval.cc
+	* OPERATORS/op-cm-cs.cc: Use scalar_value in scalar-to-matrix
+	indexed assignments.
+	* OPERATORS/op-fcm-fcs.cc: Ditto.
+	* OPERATORS/op-fm-fs.cc: Ditto.
+	* OPERATORS/op-m-s.cc: Ditto.
+	* OPERATORS/op-int.h (OCTAVE_MS_INT_ASSIGN_OPS): Use homogeneous
+	integer scalar-to-matrix assignment.
+	(OCTAVE_MM_INT_ASSIGN_OPS): Use homogeneous integer matrix-to-matrix
+	assignment.
+
+	* Cell.h (Cell::index): Remove direct idx_vector overloads.
+	(Cell::assign): Remove direct idx_vector overloads.
+	(Cell::delete_elements): Remove direct idx_vector overloads.
+	* Cell.cc (Cell::index (const octave_value_list&)): Call
+	ArrayN<octave_value>::index.
+
+	* oct-map.h (Octave_map::index): Remove direct idx_vector overloads.
+	* oct-map.cc (Octave_map::index): Ditto.
+	* ov-base-mat.cc (octave_base_mat::do_index_op): Optimize scalar
+	indexing case.
+	(octave_base_mat::assign (const octave_value_list&, const MT&)):
+	Specialize variable argument number.
+	(octave_base_mat::assign (const octave_value_list&, const 
+	typename MT::element_type&)):
+	New method overload with optimized scalar indexing case.
+
+	* ov-cell.cc (octave_base_matrix<Cell>::do_index_op,
+	octave_base_matrix<Cell>::assign,
+	octave_base_matrix<Cell>::delete_elements): Specialize.
+	(octave_cell::assign (const_octave_value_list, const octave_value&):
+	Delete method.
+	* ov-cell.h: Reflect change.
+
+	* ov-cx-mat.cc (octave_complex_matrix::assign): Delete overloads.
+	* ov-cx-mat.h: Reflect changes.
+	* ov-flt-cx-mat.cc (octave_float_complex_matrix::assign): Delete overloads.
+	* ov-flt-cx-mat.h: Reflect changes.
+	* ov-list.cc (octave_list::do_index_op): Simplify.
+	* ov-struct.cc (octave_struct::do_index_op): Simplify.
+	* pt-eval.cc (tree_evaluator::visit_simple_for_command): Optimize
+	traversing a row vector.
+
 2009-02-05  John W. Eaton  <jwe@octave.org>
 
 	* variables.cc (Vignore_function_time_stamp):
--- a/src/OPERATORS/op-cm-cs.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/OPERATORS/op-cm-cs.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -29,6 +29,7 @@
 #include "oct-obj.h"
 #include "ov.h"
 #include "ov-cx-mat.h"
+#include "ov-flt-cx-mat.h"
 #include "ov-complex.h"
 #include "ov-typeinfo.h"
 #include "ops.h"
@@ -103,7 +104,8 @@
 
 DEFNDCATOP_FN (cm_cs, complex_matrix, complex, complex_array, complex_array, concat)
 
-DEFNDASSIGNOP_FN (assign, complex_matrix, complex, complex_array, assign)
+DEFNDASSIGNOP_FN (assign, complex_matrix, complex, complex, assign)
+DEFNDASSIGNOP_FN (sgl_assign, float_complex_matrix, complex, float_complex, assign)
 
 void
 install_cm_cs_ops (void)
@@ -130,6 +132,7 @@
   INSTALL_CATOP (octave_complex_matrix, octave_complex, cm_cs);
 
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_complex, assign);
+  INSTALL_ASSIGNOP (op_asn_eq, octave_float_complex_matrix, octave_complex, sgl_assign);
 }
 
 /*
--- a/src/OPERATORS/op-fcm-fcs.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/OPERATORS/op-fcm-fcs.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -130,9 +130,9 @@
 	       float_complex_array, float_complex_array, concat)
 
 DEFNDASSIGNOP_FN (assign, float_complex_matrix, float_complex, 
-		  float_complex_array, assign)
+		  float_complex, assign)
 DEFNDASSIGNOP_FN (dbl_assign, complex_matrix, float_complex, 
-		  complex_array, assign)
+		  complex, assign)
 
 void
 install_fcm_fcs_ops (void)
--- a/src/OPERATORS/op-fm-fs.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/OPERATORS/op-fm-fs.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -119,8 +119,8 @@
 
 DEFNDCATOP_FN (fm_s, float_matrix, scalar, float_array, float_array, concat)
 
-DEFNDASSIGNOP_FN (assign, float_matrix, float_scalar, float_array, assign)
-DEFNDASSIGNOP_FN (dbl_assign, matrix, float_scalar, array, assign)
+DEFNDASSIGNOP_FN (assign, float_matrix, float_scalar, float_scalar, assign)
+DEFNDASSIGNOP_FN (dbl_assign, matrix, float_scalar, scalar, assign)
 
 void
 install_fm_fs_ops (void)
--- a/src/OPERATORS/op-int.h	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/OPERATORS/op-int.h	Thu Feb 05 13:58:11 2009 +0100
@@ -578,7 +578,7 @@
   DEFNDBINOP_FN (PFX ## _el_or, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, mx_el_or)
 
 #define OCTAVE_MS_INT_ASSIGN_OPS(PFX, TM, TS, TE) \
-  DEFNDASSIGNOP_FN (PFX ## _assign, TM ## matrix, TS ## scalar, TE ## array, assign)
+  DEFNDASSIGNOP_FN (PFX ## _assign, TM ## matrix, TS ## scalar, TM ## scalar, assign)
 
 #define OCTAVE_MS_POW_OPS(T1, T2) \
 octave_value elem_xpow (T1 ## NDArray a, octave_ ## T2  b) \
@@ -737,7 +737,7 @@
   DEFNDBINOP_FN (PFX ## _el_or,  T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, mx_el_or)
 
 #define OCTAVE_MM_INT_ASSIGN_OPS(PFX, TLHS, TRHS, TE) \
-  DEFNDASSIGNOP_FN (PFX ## _assign, TLHS ## matrix, TRHS ## matrix, TE ## array, assign)
+  DEFNDASSIGNOP_FN (PFX ## _assign, TLHS ## matrix, TRHS ## matrix, TLHS ## array, assign)
 
 #define OCTAVE_MM_POW_OPS(T1, T2) \
   octave_value \
--- a/src/OPERATORS/op-m-s.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/OPERATORS/op-m-s.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -105,8 +105,8 @@
 
 DEFNDCATOP_FN (m_s, matrix, scalar, array, array, concat)
 
-DEFNDASSIGNOP_FN (assign, matrix, scalar, array, assign)
-DEFNDASSIGNOP_FN (sgl_assign, float_matrix, scalar, float_array, assign)
+DEFNDASSIGNOP_FN (assign, matrix, scalar, scalar, assign)
+DEFNDASSIGNOP_FN (sgl_assign, float_matrix, scalar, float_scalar, assign)
 
 void
 install_m_s_ops (void)
--- a/src/oct-map.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/oct-map.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -480,6 +480,8 @@
     {
       for (const_iterator p = begin (); p != end (); p++)
 	{
+          // FIXME: this is sub-optimal: idx is converted multiple times.
+          // Need to convert here and use ArrayN<octave_value>::index.
 	  Cell tmp = contents(p).index (idx, resize_ok);
 
 	  if (error_state)
@@ -497,71 +499,6 @@
   return retval;
 }
 
-Octave_map
-Octave_map::index (idx_vector& i, int resize_ok, const octave_value& rfv) const
-{
-  Octave_map retval (dims ());
-
-  for (const_iterator p = begin (); p != end (); p++)
-    {
-      Cell tmp = contents (p).index (i, resize_ok, rfv);
-
-      if (error_state)
-	break;
-
-      retval.assign (key (p), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::index (idx_vector& i, idx_vector& j, int resize_ok,
-		   const octave_value& rfv) const
-{
-  Octave_map retval (dims ());
-
-  for (const_iterator p = begin (); p != end (); p++)
-    {
-      Cell tmp = contents (p).index (i, j, resize_ok, rfv);
-
-      if (error_state)
-	break;
-
-      retval.assign (key (p), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::index (Array<idx_vector>& ra_idx, int resize_ok,
-		   const octave_value& rfv) const
-{
-  Octave_map retval (dims ());
-
-  for (const_iterator p = begin (); p != end (); p++)
-    {
-      Cell tmp = contents (p).index (ra_idx, resize_ok, rfv);
-
-      if (error_state)
-	break;
-
-      retval.assign (key (p), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/oct-map.h	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/oct-map.h	Thu Feb 05 13:58:11 2009 +0100
@@ -179,15 +179,6 @@
   Octave_map index (const octave_value_list& idx, 
 		    bool resize_ok = false) const;
 
-  Octave_map index (idx_vector& i, int resize_ok = 0, 
-		    const octave_value& rfv = Cell::resize_fill_value ()) const;
-
-  Octave_map index (idx_vector& i, idx_vector& j, int resize_ok = 0,
-		    const octave_value& rfv = Cell::resize_fill_value ()) const;
-
-  Octave_map index (Array<idx_vector>& ra_idx, int resize_ok = 0,
-		    const octave_value& rfv = Cell::resize_fill_value ()) const;
-
 private:
 
   // The map of names to values.
--- a/src/ov-base-mat.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-base-mat.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -2,6 +2,7 @@
 
 Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006,
               2007 John W. Eaton
+Copyright (C) 2009 VZLU Prague
 
 This file is part of Octave.
 
@@ -147,41 +148,71 @@
 	idx_vector i = idx (0).index_vector ();
 
 	if (! error_state)
-	  retval = MT (matrix.index (i, resize_ok, MT::resize_fill_value ()));
+          {
+            // optimize single scalar index.
+            if (i.is_scalar () && i(0) < matrix.numel ())
+              retval = const_cast<const MT&> (matrix)(i(0));
+            else
+              retval = MT (matrix.index (i, resize_ok));
+          }
+      }
+      break;
+
+    case 2:
+      {
+        idx_vector i = idx (0).index_vector ();
+
+        if (! error_state)
+          {
+            idx_vector j = idx (1).index_vector ();
+
+            if (! error_state)
+              {
+                // optimize two scalar indices.
+                if (i.is_scalar () && j.is_scalar () && nd == 2
+                    && i(0) < matrix.rows () && j(0) < matrix.columns ())
+                  retval = const_cast<const MT&> (matrix)(i(0), j(0));
+                else
+                  retval = MT (matrix.index (i, j, resize_ok));
+              }
+          }
       }
       break;
 
     default:
       {
-	if (n_idx == 2 && nd == 2)
-	  {
-	    idx_vector i = idx (0).index_vector ();
+        Array<idx_vector> idx_vec (n_idx);
+        bool scalar_opt = n_idx == nd;
+        const dim_vector dv = matrix.dims ();
 
-	    if (! error_state)
-	      {
-		idx_vector j = idx (1).index_vector ();
+        for (octave_idx_type i = 0; i < n_idx; i++)
+          {
+            idx_vec(i) = idx(i).index_vector ();
+
+            if (error_state)
+              break;
+
+            scalar_opt = (scalar_opt && idx_vec(i).is_scalar ()
+                          && idx_vec(i)(0) < dv(0));
+          }
 
-		if (! error_state)
-		  retval = MT (matrix.index (i, j, resize_ok,
-					     MT::resize_fill_value ()));
-	      }
-	  }
-	else
-	  {
-	    Array<idx_vector> idx_vec (n_idx);
-
-	    for (octave_idx_type i = 0; i < n_idx; i++)
-	      {
-		idx_vec(i) = idx(i).index_vector ();
-
-		if (error_state)
-		  break;
-	      }
-
-	    if (! error_state)
-	      retval = MT (matrix.index (idx_vec, resize_ok,
-					 MT::resize_fill_value ()));
-	  }
+        if (! error_state)
+          {
+            if (scalar_opt)
+              {
+                // optimize all scalar indices. Don't construct an index array,
+                // but rather calc a scalar index directly.
+                octave_idx_type k = 1, j = 0;
+                for (octave_idx_type i = 0; i < n_idx; i++)
+                  {
+                    j += i * k;
+                    k *= dv (i);
+                  }
+                retval = const_cast<const MT&> (matrix)(j);
+              }
+            else
+              retval = MT (matrix.index (idx_vec, resize_ok));
+          }
       }
       break;
     }
@@ -193,14 +224,149 @@
 void
 octave_base_matrix<MT>::assign (const octave_value_list& idx, const MT& rhs)
 {
-  octave_idx_type len = idx.length ();
+  octave_idx_type n_idx = idx.length ();
+
+  switch (n_idx)
+    {
+    case 0:
+      panic_impossible ();
+      break;
+
+    case 1:
+      {
+	idx_vector i = idx (0).index_vector ();
+
+	if (! error_state)
+          matrix.assign (i, rhs);
+      }
+      break;
+
+    case 2:
+      {
+        idx_vector i = idx (0).index_vector ();
+
+        if (! error_state)
+          {
+            idx_vector j = idx (1).index_vector ();
+
+            if (! error_state)
+              matrix.assign (i, j, rhs);
+          }
+      }
+      break;
+
+    default:
+      {
+        Array<idx_vector> idx_vec (n_idx);
 
-  Array<idx_vector> ra_idx (len);
+        for (octave_idx_type i = 0; i < n_idx; i++)
+          {
+            idx_vec(i) = idx(i).index_vector ();
+
+            if (error_state)
+              break;
+          }
+
+        if (! error_state)
+          matrix.assign (idx_vec, rhs);
+      }
+      break;
+    }
+
+  // Invalidate the matrix type
+  typ.invalidate_type ();
+}
+
+template <class MT>
+void
+octave_base_matrix<MT>::assign (const octave_value_list& idx,
+                                typename MT::element_type rhs)
+{
+  octave_idx_type n_idx = idx.length ();
+
+  int nd = matrix.ndims ();
+
+  MT mrhs (dim_vector (1), rhs);
+
+  switch (n_idx)
+    {
+    case 0:
+      panic_impossible ();
+      break;
 
-  for (octave_idx_type i = 0; i < len; i++)
-    ra_idx(i) = idx(i).index_vector ();
+    case 1:
+      {
+	idx_vector i = idx (0).index_vector ();
+
+	if (! error_state)
+          {
+            // optimize single scalar index.
+            if (i.is_scalar () && i(0) < matrix.numel ())
+              matrix(i(0)) = rhs;
+            else
+              matrix.assign (i, mrhs);
+          }
+      }
+      break;
+
+    case 2:
+      {
+        idx_vector i = idx (0).index_vector ();
+
+        if (! error_state)
+          {
+            idx_vector j = idx (1).index_vector ();
+
+            if (! error_state)
+              {
+                // optimize two scalar indices.
+                if (i.is_scalar () && j.is_scalar () && nd == 2
+                    && i(0) < matrix.rows () && j(0) < matrix.columns ())
+                  matrix(i(0), j(0)) = rhs;
+                else
+                  matrix.assign (i, j, mrhs);
+              }
+          }
+      }
+      break;
 
-  matrix.assign (ra_idx, rhs, MT::resize_fill_value ());
+    default:
+      {
+        Array<idx_vector> idx_vec (n_idx);
+        bool scalar_opt = n_idx == nd;
+        const dim_vector dv = matrix.dims ();
+
+        for (octave_idx_type i = 0; i < n_idx; i++)
+          {
+            idx_vec(i) = idx(i).index_vector ();
+
+            if (error_state)
+              break;
+
+            scalar_opt = (scalar_opt && idx_vec(i).is_scalar ()
+                          && idx_vec(i)(0) < dv(0));
+          }
+
+        if (! error_state)
+          {
+            if (scalar_opt)
+              {
+                // optimize all scalar indices. Don't construct an index array,
+                // but rather calc a scalar index directly.
+                octave_idx_type k = 1, j = 0;
+                for (octave_idx_type i = 0; i < n_idx; i++)
+                  {
+                    j += i * k;
+                    k *= dv (i);
+                  }
+                matrix(k) = rhs;
+              }
+            else
+              matrix.assign (idx_vec, mrhs);
+          }
+      }
+      break;
+    }
 
   // Invalidate the matrix type
   typ.invalidate_type ();
--- a/src/ov-base-mat.h	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-base-mat.h	Thu Feb 05 13:58:11 2009 +0100
@@ -92,6 +92,8 @@
 
   void assign (const octave_value_list& idx, const MT& rhs);
 
+  void assign (const octave_value_list& idx, typename MT::element_type rhs);
+
   void delete_elements (const octave_value_list& idx);
 
   dim_vector dims (void) const { return matrix.dims (); }
--- a/src/ov-cell.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-cell.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -55,6 +55,42 @@
 #include "ls-hdf5.h"
 #include "ls-utils.h"
 
+// Cell is able to handle octave_value indexing by itself, so just forward
+// everything.
+
+template <>
+octave_value
+octave_base_matrix<Cell>::do_index_op (const octave_value_list& idx,
+                                       bool resize_ok)
+{
+  return matrix.index (idx, resize_ok);
+}
+
+template <>
+void
+octave_base_matrix<Cell>::assign (const octave_value_list& idx, const Cell& rhs)
+{
+  matrix.assign (idx, rhs);
+}
+
+template <>
+void
+octave_base_matrix<Cell>::assign (const octave_value_list& idx, octave_value rhs)
+{
+  // FIXME: Really?
+  if (rhs.is_cell ())
+    matrix.assign (idx, rhs.cell_value ());
+  else
+    matrix.assign (idx, Cell (rhs));
+}
+
+template <>
+void
+octave_base_matrix<Cell>::delete_elements (const octave_value_list& idx)
+{
+  matrix.delete_elements (idx);
+}
+
 template class octave_base_matrix<Cell>;
 
 DEFINE_OCTAVE_ALLOCATOR (octave_cell);
@@ -340,15 +376,6 @@
   return retval;
 }
 
-void
-octave_cell::assign (const octave_value_list& idx, const octave_value& rhs)
-{
-  if (rhs.is_cell ())
-    octave_base_matrix<Cell>::assign (idx, rhs.cell_value ());
-  else
-    octave_base_matrix<Cell>::assign (idx, Cell (rhs));
-}
-
 size_t
 octave_cell::byte_size (void) const
 {
--- a/src/ov-cell.h	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-cell.h	Thu Feb 05 13:58:11 2009 +0100
@@ -61,8 +61,6 @@
 
   ~octave_cell (void) { }
 
-  void assign (const octave_value_list& idx, const octave_value& rhs);
-
   octave_base_value *clone (void) const { return new octave_cell (*this); }
   octave_base_value *empty_clone (void) const { return new octave_cell (); }
 
--- a/src/ov-cx-mat.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-cx-mat.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -111,27 +111,6 @@
   return retval;
 }
 
-void
-octave_complex_matrix::assign (const octave_value_list& idx,
-			       const ComplexNDArray& rhs)
-{
-  octave_base_matrix<ComplexNDArray>::assign (idx, rhs);
-}
-
-void
-octave_complex_matrix::assign (const octave_value_list& idx,
-			       const NDArray& rhs)
-{
-  octave_idx_type len = idx.length ();
-
-  Array<idx_vector> ra_idx (len);
-
-  for (octave_idx_type i = 0; i < len; i++)
-    ra_idx(i) = idx(i).index_vector ();
-
-  matrix.assign (ra_idx, rhs);
-}
-
 double
 octave_complex_matrix::double_value (bool force_conversion) const
 {
--- a/src/ov-cx-mat.h	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-cx-mat.h	Thu Feb 05 13:58:11 2009 +0100
@@ -90,10 +90,6 @@
 
   octave_base_value *try_narrowing_conversion (void);
 
-  void assign (const octave_value_list& idx, const ComplexNDArray& rhs);
-
-  void assign (const octave_value_list& idx, const NDArray& rhs);
-
   bool is_complex_matrix (void) const { return true; }
 
   bool is_complex_type (void) const { return true; }
--- a/src/ov-flt-cx-mat.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-flt-cx-mat.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -100,27 +100,6 @@
   return retval;
 }
 
-void
-octave_float_complex_matrix::assign (const octave_value_list& idx,
-			       const FloatComplexNDArray& rhs)
-{
-  octave_base_matrix<FloatComplexNDArray>::assign (idx, rhs);
-}
-
-void
-octave_float_complex_matrix::assign (const octave_value_list& idx,
-                                     const FloatNDArray& rhs)
-{
-  octave_idx_type len = idx.length ();
-
-  Array<idx_vector> ra_idx (len);
-
-  for (octave_idx_type i = 0; i < len; i++)
-    ra_idx(i) = idx(i).index_vector ();
-
-  matrix.assign (ra_idx, rhs);
-}
-
 double
 octave_float_complex_matrix::double_value (bool force_conversion) const
 {
--- a/src/ov-flt-cx-mat.h	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-flt-cx-mat.h	Thu Feb 05 13:58:11 2009 +0100
@@ -88,10 +88,6 @@
 
   octave_base_value *try_narrowing_conversion (void);
 
-  void assign (const octave_value_list& idx, const FloatComplexNDArray& rhs);
-
-  void assign (const octave_value_list& idx, const FloatNDArray& rhs);
-
   bool is_complex_matrix (void) const { return true; }
 
   bool is_complex_type (void) const { return true; }
--- a/src/ov-list.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-list.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -72,9 +72,7 @@
 
 	if (tmp_idx.length () == 1)
 	  {
-	    idx_vector i = tmp_idx (0).index_vector ();
-
-	    Cell tmp = data.index (i);
+	    Cell tmp = data.index (tmp_idx (0));
 
 	    retval(0) = octave_value (new octave_list (tmp));
 	  }
@@ -89,9 +87,7 @@
 
 	if (tmp_idx.length () == 1)
 	  {
-	    idx_vector i = tmp_idx (0).index_vector ();
-
-	    Cell tmp = data.index (i);
+	    Cell tmp = data.index (tmp_idx (0));
 
 	    if (tmp.length () == 1)
 	      retval(0) = tmp(0);
@@ -131,9 +127,7 @@
 
   if (idx.length () == 1)
     {
-      idx_vector iidx = idx (0).index_vector ();
-
-      Cell tcell = data.index (iidx, resize_ok);
+      Cell tcell = data.index (idx (0), resize_ok);
 
       octave_value_list result;
 
--- a/src/ov-struct.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/ov-struct.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -536,63 +536,8 @@
 octave_value
 octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
 {
-  octave_value retval;
-
-  octave_idx_type n_idx = idx.length ();
-
-  int nd = map.ndims ();
-
-  switch (n_idx)
-    {
-    case 0:
-      retval = map;
-      break;
-
-    case 1:
-      {
-	idx_vector i = idx (0).index_vector ();
-
-	if (! error_state)
-	  retval = map.index (i, resize_ok, Cell::resize_fill_value ());
-      }
-      break;
-
-    default:
-      {
-	if (n_idx == 2 && nd == 2)
-	  {
-	    idx_vector i = idx (0).index_vector ();
-
-	    if (! error_state)
-	      {
-		idx_vector j = idx (1).index_vector ();
-
-		if (! error_state)
-		  retval = map.index (i, j, resize_ok,
-				      Cell::resize_fill_value ());
-	      }
-	  }
-	else
-	  {
-	    Array<idx_vector> idx_vec (n_idx);
-
-	    for (octave_idx_type i = 0; i < n_idx; i++)
-	      {
-		idx_vec(i) = idx(i).index_vector ();
-
-		if (error_state)
-		  break;
-	      }
-
-	    if (! error_state)
-	      retval = map.index (idx_vec, resize_ok,
-				  Cell::resize_fill_value ());
-	  }
-      }
-      break;
-    }
-
-  return retval;
+  // Octave_map handles indexing itself.
+  return map.index (idx, resize_ok);
 }
 
 size_t
--- a/src/pt-eval.cc	Wed Feb 04 16:05:01 2009 +0100
+++ b/src/pt-eval.cc	Thu Feb 05 13:58:11 2009 +0100
@@ -335,7 +335,7 @@
 
         dim_vector dv = rhs.dims ().redim (2);
 
-        octave_idx_type steps = dv(1);
+        octave_idx_type nrows = dv(0), steps = dv(1);
 
         if (steps > 0)
           {
@@ -343,14 +343,25 @@
             if (rhs.ndims () > 2)
               arg = arg.reshape (dv);
 
-            //octave_value_list idx(2, octave_value ());
-            octave_value_list idx(2, octave_value ());
-            idx(0) = octave_value::magic_colon_t;
+            // for row vectors, use single index to speed things up.
+            octave_value_list idx;
+            octave_idx_type iidx;
+            if (nrows == 1)
+              {
+                idx.resize (1);
+                iidx = 0;
+              }
+            else
+              {
+                idx.resize (2);
+                idx(0) = octave_value::magic_colon_t;
+                iidx = 1;
+              }
 
             for (octave_idx_type i = 1; i <= steps; i++)
               {
                 // do_index_op expects one-based indices.
-                idx(1) = i;
+                idx(iidx) = i;
                 octave_value val = arg.do_index_op (idx);
                 DO_SIMPLE_FOR_LOOP_ONCE (val);