1 #ifndef __NPY_SORT_COMMON_H__
2 #define __NPY_SORT_COMMON_H__
3
4 #include <stdlib.h>
5 #include <numpy/ndarraytypes.h>
6
7 /*
8 *****************************************************************************
9 ** SWAP MACROS **
10 *****************************************************************************
11 */
12
13 #define BOOL_SWAP(a,b) {npy_bool tmp = (b); (b)=(a); (a) = tmp;}
14 #define BYTE_SWAP(a,b) {npy_byte tmp = (b); (b)=(a); (a) = tmp;}
15 #define UBYTE_SWAP(a,b) {npy_ubyte tmp = (b); (b)=(a); (a) = tmp;}
16 #define SHORT_SWAP(a,b) {npy_short tmp = (b); (b)=(a); (a) = tmp;}
17 #define USHORT_SWAP(a,b) {npy_ushort tmp = (b); (b)=(a); (a) = tmp;}
18 #define INT_SWAP(a,b) {npy_int tmp = (b); (b)=(a); (a) = tmp;}
19 #define UINT_SWAP(a,b) {npy_uint tmp = (b); (b)=(a); (a) = tmp;}
20 #define LONG_SWAP(a,b) {npy_long tmp = (b); (b)=(a); (a) = tmp;}
21 #define ULONG_SWAP(a,b) {npy_ulong tmp = (b); (b)=(a); (a) = tmp;}
22 #define LONGLONG_SWAP(a,b) {npy_longlong tmp = (b); (b)=(a); (a) = tmp;}
23 #define ULONGLONG_SWAP(a,b) {npy_ulonglong tmp = (b); (b)=(a); (a) = tmp;}
24 #define HALF_SWAP(a,b) {npy_half tmp = (b); (b)=(a); (a) = tmp;}
25 #define FLOAT_SWAP(a,b) {npy_float tmp = (b); (b)=(a); (a) = tmp;}
26 #define DOUBLE_SWAP(a,b) {npy_double tmp = (b); (b)=(a); (a) = tmp;}
27 #define LONGDOUBLE_SWAP(a,b) {npy_longdouble tmp = (b); (b)=(a); (a) = tmp;}
28 #define CFLOAT_SWAP(a,b) {npy_cfloat tmp = (b); (b)=(a); (a) = tmp;}
29 #define CDOUBLE_SWAP(a,b) {npy_cdouble tmp = (b); (b)=(a); (a) = tmp;}
30 #define CLONGDOUBLE_SWAP(a,b) {npy_clongdouble tmp = (b); (b)=(a); (a) = tmp;}
31 #define DATETIME_SWAP(a,b) {npy_datetime tmp = (b); (b)=(a); (a) = tmp;}
32 #define TIMEDELTA_SWAP(a,b) {npy_timedelta tmp = (b); (b)=(a); (a) = tmp;}
33
34 /* Need this for the argsort functions */
35 #define INTP_SWAP(a,b) {npy_intp tmp = (b); (b)=(a); (a) = tmp;}
36
37 /*
38 *****************************************************************************
39 ** COMPARISON FUNCTIONS **
40 *****************************************************************************
41 */
42
43 NPY_INLINE static int
BOOL_LT(npy_bool a,npy_bool b)44 BOOL_LT(npy_bool a, npy_bool b)
45 {
46 return a < b;
47 }
48
49
50 NPY_INLINE static int
BYTE_LT(npy_byte a,npy_byte b)51 BYTE_LT(npy_byte a, npy_byte b)
52 {
53 return a < b;
54 }
55
56
57 NPY_INLINE static int
UBYTE_LT(npy_ubyte a,npy_ubyte b)58 UBYTE_LT(npy_ubyte a, npy_ubyte b)
59 {
60 return a < b;
61 }
62
63
64 NPY_INLINE static int
SHORT_LT(npy_short a,npy_short b)65 SHORT_LT(npy_short a, npy_short b)
66 {
67 return a < b;
68 }
69
70
71 NPY_INLINE static int
USHORT_LT(npy_ushort a,npy_ushort b)72 USHORT_LT(npy_ushort a, npy_ushort b)
73 {
74 return a < b;
75 }
76
77
78 NPY_INLINE static int
INT_LT(npy_int a,npy_int b)79 INT_LT(npy_int a, npy_int b)
80 {
81 return a < b;
82 }
83
84
85 NPY_INLINE static int
UINT_LT(npy_uint a,npy_uint b)86 UINT_LT(npy_uint a, npy_uint b)
87 {
88 return a < b;
89 }
90
91
92 NPY_INLINE static int
LONG_LT(npy_long a,npy_long b)93 LONG_LT(npy_long a, npy_long b)
94 {
95 return a < b;
96 }
97
98
99 NPY_INLINE static int
ULONG_LT(npy_ulong a,npy_ulong b)100 ULONG_LT(npy_ulong a, npy_ulong b)
101 {
102 return a < b;
103 }
104
105
106 NPY_INLINE static int
LONGLONG_LT(npy_longlong a,npy_longlong b)107 LONGLONG_LT(npy_longlong a, npy_longlong b)
108 {
109 return a < b;
110 }
111
112
113 NPY_INLINE static int
ULONGLONG_LT(npy_ulonglong a,npy_ulonglong b)114 ULONGLONG_LT(npy_ulonglong a, npy_ulonglong b)
115 {
116 return a < b;
117 }
118
119
120 NPY_INLINE static int
FLOAT_LT(npy_float a,npy_float b)121 FLOAT_LT(npy_float a, npy_float b)
122 {
123 return a < b || (b != b && a == a);
124 }
125
126
127 NPY_INLINE static int
DOUBLE_LT(npy_double a,npy_double b)128 DOUBLE_LT(npy_double a, npy_double b)
129 {
130 return a < b || (b != b && a == a);
131 }
132
133
134 NPY_INLINE static int
LONGDOUBLE_LT(npy_longdouble a,npy_longdouble b)135 LONGDOUBLE_LT(npy_longdouble a, npy_longdouble b)
136 {
137 return a < b || (b != b && a == a);
138 }
139
140
141 NPY_INLINE static int
npy_half_isnan(npy_half h)142 npy_half_isnan(npy_half h)
143 {
144 return ((h&0x7c00u) == 0x7c00u) && ((h&0x03ffu) != 0x0000u);
145 }
146
147
148 NPY_INLINE static int
npy_half_lt_nonan(npy_half h1,npy_half h2)149 npy_half_lt_nonan(npy_half h1, npy_half h2)
150 {
151 if (h1&0x8000u) {
152 if (h2&0x8000u) {
153 return (h1&0x7fffu) > (h2&0x7fffu);
154 }
155 else {
156 /* Signed zeros are equal, have to check for it */
157 return (h1 != 0x8000u) || (h2 != 0x0000u);
158 }
159 }
160 else {
161 if (h2&0x8000u) {
162 return 0;
163 }
164 else {
165 return (h1&0x7fffu) < (h2&0x7fffu);
166 }
167 }
168 }
169
170
171 NPY_INLINE static int
HALF_LT(npy_half a,npy_half b)172 HALF_LT(npy_half a, npy_half b)
173 {
174 int ret;
175
176 if (npy_half_isnan(b)) {
177 ret = !npy_half_isnan(a);
178 }
179 else {
180 ret = !npy_half_isnan(a) && npy_half_lt_nonan(a, b);
181 }
182
183 return ret;
184 }
185
186 /*
187 * For inline functions SUN recommends not using a return in the then part
188 * of an if statement. It's a SUN compiler thing, so assign the return value
189 * to a variable instead.
190 */
191 NPY_INLINE static int
CFLOAT_LT(npy_cfloat a,npy_cfloat b)192 CFLOAT_LT(npy_cfloat a, npy_cfloat b)
193 {
194 int ret;
195
196 if (a.real < b.real) {
197 ret = a.imag == a.imag || b.imag != b.imag;
198 }
199 else if (a.real > b.real) {
200 ret = b.imag != b.imag && a.imag == a.imag;
201 }
202 else if (a.real == b.real || (a.real != a.real && b.real != b.real)) {
203 ret = a.imag < b.imag || (b.imag != b.imag && a.imag == a.imag);
204 }
205 else {
206 ret = b.real != b.real;
207 }
208
209 return ret;
210 }
211
212
213 NPY_INLINE static int
CDOUBLE_LT(npy_cdouble a,npy_cdouble b)214 CDOUBLE_LT(npy_cdouble a, npy_cdouble b)
215 {
216 int ret;
217
218 if (a.real < b.real) {
219 ret = a.imag == a.imag || b.imag != b.imag;
220 }
221 else if (a.real > b.real) {
222 ret = b.imag != b.imag && a.imag == a.imag;
223 }
224 else if (a.real == b.real || (a.real != a.real && b.real != b.real)) {
225 ret = a.imag < b.imag || (b.imag != b.imag && a.imag == a.imag);
226 }
227 else {
228 ret = b.real != b.real;
229 }
230
231 return ret;
232 }
233
234
235 NPY_INLINE static int
CLONGDOUBLE_LT(npy_clongdouble a,npy_clongdouble b)236 CLONGDOUBLE_LT(npy_clongdouble a, npy_clongdouble b)
237 {
238 int ret;
239
240 if (a.real < b.real) {
241 ret = a.imag == a.imag || b.imag != b.imag;
242 }
243 else if (a.real > b.real) {
244 ret = b.imag != b.imag && a.imag == a.imag;
245 }
246 else if (a.real == b.real || (a.real != a.real && b.real != b.real)) {
247 ret = a.imag < b.imag || (b.imag != b.imag && a.imag == a.imag);
248 }
249 else {
250 ret = b.real != b.real;
251 }
252
253 return ret;
254 }
255
256
257 NPY_INLINE static void
STRING_COPY(char * s1,char * s2,size_t len)258 STRING_COPY(char *s1, char *s2, size_t len)
259 {
260 memcpy(s1, s2, len);
261 }
262
263
264 NPY_INLINE static void
STRING_SWAP(char * s1,char * s2,size_t len)265 STRING_SWAP(char *s1, char *s2, size_t len)
266 {
267 while(len--) {
268 const char t = *s1;
269 *s1++ = *s2;
270 *s2++ = t;
271 }
272 }
273
274
275 NPY_INLINE static int
STRING_LT(const char * s1,const char * s2,size_t len)276 STRING_LT(const char *s1, const char *s2, size_t len)
277 {
278 const unsigned char *c1 = (const unsigned char *)s1;
279 const unsigned char *c2 = (const unsigned char *)s2;
280 size_t i;
281 int ret = 0;
282
283 for (i = 0; i < len; ++i) {
284 if (c1[i] != c2[i]) {
285 ret = c1[i] < c2[i];
286 break;
287 }
288 }
289 return ret;
290 }
291
292
293 NPY_INLINE static void
UNICODE_COPY(npy_ucs4 * s1,npy_ucs4 * s2,size_t len)294 UNICODE_COPY(npy_ucs4 *s1, npy_ucs4 *s2, size_t len)
295 {
296 while(len--) {
297 *s1++ = *s2++;
298 }
299 }
300
301
302 NPY_INLINE static void
UNICODE_SWAP(npy_ucs4 * s1,npy_ucs4 * s2,size_t len)303 UNICODE_SWAP(npy_ucs4 *s1, npy_ucs4 *s2, size_t len)
304 {
305 while(len--) {
306 const npy_ucs4 t = *s1;
307 *s1++ = *s2;
308 *s2++ = t;
309 }
310 }
311
312
313 NPY_INLINE static int
UNICODE_LT(const npy_ucs4 * s1,const npy_ucs4 * s2,size_t len)314 UNICODE_LT(const npy_ucs4 *s1, const npy_ucs4 *s2, size_t len)
315 {
316 size_t i;
317 int ret = 0;
318
319 for (i = 0; i < len; ++i) {
320 if (s1[i] != s2[i]) {
321 ret = s1[i] < s2[i];
322 break;
323 }
324 }
325 return ret;
326 }
327
328
329 NPY_INLINE static int
DATETIME_LT(npy_datetime a,npy_datetime b)330 DATETIME_LT(npy_datetime a, npy_datetime b)
331 {
332 if (a == NPY_DATETIME_NAT) {
333 return 0;
334 }
335
336 if (b == NPY_DATETIME_NAT) {
337 return 1;
338 }
339
340 return a < b;
341 }
342
343
344 NPY_INLINE static int
TIMEDELTA_LT(npy_timedelta a,npy_timedelta b)345 TIMEDELTA_LT(npy_timedelta a, npy_timedelta b)
346 {
347 if (a == NPY_DATETIME_NAT) {
348 return 0;
349 }
350
351 if (b == NPY_DATETIME_NAT) {
352 return 1;
353 }
354
355 return a < b;
356 }
357
358
359 NPY_INLINE static void
GENERIC_COPY(char * a,char * b,size_t len)360 GENERIC_COPY(char *a, char *b, size_t len)
361 {
362 memcpy(a, b, len);
363 }
364
365
366 NPY_INLINE static void
GENERIC_SWAP(char * a,char * b,size_t len)367 GENERIC_SWAP(char *a, char *b, size_t len)
368 {
369 while(len--) {
370 const char t = *a;
371 *a++ = *b;
372 *b++ = t;
373 }
374 }
375
376 #endif
377