diff liboctave/Array.cc @ 7433:402168152bb9

[project @ 2008-01-31 18:59:09 by dbateman]
author dbateman
date Thu, 31 Jan 2008 18:59:11 +0000
parents 359f464342b3
children da006c2fe55c
line wrap: on
line diff
--- a/liboctave/Array.cc
+++ b/liboctave/Array.cc
@@ -2447,6 +2447,189 @@
   return retval;
 }
 
+template <class T>
+bool 
+ascending_compare (T a, T b)
+{
+  return (a < b);
+}
+
+template <class T>
+bool 
+descending_compare (T a, T b)
+{
+  return (a > b);
+}
+
+template <class T>
+bool 
+ascending_compare (vec_index<T> *a, vec_index<T> *b)
+{
+  return (a->vec < b->vec);
+}
+
+template <class T>
+bool 
+descending_compare (vec_index<T> *a, vec_index<T> *b)
+{
+  return (a->vec > b->vec);
+}
+
+template <class T>
+Array<T>
+Array<T>::sort (octave_idx_type dim, sortmode mode) const
+{
+  Array<T> m = *this;
+
+  dim_vector dv = m.dims ();
+
+  if (m.length () < 1)
+    return m;
+
+  octave_idx_type ns = dv(dim);
+  octave_idx_type iter = dv.numel () / ns;
+  octave_idx_type stride = 1;
+  for (int i = 0; i < dim; i++)
+    stride *= dv(i);
+
+  T *v = m.fortran_vec ();
+  octave_sort<T> lsort;
+  
+  if (mode == ASCENDING) 
+    lsort.set_compare (ascending_compare);
+  else if (mode == DESCENDING)
+    lsort.set_compare (descending_compare);
+
+  if (stride == 1)
+    {
+      for (octave_idx_type j = 0; j < iter; j++)
+	{
+	  lsort.sort (v, ns);
+	  v += ns;
+	}
+    }
+  else
+    {
+      // Don't use OCTAVE_LOCAL_BUFFER here as it doesn't work with bool
+      // on some compilers.
+      Array<T> vi (ns);
+      T *pvi = vi.fortran_vec ();
+
+      for (octave_idx_type j = 0; j < iter; j++) 
+	{
+	   octave_idx_type offset = j;
+	   octave_idx_type offset2 = 0;
+	  while (offset >= stride)
+	    {
+	      offset -= stride;
+	      offset2++;
+	    }
+	  offset += offset2 * stride * ns;
+	  
+	  for (octave_idx_type i = 0; i < ns; i++)
+	    pvi[i] = v[i*stride + offset];
+
+	  lsort.sort (pvi, ns);
+	      
+	  for (octave_idx_type i = 0; i < ns; i++)
+	    v[i*stride + offset] = pvi[i];
+	}
+    }
+
+  return m;
+}
+
+template <class T>
+Array<T>
+Array<T>::sort (Array<octave_idx_type> &sidx, octave_idx_type dim, 
+		sortmode mode) const
+{
+  Array<T> m = *this;
+
+  dim_vector dv = m.dims ();
+
+  if (m.length () < 1)
+    {
+      sidx = Array<octave_idx_type> (dv);
+      return m;
+    }
+
+  octave_idx_type ns = dv(dim);
+  octave_idx_type iter = dv.numel () / ns;
+  octave_idx_type stride = 1;
+  for (int i = 0; i < dim; i++)
+    stride *= dv(i);
+
+  T *v = m.fortran_vec ();
+  octave_sort<vec_index<T> *> indexed_sort;
+
+  if (mode == ASCENDING) 
+    indexed_sort.set_compare (ascending_compare);
+  else if (mode == DESCENDING)
+    indexed_sort.set_compare (descending_compare);
+
+  OCTAVE_LOCAL_BUFFER (vec_index<T> *, vi, ns);
+  OCTAVE_LOCAL_BUFFER (vec_index<T>, vix, ns);
+
+  for (octave_idx_type i = 0; i < ns; i++)
+    vi[i] = &vix[i];
+
+  sidx = Array<octave_idx_type> (dv);
+      
+  if (stride == 1)
+    {
+      for (octave_idx_type j = 0; j < iter; j++)
+	{
+	   octave_idx_type offset = j * ns;
+
+	  for (octave_idx_type i = 0; i < ns; i++)
+	    {
+	      vi[i]->vec = v[i];
+	      vi[i]->indx = i;
+	    }
+
+	  indexed_sort.sort (vi, ns);
+
+	  for (octave_idx_type i = 0; i < ns; i++)
+	    {
+	      v[i] = vi[i]->vec;
+	      sidx(i + offset) = vi[i]->indx;
+	    }
+	  v += ns;
+	}
+    }
+  else
+    {
+      for (octave_idx_type j = 0; j < iter; j++)
+	{
+	  octave_idx_type offset = j;
+	  octave_idx_type offset2 = 0;
+	  while (offset >= stride)
+	    {
+	      offset -= stride;
+	      offset2++;
+	    }
+	  offset += offset2 * stride * ns;
+	      
+	  for (octave_idx_type i = 0; i < ns; i++)
+	    {
+	      vi[i]->vec = v[i*stride + offset];
+	      vi[i]->indx = i;
+	    }
+
+	  indexed_sort.sort (vi, ns);
+	      
+	  for (octave_idx_type i = 0; i < ns; i++)
+	    {
+	      v[i*stride+offset] = vi[i]->vec;
+	      sidx(i*stride+offset) = vi[i]->indx;
+	    }
+	}
+    }
+
+  return m;
+}
+
 // FIXME -- this is a mess.
 
 template <class LT, class RT>