Mercurial > hg > octave-lyh
diff liboctave/Array.cc @ 8721:e9cb742df9eb
imported patch sort3.diff
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 11 Feb 2009 15:25:53 +0100 |
parents | 314be237cd5b |
children | d5af326a3ede |
line wrap: on
line diff
--- a/liboctave/Array.cc +++ b/liboctave/Array.cc @@ -1987,6 +1987,13 @@ Array<T> Array<T>::sort (octave_idx_type dim, sortmode mode) const { + if (dim < 0 || dim >= ndims ()) + { + (*current_liboctave_error_handler) + ("sort: invalid dimension"); + return Array<T> (); + } + Array<T> m (dims ()); dim_vector dv = m.dims (); @@ -2006,12 +2013,10 @@ octave_sort<T> lsort; - if (mode == ASCENDING) - lsort.set_compare (octave_sort<T>::ascending_compare); - else if (mode == DESCENDING) - lsort.set_compare (octave_sort<T>::descending_compare); + if (mode) + lsort.set_compare (mode); else - abort (); + return m; if (stride == 1) { @@ -2098,6 +2103,13 @@ Array<T>::sort (Array<octave_idx_type> &sidx, octave_idx_type dim, sortmode mode) const { + if (dim < 0 || dim >= ndims ()) + { + (*current_liboctave_error_handler) + ("sort: invalid dimension"); + return Array<T> (); + } + Array<T> m (dims ()); dim_vector dv = m.dims (); @@ -2123,12 +2135,10 @@ sidx = Array<octave_idx_type> (dv); octave_idx_type *vi = sidx.fortran_vec (); - if (mode == ASCENDING) - lsort.set_compare (octave_sort<T>::ascending_compare); - else if (mode == DESCENDING) - lsort.set_compare (octave_sort<T>::descending_compare); + if (mode) + lsort.set_compare (mode); else - abort (); + return m; if (stride == 1) { @@ -2239,6 +2249,171 @@ } template <class T> +sortmode +Array<T>::is_sorted (sortmode mode) const +{ + if (nelem () <= 1) + return ASCENDING; + + const T *lo = data (), *hi = data () + nelem () - 1; + + // Check for NaNs at the beginning and end. + if (mode != ASCENDING && _sort_isnan (*lo)) + { + mode = DESCENDING; + do + ++lo; + while (lo < hi && _sort_isnan (*lo)); + } + else if (mode != DESCENDING && _sort_isnan (*hi)) + { + mode = ASCENDING; + do + --hi; + while (lo < hi && _sort_isnan (*hi)); + } + + octave_sort<T> lsort; + + // If mode is still unknown, compare lo and hi + if (! mode) + { + if (lsort.descending_compare (*lo, *hi)) + mode = DESCENDING; + else if (lsort.ascending_compare (*lo, *hi)) + mode = ASCENDING; + else + mode = ASCENDING; + } + + lsort.set_compare (mode); + + if (! lsort.is_sorted (lo, hi - lo + 1)) + mode = UNSORTED; + + return mode; +} + +template <class T> +bool (*_sortrows_comparator (sortmode mode, + const Array<T>& /* a */, bool /* allow_chk */)) (T, T) +{ + if (mode == ASCENDING) + return octave_sort<T>::ascending_compare; + else if (mode == DESCENDING) + return octave_sort<T>::descending_compare; + else + return 0; +} + +template <class T> +Array<octave_idx_type> +Array<T>::sort_rows_idx (sortmode mode) const +{ + Array<octave_idx_type> idx; + + octave_sort<T> lsort; + + lsort.set_compare (_sortrows_comparator (mode, *this, true)); + + octave_idx_type r = rows (), c = cols (); + + idx = Array<octave_idx_type> (r); + + lsort.sort_rows (data (), idx.fortran_vec (), r, c); + + return idx; +} + + +template <class T> +sortmode +Array<T>::is_sorted_rows (sortmode mode) const +{ + octave_sort<T> lsort; + + octave_idx_type r = rows (), c = cols (); + + if (r <= 1 || c == 0) + return mode ? mode : ASCENDING; + + if (! mode) + { + // Auto-detect mode. + bool (*compare) (T, T) = _sortrows_comparator (ASCENDING, *this, false); + + octave_idx_type i; + for (i = 0; i < cols (); i++) + { + T l = elem (0, i), u = elem (rows () - 1, i); + if (compare (l, u)) + { + if (mode == DESCENDING) + { + mode = UNSORTED; + break; + } + else + mode = ASCENDING; + } + else if (compare (u, l)) + { + if (mode == ASCENDING) + { + mode = UNSORTED; + break; + } + else + mode = DESCENDING; + } + } + if (! mode && i == cols ()) + mode = ASCENDING; + } + + if (mode) + { + lsort.set_compare (_sortrows_comparator (mode, *this, false)); + + if (! lsort.is_sorted_rows (data (), r, c)) + mode = UNSORTED; + } + + return mode; + +} + +#define INSTANTIATE_ARRAY_SORT(T) template class octave_sort<T>; + +#define NO_INSTANTIATE_ARRAY_SORT(T) \ + \ +template <> Array<T> \ +Array<T>::sort (octave_idx_type, sortmode) const { return *this; } \ + \ +template <> Array<T> \ +Array<T>::sort (Array<octave_idx_type> &sidx, octave_idx_type, sortmode) const \ +{ sidx = Array<octave_idx_type> (); return *this; } \ + \ +template <> sortmode \ +Array<T>::is_sorted (sortmode) const \ +{ return UNSORTED; } \ + \ +template <> \ +bool (*_sortrows_comparator (sortmode, \ + const Array<T>&, bool)) (T, T) \ +{ return 0; } \ + \ +template <> Array<octave_idx_type> \ +Array<T>::sort_rows_idx (sortmode) const \ +{ return Array<octave_idx_type> (); } \ + \ +template <> sortmode \ +Array<T>::is_sorted_rows (sortmode) const \ +{ return UNSORTED; } \ + + + +template <class T> Array<T> Array<T>::diag (octave_idx_type k) const { @@ -2342,6 +2517,9 @@ // << prefix << "cols: " << cols () << "\n"; } +#define INSTANTIATE_ARRAY(T, API) \ + template class API Array<T> + /* ;;; Local Variables: *** ;;; mode: C++ ***