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