changeset 10490:fdccd69d26bd

rewrite sparse null assignment (part 2)
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 06 Apr 2010 13:42:59 +0200
parents d47802f0e557
children 077fef5da460
files liboctave/ChangeLog liboctave/Sparse.cc liboctave/Sparse.h src/ChangeLog src/ov-base-sparse.cc
diffstat 5 files changed, 111 insertions(+), 200 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog	Tue Apr 06 08:28:15 2010 +0200
+++ b/liboctave/ChangeLog	Tue Apr 06 13:42:59 2010 +0200
@@ -1,3 +1,14 @@
+2010-04-06  Jaroslav Hajek  <highegg@gmail.com>
+
+	* Sparse.cc (Sparse<T>::maybe_delete_elements): Rename to
+	delete_elements. Use const reference arguments.
+	(Sparse<T>::delete_elements (const idx_vector&, const idx_vector&)):
+	Rewrite.
+	(Sparse<T>::maybe_delete_elements (int dim, const idx_vector&)): New
+	overload.
+	(Sparse<T>::maybe_delete_elements (Array<idx_vector>&)): Remove
+	overload.
+
 2010-04-06  Jaroslav Hajek  <highegg@gmail.com>
 
 	* idx-vector.cc, Array-util.h, Array-util.cc: Reverse effects of
--- a/liboctave/Sparse.cc	Tue Apr 06 08:28:15 2010 +0200
+++ b/liboctave/Sparse.cc	Tue Apr 06 13:42:59 2010 +0200
@@ -1219,7 +1219,7 @@
 
 template <class T>
 void
-Sparse<T>::maybe_delete_elements (idx_vector& idx)
+Sparse<T>::delete_elements (const idx_vector& idx)
 {
   Sparse<T> retval;
 
@@ -1305,226 +1305,98 @@
   else
     {
       *this = index (idx_vector::colon);
-      maybe_delete_elements (idx);
+      delete_elements (idx);
       *this = transpose (); // We want a row vector.
     }
 }
 
 template <class T>
 void
