Macaulay2 Engine
Loading...
Searching...
No Matches
monsort.hpp
Go to the documentation of this file.
1// Copyright 2005 Michael E. Stillman
2
3#ifndef _monsort_h_
4#define _monsort_h_
5
31
32#include <cstdio>
33#include <cstdlib>
34#include "newdelete.hpp"
35
36#if !defined(SAFEC_EXPORTS)
37#include "interface/m2-types.h"
38#endif
39
40template <typename Sorter>
41// Sorter S, needs to define:
42// typename S::value
43// int S.compare(S::value a, S::value b)
44// such that: if a<b, result is <0
45// a==b, result is ==0
46// a>b, result is >0
48{
49 typedef typename Sorter::value value;
50 Sorter *M;
52 long len;
54
55 long sort_partition(long lo, long hi);
56 void sort(long lo, long hi);
57
58 void sort2(long lo, long hi);
59
60 void sort2depth(long lo, long hi, long depth);
61
62 void sortC();
63 void sortD(); // heap sort
64
65 QuickSorter(Sorter *M0, value *elems0, long len0)
66 : M(M0), elems(elems0), len(len0), maxdepth(0)
67 {
68 }
70 public:
71 static void sort(Sorter *M0, value *elems0, long len0);
72};
73
75// Algorithm A ////////////
76// Quicksort, recursive version, not used now?
78
79template <typename Sorter>
81{
82 value pivot = elems[lo];
83 long i = lo - 1;
84 long j = hi + 1;
85 for (;;)
86 {
87 do
88 {
89 j--;
90 }
91 while (M->compare(elems[j], pivot) < 0);
92 do
93 {
94 i++;
95 }
96 while (M->compare(elems[i], pivot) > 0);
97
98 if (i < j)
99 {
100 value tmp = elems[j];
101 elems[j] = elems[i];
102 elems[i] = tmp;
103 }
104 else
105 return j;
106 }
107}
108
109template <typename Sorter>
110void QuickSorter<Sorter>::sort(long lo, long hi)
111{
112 if (lo < hi)
113 {
114 long q = sort_partition(lo, hi);
115 sort(lo, q);
116 sort(q + 1, hi);
117 }
118}
119
121// Quicksort, also recursive, better pivot choices
122// But: is very poor if all elements are the same
124
125/***** macros create functional code *****/
126#define pivot_index() (begin + (end - begin) / 2)
127#define swap(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
128
129template <typename Sorter>
131{
132 value pivot;
133 value t; /* temporary variable for swap */
134 if (end > begin)
135 {
136 long l = begin + 1;
137 long r = end;
140 t); /*** choose arbitrary pivot ***/
141 pivot = elems[begin];
142 while (l < r)
143 {
144 if (M->compare(elems[l], pivot) <= 0)
145 {
146 l++;
147 }
148 else
149 {
150 while (l < --r &&
151 M->compare(elems[r], pivot) >=
152 0) /*** skip superfluous swaps ***/
153 ;
154 swap(elems[l], elems[r], t);
155 }
156 }
157 l--;
158 swap(elems[begin], elems[l], t);
159 sort2(begin, l);
160 sort2(r, end);
161 }
162}
163
165// Same as sort2, except depth information is kept
167
168template <typename Sorter>
169void QuickSorter<Sorter>::sort2depth(long begin, long end, long depth)
170{
171 value pivot;
172 value t; /* temporary variable for swap */
173 if (depth > maxdepth) maxdepth = depth;
174 if (end > begin)
175 {
176 long l = begin + 1;
177 long r = end;
180 t); /*** choose arbitrary pivot ***/
181 pivot = elems[begin];
182 while (l < r)
183 {
184 if (M->compare(elems[l], pivot) <= 0)
185 {
186 l++;
187 }
188 else
189 {
190 while (l < --r &&
191 M->compare(elems[r], pivot) >=
192 0) /*** skip superfluous swaps ***/
193 ;
194 swap(elems[l], elems[r], t);
195 }
196 }
197 l--;
198 swap(elems[begin], elems[l], t);
199 sort2depth(begin, l, depth + 1);
200 sort2depth(r, end, depth + 1);
201 }
202}
203
204#undef swap
205#undef pivot_index
206
208// Non-recursive quicksort, cribbed from numerical recipes
210
211#define SWAP(a, b) \
212 temp = (a); \
213 (a) = (b); \
214 (b) = temp;
215#define THRESH 6
216#define NSTACK 50
217
218template <typename Sorter>
220// (unsigned long n, float arr[])
221// array is: elems
222// length is: len
223{
224 unsigned long i, ir = len, j, k, l = 1, *istack;
225 int jstack = 0;
226 value a, temp;
227 long ncmps;
228 int maxstack = 0;
229 ncmps = 0;
230 istack = newarray_atomic(unsigned long, NSTACK);
231 for (;;)
232 {
233 if (ir - l < THRESH)
234 {
235 for (j = l + 1; j <= ir; j++)
236 {
237 a = elems[j];
238 for (i = j - 1; i >= l; i--)
239 {
240 ncmps++;
241 if (M->compare(elems[i], a) <= 0) break;
242 elems[i + 1] = elems[i];
243 }
244 elems[i + 1] = a;
245 }
246 if (jstack == 0) break;
247 ir = istack[jstack--];
248 l = istack[jstack--];
249 }
250 else
251 {
252 k = (l + ir) >> 1;
253 SWAP(elems[k], elems[l + 1])
254 ncmps++;
255 if (M->compare(elems[l], elems[ir]) > 0)
256 {
257 SWAP(elems[l], elems[ir])
258 }
259 ncmps++;
260 if (M->compare(elems[l + 1], elems[ir]) > 0)
261 {
262 SWAP(elems[l + 1], elems[ir])
263 }
264 ncmps++;
265 if (M->compare(elems[l], elems[l + 1]) > 0)
266 {
267 SWAP(elems[l], elems[l + 1])
268 }
269 i = l + 1;
270 j = ir;
271 a = elems[l + 1];
272 for (;;)
273 {
274 do
275 i++;
276 while (ncmps++, M->compare(elems[i], a) < 0);
277 do
278 j--;
279 while (ncmps++, M->compare(elems[j], a) > 0);
280 if (j < i) break;
281 SWAP(elems[i], elems[j]);
282 }
283 elems[l + 1] = elems[j];
284 elems[j] = a;
285 jstack += 2;
286 if (jstack > maxstack) maxstack = jstack;
287 if (jstack > NSTACK)
288 {
289 fprintf(stderr, "NSTACK too small in sort.\n");
290 exit(0);
291 }
292 if (ir - i + 1 >= j - l)
293 {
294 istack[jstack] = ir;
295 istack[jstack - 1] = i;
296 ir = j - 1;
297 }
298 else
299 {
300 istack[jstack] = j - 1;
301 istack[jstack - 1] = l;
302 l = i;
303 }
304 }
305 }
306 freemem(istack);
307 fprintf(stderr,
308 "quicksort: len = %ld ncmps = %ld 2*depth = %d\n",
309 len,
310 ncmps,
311 maxstack);
312}
313#undef THRESH
314#undef NSTACK
315#undef SWAP
316
318// sortD: heap sort
320
321template <typename Sorter>
323{
324 unsigned long i, ir, j, l;
325 value rra;
326 long ncmps;
327
328 ncmps = 0;
329 if (len < 2) return;
330 l = (len >> 1) + 1;
331 ir = len;
332 for (;;)
333 {
334 if (l > 1)
335 {
336 rra = elems[--l];
337 }
338 else
339 {
340 rra = elems[ir];
341 elems[ir] = elems[1];
342 if (--ir == 1)
343 {
344 elems[1] = rra;
345 break;
346 }
347 }
348 i = l;
349 j = l + l;
350 while (j <= ir)
351 {
352 if (j < ir)
353 {
354 ncmps++;
355 if (M->compare(elems[j], elems[j + 1]) < 0) j++;
356 }
357 ncmps++;
358 if (M->compare(rra, elems[j]) < 0)
359 {
360 elems[i] = elems[j];
361 i = j;
362 j <<= 1;
363 }
364 else
365 j = ir + 1;
366 }
367 elems[i] = rra;
368 }
369 fprintf(stderr, "hpsort: %ld, %ld\n", len, ncmps);
370}
371
373#include <ctime>
374
375template <typename Sorter>
376void QuickSorter<Sorter>::sort(Sorter *M0, value *elems0, long len0)
377{
378 QuickSorter S(M0, elems0, len0);
379 int typ = 1;
380 clock_t begin_time = clock();
381
382 switch (typ)
383 {
384 case 1:
385 S.sort2(0, len0);
386 break;
387 case 2:
388 S.sort2depth(0, len0, 1);
389 break;
390
391 case 3:
392 S.sortC();
393 break;
394
395 case 4:
396 S.sortD();
397 break;
398 }
399
400 clock_t end_time = clock();
401 long double nsecs = end_time - begin_time;
402 nsecs /= CLOCKS_PER_SEC;
403
404 if (M2_gbTrace >= 4)
405 fprintf(
406 stderr, "sort: len %ld depth %ld time %Lf\n", len0, S.maxdepth, nsecs);
407}
408#endif
409
410// Local Variables:
411// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
412// indent-tabs-mode: nil
413// End:
Sorter * M
Definition monsort.hpp:50
value * elems
Definition monsort.hpp:51
void sort(long lo, long hi)
Definition monsort.hpp:110
void sortC()
Definition monsort.hpp:219
void sort2depth(long lo, long hi, long depth)
Definition monsort.hpp:169
QuickSorter(Sorter *M0, value *elems0, long len0)
Definition monsort.hpp:65
Sorter::value value
Definition monsort.hpp:49
void sortD()
Definition monsort.hpp:322
long sort_partition(long lo, long hi)
Definition monsort.hpp:80
void sort2(long lo, long hi)
Definition monsort.hpp:130
long maxdepth
Definition monsort.hpp:53
void freemem(void *s)
Definition m2-mem.cpp:103
int M2_gbTrace
Definition m2-types.cpp:52
Engine-to-interpreter type vocabulary across the C++ / .dd boundary.
#define THRESH
Definition monsort.hpp:215
#define swap(a, b, t)
Definition monsort.hpp:127
#define SWAP(a, b)
Definition monsort.hpp:211
#define pivot_index()
Definition monsort.hpp:126
#define NSTACK
Definition monsort.hpp:216
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
our_new_delete — per-class opt-in routing of new / delete through bdwgc.
TermIterator< Nterm > begin(Nterm *ptr)
Definition ringelem.cpp:4
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5