diff liboctave/Sparse.cc @ 7433:402168152bb9

[project @ 2008-01-31 18:59:09 by dbateman]
author dbateman
date Thu, 31 Jan 2008 18:59:11 +0000
parents 164e98cdee8b
children 2467639bd8c0
line wrap: on
line diff
--- a/liboctave/Sparse.cc	Wed Jan 30 09:11:58 2008 +0000
+++ b/liboctave/Sparse.cc	Thu Jan 31 18:59:11 2008 +0000
@@ -369,9 +369,9 @@
 	{
 	  OCTAVE_QUIT;
 	  octave_sort<octave_sparse_sort_idxl *> 
-	    sort (octave_sparse_sidxl_comp);
-
-	  sort.sort (sidx, actual_nzmx);
+	    lsort (octave_sparse_sidxl_comp);
+
+	  lsort.sort (sidx, actual_nzmx);
 	  OCTAVE_QUIT;
 
 	  // Now count the unique non-zero values
@@ -487,9 +487,9 @@
 	{
 	  OCTAVE_QUIT;
 	  octave_sort<octave_sparse_sort_idxl *> 
-	    sort (octave_sparse_sidxl_comp);
-
-	  sort.sort (sidx, actual_nzmx);
+	    lsort (octave_sparse_sidxl_comp);
+
+	  lsort.sort (sidx, actual_nzmx);
 	  OCTAVE_QUIT;
 
 	  // Now count the unique non-zero values
@@ -1855,7 +1855,7 @@
 
 	      OCTAVE_LOCAL_BUFFER (octave_idx_type, itmp, 
 				   (nr > nc ? nr : nc));
-	      octave_sort<octave_idx_type> sort;
+	      octave_sort<octave_idx_type> lsort;
 
 	      if (n > nr || m > nc)
 		permutation = false;
@@ -1871,7 +1871,7 @@
 		  // for idx_vector type.
 		  for (octave_idx_type i = 0; i < n; i++)
 		    itmp [i] = idx_i.elem (i);
-		  sort.sort (itmp, n);
+		  lsort.sort (itmp, n);
 		  for (octave_idx_type i = 1; i < n; i++)
 		    if (itmp[i-1] == itmp[i])
 		      {
@@ -1883,7 +1883,7 @@
 		{
 		  for (octave_idx_type i = 0; i < m; i++)
 		    itmp [i] = idx_j.elem (i);
-		  sort.sort (itmp, m);
+		  lsort.sort (itmp, m);
 		  for (octave_idx_type i = 1; i < m; i++)
 		    if (itmp[i-1] == itmp[i])
 		      {
@@ -1920,7 +1920,7 @@
 			      retval.xridx (kk++) = ii;
 			    }
 			}
-		      sort.sort (ri + retval.xcidx (j), kk - retval.xcidx (j));
+		      lsort.sort (ri + retval.xcidx (j), kk - retval.xcidx (j));
 		      for (octave_idx_type p = retval.xcidx (j); p < kk; p++)
 			retval.xdata (p) = X [retval.xridx (p)]; 
 		      retval.xcidx(j+1) = kk;
@@ -2022,7 +2022,7 @@
 				    }
 				}
 			    }
-			  sort.sort (ri + retval.xcidx (j), 
+			  lsort.sort (ri + retval.xcidx (j), 
 				     kk - retval.xcidx (j));
 			  for (octave_idx_type p = retval.xcidx (j); 
 			       p < kk; p++)
@@ -2053,6 +2053,215 @@
   return index (ra_idx (0), ra_idx (1), resize_ok);
 }
 