-Sparse<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j)
+Sparse<T>::delete_elements (const idx_vector& idx_i, const idx_vector& idx_j)
 {
   assert (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
-
-  if (nr == 0 && nc == 0)
-    return;
+  octave_idx_type nz = nnz ();
 
   if (idx_i.is_colon ())
     {
-      if (idx_j.is_colon ())
-        {
-          // A(:,:) -- We are deleting columns and rows, so the result
-          // is [](0x0).
-
-          resize (0, 0);
-          return;
-        }
-
-      if (idx_j.is_colon_equiv (nc, 1))
+      // Deleting columns.
+      octave_idx_type lb, ub;
+      if (idx_j.extent (nc) > nc)
+        gripe_del_index_out_of_range (false, idx_j.extent (nc), nc);
+      else if (idx_j.is_cont_range (nc, lb, ub))
         {
-          // 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 (nr, 0);
-          return;
+          const Sparse<T> tmp = *this;
+          octave_idx_type lbi = tmp.cidx(lb), ubi = tmp.cidx(ub), new_nz = nz - (ubi - lbi);
+          *this = Sparse<T> (nr, nc - (ub - lb), new_nz);
+          copy_or_memcpy (lbi, tmp.data (), data ());
+          copy_or_memcpy (lbi, tmp.ridx (), ridx ());
+          copy_or_memcpy (nz - ubi, tmp.data () + ubi, xdata () + lbi);
+          copy_or_memcpy (nz - ubi, tmp.ridx () + ubi, xridx () + lbi);
+          copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1);
+          mx_inline_sub (nc - ub, xcidx () + 1, tmp.cidx () + ub + 1, ubi - lbi);
         }
+      else
+        *this = index (idx_i, idx_j.complement (nc));
     }
-
-  if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1))
+  else if (idx_j.is_colon ())
     {
-      // 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 (0, nc);
-      return;
-    }
-
-  if (idx_i.is_colon_equiv (nr, 1))
-    {
-      if (idx_j.is_colon_equiv (nc, 1))
-        resize (0, 0);
+      // Deleting rows.
+      octave_idx_type lb, ub;
+      if (idx_i.extent (nr) > nr)
+        gripe_del_index_out_of_range (false, idx_i.extent (nr), nr);
+      else if (idx_i.is_cont_range (nr, lb, ub))
+        {
+          // This is more memory-efficient than the approach below.
+          const Sparse<T> tmpl = index (idx_vector (0, lb), idx_j);
+          const Sparse<T> tmpu = index (idx_vector (ub, nr), idx_j);
+          *this = Sparse<T> (nr - (ub - lb), nc, tmpl.nnz () + tmpu.nnz ());
+          for (octave_idx_type j = 0, k = 0; j < nc; j++)
+            {
+              for (octave_idx_type i = tmpl.cidx(j); i < tmpl.cidx(j+1); i++)
+                {
+                  xdata(k) = tmpl.data(i);
+                  xridx(k++) = tmpl.ridx(i);
+                }
+              for (octave_idx_type i = tmpu.cidx(j); i < tmpu.cidx(j+1); i++)
+                {
+                  xdata(k) = tmpu.data(i);
+                  xridx(k++) = tmpu.ridx(i) + lb;
+                }
+
+              xcidx(j+1) = k;
+            }
+        }
       else
         {
-          idx_j.sort (true);
-
-          octave_idx_type num_to_delete = idx_j.length (nc);
-
-          if (num_to_delete != 0)
-            {
-              if (nr == 1 && num_to_delete == nc)
-                resize (0, 0);
-              else
-                {
-                  octave_idx_type new_nc = nc;
-                  octave_idx_type new_nnz = nnz ();
-
-                  octave_idx_type iidx = 0;
-
-                  for (octave_idx_type j = 0; j < nc; j++)
-                    {
-                      octave_quit ();
-
-                      if (j == idx_j.elem (iidx))
-                        {
-                          iidx++;
-                          new_nc--;
-                          
-                          new_nnz -= cidx(j+1) - cidx(j);
-
-                          if (iidx == num_to_delete)
-                            break;
-                        }
-                    }
-
-                  if (new_nc > 0)
-                    {
-                      const Sparse<T> tmp (*this);
-                      --rep->count;
-                      rep = new typename Sparse<T>::SparseRep (nr, new_nc, 
-                                                               new_nnz);
-                      octave_idx_type ii = 0;
-                      octave_idx_type jj = 0;
-                      iidx = 0;
-                      cidx(0) = 0;
-                      for (octave_idx_type j = 0; j < nc; j++)
-                        {
-                          octave_quit ();
-
-                          if (iidx < num_to_delete && j == idx_j.elem (iidx))
-                            iidx++;
-                          else
-                            {
-                              for (octave_idx_type i = tmp.cidx(j); 
-                                   i < tmp.cidx(j+1); i++)
-                                {
-                                  data(jj) = tmp.data(i);
-                                  ridx(jj++) = tmp.ridx(i);
-                                }
-                              cidx(++ii) = jj;
-                            }
-                        }
-
-                      dimensions.resize (2);
-                      dimensions(1) = new_nc;
-                    }
-                  else
-                    (*current_liboctave_error_handler)
-                      ("A(idx) = []: index out of range");
-                }
-            }
+          // This is done by transposing, deleting columns, then transposing
+          // again.
+          Sparse<T> tmp = transpose ();
+          tmp.delete_elements (idx_j, idx_i);
+          *this = tmp.transpose ();
         }
     }
-  else if (idx_j.is_colon_equiv (nc, 1))
-    {
-      if (idx_i.is_colon_equiv (nr, 1))
-        resize (0, 0);
-      else
-        {
-          idx_i.sort (true);
-
-          octave_idx_type num_to_delete = idx_i.length (nr);
-
-          if (num_to_delete != 0)
-            {
-              if (nc == 1 && num_to_delete == nr)
-                resize (0, 0);
-              else
-                {
-                  octave_idx_type new_nr = nr;
-                  octave_idx_type new_nnz = nnz ();
-
-                  octave_idx_type iidx = 0;
-
-                  for (octave_idx_type i = 0; i < nr; i++)
-                    {
-                      octave_quit ();
-
-                      if (i == idx_i.elem (iidx))
-                        {
-                          iidx++;
-                          new_nr--;
-                          
-                          for (octave_idx_type j = 0; j < nnz (); j++)
-                            if (ridx(j) == i)
-                              new_nnz--;
-
-                          if (iidx == num_to_delete)
-                            break;
-                        }
-                    }
-
-                  if (new_nr > 0)
-                    {
-                      const Sparse<T> tmp (*this);
-                      --rep->count;
-                      rep = new typename Sparse<T>::SparseRep (new_nr, nc, 
-                                                               new_nnz);
-
-                      octave_idx_type jj = 0;
-                      cidx(0) = 0;
-                      for (octave_idx_type i = 0; i < nc; i++)
-                        {
-                          iidx = 0;
-                          for (octave_idx_type j = tmp.cidx(i); j < tmp.cidx(i+1); j++)
-                            {
-                              octave_quit ();
-
-                              octave_idx_type ri = tmp.ridx(j);
-
-                              while (iidx < num_to_delete && 
-                                     ri > idx_i.elem (iidx))
-                                {
-                                  iidx++;
-                                }
-
-                              if (iidx == num_to_delete ||
-                                  ri != idx_i.elem(iidx))
-                                {
-                                  data(jj) = tmp.data(j);
-                                  ridx(jj++) = ri - iidx;
-                                }
-                            }
-                          cidx(i+1) = jj;
-                        }
-
-                      dimensions.resize (2);
-                      dimensions(0) = new_nr;
-                    }
-                  else
-                    (*current_liboctave_error_handler)
-                      ("A(idx) = []: index out of range");
-                }
-            }
-        }
-    }
+  else
+    (*current_liboctave_error_handler)
+      ("A null assignment can only have one non-colon index.");
 }
 
 template <class T>
 void
