changeset 9772:3ac8ea48279b

improve index reduction rules
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 03 Nov 2009 07:44:20 +0100
parents 4634a0e9ea1b
children 01f897d8a130
files liboctave/ChangeLog liboctave/idx-vector.cc
diffstat 2 files changed, 78 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog	Mon Nov 02 21:34:04 2009 -0500
+++ b/liboctave/ChangeLog	Tue Nov 03 07:44:20 2009 +0100
@@ -1,3 +1,8 @@
+2009-11-03  Jaroslav Hajek  <highegg@gmail.com>
+
+	* idx-vector.cc (idx_vector::maybe_reduce): Implement (i:k:end, :)
+	and (i:k:end, p:q) reductions.
+
 2009-11-02  Jaroslav Hajek  <highegg@gmail.com>
 
 	* mx-inlines.cc (twosum_accum): Remove FLOAT_TRUNCATE.
--- a/liboctave/idx-vector.cc	Mon Nov 02 21:34:04 2009 -0500
+++ b/liboctave/idx-vector.cc	Tue Nov 03 07:44:20 2009 +0100
@@ -420,43 +420,83 @@
   switch (j.idx_class ())
     {
     case class_colon:
-      if (rep->is_colon_equiv (n))
+      switch (rep->idx_class ())
         {
+        case class_colon:
           // (:,:) reduces to (:)
-          *this = colon;
           reduced = true;
-        }
-      else if (rep->idx_class () == class_scalar)
-        {
-          // (i,:) reduces to a range.
-          idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
-          octave_idx_type k = r->get_data ();
-          *this = new idx_range_rep (k, nj, n, DIRECT);
-          reduced = true;
+          break;
+        case class_scalar:
+          {
+            // (i,:) reduces to a range.
+            idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
+            octave_idx_type k = r->get_data ();
+            *this = new idx_range_rep (k, nj, n, DIRECT);
+            reduced = true;
+            break;
+          }
+        case class_range:
+          {
+            // (i:k:end,:) reduces to a range if i <= k and k divides n.
+            idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
+            octave_idx_type s = r->get_start (), l = r->length (n);
+            octave_idx_type t = r->get_step ();
+            if (l*t == n)
+              {
+                *this = new idx_range_rep (s, l * nj, t, DIRECT);
+                reduced = true;
+              }
+            break;
+          }
+        default:
+          break;
         }
       break;
     case class_range:
-      if (rep->is_colon_equiv (n))
+      switch (rep->idx_class ())
         {
-          // (:,i:j) reduces to a range (the step must be 1)
-          idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
-          if (rj->get_step () == 1)
-            {
-              octave_idx_type s = rj->get_start (), l = rj->length (nj);
-              *this = new idx_range_rep (s * n, l * n, 1, DIRECT);
-              reduced = true;
-            }
-        }
-      else if (rep->idx_class () == class_scalar)
-        {
-          // (k,i:d:j) reduces to a range.
-          idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
-          idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
-          octave_idx_type k = r->get_data ();
-          octave_idx_type s = rj->get_start (), l = rj->length (nj);
-          octave_idx_type t = rj->get_step ();
-          *this = new idx_range_rep (n * s + k, l, n * t, DIRECT);
-          reduced = true;
+        case class_colon:
+          {
+            // (:,i:j) reduces to a range (the step must be 1)
+            idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
+            if (rj->get_step () == 1)
+              {
+                octave_idx_type sj = rj->get_start (), lj = rj->length (nj);
+                *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT);
+                reduced = true;
+              }
+            break;
+          }
+        case class_scalar:
+          {
+            // (k,i:d:j) reduces to a range.
+            idx_scalar_rep * r = dynamic_cast<idx_scalar_rep *> (rep);
+            idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
+            octave_idx_type k = r->get_data ();
+            octave_idx_type sj = rj->get_start (), lj = rj->length (nj);
+            octave_idx_type tj = rj->get_step ();
+            *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT);
+            reduced = true;
+            break;
+          }
+        case class_range:
+          {
+            // (i:k:end,p:q) reduces to a range if i <= k and k divides n.
+            idx_range_rep * r = dynamic_cast<idx_range_rep *> (rep);
+            octave_idx_type s = r->get_start (), l = r->length (n);
+            octave_idx_type t = r->get_step ();
+            idx_range_rep * rj = dynamic_cast<idx_range_rep *> (j.rep);
+            octave_idx_type sj = rj->get_start (), lj = rj->length (nj);
+            octave_idx_type tj = rj->get_step ();
+            if (l*t == n && tj == 1)
+              {
+                *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT);
+                reduced = true;
+              }
+            break;
+          }
+        default:
+          break;
         }
       break;
     case class_scalar:
@@ -470,8 +510,8 @@
             octave_idx_type k = r->get_data () + n * rj->get_data ();
             *this = new idx_scalar_rep (k, DIRECT);
             reduced = true;
+            break;
           }
-          break;
         case class_range:
           {
             // (i:d:j,k) reduces to a range.
@@ -482,8 +522,8 @@
             octave_idx_type k = rj->get_data ();
             *this = new idx_range_rep (n * k + s, l, t, DIRECT);
             reduced = true;
+            break;
           }
-          break;
         case class_colon:
           {
             // (:,k) reduces to a range.
@@ -491,8 +531,8 @@
             octave_idx_type k = rj->get_data ();
             *this = new idx_range_rep (n * k, n, 1, DIRECT);
             reduced = true;
+            break;
           }
-          break;
         default:
           break;
         }