SURFEX v8.1
General documentation of Surfex
rsort64.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <limits.h>
4 #include <signal.h>
5 #include "intercept_alloc.h"
6 #include "raise.h"
7 
8 /* rsort64_() : 64-bit Fortran-callable RADIX-sort */
9 
10 /*
11  by Sami Saarinen, ECMWF, 22/02/2005 : Initial version derived from rsort32.c
12  - " - 23/02/2005 : Fixes and some optimizations
13  - " - 07/07/2005 : Mods in index_adj & bitsum
14  - " - 07/02/2007 : Intercepting alloc (IBM & NEC SX) + NEC SX vectorization
15 
16 
17  Thanks to Mike Fisher, ECMWF
18  and Cray SCILIB ORDERS()-function developers
19 */
20 
21 /*
22  Methods:
23 
24  2 : 64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
25  4 : Signed 64-bit ints
26  5 : Unsigned 64-bit ints
27 
28 */
29 
30 typedef unsigned int Uint32;
31 typedef unsigned long long int Uint64;
32 typedef unsigned char Uchar;
33 
34 #ifdef __uxppx__
35 #ifndef VPP
36 #define VPP
37 #endif
38 #endif
39 
40 #ifdef VPP
41 #pragma global noalias
42 #pragma global novrec
43 #elif defined(NECSX)
44 #pragma cdir options -pvctl,nodep
45 #endif
46 
47 #if defined(VPP) || defined(NECSX)
48 /* .. or any vector machine */
49 static int SpeedUp = 0;
50 #else
51 /* scalar prozezzorz */
52 static int SpeedUp = 1;
53 #endif
54 
55 #define SORT_R64 2
56 #define SORT_I64 4
57 #define SORT_U64 5
58 
59 typedef long long int ll_t;
60 
61 #define ALLOC(x,size) \
62  { ll_t bytes = (ll_t)sizeof(*x) * (size); \
63  bytes = (bytes < 1) ? 1 : bytes; \
64  x = THEmalloc(bytes); \
65  if (!x) { fprintf(stderr, \
66  "malloc() of %s (%lld bytes) failed in file=%s, line=%d\n", \
67  #x, bytes, __FILE__, __LINE__); RAISE(SIGABRT); } }
68 
69 #define FREE(x) if (x) { THEfree(x); x = NULL; }
70 
71 #define BITSUM(x) bitsum[x] += ((item >> x) & 1ull)
72 
73 #define SIGNBIT64 0x8000000000000000ull
74 #define MASKALL64 0xFFFFFFFFFFFFFFFFull
75 #define ZEROALL64 0x0000000000000000ull
76 
77 #define CVMGM(a,b,c) ( ((c) & SIGNBIT64) ? (a) : (b) )
78 
79 #define N64BITS 64
80 
81 void
82 rsort64_(const int *Mode, /* if < 10, then index[] needs to be initialized ; method = modulo 10 */
83  const int *N, /* no. of 64-bit elements */
84  const int *Inc, /* stride in terms of 64-bit elements */
85  const int *Start_addr, /* Fortran start address i.e. normally == 1 */
86  Uint64 Data[], /* 64-bit elements to be sorted */
87  int index[], /* sorting index */
88  const int *Index_adj, /* 0=index[] is a C-index, 1=index[] is a Fortran-index (the usual case) */
89  int *retc)
90 {
91  int mode = *Mode;
92  int method = mode%10;
93  int n = *N;
94  int rc = n;
95  int inc = *Inc;
96  int index_adj = *Index_adj;
97  int addr = (*Start_addr) - 1; /* Fortran to C */
98  int i, j, jj;
99  Uchar xorit = 0;
100  Uchar copytmp = 0;
101  Uchar alloc_data = 0;
102  Uint64 *data = NULL;
103  int *tmp = NULL;
104  Uint32 bitsum[N64BITS];
105 
106  if (method != SORT_R64 &&
107  method != SORT_I64 &&
108  method != SORT_U64 ) {
109  rc = -1;
110  goto finish;
111  }
112 
113  if (n <= 0) {
114  if (n < 0) rc = -2;
115  goto finish;
116  }
117 
118  if (inc < 1) {
119  rc = -3;
120  goto finish;
121  }
122 
123  if (mode < 10) {
124  /* index[] needs to be initialized */
125  for (i=0; i<n; i++) index[i] = i + index_adj; /* Fortran-index */
126  }
127 
128  j = addr;
129  data = &Data[j];
130 
131  alloc_data = ((inc > 1) || (method == SORT_R64));
132  if (alloc_data) ALLOC(data, n);
133 
134  if (method == SORT_R64) {
135  for (i=0; i<n; i++) {
136  Uint64 mask = CVMGM(MASKALL64, SIGNBIT64, Data[j]);
137  data[i] = Data[j] ^ mask;
138  j += inc;
139  }
140  }
141  else if (method == SORT_I64) {
142  if (inc == 1) { /* optimization */
143  for (i=0; i<n; i++) {
144  data[i] ^= SIGNBIT64;
145  }
146  }
147  else {
148  for (i=0; i<n; i++) {
149  data[i] = Data[j] ^ SIGNBIT64;
150  j += inc;
151  }
152  }
153  xorit = 1;
154  }
155  else if (inc > 1) {
156  for (i=0; i<n; i++) {
157  data[i] = Data[j];
158  j += inc;
159  }
160  }
161 
162  /* Check whether particular "bit-columns" are all zero or one */
163 
164  for (j=0; j<N64BITS; j++) bitsum[j] = 0;
165 
166  for (i=0; i<n; i++) {
167  Uint64 item = data[i];
168  /* Unrolled, full vector */
169  BITSUM(0) ; BITSUM(1) ; BITSUM(2) ; BITSUM(3) ;
170  BITSUM(4) ; BITSUM(5) ; BITSUM(6) ; BITSUM(7) ;
171  BITSUM(8) ; BITSUM(9) ; BITSUM(10); BITSUM(11);
172  BITSUM(12); BITSUM(13); BITSUM(14); BITSUM(15);
173  BITSUM(16); BITSUM(17); BITSUM(18); BITSUM(19);
174  BITSUM(20); BITSUM(21); BITSUM(22); BITSUM(23);
175  BITSUM(24); BITSUM(25); BITSUM(26); BITSUM(27);
176  BITSUM(28); BITSUM(29); BITSUM(30); BITSUM(31);
177  BITSUM(32); BITSUM(33); BITSUM(34); BITSUM(35);
178  BITSUM(36); BITSUM(37); BITSUM(38); BITSUM(39);
179  BITSUM(40); BITSUM(41); BITSUM(42); BITSUM(43);
180  BITSUM(44); BITSUM(45); BITSUM(46); BITSUM(47);
181  BITSUM(48); BITSUM(49); BITSUM(50); BITSUM(51);
182  BITSUM(52); BITSUM(53); BITSUM(54); BITSUM(55);
183  BITSUM(56); BITSUM(57); BITSUM(58); BITSUM(59);
184  BITSUM(60); BITSUM(61); BITSUM(62); BITSUM(63);
185  }
186 
187  ALLOC(tmp, n);
188 
189  jj = 0;
190  for (j=0; j<N64BITS; j++) {
191  int sum = bitsum[j];
192  if (sum > 0 && sum < n) { /* if 0 or n, then the whole column of bits#j 0's or 1's */
193  Uint64 mask = (1ull << j);
194  int *i1, *i2;
195 
196  if (jj%2 == 0) {
197  i1 = index;
198  i2 = tmp;
199  copytmp = 1;
200  }
201  else {
202  i1 = tmp;
203  i2 = index;
204  copytmp = 0;
205  }
206 
207  if (SpeedUp == 0) {
208  int k = 0;
209  for (i=0; i<n; i++) /* Gather zero bits */
210  if ( (data[i1[i]-index_adj] & mask) == 0 ) i2[k++] = i1[i];
211 
212  for (i=0; i<n; i++) /* Gather one bits */
213  if ( (data[i1[i]-index_adj] & mask) == mask ) i2[k++] = i1[i];
214  }
215  else
216  {
217  int k1 = 0, k2 = n-sum;
218  for (i=0; i<n; i++) { /* Gather zero & one bits in a single sweep */
219  Uint64 value = data[i1[i]-index_adj] & mask;
220  i2[value == 0 ? k1++ : k2++] = i1[i];
221  } /* for (i=0; i<n; i++) */
222  if (k1 + sum != n || k2 != n) {
223  fprintf(stderr,
224  "***Programming error in rsort64_(): k1 + sum != n || k2 != n; k1=%d,k2=%d,sum=%d,n=%d\n",
225  k1,k2,sum,n);
226  RAISE(SIGABRT);
227  }
228  }
229 
230  jj++;
231  } /* if (sum > 0 && sum < n) */
232  }
233 
234  if (copytmp) for (i=0; i<n; i++) index[i] = tmp[i];
235 
236  FREE(tmp);
237 
238  if (!alloc_data && xorit && inc == 1) {
239  /* 64-bit signed ints : backward */
240  for (i=0; i<n; i++) data[i] ^= SIGNBIT64;
241  }
242 
243  if (alloc_data) FREE(data);
244 
245  finish:
246 
247  *retc = rc;
248 }
ERROR in method
Definition: ecsort_shared.h:90
void rsort64_(const int *Mode, const int *N, const int *Inc, const int *Start_addr, Uint64 Data[], int index[], const int *Index_adj, int *retc)
Definition: rsort64.c:82
unsigned long long int Uint64
Definition: countingsort.c:41
unsigned char Uchar
Definition: rsort32.c:44
ERROR in n
Definition: ecsort_shared.h:90
unsigned int Uint32
Definition: rsort64.c:30
unsigned int Uint32
Definition: countingsort.c:43
intent(out) overrides sub arrays one Sort by the least significant key first sum(iindex(1:n))
unsigned char Uchar
Definition: rsort64.c:32
static int mask
Definition: ifssig.c:38
unsigned long long int Uint64
Definition: rsort64.c:31
long long int ll_t
Definition: rsort64.c:59
static int SpeedUp
Definition: rsort64.c:49
ERROR in index
Definition: ecsort_shared.h:90