-Sparse<T>::maybe_delete_elements (Array<idx_vector>& ra_idx)
+Sparse<T>::delete_elements (int dim, const idx_vector& idx)
 {
-  if (ra_idx.length () == 1)
-    maybe_delete_elements (ra_idx(0));
-  else if (ra_idx.length () == 2)
-    maybe_delete_elements (ra_idx(0), ra_idx(1));
+  if (dim == 0)
+    delete_elements (idx, idx_vector::colon);
+  else if (dim == 1)
+    delete_elements (idx_vector::colon, idx);
   else
-    (*current_liboctave_error_handler) 
-      ("range error for maybe_delete_elements");
+    {
+      (*current_liboctave_error_handler)
+        ("invalid dimension in delete_elements");
+      return;
+    }
 }
 
 template <class T>
--- a/liboctave/Sparse.h	Tue Apr 06 08:28:15 2010 +0200
+++ b/liboctave/Sparse.h	Tue Apr 06 13:42:59 2010 +0200
@@ -472,11 +472,11 @@
 
   idx_vector *get_idx (void) const { return idx; }
 
-  void maybe_delete_elements (idx_vector& i);
+  void delete_elements (const idx_vector& i);
 
-  void maybe_delete_elements (idx_vector& i, idx_vector& j);
+  void delete_elements (int dim, const idx_vector& i);
 
-  void maybe_delete_elements (Array<idx_vector>& ra_idx);
+  void delete_elements (const idx_vector& i, const idx_vector& j);
 
   Sparse<T> value (void);
 
--- a/src/ChangeLog	Tue Apr 06 08:28:15 2010 +0200
+++ b/src/ChangeLog	Tue Apr 06 13:42:59 2010 +0200
@@ -1,3 +1,7 @@
+2010-04-06  Jaroslav Hajek  <highegg@gmail.com>
+
+	* ov-base-sparse.cc (octave_base_sparse::delete_elements): Rewrite.
+
 2010-04-02  Judd Storrs  <jstorrs@gmail.com>
 
 	* octave.cc (intern_argv): Truncate argv when script files are
--- a/src/ov-base-sparse.cc	Tue Apr 06 08:28:15 2010 +0200
+++ b/src/ov-base-sparse.cc	Tue Apr 06 13:42:59 2010 +0200
@@ -182,12 +182,36 @@
 {
   octave_idx_type len = idx.length ();
 
-  Array<idx_vector> ra_idx (len, 1);
+  switch (len)
+    {
+    case 1:
+      {
+        idx_vector i = idx (0).index_vector ();
+
+        if (! error_state)
+          matrix.delete_elements (i);
+
+        break;
+      }
 
-  for (octave_idx_type i = 0; i < len; i++)
-    ra_idx(i) = idx(i).index_vector ();
+    case 2:
+      {
+        idx_vector i = idx (0).index_vector ();
+
+        if (! error_state)
+          {
+            idx_vector j = idx (1).index_vector ();
 
-  matrix.maybe_delete_elements (ra_idx);
+            if (! error_state)
+              matrix.delete_elements (i, j);
+          }
+
+        break;
+      }
+
+    default:
+      error ("sparse indexing needs 1 or 2 indices");
+    }
 
   // Invalidate the matrix type
   typ.invalidate_type ();