00001 /* 00002 00003 Copyright (C) 1994-2012 John W. Eaton 00004 Copyright (C) 2009 VZLU Prague 00005 00006 This file is part of Octave. 00007 00008 Octave is free software; you can redistribute it and/or modify it 00009 under the terms of the GNU General Public License as published by the 00010 Free Software Foundation; either version 3 of the License, or (at your 00011 option) any later version. 00012 00013 Octave is distributed in the hope that it will be useful, but WITHOUT 00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00015 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00016 for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with Octave; see the file COPYING. If not, see 00020 <http://www.gnu.org/licenses/>. 00021 00022 */ 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include <config.h> 00026 #endif 00027 00028 // Instantiate Arrays of double values. 00029 00030 #include "lo-mappers.h" 00031 #include "Array.h" 00032 #include "Array.cc" 00033 #include "oct-locbuf.h" 00034 00035 #define INLINE_ASCENDING_SORT 00036 #define INLINE_DESCENDING_SORT 00037 #include "oct-sort.cc" 00038 00039 template <> 00040 inline bool 00041 sort_isnan<double> (double x) 00042 { 00043 return xisnan (x); 00044 } 00045 00046 static bool 00047 nan_ascending_compare (double x, double y) 00048 { 00049 return xisnan (y) ? ! xisnan (x) : x < y; 00050 } 00051 00052 static bool 00053 nan_descending_compare (double x, double y) 00054 { 00055 return xisnan (x) ? ! xisnan (y) : x > y; 00056 } 00057 00058 Array<double>::compare_fcn_type 00059 safe_comparator (sortmode mode, const Array<double>& a , bool allow_chk) 00060 { 00061 Array<double>::compare_fcn_type result = 0; 00062 00063 if (allow_chk) 00064 { 00065 octave_idx_type k = 0; 00066 for (; k < a.numel () && ! xisnan (a(k)); k++) ; 00067 if (k == a.numel ()) 00068 { 00069 if (mode == ASCENDING) 00070 result = octave_sort<double>::ascending_compare; 00071 else if (mode == DESCENDING) 00072 result = octave_sort<double>::descending_compare; 00073 } 00074 } 00075 00076 if (! result) 00077 { 00078 if (mode == ASCENDING) 00079 result = nan_ascending_compare; 00080 else if (mode == DESCENDING) 00081 result = nan_descending_compare; 00082 } 00083 00084 return result; 00085 } 00086 00087 // The default solution using NaN-safe comparator is OK, but almost twice as 00088 // slow than this code. 00089 template <> 00090 OCTAVE_API 00091 sortmode 00092 Array<double>::is_sorted (sortmode mode) const 00093 { 00094 octave_idx_type n = numel (); 00095 00096 const double *el = data (); 00097 00098 if (n <= 1) 00099 return mode ? mode : ASCENDING; 00100 00101 if (! mode) 00102 { 00103 // Auto-detect mode. 00104 if (el[n-1] < el[0] || xisnan (el[0])) 00105 mode = DESCENDING; 00106 else 00107 mode = ASCENDING; 00108 } 00109 00110 if (mode == DESCENDING) 00111 { 00112 octave_idx_type j = 0; 00113 double r; 00114 // Sort out NaNs. 00115 do 00116 r = el[j++]; 00117 while (xisnan (r) && j < n); 00118 00119 // Orient the test so that NaN will not pass through. 00120 for (; j < n; j++) 00121 { 00122 if (r >= el[j]) 00123 r = el[j]; 00124 else 00125 { 00126 mode = UNSORTED; 00127 break; 00128 } 00129 } 00130 00131 } 00132 else if (mode == ASCENDING) 00133 { 00134 // Sort out NaNs. 00135 while (n > 0 && xisnan (el[n-1])) 00136 n--; 00137 00138 if (n > 0) 00139 { 00140 // Orient the test so that NaN will not pass through. 00141 double r = el[0]; 00142 for (octave_idx_type j = 1; j < n; j++) 00143 { 00144 if (r <= el[j]) 00145 r = el[j]; 00146 else 00147 { 00148 mode = UNSORTED; 00149 break; 00150 } 00151 } 00152 } 00153 } 00154 00155 return mode; 00156 } 00157 00158 INSTANTIATE_ARRAY_SORT (double); 00159 00160 INSTANTIATE_ARRAY (double, OCTAVE_API); 00161 00162 template OCTAVE_API std::ostream& operator << (std::ostream&, const Array<double>&); 00163 00164 #include "DiagArray2.h" 00165 #include "DiagArray2.cc" 00166 00167 template class OCTAVE_API DiagArray2<double>;