GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-sort.h
Go to the documentation of this file.
1 /*
2 Copyright (C) 2003-2018 David Bateman
3 Copyright (C) 2009-2010 VZLU Prague
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 Code stolen in large part from Python's, listobject.c, which itself had
22 no license header. However, thanks to Tim Peters for the parts of the
23 code I ripped-off.
24 
25 As required in the Python license the short description of the changes
26 made are
27 
28 * convert the sorting code in listobject.cc into a generic class,
29  replacing PyObject* with the type of the class T.
30 
31 The Python license is
32 
33  PSF LICENSE AGREEMENT FOR PYTHON 2.3
34  --------------------------------------
35 
36  1. This LICENSE AGREEMENT is between the Python Software Foundation
37  ("PSF"), and the Individual or Organization ("Licensee") accessing and
38  otherwise using Python 2.3 software in source or binary form and its
39  associated documentation.
40 
41  2. Subject to the terms and conditions of this License Agreement, PSF
42  hereby grants Licensee a nonexclusive, royalty-free, world-wide
43  license to reproduce, analyze, test, perform and/or display publicly,
44  prepare derivative works, distribute, and otherwise use Python 2.3
45  alone or in any derivative version, provided, however, that PSF's
46  License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
47  2001, 2002, 2003 Python Software Foundation; All Rights Reserved" are
48  retained in Python 2.3 alone or in any derivative version prepared by
49  Licensee.
50 
51  3. In the event Licensee prepares a derivative work that is based on
52  or incorporates Python 2.3 or any part thereof, and wants to make
53  the derivative work available to others as provided herein, then
54  Licensee hereby agrees to include in any such work a brief summary of
55  the changes made to Python 2.3.
56 
57  4. PSF is making Python 2.3 available to Licensee on an "AS IS"
58  basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
59  IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
60  DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
61  FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT
62  INFRINGE ANY THIRD PARTY RIGHTS.
63 
64  5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
65  2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
66  A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3,
67  OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
68 
69  6. This License Agreement will automatically terminate upon a material
70  breach of its terms and conditions.
71 
72  7. Nothing in this License Agreement shall be deemed to create any
73  relationship of agency, partnership, or joint venture between PSF and
74  Licensee. This License Agreement does not grant permission to use PSF
75  trademarks or trade name in a trademark sense to endorse or promote
76  products or services of Licensee, or any third party.
77 
78  8. By copying, installing or otherwise using Python 2.3, Licensee
79  agrees to be bound by the terms and conditions of this License
80  Agreement.
81 */
82 
83 #if ! defined (octave_oct_sort_h)
84 #define octave_oct_sort_h 1
85 
86 #include "octave-config.h"
87 
88 #include "lo-traits.h"
89 
90 // The maximum number of entries in a MergeState's pending-runs stack.
91 // This is enough to sort arrays of size up to about
92 // 32 * phi ** MAX_MERGE_PENDING
93 // where phi ~= 1.618. 85 is ridiculously large enough, good for an array
94 // with 2**64 elements.
95 #define MAX_MERGE_PENDING 85
96 
97 // When we get into galloping mode, we stay there until both runs win less
98 // often than MIN_GALLOP consecutive times. See listsort.txt for more info.
99 #define MIN_GALLOP 7
100 
101 // Avoid malloc for small temp arrays.
102 #define MERGESTATE_TEMP_SIZE 1024
103 
104 // Enum for type of sort function
106 
107 template <typename T>
108 class
110 {
111 public:
112 
113  typedef bool (*compare_fcn_type) (typename ref_param<T>::type,
114  typename ref_param<T>::type);
115 
116  octave_sort (void);
117 
118  octave_sort (compare_fcn_type);
119 
120  // No copying!
121 
122  octave_sort (const octave_sort&) = delete;
123 
124  octave_sort& operator = (const octave_sort&) = delete;
125 
126  ~octave_sort (void);
127 
128  void set_compare (compare_fcn_type comp) { compare = comp; }
129 
130  void set_compare (sortmode mode);
131 
132  // Sort an array in-place.
133  void sort (T *data, octave_idx_type nel);
134 
135  // Ditto, but also permute the passed indices (may not be valid indices).
136  void sort (T *data, octave_idx_type *idx, octave_idx_type nel);
137 
138  // Check whether an array is sorted.
139  bool issorted (const T *data, octave_idx_type nel);
140 
141  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
142  bool is_sorted (const T *data, octave_idx_type nel)
143  { return issorted (data, nel); }
144 
145  // Sort a matrix by rows, return a permutation
146  // vector.
147  void sort_rows (const T *data, octave_idx_type *idx,
148  octave_idx_type rows, octave_idx_type cols);
149 
150  // Determine whether a matrix (as a contiguous block) is sorted by rows.
151  bool is_sorted_rows (const T *data,
152  octave_idx_type rows, octave_idx_type cols);
153 
154  // Do a binary lookup in a sorted array.
155  octave_idx_type lookup (const T *data, octave_idx_type nel,
156  const T& value);
157 
158  // Ditto, but for an array.
159  void lookup (const T *data, octave_idx_type nel,
160  const T *values, octave_idx_type nvalues,
161  octave_idx_type *idx);
162 
163  // A linear merge of two sorted tables. rev indicates the second table is
164  // in reverse order.
165  void lookup_sorted (const T *data, octave_idx_type nel,
166  const T *values, octave_idx_type nvalues,
167  octave_idx_type *idx, bool rev = false);
168 
169  // Rearranges the array so that the elements with indices
170  // lo..up-1 are in their correct place.
171  void nth_element (T *data, octave_idx_type nel,
172  octave_idx_type lo, octave_idx_type up = -1);
173 
174  static bool ascending_compare (typename ref_param<T>::type,
175  typename ref_param<T>::type);
176 
177  static bool descending_compare (typename ref_param<T>::type,
178  typename ref_param<T>::type);
179 
180 private:
181 
182  // One MergeState exists on the stack per invocation of mergesort.
183  // It's just a convenient way to pass state around among the helper
184  // functions.
185  //
186  // DGB: This isn't needed with mergesort in a class, but it doesn't
187  // slow things up, and it is likely to make my life easier for any
188  // potential backporting of changes in the Python code.
189 
190  struct s_slice
191  {
193  };
194 
195  struct MergeState
196  {
197  MergeState (void)
198  : min_gallop (), a (nullptr), ia (nullptr), alloced (0), n (0)
199  { reset (); }
200 
201  // No copying!
202 
203  MergeState (const MergeState&) = delete;
204 
205  MergeState& operator = (const MergeState&) = delete;
206 
207  ~MergeState (void)
208  { delete [] a; delete [] ia; }
209 
210  void reset (void)
211  { min_gallop = MIN_GALLOP; n = 0; }
212 
213  void getmem (octave_idx_type need);
214 
215  void getmemi (octave_idx_type need);
216 
217  // This controls when we get *into* galloping mode. It's
218  // initialized to MIN_GALLOP. merge_lo and merge_hi tend to nudge
219  // it higher for random data, and lower for highly structured
220  // data.
222 
223  // 'a' is temp storage to help with merges. It contains room for
224  // alloced entries.
225  T *a; // may point to temparray below
228 
229  // A stack of n pending runs yet to be merged. Run #i starts at
230  // address base[i] and extends for len[i] elements. It's always
231  // true (so long as the indices are in bounds) that
232  //
233  // pending[i].base + pending[i].len == pending[i+1].base
234  //
235  // so we could cut the storage for this, but it's a minor amount,
236  // and keeping all the info explicit simplifies the code.
238  struct s_slice pending[MAX_MERGE_PENDING];
239  };
240 
241  compare_fcn_type compare;
242 
244 
245  template <typename Comp>
246  void binarysort (T *data, octave_idx_type nel,
247  octave_idx_type start, Comp comp);
248 
249  template <typename Comp>
250  void binarysort (T *data, octave_idx_type *idx, octave_idx_type nel,
251  octave_idx_type start, Comp comp);
252 
253  template <typename Comp>
254  octave_idx_type count_run (T *lo, octave_idx_type n, bool& descending,
255  Comp comp);
256 
257  template <typename Comp>
258  octave_idx_type gallop_left (T key, T *a, octave_idx_type n,
259  octave_idx_type hint, Comp comp);
260 
261  template <typename Comp>
262  octave_idx_type gallop_right (T key, T *a, octave_idx_type n,
263  octave_idx_type hint, Comp comp);
264 
265  template <typename Comp>
266  int merge_lo (T *pa, octave_idx_type na,
267  T *pb, octave_idx_type nb,
268  Comp comp);
269 
270  template <typename Comp>
271  int merge_lo (T *pa, octave_idx_type *ipa, octave_idx_type na,
272  T *pb, octave_idx_type *ipb, octave_idx_type nb,
273  Comp comp);
274 
275  template <typename Comp>
276  int merge_hi (T *pa, octave_idx_type na,
277  T *pb, octave_idx_type nb,
278  Comp comp);
279 
280  template <typename Comp>
281  int merge_hi (T *pa, octave_idx_type *ipa, octave_idx_type na,
282  T *pb, octave_idx_type *ipb, octave_idx_type nb,
283  Comp comp);
284 
285  template <typename Comp>
286  int merge_at (octave_idx_type i, T *data, Comp comp);
287 
288  template <typename Comp>
289  int merge_at (octave_idx_type i, T *data, octave_idx_type *idx, Comp comp);
290 
291  template <typename Comp>
292  int merge_collapse (T *data, Comp comp);
293 
294  template <typename Comp>
295  int merge_collapse (T *data, octave_idx_type *idx, Comp comp);
296 
297  template <typename Comp>
298  int merge_force_collapse (T *data, Comp comp);
299 
300  template <typename Comp>
301  int merge_force_collapse (T *data, octave_idx_type *idx, Comp comp);
302 
303  octave_idx_type merge_compute_minrun (octave_idx_type n);
304 
305  template <typename Comp>
306  void sort (T *data, octave_idx_type nel, Comp comp);
307 
308  template <typename Comp>
309  void sort (T *data, octave_idx_type *idx, octave_idx_type nel, Comp comp);
310 
311  template <typename Comp>
312  bool issorted (const T *data, octave_idx_type nel, Comp comp);
313 
314  template <typename Comp>
315  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
316  bool is_sorted (const T *data, octave_idx_type nel, Comp comp)
317  { return issorted (data, nel, comp); }
318 
319  template <typename Comp>
320  void sort_rows (const T *data, octave_idx_type *idx,
321  octave_idx_type rows, octave_idx_type cols,
322  Comp comp);
323 
324  template <typename Comp>
325  bool is_sorted_rows (const T *data, octave_idx_type rows,
326  octave_idx_type cols, Comp comp);
327 
328  template <typename Comp>
329  octave_idx_type lookup (const T *data, octave_idx_type nel,
330  const T& value, Comp comp);
331 
332  template <typename Comp>
333  void lookup (const T *data, octave_idx_type nel,
334  const T *values, octave_idx_type nvalues,
335  octave_idx_type *idx, Comp comp);
336 
337  template <typename Comp>
338  void lookup_sorted (const T *data, octave_idx_type nel,
339  const T *values, octave_idx_type nvalues,
340  octave_idx_type *idx, bool rev, Comp comp);
341 
342  template <typename Comp>
343  void nth_element (T *data, octave_idx_type nel,
345  Comp comp);
346 };
347 
348 template <typename T>
349 class
350 vec_index
351 {
352 public:
353  T vec;
355 };
356 #endif
MergeState * ms
Definition: oct-sort.h:243
octave_idx_type len
Definition: oct-sort.h:192
octave_idx_type * ia
Definition: oct-sort.h:226
sortmode
Definition: oct-sort.h:105
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
Definition: data.cc:6348
void set_compare(compare_fcn_type comp)
Definition: oct-sort.h:128
octave_idx_type lookup(const T *x, octave_idx_type n, T y)
octave_idx_type alloced
Definition: oct-sort.h:227
octave_idx_type indx
Definition: oct-sort.h:354
cell array If invoked with two or more scalar integer or a vector of integer values
Definition: ov-cell.cc:1241
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
compare_fcn_type compare
Definition: oct-sort.h:241
#define MAX_MERGE_PENDING
Definition: oct-sort.h:95
if_then_else< is_class_type< T >::no, T, T const & >::result type
Definition: lo-traits.h:118
octave::sys::time start
Definition: graphics.cc:12337
#define MIN_GALLOP
Definition: oct-sort.h:99
for i
Definition: data.cc:5264
octave_idx_type n
Definition: oct-sort.h:237
octave_idx_type min_gallop
Definition: oct-sort.h:221
nd group nd example For each display the value
Definition: sysdep.cc:866