# HG changeset patch # User Jaroslav Hajek # Date 1260045047 -3600 # Node ID 3a8327d51ed447d07aec1a116672911dcf10ab1b # Parent 7c8392a034e61a89f4585e5301fdf28cd5ef65d2 optimize issorted for doubles & floats diff --git a/liboctave/Array-d.cc b/liboctave/Array-d.cc --- a/liboctave/Array-d.cc +++ b/liboctave/Array-d.cc @@ -84,6 +84,76 @@ return result; } +// The default solution using NaN-safe comparator is OK, but almost twice as +// slow than this code. +template <> +sortmode +Array::is_sorted (sortmode mode) const +{ + octave_idx_type n = numel (); + + const double *el = data (); + + if (n <= 1) + return mode ? mode : ASCENDING; + + if (! mode) + { + // Auto-detect mode. + if (el[n-1] < el[0] || xisnan (el[0])) + mode = DESCENDING; + else + mode = ASCENDING; + } + + if (mode == DESCENDING) + { + octave_idx_type j = 0; + double r; + // Sort out NaNs. + do + r = el[j++]; + while (xisnan (r) && j < n); + + // Orient the test so that NaN will not pass through. + for (; j < n; j++) + { + if (r >= el[j]) + r = el[j]; + else + { + mode = UNSORTED; + break; + } + } + + } + else if (mode == ASCENDING) + { + // Sort out NaNs. + while (n > 0 && xisnan (el[n-1])) + n--; + + if (n > 0) + { + // Orient the test so that NaN will not pass through. + double r = el[0]; + for (octave_idx_type j = 1; j < n; j++) + { + if (r <= el[j]) + r = el[j]; + else + { + mode = UNSORTED; + break; + } + } + } + } + + return mode; +} + INSTANTIATE_ARRAY_SORT (double); INSTANTIATE_ARRAY (double, OCTAVE_API); diff --git a/liboctave/Array-f.cc b/liboctave/Array-f.cc --- a/liboctave/Array-f.cc +++ b/liboctave/Array-f.cc @@ -84,6 +84,76 @@ return result; } +// The default solution using NaN-safe comparator is OK, but almost twice as +// slow than this code. +template <> +sortmode +Array::is_sorted (sortmode mode) const +{ + octave_idx_type n = numel (); + + const float *el = data (); + + if (n <= 1) + return mode ? mode : ASCENDING; + + if (! mode) + { + // Auto-detect mode. + if (el[n-1] < el[0] || xisnan (el[0])) + mode = DESCENDING; + else + mode = ASCENDING; + } + + if (mode == DESCENDING) + { + octave_idx_type j = 0; + float r; + // Sort out NaNs. + do + r = el[j++]; + while (xisnan (r) && j < n); + + // Orient the test so that NaN will not pass through. + for (; j < n; j++) + { + if (r >= el[j]) + r = el[j]; + else + { + mode = UNSORTED; + break; + } + } + + } + else if (mode == ASCENDING) + { + // Sort out NaNs. + while (n > 0 && xisnan (el[n-1])) + n--; + + if (n > 0) + { + // Orient the test so that NaN will not pass through. + float r = el[0]; + for (octave_idx_type j = 1; j < n; j++) + { + if (r <= el[j]) + r = el[j]; + else + { + mode = UNSORTED; + break; + } + } + } + } + + return mode; +} + INSTANTIATE_ARRAY_SORT (float); INSTANTIATE_ARRAY (float, OCTAVE_API); diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,8 @@ +2009-12-05 Jaroslav Hajek + + * Array-d.cc (Array::is_sorted): Optimized specialization. + * Array-f.cc (Array::is_sorted): Ditto. + 2009-12-05 Jaroslav Hajek * oct-sort.cc (lookup_binary): Remove.