diff liboctave/Array.cc @ 9921:7c8392a034e6

fix & improve lookup API
author Jaroslav Hajek <highegg@gmail.com>
date Sat, 05 Dec 2009 06:10:41 +0100
parents 56fbe170d354
children bb30843c4929
line wrap: on
line diff
--- a/liboctave/Array.cc
+++ b/liboctave/Array.cc
@@ -2242,9 +2242,7 @@
 {
   Array<octave_idx_type> idx;
 
-  octave_sort<T> lsort;
-
-  lsort.set_compare (safe_comparator (mode, *this, true));
+  octave_sort<T> lsort (safe_comparator (mode, *this, true));
 
   octave_idx_type r = rows (), c = cols ();
 
@@ -2336,14 +2334,11 @@
   return lsort.lookup (data (), n, value);
 }
 
-// Ditto, but for an array of values, specializing on long runs.
-// Adds optional offset to all indices.
 template <class T>
 Array<octave_idx_type> 
-Array<T>::lookup (const Array<T>& values, sortmode mode, 
-                  bool linf, bool rinf) const
+Array<T>::lookup (const Array<T>& values, sortmode mode) const
 {
-  octave_idx_type n = numel ();
+  octave_idx_type n = numel (), nval = values.numel ();
   octave_sort<T> lsort;
   Array<octave_idx_type> idx (values.dims ());
 
@@ -2358,74 +2353,30 @@
 
   lsort.set_compare (mode);
 
-  // set offset and shift size.
-  octave_idx_type offset = 0;
-
-  if (linf && n > 0)
+  // This determines the split ratio between the O(M*log2(N)) and O(M+N) algorithms.
+  static const double ratio = 1.0;
+  sortmode vmode = UNSORTED;
+
+  // Attempt the O(M+N) algorithm if M is large enough.
+  if (nval > ratio * n / xlog2 (n + 1.0))
     {
-      offset++;
-      n--;
+      vmode = values.is_sorted ();
+      // The table must not contain a NaN.
+      if ((vmode == ASCENDING && sort_isnan<T> (values(nval-1)))
+          || (vmode == DESCENDING && sort_isnan<T> (values(0))))
+        vmode = UNSORTED;
     }
-  if (rinf && n > 0)
-    n--;
-
-  lsort.lookup (data () + offset, n, values.data (), values.numel (),
-                idx.fortran_vec (), offset);
+
+  if (vmode != UNSORTED)
+    lsort.lookup_sorted (data (), n, values.data (), nval,
+                         idx.fortran_vec (), vmode != mode);
+  else
+    lsort.lookup (data (), n, values.data (), nval, idx.fortran_vec ());
 
   return idx;
 }
 
 template <class T>
-Array<octave_idx_type> 
-Array<T>::lookupm (const Array<T>& values, sortmode mode) const
-{
-  octave_idx_type n = numel ();
-  octave_sort<T> lsort;
-  Array<octave_idx_type> idx (values.dims ());
-
-  if (mode == UNSORTED)
-    {
-      // auto-detect mode
-      if (n > 1 && lsort.descending_compare (elem (0), elem (n-1)))
-        mode = DESCENDING;
-      else
-        mode = ASCENDING;
-    }
-
-  lsort.set_compare (mode);
-
-  lsort.lookupm (data (), n, values.data (), values.numel (),
-                 idx.fortran_vec ());
-
-  return idx;
-}
-
-template <class T>
-Array<bool> 
-Array<T>::lookupb (const Array<T>& values, sortmode mode) const
-{
-  octave_idx_type n = numel ();
-  octave_sort<T> lsort;
-  Array<bool> match (values.dims ());
-
-  if (mode == UNSORTED)
-    {
-      // auto-detect mode
-      if (n > 1 && lsort.descending_compare (elem (0), elem (n-1)))
-        mode = DESCENDING;
-      else
-        mode = ASCENDING;
-    }
-
-  lsort.set_compare (mode);
-
-  lsort.lookupb (data (), n, values.data (), values.numel (),
-                 match.fortran_vec ());
-
-  return match;
-}
-
-template <class T>
 octave_idx_type 
 Array<T>::nnz (void) const
 {
@@ -2700,14 +2651,8 @@
 Array<T>::lookup (T const &, sortmode) const \
 { return 0; } \
 template <> Array<octave_idx_type>  \
-Array<T>::lookup (const Array<T>&, sortmode, bool, bool) const \
+Array<T>::lookup (const Array<T>&, sortmode) const \
 { return Array<octave_idx_type> (); } \
-template <> Array<octave_idx_type>  \
-Array<T>::lookupm (const Array<T>&, sortmode) const \
-{ return Array<octave_idx_type> (); } \
-template <> Array<bool>  \
-Array<T>::lookupb (const Array<T>&, sortmode) const \
-{ return Array<bool> (); } \
  \
 template <> octave_idx_type \
 Array<T>::nnz (void) const\