+// Can't use versions of these in Array.cc due to duplication of the 
+// instantiations for Array<double and Sparse<double>, etc
+template <class T>
+bool 
+sparse_ascending_compare (T a, T b)
+{
+  return (a < b);
+}
+
+template <class T>
+bool 
+sparse_descending_compare (T a, T b)
+{
+  return (a > b);
+}
+
+template <class T>
+bool 
+sparse_ascending_compare (vec_index<T> *a, vec_index<T> *b)
+{
+  return (a->vec < b->vec);
+}
+
+template <class T>
+bool 
+sparse_descending_compare (vec_index<T> *a, vec_index<T> *b)
+{
+  return (a->vec > b->vec);
+}
+
+template <class T>
+Sparse<T>
+Sparse<T>::sort (octave_idx_type dim, sortmode mode) const
+{
+  Sparse<T> m = *this;
+
+  octave_idx_type nr = m.rows ();
+  octave_idx_type nc = m.columns ();
+
+  if (m.length () < 1)
+    return m;
+
+  if (dim > 0)
+    {
+      m = m.transpose ();
+      nr = m.rows ();
+      nc = m.columns ();
+    }
+
+  octave_sort<T> lsort;
+
+  if (mode == ASCENDING) 
+    lsort.set_compare (sparse_ascending_compare);
+  else if (mode == DESCENDING)
+    lsort.set_compare (sparse_descending_compare);
+
+  T *v = m.data ();
+  octave_idx_type *mcidx = m.cidx ();
+  octave_idx_type *mridx = m.ridx ();
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    {
+      octave_idx_type ns = mcidx [j + 1] - mcidx [j];
+      lsort.sort (v, ns);
+
+      octave_idx_type i;
+      if (mode == ASCENDING) 
+	{
+	  for (i = 0; i < ns; i++)
+	    if (sparse_ascending_compare (static_cast<T> (0), v [i]))
+	      break;
+	}
+      else
+	{
+	  for (i = 0; i < ns; i++)
+	    if (sparse_descending_compare (static_cast<T> (0), v [i]))
+	      break;
+	}
+      for (octave_idx_type k = 0; k < i; k++)
+	mridx [k] = k;
+      for (octave_idx_type k = i; k < ns; k++)
+	mridx [k] = k - ns + nr; 
+
+      v += ns;
+      mridx += ns;
+    }
+
+  if (dim > 0)
+      m = m.transpose ();
+
+  return m;
+}
+
+template <class T>
+Sparse<T>
+Sparse<T>::sort (Array<octave_idx_type> &sidx, octave_idx_type dim, 
+		 sortmode mode) const
+{
+  Sparse<T> m = *this;
+
+  octave_idx_type nr = m.rows ();
+  octave_idx_type nc = m.columns ();
+
+  if (m.length () < 1)
+    {
+      sidx = Array<octave_idx_type> (dim_vector (nr, nc));
+      return m;
+    }
+
+  if (dim > 0)
+    {
+      m = m.transpose ();
+      nr = m.rows ();
+      nc = m.columns ();
+    }
+
+  octave_sort<vec_index<T> *> indexed_sort;
+
+  if (mode == ASCENDING) 
+    indexed_sort.set_compare (sparse_ascending_compare);
+  else if (mode == DESCENDING)
+    indexed_sort.set_compare (sparse_descending_compare);
+
+  T *v = m.data ();
+  octave_idx_type *mcidx = m.cidx ();
+  octave_idx_type *mridx = m.ridx ();
+
+  OCTAVE_LOCAL_BUFFER (vec_index<T> *, vi, nr);
+  OCTAVE_LOCAL_BUFFER (vec_index<T>, vix, nr);
+
+  for (octave_idx_type i = 0; i < nr; i++)
+    vi[i] = &vix[i];
+
+  sidx = Array<octave_idx_type> (dim_vector (nr, nc));
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    {
+      octave_idx_type ns = mcidx [j + 1] - mcidx [j];
+      octave_idx_type offset = j * nr;
+
+      if (ns == 0)
+	{
+	  for (octave_idx_type k = 0; k < nr; k++)
+	    sidx (offset + k) = k;
+	}
+      else
+	{
+	  for (octave_idx_type i = 0; i < ns; i++)
+	    {
+	      vi[i]->vec = v[i];
+	      vi[i]->indx = mridx[i];
+	    }
+
+	  indexed_sort.sort (vi, ns);
+
+	  octave_idx_type i;
+	  if (mode == ASCENDING) 
+	    {
+	      for (i = 0; i < ns; i++)
+		if (sparse_ascending_compare (static_cast<T> (0), 
+					      vi [i] -> vec))
+		  break;
+	    }
+	  else
+	    {
+	      for (i = 0; i < ns; i++)
+		if (sparse_descending_compare (static_cast<T> (0), 
+					       vi [i] -> vec))
+		  break;
+	    }
+
+	  octave_idx_type ii = 0;
+	  octave_idx_type jj = i;
+	  for (octave_idx_type k = 0; k < nr; k++)
+	    {
+	      if (ii < ns && mridx[ii] == k)
+		ii++;
+	      else
+		sidx (offset + jj++) = k;
+	    }
+
+	  for (octave_idx_type k = 0; k < i; k++)
+	    {
+	      v [k] = vi [k] -> vec;
+	      sidx (k + offset) = vi [k] -> indx;
+	      mridx [k] = k;
+	    }
+
+	  for (octave_idx_type k = i; k < ns; k++)
+	    {
+	      v [k] = vi [k] -> vec;
+	      sidx (k - ns + nr + offset) = vi [k] -> indx;
+	      mridx [k] = k - ns + nr; 
+	    }
+
+	  v += ns;
+	  mridx += ns;
+	}
+    }
+
+  if (dim > 0)
+    {
+      m = m.transpose ();
+      sidx = sidx.transpose ();
+    }
+
+  return m;
+}
+
 // FIXME
 // Unfortunately numel can overflow for very large but very sparse matrices.
 // For now just flag an error when this happens.