Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
sort_imp.h
Go to the documentation of this file.
1 #if !defined(T) || !defined(SORT_SUFFIX)
2 #error sort_imp.h not meant to be compiled by itself
3 #endif
4 
5 #define sort_data TOKEN_PASTE(sort_data ,SORT_SUFFIX)
6 #define radix_count TOKEN_PASTE(radix_count ,SORT_SUFFIX)
7 #define radix_offsets TOKEN_PASTE(radix_offsets ,SORT_SUFFIX)
8 #define radix_zeros TOKEN_PASTE(radix_zeros ,SORT_SUFFIX)
9 #define radix_passv TOKEN_PASTE(radix_passv ,SORT_SUFFIX)
10 #define radix_sortv TOKEN_PASTE(radix_sortv ,SORT_SUFFIX)
11 #define radix_passp0_b TOKEN_PASTE(radix_passp0_b ,SORT_SUFFIX)
12 #define radix_passp_b TOKEN_PASTE(radix_passp_b ,SORT_SUFFIX)
13 #define radix_passp_m TOKEN_PASTE(radix_passp_m ,SORT_SUFFIX)
14 #define radix_passp_e TOKEN_PASTE(radix_passp_e ,SORT_SUFFIX)
15 #define radix_passp0_be TOKEN_PASTE(radix_passp0_be,SORT_SUFFIX)
16 #define radix_passp_be TOKEN_PASTE(radix_passp_be, SORT_SUFFIX)
17 #define radix_sortp TOKEN_PASTE(radix_sortp ,SORT_SUFFIX)
18 #define merge_sortv TOKEN_PASTE(merge_sortv ,SORT_SUFFIX)
19 #define merge_copy_perm TOKEN_PASTE(merge_copy_perm,SORT_SUFFIX)
20 #define merge_sortp0 TOKEN_PASTE(merge_sortp0 ,SORT_SUFFIX)
21 #define merge_sortp TOKEN_PASTE(merge_sortp ,SORT_SUFFIX)
22 #define heap_sortv TOKEN_PASTE(heap_sortv ,SORT_SUFFIX)
23 
24 #define sortv PREFIXED_NAME(TOKEN_PASTE(sortv,SORT_SUFFIX))
25 #define sortp PREFIXED_NAME(TOKEN_PASTE(sortp,SORT_SUFFIX))
26 
27 typedef struct { T v; uint i; } sort_data;
28 
29 #define INC_PTR(A,stride) ((A)=(T*)((char*)(A)+(stride)))
30 #define INDEX_PTR(A,stride,i) (*(T*)((char*)(A)+(i)*(stride)))
31 
32 /*------------------------------------------------------------------------------
33 
34  Radix Sort
35 
36  stable; O(n+k) time and extra storage
37  where k = (digits in an int) * 2^(bits per digit)
38  (e.g. k = 4 * 256 = 1024 for 32-bit ints with 8-bit digits)
39 
40  brief description:
41  input sorted stably on each digit, starting with the least significant
42  counting sort is used for each digit:
43  a pass through the input counts the occurences of each digit value
44  on a second pass, each input has a known destination
45 
46  tricks:
47  all counting passes are combined into one
48  the counting pass also computes the inclusive bit-wise or of all inputs,
49  which is used to skip digit positions for which all inputs have zeros
50 
51  ----------------------------------------------------------------------------*/
52 
53 #define STATIC_DIGIT_BUCKETS 1
54 
55 #define DIGIT_BITS 8
56 #define DIGIT_VALUES (1<<DIGIT_BITS)
57 #define DIGIT_MASK ((T)(DIGIT_VALUES-1))
58 #define CEILDIV(a,b) (((a)+(b)-1)/(b))
59 #define DIGITS CEILDIV(CHAR_BIT*sizeof(T),DIGIT_BITS)
60 #define VALUE_BITS (DIGIT_BITS*DIGITS)
61 #define COUNT_SIZE (DIGITS*DIGIT_VALUES)
62 
63 /* used to unroll a tiny loop: */
64 #define COUNT_DIGIT_01(n,i) \
65  if(n>i) count[i][val&DIGIT_MASK]++, val>>=DIGIT_BITS
66 #define COUNT_DIGIT_02(n,i) COUNT_DIGIT_01(n,i); COUNT_DIGIT_01(n,i+ 1)
67 #define COUNT_DIGIT_04(n,i) COUNT_DIGIT_02(n,i); COUNT_DIGIT_02(n,i+ 2)
68 #define COUNT_DIGIT_08(n,i) COUNT_DIGIT_04(n,i); COUNT_DIGIT_04(n,i+ 4)
69 #define COUNT_DIGIT_16(n,i) COUNT_DIGIT_08(n,i); COUNT_DIGIT_08(n,i+ 8)
70 #define COUNT_DIGIT_32(n,i) COUNT_DIGIT_16(n,i); COUNT_DIGIT_16(n,i+16)
71 #define COUNT_DIGIT_64(n,i) COUNT_DIGIT_32(n,i); COUNT_DIGIT_32(n,i+32)
72 
73 static T radix_count(
74  uint (*restrict count)[DIGIT_VALUES],
75  const T *restrict A, const T *const end, const unsigned stride)
76 {
77  T bitorkey = 0;
78  memset(count,0,COUNT_SIZE*sizeof(uint));
79  do {
80  T val=*A;
81  bitorkey|=val;
83  /* above macro expands to:
84  if(DIGITS> 0) count[ 0][val&DIGIT_MASK]++, val>>=DIGIT_BITS;
85  if(DIGITS> 1) count[ 1][val&DIGIT_MASK]++, val>>=DIGIT_BITS;
86  ...
87  if(DIGITS>63) count[63][val&DIGIT_MASK]++, val>>=DIGIT_BITS;
88  */
89  } while(INC_PTR(A,stride),A!=end);
90  return bitorkey;
91 }
92 
93 #undef COUNT_DIGIT_01
94 #undef COUNT_DIGIT_02
95 #undef COUNT_DIGIT_04
96 #undef COUNT_DIGIT_08
97 #undef COUNT_DIGIT_16
98 #undef COUNT_DIGIT_32
99 #undef COUNT_DIGIT_64
100 
101 static void radix_offsets(uint *restrict c)
102 {
103  uint *const ce = c+DIGIT_VALUES;
104  uint sum = 0;
105  do {
106  const uint c0=c[0], c1=c[1], c2=c[2], c3=c[3];
107  const uint o1=sum+c0, o2=o1+c1, o3=o2+c2;
108  c[0]=sum, c[1]=o1, c[2]=o2, c[3]=o3;
109  sum = o3+c3;
110  c+=4;
111  } while(c!=ce);
112 }
113 
114 static unsigned radix_zeros(
115  T bitorkey, uint (*restrict count)[DIGIT_VALUES],
116  unsigned *restrict shift, uint **restrict offsets)
117 {
118  unsigned digits=0, sh=0; uint *c = &count[0][0];
119  do {
120  if(bitorkey&DIGIT_MASK) *shift++ = sh, *offsets++ = c, ++digits,
121  radix_offsets(c);
122  } while(bitorkey>>=DIGIT_BITS,sh+=DIGIT_BITS,c+=DIGIT_VALUES,sh!=VALUE_BITS);
123  return digits;
124 }
125 
126 static void radix_passv(
127  const T *restrict A, const T *const end, const unsigned stride,
128  const unsigned sh, uint *const restrict off, T *const restrict out)
129 {
130  do out[off[(*A>>sh)&DIGIT_MASK]++] = *A; while(INC_PTR(A,stride),A!=end);
131 }
132 
133 static void radix_sortv(
134  T *out, const T *A, const uint n, const unsigned stride,
135  T *work, uint (*restrict count)[DIGIT_VALUES])
136 {
137  const T *const end = &INDEX_PTR(A,stride,n);
138  T bitorkey = radix_count(count, A,end,stride);
139  unsigned shift[DIGITS]; uint *offsets[DIGITS];
140  const unsigned digits = radix_zeros(bitorkey,count,shift,offsets);
141  if(digits==0) {
142  memset(out,0,n*sizeof(T));
143  } else {
144  T *src, *dst; unsigned d;
145  if(out==A || (digits&1)==0) dst=out,src=work;
146  else src=out,dst=work;
147  radix_passv(A,end,stride,shift[0],offsets[0],src);
148  for(d=1;d!=digits;++d) {
149  T *t;
150  radix_passv(src,src+n,sizeof(T),shift[d],offsets[d],dst);
151  t=src,src=dst,dst=t;
152  }
153  if(src!=out) memcpy(out,src,n*sizeof(T));
154  }
155 }
156 
157 static void radix_passp0_b(
158  const T *restrict A, const uint n, const unsigned stride,
159  const unsigned sh, uint *const restrict off,
160  sort_data *const restrict out)
161 {
162  uint i=0;
163  do {
164  T v = *A;
165  sort_data *d = &out[off[(v>>sh)&DIGIT_MASK]++];
166  d->v=v, d->i=i++;
167  } while(INC_PTR(A,stride),i!=n);
168 }
169 
170 static void radix_passp_b(
171  const uint *restrict p,
172  const T *const restrict A, const uint n, const unsigned stride,
173  const unsigned sh, uint *const restrict off,
174  sort_data *const out)
175 {
176  const uint *const pe = p+n;
177  do {
178  uint j = *p++;
179  T v = INDEX_PTR(A,stride,j);
180  sort_data *d = &out[off[(v>>sh)&DIGIT_MASK]++];
181  d->v=v, d->i=j;
182  } while(p!=pe);
183 }
184 
185 static void radix_passp_m(
186  const sort_data *restrict src, const sort_data *const end,
187  const unsigned sh, uint *const restrict off,
188  sort_data *const restrict out)
189 {
190  do {
191  sort_data *d = &out[off[(src->v>>sh)&DIGIT_MASK]++];
192  d->v=src->v,d->i=src->i;
193  } while(++src!=end);
194 }
195 
196 static void radix_passp_e(
197  const sort_data *restrict src, const sort_data *const end,
198  const unsigned sh, uint *const restrict off,
199  uint *const restrict out)
200 {
201  do out[off[(src->v>>sh)&DIGIT_MASK]++]=src->i; while(++src!=end);
202 }
203 
204 static void radix_passp0_be(
205  uint *const restrict out,
206  const T *restrict A, const uint n, const unsigned stride,
207  const unsigned sh, uint *const restrict off)
208 {
209  uint i=0;
210  do out[off[(*A>>sh)&DIGIT_MASK]++]=i++; while(INC_PTR(A,stride),i!=n);
211 }
212 
213 static void radix_passp_be(
214  uint *restrict p,
215  const T *restrict A, const uint n, const unsigned stride,
216  const unsigned sh, uint *const restrict off,
217  sort_data *restrict work)
218 {
219  uint *q = p, *const qe = p+n;
220  uint *w = &work[0].i;
221  do {
222  uint j = *q++;
223  T v = INDEX_PTR(A,stride,j);
224  w[off[(v>>sh)&DIGIT_MASK]++]=j;
225  } while(q!=qe);
226  memcpy(p,w,n*sizeof(uint));
227 }
228 
229 static void radix_sortp(
230  uint *restrict idx, uint perm_start,
231  const T *restrict A, const uint n, const unsigned stride,
232  sort_data *restrict work,
233  uint (*restrict count)[DIGIT_VALUES])
234 {
235  T bitorkey = radix_count(count, A,&INDEX_PTR(A,stride,n),stride);
236  unsigned shift[DIGITS]; uint *offsets[DIGITS];
237  unsigned digits = radix_zeros(bitorkey,count,shift,offsets);
238  if(digits==0) {
239  if(!perm_start) { uint i=0; do *idx++=i++; while(i!=n); }
240  } else if(digits==1) {
241  if(perm_start) radix_passp_be (idx,A,n,stride,shift[0],offsets[0],work);
242  else radix_passp0_be(idx,A,n,stride,shift[0],offsets[0]);
243  } else {
244  sort_data *src, *dst; unsigned d;
245  if((digits&1)==0) dst=work,src=dst+n;
246  else src=work,dst=src+n;
247  if(perm_start) radix_passp_b (idx,A,n,stride,shift[0],offsets[0],src);
248  else radix_passp0_b( A,n,stride,shift[0],offsets[0],src);
249  for(d=1;d!=digits-1;++d) {
250  sort_data *t;
251  radix_passp_m(src,src+n,shift[d],offsets[d],dst);
252  t=src,src=dst,dst=t;
253  }
254  radix_passp_e(src,src+n,shift[d],offsets[d],idx);
255  }
256 }
257 
258 /*------------------------------------------------------------------------------
259 
260  Merge Sort
261 
262  stable; O(n log n) time
263 
264  ----------------------------------------------------------------------------*/
265 
266 #define MERGE_2(p,v) \
267  if(VAL(v[1])<VAL(v[0])) p[0]=v[1],p[1]=v[0]; \
268  else p[0]=v[0],p[1]=v[1]
269 #define MERGE_3(p,v) do \
270  if(VAL(v[1])<VAL(v[0])) { \
271  if(VAL(v[2])<VAL(v[1])) p[0]=v[2],p[1]=v[1],p[2]=v[0]; \
272  else { if(VAL(v[2])<VAL(v[0])) p[0]=v[1],p[1]=v[2],p[2]=v[0]; \
273  else p[0]=v[1],p[1]=v[0],p[2]=v[2]; } \
274  } else { \
275  if(VAL(v[2])<VAL(v[0])) p[0]=v[2],p[1]=v[0],p[2]=v[1]; \
276  else { if(VAL(v[2])<VAL(v[1])) p[0]=v[0],p[1]=v[2],p[2]=v[1]; \
277  else p[0]=v[0],p[1]=v[1],p[2]=v[2]; } \
278  } while(0)
279 #define MERGE_SORT() \
280  do { \
281  uint i=0, n=An, base=-n, odd=0, c=0, b=1; \
282  for(;;) { \
283  DATA *restrict p; \
284  if((c&1)==0) { \
285  base+=n, n+=(odd&1), c|=1, b^=1; \
286  while(n>3) odd<<=1,odd|=(n&1),n>>=1,c<<=1,b^=1; \
287  } else \
288  base-=n-(odd&1),n<<=1,n-=(odd&1),odd>>=1,c>>=1; \
289  if(c==0) break; \
290  p = buf[b]+base; \
291  if(n==2) { \
292  DATA v[2]; SETVAL(v[0],i), SETVAL(v[1],i+1); \
293  MERGE_2(p,v); \
294  i+=2; \
295  } else if(n==3) { \
296  DATA v[3]; SETVAL(v[0],i), SETVAL(v[1],i+1), SETVAL(v[2],i+2); \
297  MERGE_3(p,v); \
298  i+=3; \
299  } else { \
300  const uint na = n>>1, nb = (n+1)>>1; \
301  const DATA *restrict ap = buf[b^1]+base, *const ae = ap+na; \
302  DATA *restrict bp = p+na, *const be = bp+nb; \
303  for(;;) { \
304  if(VAL((*bp))<VAL((*ap))) { \
305  *p++=*bp++; \
306  if(bp!=be) continue; \
307  do *p++=*ap++; while(ap!=ae); \
308  break; \
309  } else { \
310  *p++=*ap++; \
311  if(ap==ae) break; \
312  } \
313  } \
314  } \
315  } \
316  } while(0)
317 
318 static void merge_sortv(
319  T *restrict out,
320  const T *restrict A, const uint An, const unsigned stride,
321  T *restrict work)
322 {
323  T *buf[2]; buf[0]=out, buf[1]=work;
324 #define DATA T
325 #define VAL(x) x
326 #define SETVAL(x,ai) x=*A,INC_PTR(A,stride)
327  MERGE_SORT();
328 #undef SETVAL
329 #undef VAL
330 #undef DATA
331 }
332 
333 static void merge_copy_perm(
334  uint *restrict idx, const sort_data *restrict p, uint n)
335 {
336  /*const sort_data *pe = p+n;
337  do *idx++ = (p++)->i; while(p!=pe);*/
338  uint n_by_8 = (n+7)/8;
339  switch(n%8) {
340  case 0: do { *idx++ = (p++)->i;
341  case 7: *idx++ = (p++)->i;
342  case 6: *idx++ = (p++)->i;
343  case 5: *idx++ = (p++)->i;
344  case 4: *idx++ = (p++)->i;
345  case 3: *idx++ = (p++)->i;
346  case 2: *idx++ = (p++)->i;
347  case 1: *idx++ = (p++)->i;
348  } while (--n_by_8 > 0);
349  }
350 }
351 
352 static void merge_sortp0(
353  uint *restrict idx,
354  const T *restrict A, const uint An, const unsigned stride,
355  sort_data *restrict work)
356 {
357  sort_data *buf[2]; buf[0]=work+An,buf[1]=work;
358 #define DATA sort_data
359 #define VAL(x) x.v
360 #define SETVAL(x,ai) x.v=*A,INC_PTR(A,stride),x.i=ai
361  MERGE_SORT();
362 #undef SETVAL
363 #undef VAL
364 #undef DATA
365  merge_copy_perm(idx,buf[0],An);
366 }
367 
368 static void merge_sortp(
369  uint *restrict idx,
370  const T *const restrict A, const uint An, const unsigned stride,
371  sort_data *restrict work)
372 {
373  sort_data *buf[2]; buf[0]=work+An,buf[1]=work;
374 #define DATA sort_data
375 #define VAL(x) x.v
376 #define SETVAL(x,ai) x.i=idx[ai],x.v=INDEX_PTR(A,stride,x.i)
377  MERGE_SORT();
378 #undef SETVAL
379 #undef VAL
380 #undef DATA
381  merge_copy_perm(idx,buf[0],An);
382 }
383 
384 #undef MERGE_SORT
385 #undef MERGE_3
386 #undef MERGE_2
387 
388 /*------------------------------------------------------------------------------
389 
390  Heap Sort
391 
392  in-place, stability unobservable; O(n log n) time
393 
394  ----------------------------------------------------------------------------*/
395 static void heap_sortv(T *const restrict A, unsigned n)
396 {
397  unsigned i;
398  /* build heap */
399  for(i=1;i<n;++i) {
400  T item = A[i];
401  unsigned h=i, p = (h-1)>>1;
402  if(A[p] >= item) continue;
403  do A[h]=A[p], h=p, p=(p-1)>>1; while(h && A[p] < item);
404  A[h] = item;
405  }
406  /* extract */
407  for(i=n-1;i;--i) {
408  T item = A[i];
409  unsigned h = 0;
410  A[i] = A[0];
411  for(;;) {
412  unsigned ch = 1+(h<<1), r = ch+1;
413  if(r<i && A[ch] < A[r]) ch=r;
414  if(ch>=i || item >= A[ch]) break;
415  A[h]=A[ch], h=ch;
416  }
417  A[h] = item;
418  }
419 }
420 
421 
422 /*------------------------------------------------------------------------------
423 
424  Hybrid Stable Sort
425 
426  low-overhead merge sort when n is small,
427  otherwise asymptotically superior radix sort
428 
429  result = O(n) sort with good performance for all n
430 
431  A, n, stride : specifices the input, stride in bytes
432  out : the sorted values on output
433 
434  For the value sort,
435  A and out may alias (A == out) exactly when stride == sizeof(T),
436  in which case heap sort is used for small sizes
437 
438  For the permutation sort,
439  the permutation can be both input (when start_perm!=0) and output,
440  following the convention that it is always at the start of the buffer buf;
441  the buffer will be expanded as necessary to accomodate the permutation
442  and the required scratch space
443 
444  ----------------------------------------------------------------------------*/
445 
446 void sortv(T *out, const T *A, uint n, unsigned stride, buffer *restrict buf)
447 {
448  if(n<DIGIT_VALUES) {
449  if(n<2) {
450  if(n==0) return;
451  *out = *A;
452  } else {
453  if(out==A) {
454  if(stride!=sizeof(T))
455  fail(1,__FILE__,__LINE__,"in-place sort with non-unit stride");
456  heap_sortv(out,n);
457  } else {
458  buffer_reserve(buf,n*sizeof(T));
459  merge_sortv(out, A,n,stride, (T*)buf->ptr);
460  }
461  }
462  } else if(STATIC_DIGIT_BUCKETS) {
463  static uint count[DIGITS][DIGIT_VALUES];
464  buffer_reserve(buf,n*sizeof(T));
465  radix_sortv(out, A,n,stride, (T*)buf->ptr,count);
466  } else {
467  T *restrict work;
468  uint (*restrict count)[DIGIT_VALUES];
469  const size_t count_off=align_as(uint,n*sizeof(T));
470  buffer_reserve(buf,count_off+sizeof(uint[DIGITS][DIGIT_VALUES]));
471  work = buf->ptr;
472  count = (uint(*)[DIGIT_VALUES])((char*)buf->ptr+count_off);
473  radix_sortv(out, A,n,stride, work,count);
474  }
475 }
476 
477 uint *sortp(buffer *restrict buf, int start_perm,
478  const T *restrict A, uint n, unsigned stride)
479 {
480  uint *restrict perm;
482  size_t work_off=align_as(sort_data,n*sizeof(uint));
483  if(n<DIGIT_VALUES) {
484  buffer_reserve(buf,work_off+2*n*sizeof(sort_data));
485  perm = buf->ptr;
486  work = (sort_data*)((char*)buf->ptr+work_off);
487  if(n<2) {
488  if(n==1) *perm=0;
489  } else {
490  if(start_perm) merge_sortp (perm, A,n,stride, work);
491  else merge_sortp0(perm, A,n,stride, work);
492  }
493  } else if(STATIC_DIGIT_BUCKETS){
494  static uint count[DIGITS][DIGIT_VALUES];
495  buffer_reserve(buf,work_off+2*n*sizeof(sort_data));
496  perm = buf->ptr;
497  work = (sort_data*)((char*)buf->ptr+work_off);
498  radix_sortp(perm,start_perm, A,n,stride, work,count);
499  } else {
500  uint (*restrict count)[DIGIT_VALUES];
501  const size_t count_off=align_as(uint,work_off+2*n*sizeof(sort_data));
502  buffer_reserve(buf,count_off+sizeof(uint[DIGITS][DIGIT_VALUES]));
503  perm = buf->ptr;
504  work = (sort_data*)((char*)buf->ptr+work_off);
505  count = (uint(*)[DIGIT_VALUES])((char*)buf->ptr+count_off);
506  radix_sortp(perm,start_perm, A,n,stride, work,count);
507  }
508  return perm;
509 }
510 
511 #undef STATIC_DIGIT_BUCKETS
512 
513 #undef DIGIT_BITS
514 #undef DIGIT_VALUES
515 #undef DIGIT_MASK
516 #undef CEILDIV
517 #undef DIGITS
518 #undef VALUE_BITS
519 #undef COUNT_SIZE
520 
521 #undef INDEX_PTR
522 #undef INC_PTR
523 
524 #undef sortp
525 #undef sortv
526 
527 #undef merge_sortp
528 #undef merge_sortp0
529 #undef merge_sortv
530 #undef radix_sortp
531 #undef radix_passp_be
532 #undef radix_passp0_be
533 #undef radix_passp_e
534 #undef radix_passp_m
535 #undef radix_passp_b
536 #undef radix_passp0_b
537 #undef radix_sortv
538 #undef radix_passv
539 #undef radix_zeros
540 #undef radix_offsets
541 #undef radix_count
542 #undef sort_data
543 
#define uint
Definition: types.h:70
static double sum(struct xxt *data, double v, uint n, uint tag)
Definition: xxt.c:400
#define DIGITS
Definition: sort_imp.h:59
double T
Definition: gs_test.c:14
#define DIGIT_BITS
Definition: sort_imp.h:55
#define radix_zeros
Definition: sort_imp.h:8
#define radix_passv
Definition: sort_imp.h:9
#define radix_passp_b
Definition: sort_imp.h:12
n
Definition: xxt_test.m:73
#define DIGIT_MASK
Definition: sort_imp.h:57
#define STATIC_DIGIT_BUCKETS
Definition: sort_imp.h:53
#define radix_offsets
Definition: sort_imp.h:7
ulong A[NUM][SI]
Definition: sort_test.c:17
#define radix_sortv
Definition: sort_imp.h:10
#define heap_sortv
Definition: sort_imp.h:22
#define radix_sortp
Definition: sort_imp.h:17
#define merge_sortp
Definition: sort_imp.h:21
#define sortp
Definition: sort_imp.h:25
#define radix_passp_m
Definition: sort_imp.h:13
#define DIGIT_VALUES
Definition: sort_imp.h:56
#define radix_passp0_b
Definition: sort_imp.h:11
#define buffer_reserve(b, max)
Definition: mem.h:157
p
Definition: xxt_test2.m:1
#define INDEX_PTR(A, stride, i)
Definition: sort_imp.h:30
#define radix_passp0_be
Definition: sort_imp.h:15
Definition: mem.h:111
#define COUNT_DIGIT_64(n, i)
Definition: sort_imp.h:71
#define radix_passp_e
Definition: sort_imp.h:14
#define merge_copy_perm
Definition: sort_imp.h:19
#define sort_data
Definition: sort_imp.h:5
#define restrict
Definition: c99.h:11
#define sortv
Definition: sort_imp.h:24
#define VALUE_BITS
Definition: sort_imp.h:60
for i
Definition: xxt_test.m:74
#define merge_sortv
Definition: sort_imp.h:18
#define INC_PTR(A, stride)
Definition: sort_imp.h:29
#define radix_passp_be
Definition: sort_imp.h:16
#define COUNT_SIZE
Definition: sort_imp.h:61
#define align_as(T, n)
Definition: mem.h:165
uint i
Definition: sort_imp.h:27
#define merge_sortp0
Definition: sort_imp.h:20
ulong out[N]
Definition: sort_test2.c:20
#define radix_count
Definition: sort_imp.h:6
static double work[TNR *NS]
#define MERGE_SORT()
Definition: sort_imp.h:279
void fail(int status, const char *file, unsigned line, const char *fmt,...)
Definition: fail.c:47