13 #if !defined(AARRAY_define)
22 #if defined(__cplusplus)
38 $define pragmaWarnings(NAME)
40 #if defined(__cplusplus)
41 #define AARRAY_nowarn_start \
42 _Pragma("NAME diagnostic push") \
43 _Pragma("NAME diagnostic ignored \"-Wconversion\"") \
44 _Pragma("NAME diagnostic ignored \"-Wconversion-null\"") \
45 _Pragma("NAME diagnostic ignored \"-Woverflow\"") \
46 _Pragma("NAME diagnostic ignored \"-Wnarrowing\"")
48 #define AARRAY_nowarn_start \
49 _Pragma("NAME diagnostic push") \
50 _Pragma("NAME diagnostic ignored \"-Wconversion\"") \
51 _Pragma("NAME diagnostic ignored \"-Wint-conversion\"") \
52 _Pragma("NAME diagnostic ignored \"-Wpointer-to-int-cast\"") \
53 _Pragma("NAME diagnostic ignored \"-Wbad-function-cast\"")
55 #define AARRAY_nowarn_end _Pragma("NAME diagnostic pop")
61 #define AARRAY_nowarn_pedantic_cpp_start
62 #define AARRAY_nowarn_pedantic_cpp_end
63 #if defined(__clang__)
65 #if defined(__cplusplus)
66 #undef AARRAY_nowarn_pedantic_cpp_start
67 #define AARRAY_nowarn_pedantic_cpp_start_helper \
68 _Pragma("clang diagnostic push") \
69 _Pragma("clang diagnostic ignored \"-Wc99-extensions\"") \
70 _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \
71 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
72 _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
73 #if __clang_major__ < 5
74 #define AARRAY_nowarn_pedantic_cpp_start \
75 AARRAY_nowarn_pedantic_cpp_start_helper
77 #define AARRAY_nowarn_pedantic_cpp_start \
78 AARRAY_nowarn_pedantic_cpp_start_helper \
79 _Pragma("clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"")
81 #undef AARRAY_nowarn_pedantic_cpp_end
82 #define AARRAY_nowarn_pedantic_cpp_end _Pragma("clang diagnostic pop")
84 #elif defined(__GNUC__)
86 #if defined(__cplusplus)
87 #undef AARRAY_nowarn_pedantic_cpp_start
88 #undef AARRAY_nowarn_pedantic_cpp_end
89 #define AARRAY_nowarn_pedantic_cpp_start \
90 _Pragma("GCC diagnostic push") \
91 _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
92 #define AARRAY_nowarn_pedantic_cpp_end _Pragma("GCC diagnostic pop")
94 #elif defined(_MSC_VER)
95 #define AARRAY_nowarn_start \
96 __pragma(warning(push)) \
97 __pragma(warning(disable:4047))
98 #define AARRAY_nowarn_end __pragma(warning(pop))
101 #define AARRAY_nowarn_start
102 #define AARRAY_nowarn_end
105 #if defined(__cplusplus)
106 AARRAY_nowarn_pedantic_cpp_start
107 #define AARRAY_move std::move
116 #if defined(AARRAY_c)
117 #define AARRAY_define(name, ...) name __VA_ARGS__
118 #elif defined(AARRAY_h)
119 #define AARRAY_define(name, ...) extern name;
121 #define AARRAY_define(name, ...) static inline name __VA_ARGS__
125 #if !defined(__has_feature)
126 #define __has_feature(x) 0
128 #if !defined(__has_extension)
130 #define __has_extension __has_feature
133 #if defined(__builtin_prefetch)
134 #define AARRAY_prefetch(A, B, C) __builtin_prefetch(A, B, C)
136 #define AARRAY_prefetch(A, B, C)
140 #if defined(AARRAY_UNSAFE)
141 #define AARRAY_safety(UNSAFE, ...) UNSAFE
143 #define AARRAY_safety(UNSAFE, ...) __VA_ARGS__
147 #if defined(AARRAY_WARN) || (defined(__GNUC__) && !defined(__clang__))
149 #define AARRAY_nowarn_internal_start
150 #define AARRAY_nowarn_internal_end
152 #define AARRAY_nowarn_internal_start AARRAY_nowarn_start
153 #define AARRAY_nowarn_internal_end AARRAY_nowarn_end
157 #if !defined(AARRAY_sortCache)
158 #define AARRAY_sortCache 512
165 AARRAY_define(__attribute((noreturn))
166 void AARRAY_aError(
char errLocation[],
char errMsg[]), {
167 fflush(stdout); fprintf(stderr,
"%s: %s\n", errLocation, errMsg); abort(); })
169 #
if defined(AARRAY_c)
170 void (*aError)(
char[],
char[]) = &AARRAY_aError;
171 #elif defined(AARRAY_h)
172 extern void (*aError)(
char[],
char[]);
174 static void (*aError)(
char[],
char[]) = &AARRAY_aError;
178 #define AARRAY_STRINGIFY(x) #x
179 #define AARRAY_TOSTRING(x) AARRAY_STRINGIFY(x)
180 #define AARRAY_LINE (char*)__FILE__ ":" AARRAY_TOSTRING(__LINE__)
183 #define AARRAY_aError_MsgLen 52 + 3*20 + 1
184 #define AARRAY_aError_CALL(MSG) { aError(errLoc, MSG); abort(); }
185 #define AARRAY_Error_OutOfMemory(SIZE) \
186 { char AARRAY_aError_Msg[AARRAY_aError_MsgLen]; \
187 if(0>snprintf(AARRAY_aError_Msg, AARRAY_aError_MsgLen, \
188 "out of memory (allocating=%zu)", \
190 AARRAY_aError_CALL((char*)"out of memory " \
191 "(can I interest you in a banana instead? 🍌)") \
192 else AARRAY_aError_CALL(AARRAY_aError_Msg) }
193 #define AARRAY_Error_OutOfBounds(LENGTH, POS) \
194 { char AARRAY_aError_Msg[AARRAY_aError_MsgLen]; \
195 if(0>snprintf(AARRAY_aError_Msg, AARRAY_aError_MsgLen, \
196 "out of bounds (length=%zu but pos=%zu)", \
198 AARRAY_aError_CALL((char*)"out of bounds (no info)") \
199 else AARRAY_aError_CALL(AARRAY_aError_Msg) }
200 #define AARRAY_Error_RemovalIsOutOfBounds(LENGTH, POS, RLEN) \
201 { char AARRAY_aError_Msg[AARRAY_aError_MsgLen]; \
202 if(0>snprintf(AARRAY_aError_Msg, AARRAY_aError_MsgLen, \
203 "removal is out of bounds (length=%zu but pos=%zu removal=%zu)", \
204 LENGTH, POS, RLEN)) \
205 AARRAY_aError_CALL((char*)"removal is out of bounds (no info)") \
206 else AARRAY_aError_CALL(AARRAY_aError_Msg) }
207 #define AARRAY_Error_OutOfCapacity(CAPACITY, REQ) \
208 { char AARRAY_aError_Msg[AARRAY_aError_MsgLen]; \
209 if(0>snprintf(AARRAY_aError_Msg, AARRAY_aError_MsgLen, \
210 "out of capacity (size=%zu but require=%zu)", CAPACITY, REQ)) \
211 AARRAY_aError_CALL((char*)"array is STATIC (no info)") \
212 else AARRAY_aError_CALL(AARRAY_aError_Msg) }
213 #define AARRAY_Error_ArrayIsNull(ARRAY_NO) \
214 { char AARRAY_aError_Msg[AARRAY_aError_MsgLen]; \
215 if(0>snprintf(AARRAY_aError_Msg, AARRAY_aError_MsgLen, \
216 "array is NULL (array no=%zu)", ARRAY_NO)) \
217 AARRAY_aError_CALL((char*)"array is NULL (no info)") \
218 else AARRAY_aError_CALL(AARRAY_aError_Msg) }
219 #define AARRAY_Error_ArrayIsWide \
220 (aError(AARRAY_LINE, (char*)"array type too wide (max 8 bytes)"), 0)
221 #define AARRAY_Error_WrongArgCount(ARG_NUM, MULTIPLE, ADDITION) \
222 { char AARRAY_aError_Msg[AARRAY_aError_MsgLen]; \
223 if(0>snprintf(AARRAY_aError_Msg, AARRAY_aError_MsgLen, \
224 "wrong arg count (args=%zu but should be %i + multiple of %i)", \
225 ARG_NUM, ADDITION, MULTIPLE)) \
226 AARRAY_aError_CALL((char*)"wrong arg count (no info)") \
227 else AARRAY_aError_CALL(AARRAY_aError_Msg) }
228 #define AARRAY_Error_InfiniteLoop \
229 AARRAY_aError_CALL((char*)"infinite loop (jump=0)")
230 #define AARRAY_Error_FormatStringArgs \
231 AARRAY_aError_CALL((char*)"format requires more arguments")
232 #define AARRAY_Error_FormatStringMalformed \
233 AARRAY_aError_CALL((char*)"format is malformed")
234 #define AARRAY_Error_NullParameter \
235 AARRAY_aError_CALL((char*)"parameter is NULL")
241 AARRAY_define(
size_t AARRAY_upper_power_of_two(
size_t v), {
245 v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8;
246 v |= v >> 16;
if(
sizeof(
size_t)==8) v |= v >> 32; v++;
return v; })
248 #
if defined(__GNUC__)
249 #define AARRAY_builtin_ll(name,with) \
250 (sizeof(with)<=sizeof(int)?__builtin_##name(with) : \
251 (sizeof(with)<=sizeof(long)?__builtin_##name##l(with) : \
252 __builtin_##name##ll(with)))
253 AARRAY_define(
int AARRAY_clz(
size_t value), {
254 if(!value)
return sizeof(value)*8;
255 return AARRAY_builtin_ll(clz,value); })
256 #elif defined(_MSC_VER)
259 #pragma intrinsic(_BitScanReverse,_BitScanReverse64)
260 AARRAY_define(
int AARRAY_clz(
size_t value), {
261 unsigned long result;
262 return (
int)(
sizeof(
size_t) <= 4?
263 (_BitScanReverse(&result, (
unsigned long)value)? 31-result : 32) :
264 _BitScanReverse64(&result, value)? 63-result : 64); })
266 #pragma intrinsic(_BitScanReverse)
267 AARRAY_define(
int AARRAY_clz(
size_t value), {
268 unsigned long result;
269 return (
int)(_BitScanReverse(&result, value)? 31-result : 32); })
273 AARRAY_define(
int AARRAY_clz(
size_t x), {
275 if(
sizeof(
size_t)==8 &&
276 x <= 0x00000000FFFFFFFF) { n += 32; x <<= 32; }
277 if(x <= 0x0000FFFFFFFFFFFF) { n += 16; x <<= 16; }
278 if(x <= 0x00FFFFFFFFFFFFFF) { n += 8; x <<= 8; }
279 if(x <= 0x0FFFFFFFFFFFFFFF) { n += 4; x <<= 4; }
280 if(x <= 0x3FFFFFFFFFFFFFFF) { n += 2; x <<= 2; }
281 if(x <= 0x7FFFFFFFFFFFFFFF) { n += 1; x <<= 1; }
288 #define AARRAY_FIX_POINTERS(TYPE) \
289 if(!*vec) *length = 0; \
290 else
if(vecsIncr) { \
293 size_t m = vecsIncr==5? 2: vecsIncr-1; \
294 while(m < vecsCount) { \
295 if(vecs[m] >= (uintptr_t)(*vec) && \
296 vecs[m] < (uintptr_t)(*vec)+(*length)*
sizeof(TYPE)) \
298 (uintptr_t)length-(uintptr_t)(*(
size_t**)vec-1); \
302 #define AARRAY_ALLOC_NOCAPACITY(TYPE) \
303 size_t curSize = (*length) * sizeof(TYPE) + sizeof(size_t); \
304 size_t newSize = ((*length) + (ilen-rlen)) * sizeof(TYPE) + sizeof(size_t); \
305 if((!*vec || AARRAY_clz(newSize-1) < AARRAY_clz(curSize-1))) { \
306 length = (size_t*)realloc(!*vec? NULL : length, \
307 AARRAY_upper_power_of_two(newSize)); \
308 AARRAY_safety(, if(!length) AARRAY_Error_OutOfMemory(newSize)); \
309 AARRAY_FIX_POINTERS(TYPE) } \
310 *vec = (TYPE*)(length+1);
313 #define AARRAY_ALLOC_STATIC(TYPE) \
314 (void)vecsIncr; (void)vecsCount; (void)vecs; \
315 size_t curSize = *vec? *(*(size_t**)vec-2) : 0; \
316 size_t newSize = ((*length) + (ilen-rlen)) * sizeof(TYPE) + sizeof(size_t) * 2; \
317 if(!*vec) AARRAY_Error_OutOfCapacity((size_t)0, newSize); \
318 AARRAY_safety((void)curSize;, \
319 if(newSize>curSize) \
320 AARRAY_Error_OutOfCapacity(curSize, newSize))
328 #define AARRAY_ALLOC_STD(TYPE) \
329 size_t curSize = *vec? *(*(size_t**)vec-2) : 0; \
330 size_t newSize = ((*length) + (ilen-rlen)) * sizeof(TYPE) + sizeof(size_t) * 2; \
331 if((!*vec || newSize > curSize)) { \
332 newSize += newSize >> 1; \
333 length = (size_t*)realloc(!*vec? NULL : length-1, newSize); \
334 AARRAY_safety(, if(!length) AARRAY_Error_OutOfMemory(newSize)); \
337 AARRAY_FIX_POINTERS(TYPE) } \
338 *vec = (TYPE*)(length+1);
341 #define AARRAY_Expand(TYPE, GROWTH) \
345 size_t lengthHolder = 0, *length = &lengthHolder; \
346 if(*vec) length = *(size_t**)vec-1; \
347 AARRAY_safety((void)errLoc;, \
348 if(pos > *length) AARRAY_Error_OutOfBounds(*length, pos) \
349 if(rlen > (*length) - pos) \
350 AARRAY_Error_RemovalIsOutOfBounds(*length, pos, rlen)) \
351 if(rlen > ilen && (*length)-(pos+rlen)) \
353 memmove(&((*vec)[pos+ilen]), &((*vec)[pos+rlen]), \
354 sizeof(TYPE) * ((*length) - (pos+rlen))); \
356 AARRAY_ALLOC_##GROWTH(TYPE) \
357 if(rlen < ilen && (*length)-(pos+rlen)) { \
359 memmove(&((*vec)[pos+ilen]), &((*vec)[pos+rlen]), \
360 sizeof(TYPE) * ((*length) - (pos+rlen))); }
366 $define AARRAY_Replace(TYPE, GROWTH,)
367 AARRAY_define(TYPE*AARRAY_Replace_$
##GROWTH$##_$##TYPE(char errLoc[],
368 TYPE*vec[],
size_t pos,
size_t rlen,
size_t ilen, TYPE items[]), {
370 if(vec) { AARRAY_prefetch((
size_t*)*vec-1, 1, 1); }
373 size_t vecsCount = 1;
size_t vecsIncr = 0;
374 uintptr_t*vecs = (uintptr_t*)(
void*)items;
375 TYPE*vecHolder = NULL;
if(!vec) vec = &vecHolder;
376 AARRAY_Expand(TYPE, GROWTH);
378 if(ilen) memcpy(&((*vec)[pos]), vecs,
sizeof(TYPE) * ilen);
379 *((*(
size_t**)vec)-1) += ilen-rlen; }
387 $define GENERATE_GENERICS(GENERATOR, GROWTH, FTYPE)
388 GENERATOR(uint8_t, GROWTH, FTYPE)
389 GENERATOR(uint16_t, GROWTH, FTYPE)
390 GENERATOR(uint32_t, GROWTH, FTYPE)
391 GENERATOR(uint64_t, GROWTH, FTYPE)
392 static void(*
const GENERATOR$##_$##GROWTH$##_FUNCTIONS[9])(void) = {
394 (void(*)(void))&GENERATOR$##_$##GROWTH$##_uint8_t,
395 (void(*)(void))&GENERATOR$##_$##GROWTH$##_uint16_t, 0,
396 (void(*)(void))&GENERATOR$##_$##GROWTH$##_uint32_t, 0, 0, 0,
397 (void(*)(void))&GENERATOR$##_$##GROWTH$##_uint64_t };
399 $define GENERATE_GENERICS_GROWTH(FNAME)
400 GENERATE_GENERICS(AARRAY_$##FNAME,NOCAPACITY)
401 GENERATE_GENERICS(AARRAY_$##FNAME,STATIC)
402 GENERATE_GENERICS(AARRAY_$##FNAME,STD)
404 GENERATE_GENERICS_GROWTH(Replace)
406 $define AARRAY_Append(TYPE, GROWTH,)
407 AARRAY_define(TYPE*AARRAY_Append_$
##GROWTH$##_$##TYPE(char errLoc[],
408 TYPE*vec[],
size_t ilen, TYPE items[]), {
409 size_t pos = vec && *vec?
411 *(*(
size_t**)vec-1) : 0;
412 return AARRAY_Replace_$##GROWTH$##_$##TYPE(
413 errLoc, vec, pos, 0, ilen, items); })
415 GENERATE_GENERICS_GROWTH(Append)
417 $define AARRAY_Concat(TYPE, GROWTH,)
418 AARRAY_define(TYPE*AARRAY_Concat_$
##GROWTH$##_$##TYPE(char errLoc[],
419 TYPE*vec[],
size_t vecsCount, TYPE*vecs_[]), {
420 if(vec) { AARRAY_prefetch((
size_t*)*vec-1, 1, 1); }
421 uintptr_t*vecs = (uintptr_t*)vecs_;
422 size_t rlen = 0;
size_t ilen = 0;
423 size_t n = (size_t)-1;
424 while(++n < vecsCount)
if(vecs[n])
425 ilen += *((
size_t*)vecs[n]-1);
428 TYPE*vecHolder = NULL;
if(!vec) vec = &vecHolder;
429 size_t pos = *vec? *(*(
size_t**)vec-1) : 0;
430 AARRAY_Expand(TYPE, GROWTH);
432 size_t vLen = *(*(
size_t**)vec-1);
433 n = (size_t)-1;
while(++n < vecsCount) {
434 if(!vecs[n])
continue;
435 size_t ns = (size_t)-1, vsnLen;
436 vsnLen = *((
size_t*)vecs[n]-1);
437 while(++ns < vsnLen) (*vec)[vLen+ns] = vecs_[n][ns];
439 *(*(
size_t**)vec-1) += ilen; }
442 GENERATE_GENERICS_GROWTH(Concat)
444 $define AARRAY_GenericArray(TYPE, GROWTH,)
445 AARRAY_define(TYPE*AARRAY_GenericArray_$
##GROWTH$##_$##TYPE(char errLoc[],
446 TYPE*vec[],
size_t pos,
size_t rlen,
size_t vecsCount, uintptr_t vecs[]), {
447 size_t n = 0;
size_t alen, ilen = 0;
449 while(n < vecsCount) {
451 AARRAY_safety(,
if(alen && vecs[n+1]==(uintptr_t)NULL)
452 AARRAY_Error_ArrayIsNull((n+2)/2));
453 if(alen==SIZE_MAX) {
while(((TYPE*)vecs[n+1])[++alen]) { }
455 ilen += alen; n+=vecsIncr; }
457 TYPE*vecHolder = NULL;
if(!vec) vec = &vecHolder;
458 AARRAY_Expand(TYPE, GROWTH);
460 n = 0;
while(n < vecsCount) {
463 memcpy(&((*vec)[pos]), (
void*)vecs[n+1],
sizeof(TYPE)*alen);
464 pos += alen; } n+=vecsIncr; }
465 *(*(
size_t**)vec-1) += ilen-rlen; }
468 GENERATE_GENERICS_GROWTH(GenericArray)
470 $define AARRAY_ReplaceArray(TYPE, GROWTH,)
471 AARRAY_define(TYPE*AARRAY_ReplaceArray_$
##GROWTH$##_$##TYPE(char errLoc[],
472 TYPE*vec[],
size_t pos,
size_t rlen,
size_t vecsCount, uintptr_t vecs[]), {
473 if(vec) { AARRAY_prefetch((
size_t*)*vec-1, 1, 1); }
474 AARRAY_safety(,
if((vecsCount+3) % 2 != 1)
475 AARRAY_Error_WrongArgCount(vecsCount+3, 2, 3));
476 return AARRAY_GenericArray_$##GROWTH$##_$##TYPE(
477 errLoc, vec, pos, rlen, vecsCount, vecs); })
479 GENERATE_GENERICS_GROWTH(ReplaceArray)
481 $define AARRAY_AppendArray(TYPE, GROWTH,)
482 AARRAY_define(TYPE*AARRAY_AppendArray_$
##GROWTH$##_$##TYPE(char errLoc[],
483 TYPE*vec[],
size_t vecsCount, uintptr_t vecs[]), {
484 if(vec) { AARRAY_prefetch((
size_t*)*vec-1, 1, 1); }
485 AARRAY_safety(,
if((vecsCount+1) % 2 != 1)
486 AARRAY_Error_WrongArgCount(vecsCount+1, 2, 1));
487 size_t pos = vec && *vec? *(*(
size_t**)vec-1) : 0;
488 return AARRAY_GenericArray_$##GROWTH$##_$##TYPE(
489 errLoc, vec, pos, 0, vecsCount, vecs); })
491 GENERATE_GENERICS_GROWTH(AppendArray)
493 $define AARRAY_Multi(TYPE, GROWTH,)
494 AARRAY_define(TYPE*AARRAY_Multi_$
##GROWTH$##_$##TYPE(char errLoc[],
495 TYPE*vec[],
size_t pos,
size_t rlen,
size_t vecsCount, uintptr_t vecs[]), {
496 if(vec) { AARRAY_prefetch((
size_t*)*vec-1, 1, 1); }
497 size_t lengthHolder = 0, *length = &lengthHolder;
498 if(vec && *vec) length = *(
size_t**)vec-1;
499 size_t n = 0, alen, ilen = 0, atimes, newlen = *length, maxlen = newlen;
500 size_t saved_pos = pos, saved_rlen = rlen;
502 AARRAY_safety(,
if((vecsCount+3) % 5 != 1)
503 AARRAY_Error_WrongArgCount(vecsCount+3, 5, 1));
504 while(n < vecsCount) {
505 atimes = vecs[n]; alen = vecs[n+1];
506 AARRAY_safety(,
if(atimes && alen && !vecs[n+2])
507 AARRAY_Error_ArrayIsNull(n/5+1));
508 if(alen==SIZE_MAX) {
while(((TYPE*)vecs[n+2])[++alen]) { }
511 if(n) { pos = vecs[n-2]; rlen = vecs[n-1]; }
512 if(pos > newlen) AARRAY_Error_OutOfBounds(*length, pos)
513 if(rlen > newlen - pos) AARRAY_Error_RemovalIsOutOfBounds(newlen, pos, rlen)
514 ilen = atimes? atimes * alen : alen;
515 newlen += ilen - rlen;
516 if(newlen > maxlen) maxlen = newlen;
518 ilen = maxlen - *length; rlen = 0;
520 TYPE*vecHolder = NULL;
if(!vec) vec = &vecHolder;
521 AARRAY_ALLOC_$##GROWTH(TYPE)
523 n = 0; pos = saved_pos; rlen = saved_rlen;
525 atimes = vecs[n]; alen = vecs[n+1];
526 if(n) { pos = vecs[n-2]; rlen = vecs[n-1]; }
527 ilen = atimes? atimes * alen : alen;
529 memmove(&((*vec)[pos+ilen]), &((*vec)[pos+rlen]),
530 sizeof(TYPE) * ((*length) - (pos+rlen)));
531 *length += ilen-rlen; }
533 else while(atimes--) {
534 memcpy(&((*vec)[pos]), (
void*)vecs[n+2],
sizeof(TYPE) * alen);
537 }
while(n < vecsCount); }
540 GENERATE_GENERICS_GROWTH(Multi)
542 $define AARRAY_Mem(TYPE, GROWTH,)
543 AARRAY_define(TYPE*AARRAY_Mem_$
##GROWTH$##_$##TYPE(
544 char errLoc[],
size_t vec[]), {
546 if(!vec)
return NULL;
547 if($exec [ GROWTH = NOCAPACITY ] && echo
'1) {' || echo
'0) {'
548 return (TYPE*)(vec-1); }
549 return (TYPE*)(vec-2); })
551 GENERATE_GENERICS_GROWTH(Mem)
553 $define AARRAY_Array(TYPE, GROWTH,)
554 AARRAY_define(TYPE*AARRAY_Array_$
##GROWTH$##_$##TYPE(
555 char errLoc[],
size_t vec[],
size_t sizebytes,
int maximize), {
556 AARRAY_safety((
void)errLoc;,
if(!vec) AARRAY_Error_ArrayIsNull((
size_t)0));
557 if($exec [ GROWTH = NOCAPACITY ] && echo
'1) {' || echo
'0) {'
558 AARRAY_safety(,
if(sizebytes <
sizeof(
size_t) ) AARRAY_Error_OutOfCapacity(sizebytes,
sizeof(
size_t) ))
560 size_t len = ((
size_t)1)<<(63-AARRAY_clz((sizebytes-
sizeof(
size_t))/
sizeof(TYPE)));
561 if(maximize || len < *vec) *vec = len;
562 return (TYPE*)(vec+1); }
564 AARRAY_safety(,
if(sizebytes <
sizeof(
size_t)*2) AARRAY_Error_OutOfCapacity(sizebytes,
sizeof(
size_t)*2))
565 size_t len = (sizebytes -
sizeof(size_t)*2) /
sizeof(TYPE);
566 if(maximize || len < *(vec+1)) *(vec+1) = len;
568 return (TYPE*)(vec+2); } })
570 GENERATE_GENERICS_GROWTH(Array)
576 $define AARRAY_Args(sizeofType, ...) AARRAY_nowarn_internal_start \
577 (sizeofType==1? sizeof((uint8_t []){(uint8_t)(uintptr_t)__VA_ARGS__}) : \
578 sizeofType==2?
sizeof((uint16_t[]){(uint16_t)(uintptr_t)__VA_ARGS__}) : \
579 sizeofType<=4?
sizeof((uint32_t[]){(uint32_t)(uintptr_t)__VA_ARGS__}) : \
580 sizeof((uint64_t[]){(uint64_t)(uintptr_t)__VA_ARGS__})) / sizeofType, \
581 (sizeofType==1? (
void*)AARRAY_move((uint8_t []){(uint8_t)(uintptr_t)__VA_ARGS__}) : \
582 sizeofType==2? (
void*)AARRAY_move((uint16_t[]){(uint16_t)(uintptr_t)__VA_ARGS__}) : \
583 sizeofType<=4? (
void*)AARRAY_move((uint32_t[]){(uint32_t)(uintptr_t)__VA_ARGS__}) : \
584 (
void*)AARRAY_move((uint64_t[]){(uint64_t)(uintptr_t)__VA_ARGS__})) \
585 AARRAY_nowarn_internal_end
588 $define AARRAY_64bitArgs(...) AARRAY_nowarn_internal_start \
589 sizeof((uint64_t[]){(uint64_t)__VA_ARGS__}) /
sizeof(uint64_t), \
590 (uint64_t*)AARRAY_move((uint64_t[]){(uint64_t)(uintptr_t)__VA_ARGS__}) \
591 AARRAY_nowarn_internal_end
594 $define AARRAY_PtrArgs_WARN(...) \
595 sizeof((
void*[]){(
void*)__VA_ARGS__}) /
sizeof(
void*), \
596 (uintptr_t*)AARRAY_move((
void*[]){(
void*)__VA_ARGS__})
601 $define AARRAY_PtrArgs(...) AARRAY_nowarn_internal_start \
602 sizeof((uintptr_t[]){(uintptr_t)__VA_ARGS__}) /
sizeof(uintptr_t), \
603 (uintptr_t*)AARRAY_move((uintptr_t[]){(uintptr_t)__VA_ARGS__}) \
604 AARRAY_nowarn_internal_end
607 #define AARRAY_ArgsTail(A, ...) __VA_ARGS__
609 #if defined(AARRAY_NOTYPEOF) \
610 || (defined(_MSC_VER) && !__has_feature(cxx_decltype))
612 #define AARRAY_typeof(TYPE, EXPR) EXPR
613 #elif __has_feature(cxx_decltype)
615 #define AARRAY_typeof(TYPE, EXPR) (__decltype(TYPE+0))(EXPR)
617 #define AARRAY_typeof(TYPE, EXPR) \
618 AARRAY_nowarn_internal_start (__typeof(TYPE))(EXPR) AARRAY_nowarn_internal_end
621 $define TEST_width(type)
sizeof(type) > 8 ? AARRAY_Error_ArrayIsWide :
sizeof(type)
624 $define GENERATE_api(NAME, GROWTH)
625 #define aAppend$##NAME(vec, ...) \
626 (AARRAY_typeof(*vec, (void*(*)(char[], void**, size_t, void*)) \
627 AARRAY_Append_$##GROWTH$##_FUNCTIONS[TEST_width(**vec)]) \
628 (AARRAY_LINE, (void**)vec, AARRAY_Args(sizeof(**vec), __VA_ARGS__)))
629 #define aReplace$##NAME(vec, pos, rlen, ...) \
630 (AARRAY_typeof(*vec, (void*(*)( \
631 char[], void**, size_t, size_t, size_t, void*)) \
632 AARRAY_Replace_$##GROWTH$##_FUNCTIONS[TEST_width(**vec)]) \
633 (AARRAY_LINE, (void**)vec, pos, rlen, \
634 AARRAY_Args(sizeof(**vec), __VA_ARGS__)))
635 #define aDelete$##NAME(vec, pos, rlen) \
636 (AARRAY_typeof(*vec, (void*(*)( \
637 char[], void**, size_t, size_t, size_t, void*)) \
638 AARRAY_Replace_$##GROWTH$##_FUNCTIONS[TEST_width(**vec)]) \
639 (AARRAY_LINE, (void**)vec, pos, rlen, 0, NULL))
640 #define aConcat$##NAME(vec, ...) \
641 (AARRAY_typeof(*vec, (void*(*)(char[], void**, size_t, uintptr_t*)) \
642 AARRAY_Concat_$##GROWTH$##_FUNCTIONS[TEST_width(**vec)]) \
643 (AARRAY_LINE, (void**)vec, AARRAY_PtrArgs_WARN(__VA_ARGS__)))
644 #define aAppendArray$##NAME(vec, ...) \
645 (AARRAY_typeof(*vec, (void*(*)(char[], void**, size_t, uintptr_t*)) \
646 AARRAY_AppendArray_$##GROWTH$##_FUNCTIONS[TEST_width(**vec)]) \
647 (AARRAY_LINE, (void**)vec, AARRAY_PtrArgs(__VA_ARGS__)))
648 #define aReplaceArray$##NAME(vec, pos, rlen, ...) \
649 (AARRAY_typeof(*vec, (void*(*)( \
650 char[], void**, size_t, size_t, size_t, uintptr_t*)) \
651 AARRAY_ReplaceArray_$##GROWTH$##_FUNCTIONS[TEST_width(**vec)]) \
652 (AARRAY_LINE, (void**)vec, pos, rlen, AARRAY_PtrArgs(__VA_ARGS__)))
653 #define aMulti$##NAME(vec, pos, rlen, arrTimes, ...) \
654 (AARRAY_typeof(*vec, (void*(*)( \
655 char[], void**, size_t, size_t, size_t, uintptr_t*)) \
656 AARRAY_Multi_$##GROWTH$##_FUNCTIONS[TEST_width(**vec)]) \
657 (AARRAY_LINE, (void**)vec, pos, rlen, \
658 AARRAY_PtrArgs(arrTimes, __VA_ARGS__)))
659 #define aMem$##NAME(vec) \
660 (AARRAY_typeof(vec, (void*(*)(char[], void*)) \
661 AARRAY_Mem_$##GROWTH$##_FUNCTIONS[TEST_width(*vec)]) \
662 (AARRAY_LINE, (void*)vec))
663 #define aArray$##NAME(vec, size, maximize) \
664 (AARRAY_typeof(vec, (void*(*)(char[], void*, size_t, int)) \
665 AARRAY_Array_$##GROWTH$##_FUNCTIONS[TEST_width(*vec)]) \
666 (AARRAY_LINE, (void*)vec, size, maximize))
668 GENERATE_api(_NOCAPACITY, NOCAPACITY)
669 GENERATE_api(_STATIC, STATIC)
673 $define safe_void(stars, data)
674 0?(
void$##stars)(uintptr_t)
sizeof( \
678 AARRAY_define(
void AARRAY_Free(
void*vec[]), {
679 if(*vec) { free((
size_t*)*vec-2); *vec = NULL; } })
680 AARRAY_define(
void AARRAY_Free_STATIC(
void*vec[]), {
682 AARRAY_define(
void AARRAY_Free_NOCAPACITY(
void*vec[]), {
683 if(*vec) { free((
size_t*)*vec-1); *vec = NULL; } })
685 AARRAY_Free(safe_void(**,vec))
686 #define aFree_STATIC(vec) \
687 AARRAY_Free_STATIC(safe_void(**,vec))
688 #define aFree_NOCAPACITY(vec) \
689 AARRAY_Free_NOCAPACITY(safe_void(**,vec))
695 AARRAY_define(
size_t AARRAY_aCapacity(
void*vec), {
696 return !vec? 0 : *((
size_t*)vec-2) -
sizeof(size_t)*2; })
697 AARRAY_define(
size_t AARRAY_aCapacity_STATIC(
void*vec), {
698 return AARRAY_aCapacity(vec); })
699 AARRAY_define(
size_t AARRAY_aCapacity_NOCAPACITY(
void*vec), {
700 return !vec? 0 : ((size_t)1) << (64-AARRAY_clz((*((
size_t*)vec-1))-1)); })
701 #define aCapacity(vec) (AARRAY_aCapacity(safe_void(*,vec))/
sizeof(*vec))
702 #define aCapacity_STATIC(vec) (AARRAY_aCapacity_STATIC(safe_void(*,vec))/
sizeof(*vec))
703 #define aCapacity_NOCAPACITY(vec) AARRAY_aCapacity_NOCAPACITY(safe_void(*,vec))
705 AARRAY_define(
size_t AARRAY_aLength(
void*vec), {
706 return !vec? 0 : *((
size_t*)vec-1); })
707 #define aLength(vec) AARRAY_aLength(safe_void(*,vec))
709 $define AARRAY_Length2(TYPE, ...)
710 AARRAY_define(TYPE AARRAY_Length2__$
##TYPE(
711 char errLoc[], TYPE vec[],
size_t pos), {
712 if(!vec) AARRAY_safety(
return 0; (void)errLoc;,
713 {
if(pos==0)
return 0;
else AARRAY_Error_OutOfBounds(aLength(vec), pos); })
714 size_t*length = (
size_t*)(
void*)vec-1;
715 AARRAY_safety(,
if(pos > *length)
716 AARRAY_Error_OutOfBounds(aLength(vec), pos));
721 return vec[pos-1]; })
723 GENERATE_GENERICS(AARRAY_Length2)
724 #define aLength2(vec, len) \
725 AARRAY_typeof(*vec, (uint64_t(*)(char[], void*, size_t)) \
726 AARRAY_Length2__FUNCTIONS[TEST_width(*vec)]) \
727 (AARRAY_LINE, (void*)vec, len)
729 $define AARRAY_ZLength2(TYPE, ...)
730 AARRAY_define(TYPE AARRAY_ZLength2__$
##TYPE(
731 char errLoc[], TYPE vec[],
size_t pos), {
732 return AARRAY_Length2__$##TYPE(errLoc, vec, aLength(vec) - pos); })
734 GENERATE_GENERICS(AARRAY_ZLength2)
735 #define aZLength2(vec, len) \
736 (AARRAY_typeof(*vec, (uint64_t(*)(char[], void*, size_t)) \
737 AARRAY_ZLength2__FUNCTIONS[TEST_width(*vec)]) \
738 (AARRAY_LINE, (void*)vec, len))
740 $define AARRAY_AtPtr(TYPE, ...)
741 AARRAY_define(TYPE*AARRAY_AtPtr__$
##TYPE(
742 char errLoc[], TYPE vec[],
size_t pos), {
743 AARRAY_safety((
void)errLoc;,
744 if(pos >= aLength(vec)) AARRAY_Error_OutOfBounds(aLength(vec), pos));
745 return &(vec[pos]); })
747 GENERATE_GENERICS(AARRAY_AtPtr)
748 #define aAtPtr(vec, pos) \
749 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, size_t)) \
750 AARRAY_AtPtr__FUNCTIONS[TEST_width(*vec)]) \
751 (AARRAY_LINE, (void*)vec, pos))
753 $define AARRAY_ZAtPtr(TYPE, ...)
754 AARRAY_define(TYPE*AARRAY_ZAtPtr__$
##TYPE(
755 char errLoc[], TYPE vec[],
size_t pos), {
756 return AARRAY_AtPtr__$##TYPE(errLoc, vec, aLength(vec) - (pos+1)); })
758 GENERATE_GENERICS(AARRAY_ZAtPtr)
759 #define aZAtPtr(vec, pos) \
760 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, size_t)) \
761 AARRAY_ZAtPtr__FUNCTIONS[TEST_width(*vec)]) \
762 (AARRAY_LINE, (void*)vec, pos))
764 $define AARRAY_At(TYPE, ...)
765 AARRAY_define(TYPE AARRAY_At__$
##TYPE(
766 char errLoc[], TYPE vec[],
size_t pos), {
767 AARRAY_safety((
void)errLoc;,
768 if(pos >= aLength(vec)) AARRAY_Error_OutOfBounds(aLength(vec), pos));
771 GENERATE_GENERICS(AARRAY_At)
772 #define aAt(vec, pos) \
773 (AARRAY_typeof(*vec, (uint64_t(*)(char[], void*, size_t)) \
774 AARRAY_At__FUNCTIONS[TEST_width(*vec)]) \
775 (AARRAY_LINE, (void*)vec, pos))
777 $define AARRAY_ZAt(TYPE, ...)
778 AARRAY_define(TYPE AARRAY_ZAt__$
##TYPE(
779 char errLoc[], TYPE vec[],
size_t pos), {
780 return AARRAY_At__$##TYPE(errLoc, vec, aLength(vec) - (pos+1)); })
782 GENERATE_GENERICS(AARRAY_ZAt)
783 #define aZAt(vec, pos) \
784 (AARRAY_typeof(*vec, (uint64_t(*)(char[], void*, size_t)) \
785 AARRAY_ZAt__FUNCTIONS[TEST_width(*vec)]) \
786 (AARRAY_LINE, (void*)vec, pos))
788 $define AARRAY_At2(TYPE, ...)
789 AARRAY_define(TYPE AARRAY_At2__$
##TYPE(
790 char errLoc[], TYPE vec[],
size_t pos, TYPE item), {
791 AARRAY_safety((
void)errLoc;,
792 if(pos >= aLength(vec)) AARRAY_Error_OutOfBounds(aLength(vec), pos));
796 GENERATE_GENERICS(AARRAY_At2)
797 #define aAt2(vec, pos, item) \
798 (AARRAY_typeof(*vec, (uint64_t(*)(char[], void*, size_t, uint64_t)) \
799 AARRAY_At2__FUNCTIONS[TEST_width(*vec)]) \
800 (AARRAY_LINE, (void*)vec, pos, \
801 AARRAY_nowarn_internal_start (uint64_t)item AARRAY_nowarn_internal_end))
803 $define AARRAY_ZAt2(TYPE, ...)
804 AARRAY_define(TYPE AARRAY_ZAt2__$
##TYPE(
805 char errLoc[], TYPE vec[],
size_t pos, TYPE item), {
806 return AARRAY_At2__$##TYPE(errLoc, vec, aLength(vec) - (pos+1), item); })
808 GENERATE_GENERICS(AARRAY_ZAt2)
809 #define aZAt2(vec, pos, item) \
810 (AARRAY_typeof(*vec, (uint64_t(*)(char[], void*, size_t, uint64_t)) \
811 AARRAY_ZAt2__FUNCTIONS[TEST_width(*vec)]) \
812 (AARRAY_LINE, (void*)vec, pos, \
813 AARRAY_nowarn_internal_start item AARRAY_nowarn_internal_end))
815 $define AARRAY_Cmp(TYPE, ...)
816 AARRAY_define(
int AARRAY_Cmp__$
##TYPE(
817 TYPE vec[],
size_t n, TYPE*vecs[]), {
819 if(vec == vecs[n])
continue;
820 if(aLength(vec) != aLength(vecs[n]))
return 0;
821 if(aLength(vec)==0)
continue;
825 size_t m = SIZE_MAX;
while(++m < aLength(vec))
if(vec[m]!=vecs[n][m])
return 0; }
828 GENERATE_GENERICS(AARRAY_Cmp)
829 #define aCmp(vec, ...) \
830 (((int(*)(void*, size_t, void*)) \
831 AARRAY_Cmp__FUNCTIONS[TEST_width(*vec)]) \
832 ((void*)vec, AARRAY_PtrArgs_WARN(__VA_ARGS__)))
834 $define AARRAY_IndexOf(TYPE, ...)
835 AARRAY_define(
size_t AARRAY_IndexOf__$
##TYPE(TYPE vec[], TYPE item), {
836 size_t length = aLength(vec), i = (size_t)-1;
837 while(++i < length)
if(vec[i]==item)
return i;
838 return (
size_t)-1; })
840 GENERATE_GENERICS(AARRAY_IndexOf,)
841 #define aIndexOf(vec, item) \
842 ((size_t(*)(void*, uint64_t)) \
843 AARRAY_IndexOf__FUNCTIONS[TEST_width(*vec)])(vec, \
844 AARRAY_nowarn_internal_start item AARRAY_nowarn_internal_end)
846 $define AARRAY_ZIndexOf(TYPE, ...)
847 AARRAY_define(
size_t AARRAY_ZIndexOf__$
##TYPE(TYPE vec[], TYPE item), {
848 size_t i = aLength(vec);
849 while(i--)
if(vec[i]==item)
return i;
850 return (
size_t)-1; })
852 GENERATE_GENERICS(AARRAY_ZIndexOf,)
853 #define aZIndexOf(vec, item) \
854 ((size_t(*)(void*, uint64_t)) \
855 AARRAY_ZIndexOf__FUNCTIONS[TEST_width(*vec)])(vec, \
856 AARRAY_nowarn_internal_start item AARRAY_nowarn_internal_end)
861 $define AARRAY_Map(TYPE, FNAME, FTYPE)
862 AARRAY_define(
void AARRAY_Map_$##FNAME$##_$##TYPE(
863 char errLoc[], TYPE vec[], FTYPE(TYPE)), {
864 AARRAY_safety((
void)errLoc,
if(!f) AARRAY_Error_NullParameter);
865 size_t n = (size_t)-1;
867 while(++n < aLength(vec)) f(&(vec[n]) $exec
case 'FTYPE()' in *
'data') echo
', data';; esac; echo
'); })'
869 $define AARRAY_Loop(TYPE, FNAME, FTYPE)
870 AARRAY_define(
int AARRAY_Loop_$##FNAME$##_$##TYPE(
871 char errLoc[], TYPE vec[],
size_t pos, FTYPE), {
872 AARRAY_safety((
void)errLoc,
if(!f) AARRAY_Error_NullParameter);
874 while(pos < aLength(vec)) {
875 if((offset > 0 && pos < (
size_t)offset) ||
876 (offset < 0 && pos > (
size_t)offset))
return offset;
877 offset = f(pos $exec
case 'FTYPE' in *
'data') echo
', data';; esac; echo
');'
878 if(!offset)
return 0;
880 if(offset > 0) pos += (size_t) offset;
881 else pos -= (size_t)-offset; }
884 $define AARRAY_Filter(TYPE, FNAME, FTYPE)
885 AARRAY_define(TYPE* AARRAY_Filter_$##FNAME$##_$##TYPE(
886 char errLoc[], TYPE vec[], FTYPE(TYPE)), {
887 AARRAY_safety((
void)errLoc,
if(!f) AARRAY_Error_NullParameter);
888 size_t n = (size_t)-1, nn = (
size_t)-1;
889 while(++n < aLength(vec)) {
890 if(f(vec[n] $exec
case 'FTYPE()' in *
'data') echo
', data';; esac; echo
'))'
891 vec[++nn] = vec[n]; }
892 (void)aLength2(vec, nn+1);
895 $define FUNC_void_ptrT__D(TYPE) void(*f)(TYPE*,
void*),
void*data
897 $define FUNC_void_ptrT(TYPE) void(*f)(TYPE*)
899 GENERATE_GENERICS(AARRAY_Map, FUNC_3, FUNC_void_ptrT__D)
900 GENERATE_GENERICS(AARRAY_Map, FUNC_2, FUNC_void_ptrT)
901 #define AARRAY_aMap_FUNC_3(vec, f, data) \
902 ((void(*)(char[], void*, void(*)(void), void*)) \
903 AARRAY_Map_FUNC_3_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, (void(*)(void))f, data)
904 #define AARRAY_aMap_FUNC_2(vec, f) \
905 ((void(*)(char[], void*, void(*)(void))) \
906 AARRAY_Map_FUNC_2_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, (void(*)(void))f)
907 $define FUNC_int_size__D int(*f)(size_t,
void*),
void*data
909 GENERATE_GENERICS(AARRAY_Loop, FUNC_4, FUNC_int_size__D)
910 GENERATE_GENERICS(AARRAY_Loop, FUNC_3,
int(*f)(
size_t))
911 #define AARRAY_aLoop_FUNC_4(vec, pos, f, data) \
912 ((int(*)(char[], void*, size_t, int(*)(size_t, void*), void*)) \
913 AARRAY_Loop_FUNC_4_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, pos, f, data)
914 #define AARRAY_aLoop_FUNC_3(vec, pos, f) \
915 ((int(*)(char[], void*, size_t, int(*)(size_t))) \
916 AARRAY_Loop_FUNC_3_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, pos, f)
917 $define FUNC_int_T__D(TYPE) int(*f)(TYPE,
void*),
void*data
919 $define FUNC_int_T(TYPE) int(*f)(TYPE)
921 GENERATE_GENERICS(AARRAY_Filter, FUNC_3, FUNC_int_T__D)
922 GENERATE_GENERICS(AARRAY_Filter, FUNC_2, FUNC_int_T)
923 #define AARRAY_aFilter_FUNC_3(vec, f, data) \
924 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, void(*)(void), void*)) \
925 AARRAY_Filter_FUNC_3_FUNCTIONS[TEST_width(*vec)]) \
926 (AARRAY_LINE, vec,(void(*)(void))f, data))
927 #define AARRAY_aFilter_FUNC_2(vec, f) \
928 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, void(*)(void))) \
929 AARRAY_Filter_FUNC_2_FUNCTIONS[TEST_width(*vec)]) \
930 (AARRAY_LINE, vec,(void(*)(void))f))
932 #if __has_extension(blocks)
933 $define BLOCK_void_ptrT__D(TYPE) void(^f)(TYPE*,
void*),
void*data
935 $define BLOCK_void_ptrT(TYPE) void(^f)(TYPE*)
937 GENERATE_GENERICS(AARRAY_Map, BLOCK_3, BLOCK_void_ptrT__D)
938 GENERATE_GENERICS(AARRAY_Map, BLOCK_2, BLOCK_void_ptrT)
939 #define AARRAY_aMap_BLOCK_3(vec, f, data) \
940 ((void(*)(char[], void*, void(^)(void*, void*), void*)) \
941 AARRAY_Map_BLOCK_3_FUNCTIONS[TEST_width(*vec)]) \
942 (AARRAY_LINE, vec, (void(^)(void*, void*))f, data)
943 #define AARRAY_aMap_BLOCK_2(vec, f) \
944 ((void(*)(char[], void*, void(^)(void*))) \
945 AARRAY_Map_BLOCK_2_FUNCTIONS[TEST_width(*vec)]) \
946 (AARRAY_LINE, vec, (void(^)(void*))f)
947 $define BLOCK_int_size__D int(^f)(size_t,
void*),
void*data
949 GENERATE_GENERICS(AARRAY_Loop, BLOCK_4, BLOCK_int_size__D)
950 GENERATE_GENERICS(AARRAY_Loop, BLOCK_3,
int (^f)(
size_t))
951 #define AARRAY_aLoop_BLOCK_4(vec, pos, f, data) \
952 ((int(*)(char[], void*, size_t, int(^)(size_t, void*), void*)) \
953 AARRAY_Loop_BLOCK_4_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, pos, f, data)
954 #define AARRAY_aLoop_BLOCK_3(vec, pos, f) \
955 ((int(*)(char[], void*, size_t, int(^)(size_t))) \
956 AARRAY_Loop_BLOCK_3_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, pos, f)
957 $define BLOCK_int_T__D(TYPE) int(^f)(TYPE,
void*),
void*data
959 $define BLOCK_int_T(TYPE) int(^f)(TYPE)
961 GENERATE_GENERICS(AARRAY_Filter, BLOCK_3, BLOCK_int_T__D)
962 GENERATE_GENERICS(AARRAY_Filter, BLOCK_2, BLOCK_int_T)
963 #define AARRAY_aFilter_BLOCK_3(vec, f, data) \
964 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, int(^)(uint64_t, void*), void*)) \
965 AARRAY_Filter_BLOCK_3_FUNCTIONS[TEST_width(*vec)]) \
966 (AARRAY_LINE, vec,(int(^)(uint64_t, void*))f, data))
967 #define AARRAY_aFilter_BLOCK_2(vec, f) \
968 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, int(^)(uint64_t))) \
969 AARRAY_Filter_BLOCK_2_FUNCTIONS[TEST_width(*vec)]) \
970 (AARRAY_LINE, vec,(int(^)(uint64_t))f))
973 #if defined(__cplusplus)
974 $define LAMBDA_void_ptrT__D(TYPE) std::function<void(TYPE*,
void*)> f,
void*data
976 $define LAMBDA_void_ptrT(TYPE) std::function<void(TYPE*)> f
978 GENERATE_GENERICS(AARRAY_Map, LAMBDA_3, LAMBDA_void_ptrT__D)
979 GENERATE_GENERICS(AARRAY_Map, LAMBDA_2, LAMBDA_void_ptrT)
980 #define AARRAY_aMap_LAMBDA_3(vec, f, data) \
981 ((void(*)(char[], void*, std::function<void(void*, void*)>, void*)) \
982 AARRAY_Map_LAMBDA_3_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, f, data)
983 #define AARRAY_aMap_LAMBDA_2(vec, f) \
984 ((void(*)(char[], void*, std::function<void(void*)>)) \
985 AARRAY_Map_LAMBDA_2_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, f)
986 $define LAMBDA_int_size__D std::function<int(
size_t,
void*)> f,
void*data
988 GENERATE_GENERICS(AARRAY_Loop, LAMBDA_4, LAMBDA_int_size__D)
989 GENERATE_GENERICS(AARRAY_Loop, LAMBDA_3, std::function<
int(
size_t)> f)
990 #define AARRAY_aLoop_LAMBDA_4(vec, pos, f, data) \
991 ((int(*)(char[], void*, size_t, std::function<int(size_t, void*)>, void*)) \
992 AARRAY_Loop_LAMBDA_4_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, pos, f, data)
993 #define AARRAY_aLoop_LAMBDA_3(vec, pos, f) \
994 ((int(*)(char[], void*, size_t, std::function<int(size_t)>)) \
995 AARRAY_Loop_LAMBDA_3_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, pos, f)
996 $define LAMBDA_int_T__D(TYPE) std::function<int(TYPE,
void*)> f,
void*data
998 $define LAMBDA_int_T(TYPE) std::function<int(TYPE)> f
1000 GENERATE_GENERICS(AARRAY_Filter, LAMBDA_3, LAMBDA_int_T__D)
1001 GENERATE_GENERICS(AARRAY_Filter, LAMBDA_2, LAMBDA_int_T)
1002 #define AARRAY_aFilter_LAMBDA_3(vec, f, data) \
1003 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, std::function<int(uint64_t, void*)>, void*))\
1004 AARRAY_Filter_LAMBDA_3_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, f, data))
1005 #define AARRAY_aFilter_LAMBDA_2(vec, f) \
1006 (AARRAY_typeof(vec, (uint64_t*(*)(char[], void*, std::function<int(uint64_t)>))\
1007 AARRAY_Filter_LAMBDA_2_FUNCTIONS[TEST_width(*vec)])(AARRAY_LINE, vec, f))
1015 $define AARRAY_Fold(TYPEB, TYPE, FNAME, FTYPE)
1016 AARRAY_define(TYPEB AARRAY_Fold_$##FNAME$##_$##TYPEB$##_$##TYPE(
1017 char errLoc[], TYPE*vec, TYPEB base,
1018 FTYPE(TYPEB,TYPE)), {
1019 AARRAY_safety((
void)errLoc,
if(!f) AARRAY_Error_NullParameter);
1020 size_t n = (size_t)-1;
1021 while(++n < aLength(vec)) base = f(base,vec[n] $exec
case 'FTYPE(,)' in *
'data') echo
', data';; esac; echo
');'
1024 $define AARRAY_Fold_TYPEB(TYPE, FNAME, FTYPE)
1025 AARRAY_Fold(uint8_t, TYPE, FNAME, FTYPE)
1026 AARRAY_Fold(uint16_t, TYPE, FNAME, FTYPE)
1027 AARRAY_Fold(uint32_t, TYPE, FNAME, FTYPE)
1028 AARRAY_Fold(uint64_t, TYPE, FNAME, FTYPE)
1030 $define AARRAY_Fold_FNAME(FNAME, FTYPE)
1031 AARRAY_Fold_TYPEB(uint8_t, FNAME, FTYPE)
1032 AARRAY_Fold_TYPEB(uint16_t, FNAME, FTYPE)
1033 AARRAY_Fold_TYPEB(uint32_t, FNAME, FTYPE)
1034 AARRAY_Fold_TYPEB(uint64_t, FNAME, FTYPE)
1035 static void(*
const AARRAY_Fold_$##FNAME$##_FUNCTIONS[9][9])(void) = { {
1038 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint8_t_uint8_t,
1039 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint8_t_uint16_t, 0,
1040 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint8_t_uint32_t, 0, 0, 0,
1041 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint8_t_uint64_t }, {
1043 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint16_t_uint8_t,
1044 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint16_t_uint16_t, 0,
1045 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint16_t_uint32_t, 0, 0, 0,
1046 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint16_t_uint64_t }, {0}, {
1048 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint32_t_uint8_t,
1049 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint32_t_uint16_t, 0,
1050 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint32_t_uint32_t, 0, 0, 0,
1051 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint32_t_uint64_t }, {0}, {0}, {0}, {
1053 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint64_t_uint8_t,
1054 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint64_t_uint16_t, 0,
1055 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint64_t_uint32_t, 0, 0, 0,
1056 (void(*)(void))&AARRAY_Fold_$##FNAME$##_uint64_t_uint64_t } };
1058 $define AARRAY_FUNCTION_TB_TB_T__D(TYPEB, TYPE) TYPEB(*f)(TYPEB,TYPE,
void*),
void*data
1060 $define AARRAY_FUNCTION_TB_TB_T(TYPEB, TYPE) TYPEB(*f)(TYPEB,TYPE)
1062 AARRAY_Fold_FNAME(FUNC_4, AARRAY_FUNCTION_TB_TB_T__D)
1063 AARRAY_Fold_FNAME(FUNC_3, AARRAY_FUNCTION_TB_TB_T)
1064 #define AARRAY_aFold_FUNC_4(vec, base, f, data) \
1065 (AARRAY_typeof(base, (uint64_t(*)(char[], void*, uint64_t, void(*)(void), void*)) \
1066 AARRAY_Fold_FUNC_4_FUNCTIONS[TEST_width(base)][TEST_width(*vec)]) \
1067 (AARRAY_LINE, vec, (uint64_t)base, (void(*)(void))f, data))
1068 #define AARRAY_aFold_FUNC_3(vec, base, f) \
1069 (AARRAY_typeof(base, (uint64_t(*)(char[], void*, uint64_t, void(*)(void))) \
1070 AARRAY_Fold_FUNC_3_FUNCTIONS[TEST_width(base)][TEST_width(*vec)]) \
1071 (AARRAY_LINE, vec, (uint64_t)base, (void(*)(void))f))
1073 #if __has_extension(blocks)
1074 $define AARRAY_BLOCK_TB_TB_T__D(TYPEB, TYPE) TYPEB(^f)(TYPEB,TYPE,
void*),
void*data
1076 $define AARRAY_BLOCK_TB_TB_T(TYPEB, TYPE) TYPEB(^f)(TYPEB,TYPE)
1078 AARRAY_Fold_FNAME(BLOCK_4, AARRAY_BLOCK_TB_TB_T__D)
1079 AARRAY_Fold_FNAME(BLOCK_3, AARRAY_BLOCK_TB_TB_T)
1080 #define AARRAY_aFold_BLOCK_4(vec, base, f, data) \
1081 (AARRAY_typeof(base, (uint64_t(*)(char[], void*, uint64_t, \
1082 uint64_t(^)(uint64_t,uint64_t,void*), void*)) \
1083 AARRAY_Fold_BLOCK_4_FUNCTIONS[TEST_width(base)][TEST_width(*vec)]) \
1084 (AARRAY_LINE, vec, (uint64_t)base, (uint64_t(^)(uint64_t,uint64_t,void*))f, data))
1085 #define AARRAY_aFold_BLOCK_3(vec, base, f) \
1086 (AARRAY_typeof(base, (uint64_t(*)(char[], void*, uint64_t, \
1087 uint64_t(^)(uint64_t,uint64_t))) \
1088 AARRAY_Fold_BLOCK_3_FUNCTIONS[TEST_width(base)][TEST_width(*vec)]) \
1089 (AARRAY_LINE, vec, (uint64_t)base, (uint64_t(^)(uint64_t,uint64_t))f))
1091 #if defined(__cplusplus)
1092 $define AARRAY_LAMBDA_TB_TB_T__D(TYPEB, TYPE) std::function<TYPEB(TYPEB,TYPE,
void*)>f,
void*data
1094 $define AARRAY_LAMBDA_TB_TB_T(TYPEB, TYPE) std::function<TYPEB(TYPEB,TYPE)>f
1096 AARRAY_Fold_FNAME(LAMBDA_4, AARRAY_LAMBDA_TB_TB_T__D)
1097 AARRAY_Fold_FNAME(LAMBDA_3, AARRAY_LAMBDA_TB_TB_T)
1098 #define AARRAY_aFold_LAMBDA_4(vec, base, f, data) \
1099 (AARRAY_typeof(base, (uint64_t(*)(char[], void*, uint64_t, \
1100 std::function<uint64_t(uint64_t,uint64_t,void*)>, void*)) \
1101 AARRAY_Fold_LAMBDA_4_FUNCTIONS[TEST_width(base)][TEST_width(*vec)]) \
1102 (AARRAY_LINE, vec, (uint64_t)base, f, data))
1103 #define AARRAY_aFold_LAMBDA_3(vec, base, f) \
1104 (AARRAY_typeof(base, (uint64_t(*)(char[], void*, uint64_t, \
1105 std::function<uint64_t(uint64_t,uint64_t)>)) \
1106 AARRAY_Fold_LAMBDA_3_FUNCTIONS[TEST_width(base)][TEST_width(*vec)]) \
1107 (AARRAY_LINE, vec, (uint64_t)base, f))
1111 #define AARRAY_ARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
1112 #define AARRAY_ARGS(...) AARRAY_ARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
1113 #define AARRAY_CONCAT(a, b) a##b
1114 #define AARRAY_CONCAT_EXPAND(a, b) AARRAY_CONCAT(a, b)
1115 #define aMap_FUNC(...) AARRAY_CONCAT_EXPAND(AARRAY_aMap_FUNC_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1116 #define aMap_BLOCK(...) AARRAY_CONCAT_EXPAND(AARRAY_aMap_BLOCK_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1117 #define aMap_LAMBDA(...) AARRAY_CONCAT_EXPAND(AARRAY_aMap_LAMBDA_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1118 #define aLoop_FUNC(...) AARRAY_CONCAT_EXPAND(AARRAY_aLoop_FUNC_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1119 #define aLoop_BLOCK(...) AARRAY_CONCAT_EXPAND(AARRAY_aLoop_BLOCK_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1120 #define aLoop_LAMBDA(...) AARRAY_CONCAT_EXPAND(AARRAY_aLoop_LAMBDA_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1121 #define aFilter_FUNC(...) AARRAY_CONCAT_EXPAND(AARRAY_aFilter_FUNC_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1122 #define aFilter_BLOCK(...) AARRAY_CONCAT_EXPAND(AARRAY_aFilter_BLOCK_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1123 #define aFilter_LAMBDA(...) AARRAY_CONCAT_EXPAND(AARRAY_aFilter_LAMBDA_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1124 #define aFold_FUNC(...) AARRAY_CONCAT_EXPAND(AARRAY_aFold_FUNC_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1125 #define aFold_BLOCK(...) AARRAY_CONCAT_EXPAND(AARRAY_aFold_BLOCK_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1126 #define aFold_LAMBDA(...) AARRAY_CONCAT_EXPAND(AARRAY_aFold_LAMBDA_, AARRAY_ARGS(__VA_ARGS__))(__VA_ARGS__)
1134 $define AARRAY_swap(TYPE, a, b) { TYPE temp = a;
1138 $define AARRAY_SWAP(TYPE, x, y) \
1139 if(f(array[sRange+y], array[sRange+x]) ||
1140 (order[x] > order[y] && !f(array[sRange+x], array[sRange+y]))) {
1141 AARRAY_swap(TYPE, array[sRange+x], array[sRange+y]);
1142 AARRAY_swap(uint8_t, order[x], order[y]); }
1144 $define AARRAY_blockSwap(TYPE, array, start1, start2, block_size)
1145 for(
size_t n = 0; n < block_size; n++)
1146 AARRAY_swap(TYPE, array[start1+n], array[start2+n])
1148 $define AARRAY_PULL(_to) \
1149 pull[pull_index].sRange = sA; \
1150 pull[pull_index].eRange = eB; \
1151 pull[pull_index].count = count; \
1152 pull[pull_index].from = index; \
1153 pull[pull_index].to = _to;
1155 $define AARRAY_sortFindFirstForward(FNAME, value, start, end, unique)
1156 if(end-start == 0) index = start;
1159 size_t skip = (end-start)/(unique);
1161 for(index = start+skip; f(array[index-1], value); index += skip)
1162 if(index >= end-skip) {
1163 index = AARRAY_aSortBinaryFirst_$##FNAME(array, value, index, end, f);
1164 indexSet = 1;
break; }
1165 if(!indexSet) index =
1166 AARRAY_aSortBinaryFirst_$##FNAME(array, value, index-skip, index, f); }
1168 $define AARRAY_sortFindLastForward(FNAME, value, start, end, unique)
1169 if(end-start == 0) index = start;
1172 size_t skip = (end-start)/(unique);
1174 for(index = start+skip; !f(value, array[index-1]); index += skip)
1175 if(index >= end-skip) {
1176 index = AARRAY_aSortBinaryLast_$##FNAME(array, value, index, end, f);
1177 indexSet = 1;
break; }
1178 if(!indexSet) index =
1179 AARRAY_aSortBinaryLast_$##FNAME(array, value, index-skip, index, f); }
1181 $define AARRAY_sortFindFirstBackward(FNAME, value, start, end, unique)
1182 if(end-start == 0) index = start;
1185 size_t skip = (end-start)/(unique);
1187 for(index = end-skip; index > start
1188 && !f(array[index-1], value); index -= skip)
1189 if(index < start+skip) {
1190 index = AARRAY_aSortBinaryFirst_$##FNAME(array, value, start, index, f);
1191 indexSet = 1;
break; }
1192 if(!indexSet) index =
1193 AARRAY_aSortBinaryFirst_$##FNAME(array, value, index, index+skip, f); }
1195 $define AARRAY_sortFindLastBackward(FNAME, value, start, end, unique)
1196 if(end-start == 0) index = start;
1199 size_t skip = (end-start)/(unique);
1201 for(index = end-skip; index > start
1202 && f(value, array[index-1]); index -= skip)
1203 if(index < start+skip) {
1204 index = AARRAY_aSortBinaryLast_$##FNAME(array, value, start, index, f);
1205 indexSet = 1;
break; }
1206 if(!indexSet) index =
1207 AARRAY_aSortBinaryLast_$##FNAME(array, value, index, index+skip, f); }
1209 $define AARRAY_sortReverse(TYPE, ...)
1210 AARRAY_define(
void AARRAY_sortReverse__$
##TYPE(
1211 TYPE vec[],
size_t start,
size_t end), {
1212 for(
size_t n = (end-start)/2; n > 0; n--) {
1213 TYPE temp = vec[start+n-1];
1214 vec[start+n-1] = vec[end-n];
1215 vec[end-n] = temp; } })
1217 $define AARRAY_sortBinaryFirst(TYPE, FNAME, FTYPE)
1218 AARRAY_define(
size_t AARRAY_sortBinaryFirst_$##FNAME$##_$##TYPE(
1219 const TYPE array[],
const TYPE value,
1220 size_t start,
size_t end, FTYPE(TYPE)), {
1223 if(start >= rend)
return start;
1224 while(start < end) {
1225 size_t mid = start+(end-start)/2;
1226 if(f(array[mid], value)) start = mid+1;
1228 if(start == rend-1 && f(array[start], value)) start++;
1231 $define AARRAY_sortBinaryLast(TYPE, FNAME, FTYPE)
1232 AARRAY_define(
size_t AARRAY_sortBinaryLast_$##FNAME$##_$##TYPE(
1233 const TYPE array[],
const TYPE value,
1234 size_t start,
size_t end, FTYPE(TYPE)), {
1237 if(start >= rend)
return end;
1238 while(start < end) {
1239 size_t mid = start+(end-start)/2;
1240 if(!f(value, array[mid])) start = mid+1;
1242 if(start == rend-1 && !f(value, array[start])) start++;
1246 size_t size, power_of_two;
1247 size_t numerator, decimal;
1248 size_t denominator, decimal_step, numerator_step; } AARRAY_sortIt;
1249 $define AARRAY_sortNextRange(TYPE, ...)
1250 AARRAY_define(
void AARRAY_sortNextRange__$
##TYPE(
1251 AARRAY_sortIt*it,
size_t*start,
size_t*end), {
1252 *start = it->decimal;
1253 it->decimal += it->decimal_step;
1254 it->numerator += it->numerator_step;
1255 if(it->numerator >= it->denominator) {
1256 it->numerator -= it->denominator;
1258 *end = it->decimal; })
1260 $define AARRAY_sortNextLevel(TYPE, ...)
1261 AARRAY_define(
int AARRAY_sortNextLevel__$
##TYPE(AARRAY_sortIt*it), {
1262 it->decimal_step += it->decimal_step;
1263 it->numerator_step += it->numerator_step;
1264 if(it->numerator_step >= it->denominator) {
1265 it->numerator_step -= it->denominator;
1266 it->decimal_step++; }
1267 return it->decimal_step < it->size; })
1269 GENERATE_GENERICS(AARRAY_sortReverse)
1270 #define AARRAY_aSortReverse(vec, start, end) \
1271 (((int(*)(void*, size_t, size_t)) \
1272 AARRAY_sortReverse__FUNCTIONS[TEST_width(*vec)])((void*)vec, start, end))
1274 $define AARRAY_sortRotate(TYPE, ...)
1275 AARRAY_define(
void AARRAY_sortRotate__$
##TYPE(
1276 TYPE array[],
const size_t amount,
size_t start,
size_t end,
1277 TYPE cache[],
const size_t cacheSize), {
1278 if(end-start == 0)
return;
1279 size_t sA = start, eA = start+amount, sB = start+amount, eB = end;
1280 if(eA-sA <= eB-sB) {
1281 if(eA-sA <= cacheSize) {
1282 memcpy(&cache[0], &array[sA], (eA-sA)*
sizeof(array[0]));
1283 memmove(&array[sA], &array[sB], (eB-sB)*
sizeof(array[0]));
1284 memcpy(&array[sA+(eB-sB)], &cache[0], (eA-sA)*
sizeof(array[0]));
1287 if(eB-sB <= cacheSize) {
1288 memcpy(&cache[0], &array[sB], (eB-sB)*
sizeof(array[0]));
1289 memmove(&array[eB-(eA-sA)], &array[sA], (eA-sA)*
sizeof(array[0]));
1290 memcpy(&array[sA], &cache[0], (eB-sB)*
sizeof(array[0]));
1292 AARRAY_aSortReverse(array, sA, eA);
1293 AARRAY_aSortReverse(array, sB, eB);
1294 AARRAY_aSortReverse(array, start, end); })
1296 $define AARRAY_sortMergeInto(TYPE, FNAME, FTYPE)
1297 AARRAY_define(
void AARRAY_sortMergeInto_$##FNAME$##_$##TYPE(
1298 TYPE from[],
size_t sA,
size_t eA,
size_t sB,
size_t eB,
1299 FTYPE(TYPE), TYPE into[]), {
1300 TYPE*A_index = &from[sA], *B_index = &from[sB];
1301 TYPE*A_last = &from[eA], *B_last = &from[eB];
1302 TYPE*insert_index = &into[0];
1304 if(!f(*B_index, *A_index)) {
1305 *insert_index = *A_index;
1308 if(A_index == A_last) {
1309 memcpy(insert_index, B_index, (
size_t)(B_last-B_index)*
sizeof(from[0]));
1312 *insert_index = *B_index;
1315 if(B_index == B_last) {
1316 memcpy(insert_index, A_index, (
size_t)(A_last-A_index)*
sizeof(from[0]));
1319 $define AARRAY_sortMergeExternal(TYPE, FNAME, FTYPE)
1320 AARRAY_define(
void AARRAY_sortMergeExternal_$##FNAME$##_$##TYPE(
1321 TYPE array[],
size_t sA,
size_t eA,
size_t sB,
size_t eB,
1322 FTYPE(TYPE), TYPE cache[]), {
1323 TYPE*A_index = &cache[0];
1324 TYPE*B_index = &array[sB];
1325 TYPE*insert_index = &array[sA];
1326 TYPE*A_last = &cache[eA-sA];
1327 TYPE*B_last = &array[eB];
1328 if(eB-sB > 0 && eA-sA > 0) {
1330 if(!f(*B_index, *A_index)) {
1331 *insert_index = *A_index;
1334 if(A_index == A_last)
break; }
1336 *insert_index = *B_index;
1339 if(B_index == B_last)
break; } } }
1340 memcpy(insert_index, A_index, (
size_t)(A_last-A_index)*
sizeof(array[0])); })
1342 $define AARRAY_sortMergeInternal(TYPE, FNAME, FTYPE)
1343 AARRAY_define(
void AARRAY_sortMergeInternal_$##FNAME$##_$##TYPE(
1344 TYPE array[],
size_t sA,
size_t eA,
size_t sB,
size_t eB,
1345 FTYPE(TYPE),
size_t sBuff), {
1346 size_t A_count = 0, B_count = 0, insert = 0;
1347 if(eB-sB > 0 && eA-sA > 0) {
1349 if(!f(array[sB+B_count], array[sBuff+A_count])) {
1350 AARRAY_swap(TYPE, array[sA+insert], array[sBuff+A_count]);
1353 if(A_count >= eA-sA)
break; }
1355 AARRAY_swap(TYPE, array[sA+insert], array[sB+B_count]);
1358 if(B_count >= eB-sB)
break; } } }
1359 AARRAY_blockSwap(TYPE, array, sBuff+A_count, sA+insert, (eA-sA)-A_count); })
1361 $define FUNC_int_TT(TYPE) int(*f)(TYPE,TYPE)
1363 $define BLOCK_int_TT(TYPE) int(^f)(TYPE,TYPE)
1365 $define LAMBDA_int_TT(TYPE) std::function<int(TYPE, TYPE)>f
1367 GENERATE_GENERICS(AARRAY_sortRotate)
1368 #define AARRAY_aSortRotate(vec, value, start, end, vecb, cacheSize) \
1369 (((void(*)(void*, size_t, size_t, size_t, void*, size_t)) \
1370 AARRAY_sortRotate__FUNCTIONS[TEST_width(*vec)]) \
1371 ((void*)vec, value, start, end, vecb, cacheSize))
1372 GENERATE_GENERICS(AARRAY_sortBinaryFirst, FUNC, FUNC_int_TT)
1373 GENERATE_GENERICS(AARRAY_sortBinaryLast, FUNC, FUNC_int_TT)
1374 #define AARRAY_aSortBinaryFirst_FUNC(vec, value, start, end, f) \
1375 (((size_t(*)(void*, uint64_t, size_t, size_t, void(*)(void))) \
1376 AARRAY_sortBinaryFirst_FUNC_FUNCTIONS[TEST_width(*vec)]) \
1377 ((void*)vec, value, start, end, (void(*)(void))f))
1378 #define AARRAY_aSortBinaryLast_FUNC(vec, value, start, end, f) \
1379 (((size_t(*)(void*, uint64_t, size_t, size_t, void(*)(void))) \
1380 AARRAY_sortBinaryLast_FUNC_FUNCTIONS[TEST_width(*vec)]) \
1381 ((void*)vec, value, start, end, (void(*)(void))f))
1383 #if __has_extension(blocks)
1384 GENERATE_GENERICS(AARRAY_sortBinaryFirst, BLOCK, BLOCK_int_TT)
1385 GENERATE_GENERICS(AARRAY_sortBinaryLast, BLOCK, BLOCK_int_TT)
1386 #define AARRAY_aSortBinaryFirst_BLOCK(vec, value, start, end, f) \
1387 (((size_t(*)(void*, uint64_t, size_t, size_t, void*)) \
1388 AARRAY_sortBinaryFirst_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
1389 ((void*)vec, value, start, end, (void*)f))
1390 #define AARRAY_aSortBinaryLast_BLOCK(vec, value, start, end, f) \
1391 (((size_t(*)(void*, uint64_t, size_t, size_t, void*)) \
1392 AARRAY_sortBinaryLast_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
1393 ((void*)vec, value, start, end, (void*)f))
1395 #if defined(__cplusplus)
1396 GENERATE_GENERICS(AARRAY_sortBinaryFirst, LAMBDA, LAMBDA_int_TT)
1397 GENERATE_GENERICS(AARRAY_sortBinaryLast, LAMBDA, LAMBDA_int_TT)
1398 #define AARRAY_aSortBinaryFirst_LAMBDA(vec, value, start, end, f) \
1399 (((size_t(*)(void*, uint64_t, size_t, size_t, std::function<int(int,int)>)) \
1400 AARRAY_sortBinaryFirst_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
1401 ((void*)vec, value, start, end, (std::function<int(int,int)>)f))
1402 #define AARRAY_aSortBinaryLast_LAMBDA(vec, value, start, end, f) \
1403 (((size_t(*)(void*, uint64_t, size_t, size_t, std::function<int(int,int)>)) \
1404 AARRAY_sortBinaryLast_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
1405 ((void*)vec, value, start, end, (std::function<int(int,int)>)f))
1408 $define AARRAY_sortMergeInPlace(TYPE, FNAME, FTYPE)
1409 AARRAY_define(
void AARRAY_sortMergeInPlace_$##FNAME$##_$##TYPE(
1410 TYPE array[],
size_t sA,
size_t eA,
size_t sB,
size_t eB,
1411 FTYPE(TYPE), TYPE cache[]), {
1412 if(eA-sA == 0 || eB-sB == 0)
return;
1414 size_t mid = AARRAY_aSortBinaryFirst_$##FNAME(array, array[sA], sB, eB, f);
1415 size_t amount = mid-eA;
1416 AARRAY_aSortRotate(array, eA-sA, sA, mid, cache, AARRAY_sortCache);
1417 if(eB == mid)
break;
1419 sA = sA+amount; eA = sB;
1420 sA = AARRAY_aSortBinaryLast_$##FNAME(array, array[sA], sA, eA, f);
1421 if(eA-sA == 0)
break; } })
1423 GENERATE_GENERICS(AARRAY_sortNextRange)
1424 GENERATE_GENERICS(AARRAY_sortNextLevel)
1425 #define AARRAY_aSortNextRange(vec, iter, start, end) \
1426 (((void(*)(AARRAY_sortIt*, size_t*, size_t*)) \
1427 AARRAY_sortNextRange__FUNCTIONS[TEST_width(*vec)])(iter, start, end))
1428 #define AARRAY_aSortNextLevel(vec, iter) \
1429 (((int (*)(AARRAY_sortIt*)) \
1430 AARRAY_sortNextLevel__FUNCTIONS[TEST_width(*vec)])(iter))
1431 GENERATE_GENERICS(AARRAY_sortMergeInto, FUNC, FUNC_int_TT)
1432 GENERATE_GENERICS(AARRAY_sortMergeExternal, FUNC, FUNC_int_TT)
1433 GENERATE_GENERICS(AARRAY_sortMergeInternal, FUNC, FUNC_int_TT)
1434 GENERATE_GENERICS(AARRAY_sortMergeInPlace, FUNC, FUNC_int_TT)
1435 #define AARRAY_aSortMergeInto_FUNC(vec, s1, s2, s3, s4, f, vecb) \
1436 (((void(*)(void*, size_t, size_t, size_t, size_t, void(*)(void), void*)) \
1437 AARRAY_sortMergeInto_FUNC_FUNCTIONS[TEST_width(*vec)]) \
1438 ((void*)vec, s1, s2, s3, s4, (void(*)(void))f, vecb))
1439 #define AARRAY_aSortMergeExternal_FUNC(vec, s1, s2, s3, s4, f, vecb) \
1440 (((void(*)(void*, size_t, size_t, size_t, size_t, void(*)(void), void*)) \
1441 AARRAY_sortMergeExternal_FUNC_FUNCTIONS[TEST_width(*vec)]) \
1442 ((void*)vec, s1, s2, s3, s4, (void(*)(void))f, vecb))
1443 #define AARRAY_aSortMergeInternal_FUNC(vec, s1, s2, s3, s4, f, s5) \
1444 (((void(*)(void*, size_t, size_t, size_t, size_t, void(*)(void), size_t)) \
1445 AARRAY_sortMergeInternal_FUNC_FUNCTIONS[TEST_width(*vec)]) \
1446 ((void*)vec, s1, s2, s3, s4, (void(*)(void))f, s5))
1447 #define AARRAY_aSortMergeInPlace_FUNC(vec, s1, s2, s3, s4, f, vecb) \
1448 (((void(*)(void*, size_t, size_t, size_t, size_t, void(*)(void), void*)) \
1449 AARRAY_sortMergeInPlace_FUNC_FUNCTIONS[TEST_width(*vec)]) \
1450 ((void*)vec, s1, s2, s3, s4, (void(*)(void))f, vecb))
1452 #if __has_extension(blocks)
1453 GENERATE_GENERICS(AARRAY_sortMergeInto, BLOCK, BLOCK_int_TT)
1454 GENERATE_GENERICS(AARRAY_sortMergeExternal, BLOCK, BLOCK_int_TT)
1455 GENERATE_GENERICS(AARRAY_sortMergeInternal, BLOCK, BLOCK_int_TT)
1456 GENERATE_GENERICS(AARRAY_sortMergeInPlace, BLOCK, BLOCK_int_TT)
1457 #define AARRAY_aSortMergeInto_BLOCK(vec, s1, s2, s3, s4, f, vecb) \
1458 (((void(*)(void*, size_t, size_t, size_t, size_t, void*, void*)) \
1459 AARRAY_sortMergeInto_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
1460 ((void*)vec, s1, s2, s3, s4, (void*)f, vecb))
1461 #define AARRAY_aSortMergeExternal_BLOCK(vec, s1, s2, s3, s4, f, vecb) \
1462 (((void(*)(void*, size_t, size_t, size_t, size_t, void*, void*)) \
1463 AARRAY_sortMergeExternal_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
1464 ((void*)vec, s1, s2, s3, s4, (void*)f, vecb))
1465 #define AARRAY_aSortMergeInternal_BLOCK(vec, s1, s2, s3, s4, f, s5) \
1466 (((void(*)(void*, size_t, size_t, size_t, size_t, void*, size_t)) \
1467 AARRAY_sortMergeInternal_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
1468 ((void*)vec, s1, s2, s3, s4, (void*)f, s5))
1469 #define AARRAY_aSortMergeInPlace_BLOCK(vec, s1, s2, s3, s4, f, vecb) \
1470 (((void(*)(void*, size_t, size_t, size_t, size_t, void*, void*)) \
1471 AARRAY_sortMergeInPlace_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
1472 ((void*)vec, s1, s2, s3, s4, (void*)f, vecb))
1474 #if defined(__cplusplus)
1475 GENERATE_GENERICS(AARRAY_sortMergeInto, LAMBDA, LAMBDA_int_TT)
1476 GENERATE_GENERICS(AARRAY_sortMergeExternal, LAMBDA, LAMBDA_int_TT)
1477 GENERATE_GENERICS(AARRAY_sortMergeInternal, LAMBDA, LAMBDA_int_TT)
1478 GENERATE_GENERICS(AARRAY_sortMergeInPlace, LAMBDA, LAMBDA_int_TT)
1479 #define AARRAY_aSortMergeInto_LAMBDA(vec, s1, s2, s3, s4, f, vecb) \
1480 (((void(*)(void*, size_t, size_t, size_t, size_t, \
1481 std::function<int(int,int)>, void*)) \
1482 AARRAY_sortMergeInto_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
1483 ((void*)vec, s1, s2, s3, s4, (std::function<int(int,int)>)f, vecb))
1484 #define AARRAY_aSortMergeExternal_LAMBDA(vec, s1, s2, s3, s4, f, vecb) \
1485 (((void(*)(void*, size_t, size_t, size_t, size_t, \
1486 std::function<int(int,int)>, void*)) \
1487 AARRAY_sortMergeExternal_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
1488 ((void*)vec, s1, s2, s3, s4, (std::function<int(int,int)>)f, vecb))
1489 #define AARRAY_aSortMergeInternal_LAMBDA(vec, s1, s2, s3, s4, f, s5) \
1490 (((void(*)(void*, size_t, size_t, size_t, size_t, \
1491 std::function<int(int,int)>, size_t)) \
1492 AARRAY_sortMergeInternal_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
1493 ((void*)vec, s1, s2, s3, s4, (std::function<int(int,int)>)f, s5))
1494 #define AARRAY_aSortMergeInPlace_LAMBDA(vec, s1, s2, s3, s4, f, vecb) \
1495 (((void(*)(void*, size_t, size_t, size_t, size_t, \
1496 std::function<int(int,int)>, void*)) \
1497 AARRAY_sortMergeInPlace_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
1498 ((void*)vec, s1, s2, s3, s4, (std::function<int(int,int)>)f, vecb))
1502 AARRAY_define(int64_t AARRAY_sqrt(int64_t x), {
1505 int64_t op = x, res, one;
1508 one = ((uint64_t)1) << 62;
1509 while (one > op) one >>= 2;
1511 if (op >= res + one) {
1512 op = op - (res + one);
1513 res = res + 2 * one; }
1544 $define AARRAY_sort(TYPE, FNAME, FTYPE)
1545 AARRAY_define(TYPE*AARRAY_sort_$##FNAME$##_$##TYPE(
1546 TYPE array[], FTYPE(TYPE)), {
1547 size_t size = aLength(array);
1548 TYPE cache[AARRAY_sortCache];
1552 if(f(array[1], array[0])) AARRAY_swap(TYPE, array[0], array[1]);
1553 if(f(array[2], array[1])) {
1554 AARRAY_swap(TYPE, array[1], array[2]);
1555 if(f(array[1], array[0])) AARRAY_swap(TYPE, array[0], array[1]); } }
1556 else if(size == 2) {
1557 if(f(array[1], array[0])) AARRAY_swap(TYPE, array[0], array[1]); }
1563 s = s | (s >> 1); s = s | (s >> 2); s = s | (s >> 4);
1564 s = s | (s >> 8); s = s | (s >> 16);
1565 if(
sizeof(
size_t)==8) s = s | (s >> 32);
1567 it.power_of_two = s;
1568 it.denominator = it.power_of_two/4;
1569 it.numerator_step = it.size % it.denominator;
1570 it.decimal_step = it.size/it.denominator;
1571 it.numerator = it.decimal = 0;
1572 while(!(it.decimal >= it.size)) {
1573 uint8_t order[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1574 size_t sRange, eRange;
1575 AARRAY_aSortNextRange(array, &it, &sRange, &eRange);
1576 if(eRange-sRange==8) {
1577 AARRAY_SWAP(TYPE, 0, 1); AARRAY_SWAP(TYPE, 2, 3); AARRAY_SWAP(TYPE, 4, 5);
1578 AARRAY_SWAP(TYPE, 6, 7); AARRAY_SWAP(TYPE, 0, 2); AARRAY_SWAP(TYPE, 1, 3);
1579 AARRAY_SWAP(TYPE, 4, 6); AARRAY_SWAP(TYPE, 5, 7); AARRAY_SWAP(TYPE, 1, 2);
1580 AARRAY_SWAP(TYPE, 5, 6); AARRAY_SWAP(TYPE, 0, 4); AARRAY_SWAP(TYPE, 3, 7);
1581 AARRAY_SWAP(TYPE, 1, 5); AARRAY_SWAP(TYPE, 2, 6); AARRAY_SWAP(TYPE, 1, 4);
1582 AARRAY_SWAP(TYPE, 3, 6); AARRAY_SWAP(TYPE, 2, 4); AARRAY_SWAP(TYPE, 3, 5);
1583 AARRAY_SWAP(TYPE, 3, 4); }
1584 else if(eRange-sRange==7) {
1585 AARRAY_SWAP(TYPE, 1, 2); AARRAY_SWAP(TYPE, 3, 4); AARRAY_SWAP(TYPE, 5, 6);
1586 AARRAY_SWAP(TYPE, 0, 2); AARRAY_SWAP(TYPE, 3, 5); AARRAY_SWAP(TYPE, 4, 6);
1587 AARRAY_SWAP(TYPE, 0, 1); AARRAY_SWAP(TYPE, 4, 5); AARRAY_SWAP(TYPE, 2, 6);
1588 AARRAY_SWAP(TYPE, 0, 4); AARRAY_SWAP(TYPE, 1, 5); AARRAY_SWAP(TYPE, 0, 3);
1589 AARRAY_SWAP(TYPE, 2, 5); AARRAY_SWAP(TYPE, 1, 3); AARRAY_SWAP(TYPE, 2, 4);
1590 AARRAY_SWAP(TYPE, 2, 3); }
1591 else if(eRange-sRange==6) {
1592 AARRAY_SWAP(TYPE, 1, 2); AARRAY_SWAP(TYPE, 4, 5); AARRAY_SWAP(TYPE, 0, 2);
1593 AARRAY_SWAP(TYPE, 3, 5); AARRAY_SWAP(TYPE, 0, 1); AARRAY_SWAP(TYPE, 3, 4);
1594 AARRAY_SWAP(TYPE, 2, 5); AARRAY_SWAP(TYPE, 0, 3); AARRAY_SWAP(TYPE, 1, 4);
1595 AARRAY_SWAP(TYPE, 2, 4); AARRAY_SWAP(TYPE, 1, 3); AARRAY_SWAP(TYPE, 2, 3); }
1596 else if(eRange-sRange==5) {
1597 AARRAY_SWAP(TYPE, 0, 1); AARRAY_SWAP(TYPE, 3, 4); AARRAY_SWAP(TYPE, 2, 4);
1598 AARRAY_SWAP(TYPE, 2, 3); AARRAY_SWAP(TYPE, 1, 4); AARRAY_SWAP(TYPE, 0, 3);
1599 AARRAY_SWAP(TYPE, 0, 2); AARRAY_SWAP(TYPE, 1, 3); AARRAY_SWAP(TYPE, 1, 2); }
1600 else if(eRange-sRange==4) {
1601 AARRAY_SWAP(TYPE, 0, 1); AARRAY_SWAP(TYPE, 2, 3); AARRAY_SWAP(TYPE, 0, 2);
1602 AARRAY_SWAP(TYPE, 1, 3); AARRAY_SWAP(TYPE, 1, 2); } }
1603 if(size < 8)
return array;
1605 if(it.decimal_step < AARRAY_sortCache) {
1606 if((it.decimal_step+1)*4 <= AARRAY_sortCache
1607 && it.decimal_step*4 <= size) {
1608 it.numerator = it.decimal = 0;
1609 while(!(it.decimal >= it.size)) {
1611 sA1, sB1, sA2, sB2, sA3, sB3,
1612 eA1, eB1, eA2, eB2, eA3, eB3;
1613 AARRAY_aSortNextRange(array, &it, &sA1, &eA1);
1614 AARRAY_aSortNextRange(array, &it, &sB1, &eB1);
1615 AARRAY_aSortNextRange(array, &it, &sA2, &eA2);
1616 AARRAY_aSortNextRange(array, &it, &sB2, &eB2);
1617 if(f(array[eB1-1], array[sA1])) {
1618 memcpy(&cache[eB1-sB1], &array[sA1], (eA1-sA1)*
sizeof(array[0]));
1619 memcpy(&cache[0], &array[sB1], (eB1-sB1)*
sizeof(array[0])); }
1620 else if(f(array[sB1], array[eA1-1])) {
1621 AARRAY_aSortMergeInto_$##FNAME(
1622 array, sA1, eA1, sB1, eB1, f, &cache[0]); }
1624 if(!f(array[sB2], array[eA2-1])
1625 && !f(array[sA2], array[eB1-1]))
continue;
1626 memcpy(&cache[0], &array[sA1], (eA1-sA1)*
sizeof(array[0]));
1627 memcpy(&cache[(eA1-sA1)], &array[sB1],
1628 (eB1-sB1)*
sizeof(array[0])); }
1630 if(f(array[eB2-1], array[sA2])) {
1631 memcpy(&cache[(eA1-sA1)+(eB2-sB2)], &array[sA2],
1632 (eA2-sA2)*
sizeof(array[0]));
1633 memcpy(&cache[eA1-sA1], &array[sB2], (eB2-sB2)*
sizeof(array[0])); }
1634 else if(f(array[sB2], array[eA2-1])) {
1635 AARRAY_aSortMergeInto_$##FNAME(
1636 array, sA2, eA2, sB2, eB2, f, &cache[eA1-sA1]); }
1638 memcpy(&cache[eA1-sA1], &array[sA2], (eA2-sA2)*
sizeof(array[0]));
1639 memcpy(&cache[(eA1-sA1)+(eA2-sA2)], &array[sB2],
1640 (eB2-sB2)*
sizeof(array[0])); }
1642 sA3 = 0; eA3 = eA1-sA1;
1643 sB3 = eA1-sA1; eB3 = (eA1-sA1)+(eA2-sA2);
1644 if(f(cache[eB3-1], cache[sA3])) {
1645 memcpy(&array[sA1+(eA2-sA2)], &cache[sA3],
1646 (eA3-sA3)*
sizeof(array[0]));
1647 memcpy(&array[sA1], &cache[sB3], (eB3-sB3)*
sizeof(array[0])); }
1648 else if(f(cache[sB3], cache[eA3-1])) {
1649 AARRAY_aSortMergeInto_$##FNAME(
1650 cache, sA3, eA3, sB3, eB3, f, &array[sA1]); }
1652 memcpy(&array[sA1], &cache[sA3], (eA3-sA3)*
sizeof(array[0]));
1653 memcpy(&array[sA1+(eA1-sA1)], &cache[sB3],
1654 (eB3-sB3)*
sizeof(array[0])); } }
1655 AARRAY_aSortNextLevel(array, &it); }
1657 it.numerator = it.decimal = 0;
1658 while(!(it.decimal >= it.size)) {
1659 size_t sA, eA, sB, eB;
1660 AARRAY_aSortNextRange(array, &it, &sA, &eA);
1661 AARRAY_aSortNextRange(array, &it, &sB, &eB);
1662 if(f(array[eB-1], array[sA]))
1663 AARRAY_aSortRotate(array, eA-sA, sA, eB, cache, AARRAY_sortCache);
1664 else if(f(array[sB], array[eA-1])) {
1665 memcpy(&cache[0], &array[sA], (eA-sA)*
sizeof(array[0]));
1666 AARRAY_aSortMergeExternal_$##FNAME(
1667 array, sA, eA, sB, eB, f, cache); } } } }
1669 size_t block_size = (size_t)AARRAY_sqrt((int64_t)it.decimal_step);
1670 size_t buffer_size = it.decimal_step/block_size+1;
1671 int find_separately;
1672 size_t sBuff1, eBuff1, sBuff2, eBuff2, sA, eA, sB, eB;
1673 size_t index, last, count, find, start, pull_index = 0;
1674 struct {
size_t from, to, count, sRange, eRange; } pull[2];
1675 pull[0].from = pull[0].to = pull[0].count = 0;
1676 pull[1].from = pull[1].to = pull[1].count = 0;
1677 pull[0].sRange = pull[0].eRange = 0;
1678 pull[1].sRange = pull[1].eRange = 0;
1679 sBuff1 = 0; eBuff1 = 0;
1680 sBuff2 = 0; eBuff2 = 0;
1681 find_separately = 0;
1682 find = buffer_size+buffer_size;
1683 if(block_size <= AARRAY_sortCache)
1685 else if(find > it.decimal_step) {
1687 find_separately = 1; }
1688 it.numerator = it.decimal = 0;
1689 while(!(it.decimal >= it.size)) {
1690 AARRAY_aSortNextRange(array, &it, &sA, &eA);
1691 AARRAY_aSortNextRange(array, &it, &sB, &eB);
1692 for(last = sA, count = 1; count < find; last = index, count++) {
1693 AARRAY_sortFindLastForward(
1694 FNAME, array[last], (last+1), eA, find-count);
1695 if(index == eA)
break; }
1697 if(count >= buffer_size) {
1700 if(count == buffer_size+buffer_size) {
1701 sBuff1 = sA; eBuff1 = sA+buffer_size;
1702 sBuff2 = sA+buffer_size; eBuff2 = sA+count;
1704 else if(find == buffer_size+buffer_size) {
1705 sBuff1 = sA; eBuff1 = sA+count;
1706 find = buffer_size; }
1707 else if(block_size <= AARRAY_sortCache) {
1708 sBuff1 = sA; eBuff1 = sA+count;
1710 else if(find_separately) {
1711 sBuff1 = sA; eBuff1 = sA+count;
1712 find_separately = 0; }
1714 sBuff2 = sA; eBuff2 = sA+count;
1716 else if(pull_index == 0 && count > eBuff1-sBuff1) {
1717 sBuff1 = sA; eBuff1 = sA+count;
1719 for(last = eB-1, count = 1; count < find; last = index-1, count++) {
1720 AARRAY_sortFindFirstBackward(
1721 FNAME, array[last], sB, last, find-count);
1722 if(index == sB)
break; }
1724 if(count >= buffer_size) {
1727 if(count == buffer_size+buffer_size) {
1728 sBuff1 = eB-count; eBuff1 = eB-buffer_size;
1729 sBuff2 = eB-buffer_size; eBuff2 = eB;
1731 else if(find == buffer_size+buffer_size) {
1732 sBuff1 = eB-count; eBuff1 = eB;
1733 find = buffer_size; }
1734 else if(block_size <= AARRAY_sortCache) {
1735 sBuff1 = eB-count; eBuff1 = eB;
1737 else if(find_separately) {
1738 sBuff1 = eB-count; eBuff1 = eB;
1739 find_separately = 0; }
1741 if(pull[0].sRange == sA) pull[0].eRange -= pull[1].count;
1742 sBuff2 = eB-count; eBuff2 = eB;
1744 else if(pull_index == 0 && count > (eBuff1-sBuff1)) {
1745 sBuff1 = eB-count; eBuff1 = eB;
1746 AARRAY_PULL(eB); } }
1747 for(pull_index = 0; pull_index < 2; pull_index++) {
1748 size_t sRange, eRange;
1749 size_t length = pull[pull_index].count;
1750 if(pull[pull_index].to < pull[pull_index].from) {
1751 index = pull[pull_index].from;
1752 for(count = 1; count < length; count++) {
1753 size_t index_ = index;
1754 AARRAY_sortFindFirstBackward(
1755 FNAME, array[index_-1], pull[pull_index].to,
1756 (pull[pull_index].from-(count-1)), length-count);
1757 sRange = index+1; eRange = pull[pull_index].from+1;
1758 AARRAY_aSortRotate(array, (eRange-sRange)-count, sRange, eRange,
1759 cache, AARRAY_sortCache);
1760 pull[pull_index].from = index+count; } }
1761 else if(pull[pull_index].to > pull[pull_index].from) {
1762 index = pull[pull_index].from+1;
1763 for(count = 1; count < length; count++) {
1764 AARRAY_sortFindLastForward(
1765 FNAME, array[index], index, pull[pull_index].to, length-count);
1766 sRange = pull[pull_index].from; eRange = index-1;
1768 array, count, sRange, eRange, cache, AARRAY_sortCache);
1769 pull[pull_index].from = index-1-count; } } }
1770 buffer_size = eBuff1-sBuff1;
1771 block_size = it.decimal_step/buffer_size+1;
1772 it.numerator = it.decimal = 0;
1773 while(!(it.decimal >= it.size)) {
1774 AARRAY_aSortNextRange(array, &it, &sA, &eA);
1775 AARRAY_aSortNextRange(array, &it, &sB, &eB);
1777 if(start == pull[0].sRange) {
1778 if(pull[0].from > pull[0].to) {
1779 sA += pull[0].count;
1780 if(eA-sA == 0)
continue; }
1781 else if(pull[0].from < pull[0].to) {
1782 eB -= pull[0].count;
1783 if(eB-sB == 0)
continue; } }
1784 if(start == pull[1].sRange) {
1785 if(pull[1].from > pull[1].to) {
1786 sA += pull[1].count;
1787 if(eA-sA == 0)
continue; }
1788 else if(pull[1].from < pull[1].to) {
1789 eB -= pull[1].count;
1790 if(eB-sB == 0)
continue; ; } }
1791 if(f(array[eB-1], array[sA]))
1792 AARRAY_aSortRotate(array, eA-sA, sA, eB, cache, AARRAY_sortCache);
1793 else if(f(array[eA], array[eA-1])) {
1795 sBlockA, eBlockA, sFirstA, eFirstA, sLastA,
1796 eLastA, sLastB, eLastB, sBlockB, eBlockB;
1797 size_t indexA, findA;
1798 sBlockA = sA; eBlockA = eA;
1799 sFirstA = sA; eFirstA = sA+(eBlockA-sBlockA) % block_size;
1800 for(indexA = sBuff1, index = eFirstA; index < eBlockA;
1801 indexA++, index += block_size)
1802 AARRAY_swap(TYPE, array[indexA], array[index]);
1805 sLastB = 0; eLastB = 0;
1806 sBlockB = sB; eBlockB = sB+(block_size < eB-sB? block_size : eB-sB);
1807 sBlockA += eFirstA-sFirstA;
1809 if(eLastA-sLastA <= AARRAY_sortCache)
1810 memcpy(&cache[0], &array[sLastA], (eLastA-sLastA)*
sizeof(array[0]));
1811 else if(eBuff2-sBuff2 > 0)
1812 AARRAY_blockSwap(TYPE, array, sLastA, sBuff2, eLastA-sLastA);
1813 if(eBlockA-sBlockA > 0) {
1815 if((eLastB-sLastB > 0 && !f(array[eLastB-1], array[indexA]))
1816 || eBlockB-sBlockB == 0) {
1817 size_t B_split = AARRAY_aSortBinaryFirst_$##FNAME(
1818 array, array[indexA], sLastB, eLastB, f);
1819 size_t B_remaining = eLastB-B_split;
1820 size_t minA = sBlockA;
1821 for(findA = minA+block_size; findA < eBlockA;
1822 findA += block_size)
1823 if(f(array[findA], array[minA])) minA = findA;
1824 AARRAY_blockSwap(TYPE, array, sBlockA, minA, block_size);
1825 AARRAY_swap(TYPE, array[sBlockA], array[indexA]);
1827 if(eLastA-sLastA <= AARRAY_sortCache)
1828 AARRAY_aSortMergeExternal_$##FNAME(
1829 array, sLastA, eLastA, eLastA, B_split, f, cache);
1830 else if(eBuff2-sBuff2 > 0)
1831 AARRAY_aSortMergeInternal_$##FNAME(
1832 array, sLastA, eLastA, eLastA, B_split, f, sBuff2);
1834 AARRAY_aSortMergeInPlace_$##FNAME(
1835 array, sLastA, eLastA, eLastA, B_split, f, cache);
1836 if(eBuff2-sBuff2 > 0 || block_size <= AARRAY_sortCache) {
1837 if(block_size <= AARRAY_sortCache)
1838 memcpy(&cache[0], &array[sBlockA],
1839 block_size*
sizeof(array[0]));
1840 else AARRAY_blockSwap(TYPE, array, sBlockA, sBuff2,
1842 AARRAY_blockSwap(TYPE, array, B_split,
1843 sBlockA+block_size-B_remaining,
1846 AARRAY_aSortRotate(array, sBlockA-B_split, B_split,
1847 sBlockA+block_size, cache, AARRAY_sortCache);
1848 sLastA = sBlockA-B_remaining; eLastA =
1849 sBlockA-B_remaining+block_size;
1850 sLastB = eLastA; eLastB = eLastA+B_remaining;
1851 sBlockA += block_size;
1852 if(eBlockA-sBlockA == 0)
break; }
1853 else if(eBlockB-sBlockB < block_size) {
1855 array, sBlockB-sBlockA, sBlockA, eBlockB, cache, 0);
1856 sLastB = sBlockA; eLastB = sBlockA+(eBlockB-sBlockB);
1857 sBlockA += eBlockB-sBlockB;
1858 eBlockA += eBlockB-sBlockB;
1859 eBlockB = sBlockB; }
1861 AARRAY_blockSwap(TYPE, array, sBlockA, sBlockB, block_size);
1862 sLastB = sBlockA; eLastB = sBlockA+block_size;
1863 sBlockA += block_size;
1864 eBlockA += block_size;
1865 sBlockB += block_size;
1866 if(eBlockB > eB-block_size) eBlockB = eB;
1867 else eBlockB += block_size; } } }
1868 if(eLastA-sLastA <= AARRAY_sortCache)
1869 AARRAY_aSortMergeExternal_$##FNAME(
1870 array, sLastA, eLastA, eLastA, eB, f, cache);
1871 else if(eBuff2-sBuff2 > 0)
1872 AARRAY_aSortMergeInternal_$##FNAME(
1873 array, sLastA, eLastA, eLastA, eB, f, sBuff2);
1875 AARRAY_aSortMergeInPlace_$##FNAME(
1876 array, sLastA, eLastA, eLastA, eB, f, cache); } }
1879 for(i = sBuff2+1; i < eBuff2; i++) {
1880 const TYPE temp = array[i];
1881 for(j = i; j > sBuff2 && f(temp, array[j-1]); j--)
1882 array[j] = array[j-1];
1884 for(pull_index = 0; pull_index < 2; pull_index++) {
1885 size_t amount, unique = pull[pull_index].count*2;
1886 if(pull[pull_index].from > pull[pull_index].to) {
1888 sBuff = pull[pull_index].sRange,
1889 eBuff = pull[pull_index].sRange+pull[pull_index].count;
1890 while(eBuff-sBuff > 0) {
1891 AARRAY_sortFindFirstForward(FNAME, array[sBuff], eBuff,
1892 pull[pull_index].eRange, unique);
1893 amount = index-eBuff;
1894 AARRAY_aSortRotate(array, eBuff-sBuff, sBuff, index,
1895 cache, AARRAY_sortCache);
1896 sBuff += (amount+1);
1899 else if(pull[pull_index].from < pull[pull_index].to) {
1901 sBuff = pull[pull_index].eRange-pull[pull_index].count,
1902 eBuff = pull[pull_index].eRange;
1903 while(eBuff-sBuff > 0) {
1904 AARRAY_sortFindLastBackward(FNAME, array[eBuff-1],
1905 pull[pull_index].sRange,
1907 amount = sBuff-index;
1909 array, amount, index, eBuff, cache, AARRAY_sortCache);
1911 eBuff -= (amount+1);
1912 unique -= 2; } } } }
1913 if(!AARRAY_aSortNextLevel(array, &it))
break; }
1916 $define AARRAY_sortCompare(TYPE,,)
1917 AARRAY_define(
int AARRAY_sortCompare__$
##TYPE(TYPE a, TYPE b), {
1920 GENERATE_GENERICS(AARRAY_sortCompare,,)
1921 GENERATE_GENERICS(AARRAY_sort, FUNC, FUNC_int_TT)
1922 #define aSort(vec) \
1923 (AARRAY_typeof(vec, (uint64_t*(*)(void*,void(*)(void))) \
1924 AARRAY_sort_FUNC_FUNCTIONS[TEST_width(*vec)])((void*)vec, (void(*)(void)) \
1925 AARRAY_sortCompare__FUNCTIONS[TEST_width(*vec)]))
1926 #define aSortF_FUNC(vec, f) \
1927 (AARRAY_typeof(vec, (uint64_t*(*)(void*,void(*)(void))) \
1928 AARRAY_sort_FUNC_FUNCTIONS[TEST_width(*vec)])((void*)vec, (void(*)(void))f))
1930 #if __has_extension(blocks)
1931 GENERATE_GENERICS(AARRAY_sort, BLOCK, BLOCK_int_TT)
1932 #define aSortF_BLOCK(vec, f) \
1933 (AARRAY_typeof(vec, (uint64_t*(*)(void*, void*)) \
1934 AARRAY_sort_BLOCK_FUNCTIONS[TEST_width(*vec)])((void*)vec, (void*)f))
1936 #if defined(__cplusplus)
1937 GENERATE_GENERICS(AARRAY_sort, LAMBDA, LAMBDA_int_TT)
1938 #define aSortF_LAMBDA(vec, f) \
1939 (AARRAY_typeof(vec, (uint64_t*(*)(void*, \
1940 std::function<int(uint64_t,uint64_t)>)) \
1941 AARRAY_sort_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
1942 ((void*)vec, (std::function<int(uint64_t,uint64_t)>)f))
1949 $define AARRAY_searchCompare(TYPE,,)
1950 AARRAY_define(int64_t AARRAY_searchCompare__$
##TYPE(TYPE a, TYPE b), {
1951 $exec [ TYPE = int64_t ] && echo
'if((a^b)>(UINT64_MAX>>1)) return a<b? INT64_MIN : INT64_MAX;'
1952 return (int64_t)((uint64_t)a-(uint64_t)b); })
1957 $define AARRAY_binary(TYPE, FNAME, FTYPE)
1958 AARRAY_define(
int AARRAY_binary_$##FNAME$##_$##TYPE(
1959 TYPE*vec,
size_t*index, TYPE key, FTYPE(TYPE)), {
1960 size_t min = 0, mid = 0, max = aLength(vec);
1961 if(!max) { *index = 0;
return 0; }
1963 mid = (min + max) >> 1;
1964 int64_t cmp = f(key, vec[mid]);
1965 if(cmp == 0) { *index = mid;
return 1; }
1966 if(cmp < 0) max = mid;
1968 *index = mid;
return 0; })
1984 $define AARRAY_pingpong(TYPE, FNAME, FTYPE)
1985 AARRAY_define(
int AARRAY_pingpong_$##FNAME$##_$##TYPE(
1986 TYPE*vec,
size_t*index, TYPE key, FTYPE(TYPE)), {
1987 size_t min = 0, max = aLength(vec);
1988 if(!max) { *index = 0;
return 0; }
1990 size_t a = min+(max>>3), b = max-1-(max>>3), c;
1991 int64_t fa = f(key, vec[a]), fb = f(key, vec[b]);
1994 c = fb-fa? b - (size_t)((
double)fb * (double)(b-a) / (double)(fb-fa)) : max-((max-min)>>1);
1996 a = b; b = c < min ? min : c >= max ? max-1 : c;
1997 fa = fb; fb = f(key, vec[b]);
1998 if(fb == 0) { *index = b;
return 1; }
1999 if(fb > 0) min = b+1;
else max = b; }
2000 *index = max;
return 0; })
2003 $define AARRAY_pingpongS(TYPE, FNAME, FTYPE)
2004 AARRAY_define(
int AARRAY_pingpongS_$##FNAME$##_$##TYPE(
2005 TYPE*vec,
size_t*index, TYPE*key, FTYPE(TYPE*),
size_t stride), {
2006 size_t min = 0, max = aLength(vec)/stride;
2007 if(!max) { *index = 0;
return 0; }
2009 size_t a = min+(max>>3), b = max-1-(max>>3), c;
2010 int64_t fa = f(key, vec+a*stride),
2011 fb = f(key, vec+b*stride);
2014 c = fb-fa? b - (size_t)((
double)fb * (double)(b-a) / (double)(fb-fa)) : max-((max-min)>>1);
2016 a = b; b = c < min ? min : c >= max ? max-1 : c;
2017 fa = fb; fb = f(key, vec+b*stride);
2018 if(fb == 0) { *index = b;
return 1; }
2019 if(fb > 0) min = b+1;
else max = b; }
2020 *index = max;
return 0; })
2022 $define FUNC_T_TT(TYPE) int64_t(*f)(TYPE,TYPE)
2024 $define BLOCK_T_TT(TYPE) int64_t(^f)(TYPE,TYPE)
2026 $define LAMBDA_T_TT(TYPE) std::function<int64_t(TYPE,TYPE)>f
2028 GENERATE_GENERICS(AARRAY_searchCompare,,)
2029 GENERATE_GENERICS(AARRAY_binary, FUNC, FUNC_T_TT)
2030 GENERATE_GENERICS(AARRAY_pingpong, FUNC, FUNC_T_TT)
2031 GENERATE_GENERICS(AARRAY_pingpongS, FUNC, FUNC_T_TT)
2032 #define aSearch(vec, index, key) \
2033 ((int(*)(void*, size_t*, uint64_t, void(*)(void))) \
2034 AARRAY_binary_FUNC_FUNCTIONS[TEST_width(*vec)]) \
2035 (vec, index, (uint64_t)key, \
2036 (void(*)(void))AARRAY_searchCompare__FUNCTIONS[TEST_width(*vec)])
2037 #define aSearchF_FUNC(vec, index, key, f) \
2038 ((int(*)(void*, size_t*, uint64_t, void(*)(void))) \
2039 AARRAY_binary_FUNC_FUNCTIONS[TEST_width(*vec)]) \
2040 (vec, index, (uint64_t)key, (void(*)(void))f)
2041 #define aSearchP(vec, index, key) \
2042 ((int(*)(void*, size_t*, uint64_t, void(*)(void))) \
2043 AARRAY_pingpong_FUNC_FUNCTIONS[TEST_width(*vec)]) \
2044 (vec, index, (uint64_t)key, \
2045 (void(*)(void))AARRAY_searchCompare__FUNCTIONS[TEST_width(*vec)])
2046 #define aSearchPF_FUNC(vec, index, key, f) \
2047 ((int(*)(void*, size_t*, uint64_t, void(*)(void))) \
2048 AARRAY_pingpong_FUNC_FUNCTIONS[TEST_width(*vec)]) \
2049 (vec, index, (uint64_t)key, (void(*)(void))f)
2050 #define aSearchPS_FUNC(vec, index, key, f, stride) \
2051 ((int(*)(void*, size_t*, uint64_t, void(*)(void), size_t)) \
2052 AARRAY_pingpongS_FUNC_FUNCTIONS[TEST_width(*vec)]) \
2053 (vec, index, (uint64_t)key, (void(*)(void))f, stride)
2055 #if __has_extension(blocks)
2056 GENERATE_GENERICS(AARRAY_binary, BLOCK, BLOCK_T_TT)
2057 GENERATE_GENERICS(AARRAY_pingpong, BLOCK, BLOCK_T_TT)
2058 GENERATE_GENERICS(AARRAY_pingpongS, BLOCK, BLOCK_T_TT)
2059 #define aSearchF_BLOCK(vec, index, key, f) \
2060 ((int(*)(void*, size_t*, uint64_t, void*)) \
2061 AARRAY_binary_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
2062 (vec, index, (uint64_t)key, (void*)f)
2063 #define aSearchPF_BLOCK(vec, index, key, f) \
2064 ((int(*)(void*, size_t*, uint64_t, void*)) \
2065 AARRAY_pingpong_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
2066 (vec, index, (uint64_t)key, (void*)f)
2067 #define aSearchPS_BLOCK(vec, index, key, f, stride) \
2068 ((int(*)(void*, size_t*, uint64_t, void*, size_t)) \
2069 AARRAY_pingpongS_BLOCK_FUNCTIONS[TEST_width(*vec)]) \
2070 (vec, index, (uint64_t)key, (void*)f, stride)
2072 #if defined(__cplusplus)
2073 GENERATE_GENERICS(AARRAY_binary, LAMBDA, LAMBDA_T_TT)
2074 GENERATE_GENERICS(AARRAY_pingpong, LAMBDA, LAMBDA_T_TT)
2075 GENERATE_GENERICS(AARRAY_pingpongS, LAMBDA, LAMBDA_T_TT)
2076 #define aSearchF_LAMBDA(vec, index, key, f) \
2077 ((int(*)(void*, size_t*, uint64_t, \
2078 std::function<int64_t(uint64_t,uint64_t)>)) \
2079 AARRAY_binary_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
2080 (vec, index, (uint64_t)key, \
2081 (std::function<int64_t(uint64_t,uint64_t)>)f)
2082 #define aSearchPF_LAMBDA(vec, index, key, f) \
2083 ((int(*)(void*, size_t*, uint64_t, \
2084 std::function<int64_t(uint64_t,uint64_t)>)) \
2085 AARRAY_pingpong_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
2086 (vec, index, (uint64_t)key, \
2087 (std::function<int64_t(uint64_t,uint64_t)>)f)
2088 #define aSearchPS_LAMBDA(vec, index, key, f, stride) \
2089 ((int(*)(void*, size_t*, uint64_t, \
2090 std::function<int64_t(uint64_t*,uint64_t*)>, size_t)) \
2091 AARRAY_pingpongS_LAMBDA_FUNCTIONS[TEST_width(*vec)]) \
2092 (vec, index, (uint64_t)key, \
2093 (std::function<int64_t(uint64_t*,uint64_t*)>)f, stride)
2099 #if !defined(AARRAY_NOCONVENIENCE)
2100 #if __has_extension(blocks)
2101 #define aMap aMap_BLOCK
2102 #define aFilter aFilter_BLOCK
2103 #define aFold aFold_BLOCK
2104 #define aLoop aLoop_BLOCK
2105 #define aSortF aSortF_BLOCK
2106 #define aSearchF aSearchF_BLOCK
2107 #define aSearchPS aSearchPS_BLOCK
2108 #define aSearchPF aSearchPF_BLOCK
2109 #elif defined(__cplusplus)
2110 #define aMap aMap_LAMBDA
2111 #define aFilter aFilter_LAMBDA
2112 #define aFold aFold_LAMBDA
2113 #define aLoop aLoop_LAMBDA
2114 #define aSortF aSortF_LAMBDA
2115 #define aSearchF aSearchF_LAMBDA
2116 #define aSearchPS aSearchPS_LAMBDA
2117 #define aSearchPF aSearchPF_LAMBDA
2119 #define aMap aMap_FUNC
2120 #define aFilter aFilter_FUNC
2121 #define aFold aFold_FUNC
2122 #define aLoop aLoop_FUNC
2123 #define aSortF aSortF_FUNC
2124 #define aSearchF aSearchF_FUNC
2125 #define aSearchPS aSearchPS_FUNC
2126 #define aSearchPF aSearchPF_FUNC
2134 $define AARRAY_Write(TYPE, ...)
2135 AARRAY_define(
int AARRAY_Write__$
##TYPE(
2136 char errLoc[], FILE*file,
size_t vecsCount, uintptr_t vecs[]), {
2137 AARRAY_safety((
void)errLoc,
if(!file) AARRAY_Error_NullParameter);
2138 size_t n = (size_t)-1;
while(++n < vecsCount)
2140 *((
size_t*)vecs[n]-1) >
2141 fwrite((
void*)vecs[n],
sizeof(TYPE), *((
size_t*)vecs[n]-1), file))
2145 $define AARRAY_WriteE(TYPE, ...)
2146 AARRAY_define(
int AARRAY_WriteE__$##TYPE(
2147 size_t vecsCount, uintptr_t vecs[]), {
2149 size_t n = (size_t)-1;
while(++n < vecsCount)
2151 *((
size_t*)vecs[n]-1) >
2152 fwrite((
void*)vecs[n],
sizeof(TYPE), *((
size_t*)vecs[n]-1), stderr))
2157 GENERATE_GENERICS(AARRAY_Write,)
2158 GENERATE_GENERICS(AARRAY_WriteE,)
2160 #define AARRAY_ArgsHead(A, ...) A
2162 #define aWriteF(file, ...) \
2163 ((int(*)(char[], FILE*, size_t, uintptr_t[])) \
2164 AARRAY_Write__FUNCTIONS[TEST_width(*AARRAY_ArgsHead(__VA_ARGS__, NULL))]) \
2165 (AARRAY_LINE, file, \
2166 AARRAY_nowarn_internal_start AARRAY_PtrArgs(__VA_ARGS__) \
2167 AARRAY_nowarn_internal_end)
2168 #define aWrite(...) aWriteF(stdout, __VA_ARGS__)
2169 #define aWriteE(...) \
2170 ((int(*)(size_t, uintptr_t[])) \
2171 AARRAY_WriteE__FUNCTIONS[TEST_width(*AARRAY_ArgsHead(__VA_ARGS__, NULL))]) \
2173 AARRAY_nowarn_internal_start AARRAY_PtrArgs(__VA_ARGS__) \
2174 AARRAY_nowarn_internal_end)
2183 AARRAY_define(
void AARRAY_percent_parse(
2184 char errLoc[],
const char fmt[],
size_t*pptr,
2185 char*pspecifier,
int*pnum1,
int*pnum2,
2186 size_t*pstart,
size_t*pend,
size_t*doublePercent), {
2188 char specifier = *pspecifier;
int num1 = *pnum1, num2 = *pnum2;
2189 size_t start = *pstart;
size_t end = *pend;
size_t ptr = *pptr;
2191 if(fmt[ptr] ==
'\0') {
2193 specifier =
'e';
break; }
2194 else if(0==strncmp(fmt+ptr,
"%v", 2)) {
2196 ptr = start = ptr+2;
2197 specifier =
'v';
break; }
2198 else if(0==strncmp(fmt+ptr,
"%s", 2)) {
2200 ptr = start = ptr+2;
2201 specifier =
's';
break; }
2202 else if(0==strncmp(fmt+ptr,
"%c", 2)) {
2204 ptr = start = ptr+2;
2205 specifier =
'c';
break; }
2206 else if(0==strncmp(fmt+ptr,
"%%", 2)) {
2208 ptr = start = ptr+2;
2209 *doublePercent = ptr;
2210 specifier =
'%';
break; }
2211 else if(fmt[ptr] ==
'%') {
2215 ptr++;
size_t ptr_start = ptr;
2216 AARRAY_safety((
void)errLoc;,
2217 if(fmt[ptr]==
'\0') AARRAY_Error_FormatStringMalformed);
2220 char num_str[] =
"10";
2221 while(fmt[ptr] >=
'0' && fmt[ptr] <=
'9') ptr++;
2222 AARRAY_safety(,
if(ptr-ptr_start > 2) AARRAY_Error_FormatStringMalformed
2223 else)
if(ptr != ptr_start) {
2224 num_str[0] = fmt[ptr_start];
2225 num_str[1] = (ptr != ptr_start+1 ? fmt[ptr_start+1] :
'\0');
2226 num1 = (int)strtoul(num_str, NULL, 10); }
2229 specifier = fmt[ptr++];
2230 AARRAY_safety(,
if((specifier !=
'i' && specifier !=
'u' &&
2231 specifier !=
'f' && specifier !=
'd') ||
2232 (num1 < 2 || num1 > 64))
2233 AARRAY_Error_FormatStringMalformed);
2235 if(specifier ==
'i' || specifier ==
'u') {
2236 if(0==strncmp(fmt+ptr,
"ll", 2)) {
2237 num2 =
sizeof(
long long)*8; ptr+=2; }
2238 else if(0==strncmp(fmt+ptr,
"16", 2)) { num2 = 16; ptr+=2; }
2239 else if(0==strncmp(fmt+ptr,
"32", 2)) { num2 = 32; ptr+=2; }
2240 else if(0==strncmp(fmt+ptr,
"64", 2)) { num2 = 64; ptr+=2; }
2241 else switch(fmt[ptr]) {
2242 case 'c':
case '8': num2 =
sizeof(char)*8; ptr++;
break;
2243 case 's': num2 =
sizeof(short)*8; ptr++;
break;
2244 case 'i': num2 =
sizeof(int)*8; ptr++;
break;
2245 case 'l': num2 =
sizeof(long)*8; ptr++;
break;
2246 case 'z': num2 =
sizeof(size_t)*8; ptr++;
break;
2247 case 'm': num2 =
sizeof(intmax_t)*8; ptr++;
break;
2248 case 'p': num2 =
sizeof(intptr_t)*8; ptr++;
break;
2249 default: num2 =
sizeof(int)*8; } }
2250 else if(specifier ==
'f'){ num2 =
sizeof(float)*8; }
2251 else if(specifier ==
'd'){ num2 =
sizeof(double)*8; }
2252 else { AARRAY_safety(, AARRAY_Error_FormatStringMalformed); }
2253 AARRAY_safety(,
if(!num2) AARRAY_Error_FormatStringMalformed);
2258 *pspecifier = specifier; *pnum1 = num1; *pnum2 = num2;
2259 *pend = end; *pstart = start; *pptr = ptr; })
2261 static const char AARRAY_baseChars[] =
2262 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._";
2263 AARRAY_define(
void AARRAY_u_to_str(
2266 char str[(8 *
sizeof(int64_t))+1],
int base), {
2269 if(base<2 || base>64) base = 10;
2271 do *walkstr++ = AARRAY_baseChars[value%(
unsigned int)base];
while(value/=(
unsigned int)base);
2273 char aux;
while(--walkstr>str) aux=*walkstr, *walkstr=*str, *str++=aux; })
2274 AARRAY_define(
void AARRAY_i_to_str(
2276 char str[(8 *
sizeof(int64_t))+1],
int base), {
2279 if(base<2 || base>64) base = 10;
2280 uint8_t sign = value < 0;
2281 if(sign) value = -value;
2283 do *walkstr++ = AARRAY_baseChars[(uint64_t)value%(
unsigned int)base];
2284 while((value=(int64_t)((uint64_t)value/(
unsigned int)base)));
2285 if(sign) *walkstr++ =
'-';
2286 else *walkstr++ =
'+';
2288 char aux;
while(--walkstr>str) aux=*walkstr, *walkstr=*str, *str++=aux; })
2291 $define OUTPUT_A(A,B) A
2293 $define OUTPUT_B(A,B) B
2295 $define FMT_PRINT(isCHAR, isCHARptr, isINT8, isINT16, isINT32,
2296 isINT64, isFLOAT, isDOUBLE, OUTPUT_AB)
2298 OUTPUT_AB(
if(EOF==fputc(
'%', fmtOut))
return -1,
2299 (
void)aAppend(fmtOut,
'%'));
2302 AARRAY_safety(,
if(vc>=vecCount) AARRAY_Error_FormatStringArgs);
2303 AARRAY_safety(,
if(!vec[vc]) AARRAY_Error_NullParameter)
2304 OUTPUT_AB(
if(EOF==fputs(isCHARptr, fmtOut))
return -1,
2305 (
void)aAppendArray(fmtOut, SIZE_MAX,
2306 (uintptr_t)AARRAY_move(isCHARptr)));
2309 AARRAY_safety(,
if(vc>=vecCount) AARRAY_Error_FormatStringArgs);
2310 OUTPUT_AB(
if(EOF==fputc(isCHAR, fmtOut))
return -1,
2311 (
void)aAppend(fmtOut, (uint8_t)isCHAR));
2314 AARRAY_safety(,
if(vc>=vecCount) AARRAY_Error_FormatStringArgs);
2315 AARRAY_u_to_str((num2==8? isINT8 :
2316 (num2==16? isINT16 : (num2==32? isINT32 :isINT64))),
2318 OUTPUT_AB(
if(EOF==fputs(buffer, fmtOut))
return -1,
2319 (
void)aAppendArray(fmtOut, SIZE_MAX,
2320 (uintptr_t)AARRAY_move(buffer)));
2323 AARRAY_safety(,
if(vc>=vecCount) AARRAY_Error_FormatStringArgs);
2324 AARRAY_i_to_str((num2==8? (int8_t)isINT8 :
2325 (num2==16? (int16_t)isINT16 :
2326 (num2==32? (int32_t)isINT32 : (int64_t)isINT64))),
2328 OUTPUT_AB(
if(EOF==fputs(buffer, fmtOut))
return -1,
2329 (
void)aAppendArray(fmtOut, SIZE_MAX,
2330 (uintptr_t)AARRAY_move(buffer)));
2332 case 'f':
case 'd': {
2333 AARRAY_safety(,
if(vc>=vecCount) AARRAY_Error_FormatStringArgs);
2334 OUTPUT_AB(
if(EOF==fprintf(fmtOut,
"%g",
2335 specifier==
'f'?(
double)isFLOAT:isDOUBLE))
return -1,
2336 int len = snprintf(*fmtOut, 0,
"%g",
2337 specifier==
'f'?(
double)isFLOAT:isDOUBLE);
2339 size_t oldlen = aLength(*fmtOut);
2340 (void)aMulti(fmtOut, oldlen, 0, 0, (uintptr_t)len+1, 0);
2341 snprintf(&(*fmtOut)[oldlen], (
size_t)len+1,
"%g",
2342 specifier==
'f'?(
double)isFLOAT:isDOUBLE);
2343 (void)aZLength2(*fmtOut, 1));
2346 $define GENERATE_Fmt(NAME, OUTPUT_AB)
2347 AARRAY_define(
int AARRAY_Fmt_$##NAME(
char errLoc[],
2348 OUTPUT_AB(FILE*,
char**) fmtOut,
2349 size_t vecCount, uint64_t vec[]), {
2350 AARRAY_safety(,
if(!fmtOut) AARRAY_Error_NullParameter);
2351 size_t ptr= 0, prevStart = 0, start = 0, end = 0, vc = 0;
2352 char specifier = 0;
size_t doublePercent;
2354 int num1 = 0, num2 = 0;
2355 if(!vecCount)
return 0;
2356 char*fmt = (
char*)vec[vc++];
2357 AARRAY_safety(,
if(!fmt) AARRAY_Error_NullParameter);
2359 char buffer[(8 *
sizeof(intmax_t))+1];
2362 AARRAY_percent_parse(errLoc, fmt, &ptr,
2363 &specifier, &num1, &num2, &start, &end,
2365 OUTPUT_AB(
if(end-prevStart < fwrite(fmt+prevStart,
sizeof(
char),
2366 end-prevStart, fmtOut))
return -1,
2367 (
void)aAppendArray(fmtOut, end-prevStart,
2368 (uintptr_t)AARRAY_move(&fmt[prevStart])));
2371 AARRAY_safety(, OUTPUT_AB(, (
void)aAppend(fmtOut,
'X'); (void)aZLength2(*fmtOut, 1)));
2373 FMT_PRINT((
char)vec[vc], (
char*)vec[vc], (uint8_t)vec[vc],
2374 (uint16_t)vec[vc], (uint32_t)vec[vc], (uint64_t)vec[vc],
2375 *(
float*)&vec[vc], *(
double*)&vec[vc], OUTPUT_AB)
2377 AARRAY_safety(,
if(vc>=vecCount) AARRAY_Error_FormatStringArgs);
2381 AARRAY_percent_parse(errLoc, fmt, &ptr,
2382 &specifier, &num1, &num2, &start, &end,
2384 while(specifier ==
'%');
2385 AARRAY_safety(,
if(specifier==
'e' || specifier==
'v')
2386 AARRAY_Error_FormatStringMalformed);
2387 size_t nn = (size_t)-1;
while(++nn < aLength((uintptr_t*)(vec[vc]))) {
2392 size_t ptr2 = prevStart;
while(ptr2 < doublePercent)
2394 case '%': ptr2+=2; OUTPUT_AB(fputc(
'%', fmtOut),
2395 (
void)aAppend(fmtOut,
'%'));
break;
2396 default: OUTPUT_AB(fputc(fmt[ptr2++], fmtOut),
2397 (
void)aAppend(fmtOut, (uint8_t)fmt[ptr2++])); }
2398 prevStart = doublePercent; }
2399 OUTPUT_AB(
if(end-prevStart <fwrite(fmt+prevStart,
sizeof(
char),
2400 end-prevStart, fmtOut))
return -1,
2401 (
void)aAppendArray(fmtOut, end-prevStart,
2402 (uintptr_t)AARRAY_move(&fmt[prevStart]))); }
2404 FMT_PRINT(((
char*)vec[vc])[nn], ((
char**)vec[vc])[nn],
2405 ((uint8_t*)vec[vc])[nn], ((uint16_t*)vec[vc])[nn],
2406 ((uint32_t*)vec[vc])[nn], ((uint64_t*)vec[vc])[nn],
2407 ((
float*)vec[vc])[nn], ((
double*)vec[vc])[nn], OUTPUT_AB); } }
2413 GENERATE_Fmt(File, OUTPUT_A)
2414 GENERATE_Fmt(Array, OUTPUT_B)
2416 AARRAY_define(
int AARRAY_Fmt_Error(
2417 char errLoc[],
size_t vecCount, uint64_t vec[]), {
2419 int returnValue = AARRAY_Fmt_File(errLoc, stderr, vecCount, vec);
2421 return returnValue; })
2423 #define aFmt(...) AARRAY_Fmt_File (AARRAY_LINE, stdout, \
2424 AARRAY_64bitArgs(__VA_ARGS__))
2425 #define aFmtE(...) AARRAY_Fmt_Error(AARRAY_LINE, \
2426 AARRAY_64bitArgs(__VA_ARGS__))
2427 #define aFmtF(file, ...) AARRAY_Fmt_File (AARRAY_LINE, file, \
2428 AARRAY_64bitArgs(__VA_ARGS__))
2429 #define aFmtA(array, ...) AARRAY_Fmt_Array(AARRAY_LINE, array, \
2430 AARRAY_64bitArgs(__VA_ARGS__))
2435 #if !defined(AARRAY_NOCONVENIENCE)
2438 #define aAA aAppendArray
2439 #define aRA aReplaceArray
2444 #define aL2 aLength2
2445 #define aZL2 aZLength2
2455 #define aStr(string) aAppendArray((char**)NULL, SIZE_MAX, (uintptr_t)string)
2458 #if defined(__cplusplus)
2459 AARRAY_nowarn_pedantic_cpp_end