diff liboctave/Range.cc @ 9986:672e1b49e01e

optimize indexing of ranges by single subscripts
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 15 Dec 2009 10:04:34 +0100
parents 967a692ddfe2
children 4c0cdbe0acca
line wrap: on
line diff
--- a/liboctave/Range.cc	Tue Dec 15 10:01:35 2009 +0100
+++ b/liboctave/Range.cc	Tue Dec 15 10:04:34 2009 +0100
@@ -81,6 +81,57 @@
   return cache;
 }
 
+double
+Range::checkelem (octave_idx_type i) const
+{
+  if (i < 0 || i >= rng_nelem)
+    (*current_liboctave_error_handler) ("Range::elem (%d): range error", i);
+
+  return rng_base + rng_inc * i;
+}
+
+struct _rangeidx_helper
+{
+  double *array, base, inc;
+  _rangeidx_helper (double *a, double b, double i) 
+    : array (a), base (b), inc (i) { }
+  void operator () (octave_idx_type i)
+    { *array++ = base + i * inc; }
+};
+
+Array<double> 
+Range::index (const idx_vector& i) const
+{
+  Array<double> retval;
+
+  octave_idx_type n = rng_nelem;
+
+  if (i.is_colon ())
+    {
+      retval = matrix_value ().reshape (dim_vector (rng_nelem, 1));
+    }
+  else if (i.extent (n) != n)
+    {
+      (*current_liboctave_error_handler)
+        ("A(I): Index exceeds matrix dimension.");
+    }
+  else
+    {
+      dim_vector rd = i.orig_dimensions ();
+      octave_idx_type il = i.length (n);
+
+      // taken from Array.cc.
+
+      if (n != 1 && rd.is_vector ())
+        rd = dim_vector (1, il);
+
+      retval.clear (rd);
+
+      i.loop (n, _rangeidx_helper (retval.fortran_vec (), rng_base, rng_inc));
+    }
+
+  return retval;
+}
 
 // NOTE: max and min only return useful values if nelem > 0.