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