43 #define P00_QSWAP_MEMCPY(P, A, B) \
45 void * p00Ma = (P)+(A); \
46 void * p00Mb = (P)+(B); \
48 memcpy(&p00_tmp, p00Ma, p00_s); \
49 memcpy(p00Ma, p00Mb, p00_s); \
50 memcpy(p00Mb, &p00_tmp, p00_s); \
54 #define P00_QSWAP_VCPY_(A, B) \
55 for (size_t p00Mi = 0; p00Mi < p00_vsize; ++p00Mi) \
56 (A)[p00Mi] = (B)[p00Mi]
59 #define P00_QSWAP_VCPY(P, A, B) \
61 P00_QSWAP_VCPY_(p00_tmp, (P)[A]); \
62 P00_QSWAP_VCPY_((P)[A], (P)[B]); \
63 P00_QSWAP_VCPY_((P)[B], p00_tmp); \
66 #define P00_QSWAP_ASSIGN(P, A, B) \
73 #define P00_QCOMP(A, B) p00_comp(&p00_B[A], &p00_B[B], p00_ctx)
75 #define P00_QPUSH(P, B, T) \
77 register p00_qsort *const p00Mp = ++(P); \
82 #define P00_QTOP(P, B, T) \
83 register size_t const B = (P)->bot; \
84 register size_t const T = (P)->top
86 #define P00_QEMPTY(S, P) ((S) == (P))
88 #define P00_QSORT_BODY(SWAP) \
89 if (p00_n > RSIZE_MAX || p00_s > RSIZE_MAX) return EDOM; \
90 if (p00_n && (!p00_base || !p00_comp)) return EINVAL; \
92 register p99_seed *const seed = p99_seed_get(); \
94 P99_CONSTANT(int, p00_tail, 20); \
96 p00_qsort p00_a[(p99_arith_log2(p00_n) + 1)*p00_tail]; \
97 p00_qsort* p00_p = p00_a; \
98 P00_QPUSH(p00_p, 0, p00_n); \
99 while(!P00_QEMPTY(p00_a, p00_p)) { \
101 P00_QTOP(p00_p, p00_bot, p00_top); \
102 register size_t const p00_len = p00_top - p00_bot; \
107 if (P00_QCOMP(p00_bot, p00_bot + 1) > 0) \
108 SWAP(p00_B, p00_bot, p00_bot + 1); \
116 size_t p00_c = p99_rand(seed) % p00_len; \
117 if (p00_c) SWAP(p00_B, p00_bot, p00_bot + p00_c); \
122 register size_t p00_b = p00_bot + 1; \
123 register size_t p00_t = p00_top; \
125 while (P99_LIKELY(p00_b < p00_t)) { \
127 while (!(P00_QCOMP(p00_bot, p00_b) < 0)) { \
129 if (P99_UNLIKELY(p00_b == p00_t)) goto P00_RECURSE; \
131 while (P00_QCOMP(p00_bot, p00_t - 1) < 0){ \
133 if (P99_UNLIKELY(p00_b == p00_t)) goto P00_RECURSE; \
138 SWAP(p00_B, p00_b, p00_t); \
142 if ((p00_b - p00_bot) > 1) { \
145 SWAP(p00_B, p00_bot, p00_b); \
147 register size_t const p00_bb = p00_b; \
148 for (register size_t p00_c = p00_bot; \
150 if (P00_QCOMP(p00_bb, p00_c) <= 0) { \
152 if (p00_c == p00_b) break; \
153 SWAP(p00_B, p00_c, p00_b); \
160 if (P99_UNLIKELY(p00_len >= p00_tail)) { \
161 size_t p00Mmax = p00_len*0.99; \
163 if (P99_UNLIKELY(((p00_b - p00_bot) >= p00Mmax) \
165 ((p00_top - p00_t) >= p00Mmax))) \
169 if ((p00_b - p00_bot) > 1) P00_QPUSH(p00_p, p00_bot, p00_b); \
170 if ((p00_top - p00_t) > 1) P00_QPUSH(p00_p, p00_t, p00_top); \
178 errno_t p00_qsort_generic16(
void *p00_base,
182 int (*p00_comp)(
const void *,
const void *,
void *),
185 size_t const p00_vsize = p00_s /
sizeof(uint16_t);
186 typedef uint16_t p00_el[p00_vsize];
187 register p00_el *
const p00_B = p00_base;
189 P00_QSORT_BODY(P00_QSWAP_VCPY);
194 errno_t p00_qsort_generic32(
void *p00_base,
198 int (*p00_comp)(
const void *,
const void *,
void *),
201 size_t const p00_vsize = p00_s /
sizeof(uint32_t);
202 typedef uint32_t p00_el[p00_vsize];
203 register p00_el *
const p00_B = p00_base;
205 P00_QSORT_BODY(P00_QSWAP_VCPY);
210 errno_t p00_qsort_generic64(
void *p00_base,
214 int (*p00_comp)(
const void *,
const void *,
void *),
217 size_t const p00_vsize = p00_s /
sizeof(uint64_t);
218 typedef uint64_t p00_el[p00_vsize];
219 register p00_el *
const p00_B = p00_base;
221 P00_QSORT_BODY(P00_QSWAP_VCPY);
227 errno_t p00_qsort_generic128(
void *p00_base,
231 int (*p00_comp)(
const void *,
const void *,
void *),
234 size_t const p00_vsize = p00_s /
sizeof(uint128_t);
235 typedef uint128_t p00_el[p00_vsize];
236 register p00_el *
const p00_B = p00_base;
238 P00_QSORT_BODY(P00_QSWAP_VCPY);
241 # ifdef P99X_UINT128_MAX
243 errno_t p00_qsort_generic128(
void *p00_base,
247 int (*p00_comp)(
const void *,
const void *,
void *),
252 register p00_el *
const p00_B = p00_base;
254 P00_QSORT_BODY(P00_QSWAP_VCPY);
261 errno_t p00_qsort_generic(
void *p00_base,
265 int (*p00_comp)(
const void *,
const void *,
void *),
268 typedef unsigned char p00_el[p00_s];
269 register p00_el *
const p00_B = p00_base;
271 P00_QSORT_BODY(P00_QSWAP_MEMCPY);
275 #define P00_QSORT_DECLARE(T) \
277 errno_t P99_PASTE2(p00_qsort_, T)(void *p00_base, \
281 int (*p00_comp)(const void *, const void *, void *), \
284 register T *const p00_B = p00_base; \
285 _Alignas(sizeof(max_align_t)) T p00_tmp; \
286 P00_QSORT_BODY(P00_QSWAP_ASSIGN); \
288 P99_MACRO_END(p00_qsort_, T)
290 P00_QSORT_DECLARE(_Bool);
291 P00_QSORT_DECLARE(
schar);
292 P00_QSORT_DECLARE(
uchar);
293 P00_QSORT_DECLARE(
char);
294 P00_QSORT_DECLARE(
short);
295 P00_QSORT_DECLARE(
ushort);
296 P00_QSORT_DECLARE(
signed);
297 P00_QSORT_DECLARE(
unsigned);
298 P00_QSORT_DECLARE(
long);
299 P00_QSORT_DECLARE(
ulong);
300 P00_QSORT_DECLARE(
llong);
301 P00_QSORT_DECLARE(
ullong);
302 P00_QSORT_DECLARE(
float);
303 P00_QSORT_DECLARE(
double);
305 #ifndef __STDC_NO_COMPLEX__
306 P00_QSORT_DECLARE(
cfloat);
313 P00_QSORT_DECLARE(
size_t);
315 P00_QSORT_DECLARE(intptr_t);
316 P00_QSORT_DECLARE(uintptr_t);
319 P00_QSORT_DECLARE(uint8_t);
320 P00_QSORT_DECLARE(int8_t);
323 P00_QSORT_DECLARE(uint16_t);
324 P00_QSORT_DECLARE(int16_t);
327 P00_QSORT_DECLARE(uint32_t);
328 P00_QSORT_DECLARE(int32_t);
331 P00_QSORT_DECLARE(uint64_t);
332 P00_QSORT_DECLARE(int64_t);
335 P00_QSORT_DECLARE(uint128_t);
336 P00_QSORT_DECLARE(int128_t);
338 # ifdef P99X_UINT128_MAX
345 errno_t p00_qsort_s(
void *p00_base,
349 int (*p00_comp)(
const void *,
const void *,
void *),
353 case sizeof(uint16_t):
354 return p00_qsort_generic16(p00_base, p00_n, p00_a, p00_s, p00_comp, p00_ctx);
357 case sizeof(uint32_t):
358 return p00_qsort_generic32(p00_base, p00_n, p00_a, p00_s, p00_comp, p00_ctx);
361 case sizeof(uint64_t):
362 return p00_qsort_generic64(p00_base, p00_n, p00_a, p00_s, p00_comp, p00_ctx);
365 case sizeof(uint128_t):
366 return p00_qsort_generic128(p00_base, p00_n, p00_a, p00_s, p00_comp, p00_ctx);
368 # ifdef P99X_UINT128_MAX
370 return p00_qsort_generic128(p00_base, p00_n, p00_a, p00_s, p00_comp, p00_ctx);
374 return p00_qsort_generic(p00_base, p00_n, p00_a, p00_s, p00_comp, p00_ctx);
378 # define P99_ALIGNOF(B) alignof(P99_TYPEOF(B))
380 # ifdef __STDC_NO_COMPLEX__
381 # define P99_ALIGNOF(B) \
382 P99_GENERIC(&((B)[0]), \
386 (float*, alignof(float)), \
387 (double*, alignof(double)), \
388 (double*, alignof(cdouble)), \
390 (_Bool*, alignof(_Bool)), \
391 (char*, alignof(char)), \
392 (uchar*, alignof(uchar)), \
393 (schar*, alignof(schar)), \
395 (ushort*, alignof(ushort)), \
396 (short*, alignof(short)), \
398 (unsigned*, alignof(unsigned)), \
399 (signed*, alignof(signed)), \
401 (long*, alignof(long)), \
402 (ulong*, alignof(ulong)), \
404 (llong*, alignof(llong)), \
405 (ullong*, alignof(ullong)) \
408 # define P99_ALIGNOF(B) \
409 P99_GENERIC(&((B)[0]), \
413 (float*, alignof(float)), \
414 (double*, alignof(double)), \
415 (ldouble*, alignof(ldouble)), \
417 (cfloat*, alignof(cfloat)), \
418 (cdouble*, alignof(cdouble)), \
419 (cldouble*, alignof(cldouble)), \
421 (_Bool*, alignof(_Bool)), \
422 (char*, alignof(char)), \
423 (uchar*, alignof(uchar)), \
424 (schar*, alignof(schar)), \
426 (ushort*, alignof(ushort)), \
427 (short*, alignof(short)), \
429 (unsigned*, alignof(unsigned)), \
430 (signed*, alignof(signed)), \
432 (long*, alignof(long)), \
433 (ulong*, alignof(ulong)), \
435 (llong*, alignof(llong)), \
436 (ullong*, alignof(ullong)) \
467 #ifdef __STDC_NO_COMPLEX__
468 #define qsort_s(B, N, S, CMP, CTX) \
469 P99_CONSTRAINT_TRIGGER( \
470 P99_GENERIC(&((B)[0]), \
472 (void_ptr*, p00_qsort_void_ptr), \
474 (float*, p00_qsort_float), \
475 (double*, p00_qsort_double), \
476 (double*, p00_qsort_cdouble), \
478 (_Bool*, p00_qsort__Bool), \
479 (char*, p00_qsort_char), \
480 (uchar*, p00_qsort_uchar), \
481 (schar*, p00_qsort_schar), \
483 (ushort*, p00_qsort_ushort), \
484 (short*, p00_qsort_short), \
486 (unsigned*, p00_qsort_unsigned), \
487 (signed*, p00_qsort_signed), \
489 (long*, p00_qsort_long), \
490 (ulong*, p00_qsort_ulong), \
492 (llong*, p00_qsort_llong), \
493 (ullong*, p00_qsort_ullong) \
494 )((B), (N), P99_ALIGNOF((B)[0]), (S), (CMP), (CTX)), \
495 "qsort_s runtime constraint violation")
497 #define qsort_s(B, N, S, CMP, CTX) \
498 P99_CONSTRAINT_TRIGGER( \
499 P99_GENERIC(&((B)[0]), \
501 (void_ptr*, p00_qsort_void_ptr), \
503 (float*, p00_qsort_float), \
504 (double*, p00_qsort_double), \
505 (ldouble*, p00_qsort_ldouble), \
507 (cfloat*, p00_qsort_cfloat), \
508 (cdouble*, p00_qsort_cdouble), \
509 (cldouble*, p00_qsort_cldouble), \
511 (_Bool*, p00_qsort__Bool), \
512 (char*, p00_qsort_char), \
513 (uchar*, p00_qsort_uchar), \
514 (schar*, p00_qsort_schar), \
516 (ushort*, p00_qsort_ushort), \
517 (short*, p00_qsort_short), \
519 (unsigned*, p00_qsort_unsigned), \
520 (signed*, p00_qsort_signed), \
522 (long*, p00_qsort_long), \
523 (ulong*, p00_qsort_ulong), \
525 (llong*, p00_qsort_llong), \
526 (ullong*, p00_qsort_ullong) \
527 )((B), (N), P99_ALIGNOF((B)[0]), (S), (CMP), (CTX)), \
528 "qsort_s runtime constraint violation")
544 int (*p00_comp)(
const void *,
const void *,
void *),
546 typedef unsigned char p00_el[p00_s];
547 p00_el *
const p00_B = p00_base;
548 for (
register rsize_t p00_r = 1; p00_r < p00_n; ++p00_r) {
549 if (p00_comp(&p00_B[p00_r - 1], &p00_B[p00_r], p00_ctx) > 0)
562 int (*p00_comp)(
const void *,
const void *,
void *),
564 return !(
p99_mismatch(p00_base, p00_n, p00_s, p00_comp, p00_ctx) < p00_n);