-
Notifications
You must be signed in to change notification settings - Fork 0
/
mackro_tricks.h
510 lines (435 loc) · 24.9 KB
/
mackro_tricks.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
#ifndef MACKRO_TRICKS
#define MACKRO_TRICKS
/******************************
* Mad<ro Trid<s *
* *
* Preprocessing time binary *
* arithmetic and cycles! *
* *
* By: Nuno Fernandes *
* (a.k.a UnknowableCoder) *
* *
******************************/
//Inspiration and hints taken from:
//https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
//This implementation handles arbitrary size arithmetics.
//LOGIC VALUES: , 0, 1
//INTERNALLY USED IDENTIFIERS: x, z
//(obviously should not be #defined,
// but, unless being deliberately obnoxious,
// why would someone do that?)
#define MACKRO_EMPTY()
#define MACKRO_DEFER(id) id MACKRO_EMPTY()
#define MACKRO_OBSTRUCT(...) __VA_ARGS__ MACKRO_DEFER(MACKRO_EMPTY)()
#define MACKRO_ABSORB(...)
#define MACKRO_EXPAND(...) __VA_ARGS__
//Increase the depth of recursion to
//enable larger/more complex/nested cycles.
#define MACKRO_EVAL(...) MACKRO_EVAL1(MACKRO_EVAL1(MACKRO_EVAL1(__VA_ARGS__)))
#define MACKRO_EVAL1(...) MACKRO_EVAL2(MACKRO_EVAL2(MACKRO_EVAL2(__VA_ARGS__)))
#define MACKRO_EVAL2(...) MACKRO_EVAL3(MACKRO_EVAL3(MACKRO_EVAL3(__VA_ARGS__)))
#define MACKRO_EVAL3(...) MACKRO_EVAL4(MACKRO_EVAL4(MACKRO_EVAL4(__VA_ARGS__)))
#define MACKRO_EVAL4(...) MACKRO_EVAL5(MACKRO_EVAL5(MACKRO_EVAL5(__VA_ARGS__)))
#define MACKRO_EVAL5(...) MACKRO_EVAL6(MACKRO_EVAL6(MACKRO_EVAL6(__VA_ARGS__)))
#define MACKRO_EVAL6(...) MACKRO_EVAL7(MACKRO_EVAL7(MACKRO_EVAL7(__VA_ARGS__)))
#define MACKRO_EVAL7(...) MACKRO_EVAL_BASE(MACKRO_EVAL_BASE(MACKRO_EVAL_BASE(__VA_ARGS__)))
#define MACKRO_EVAL_BASE(...) __VA_ARGS__
#define MACKRO_CAT(A, ...) MACKRO_CAT_H(A, __VA_ARGS__)
#define MACKRO_CAT_H(A, ...) A ## __VA_ARGS__
#define MACKRO_NOT(x) MACKRO_NOT_IMP(x)
#define MACKRO_NOT_IMP(x) MACKRO_CAT(MACKRO_NOT_, x)()
#define MACKRO_NOT_0() 1
#define MACKRO_NOT_1() 0
#define MACKRO_NOT_()
#define MACKRO_AND(x, y) MACKRO_AND_IMP(x, y)
#define MACKRO_AND_IMP(x, y) MACKRO_CAT(MACKRO_AND_, x) (y)
#define MACKRO_AND_0(y) 0
#define MACKRO_AND_1(y) y
#define MACKRO_AND_(y)
#define MACKRO_OR(x, y) MACKRO_OR_IMP(x, y)
#define MACKRO_OR_IMP(x, y) MACKRO_CAT(MACKRO_OR_, x) (y)
#define MACKRO_OR_0(y) y
#define MACKRO_OR_1(y) 1
#define MACKRO_OR_(y)
#define MACKRO_NAND(x, y) MACKRO_NAND_IMP(x, y)
#define MACKRO_NAND_IMP(x, y) MACKRO_CAT(MACKRO_CAT(MACKRO_NAND_, x), y)()
#define MACKRO_NAND_00() 1
#define MACKRO_NAND_01() 1
#define MACKRO_NAND_10() 1
#define MACKRO_NAND_11() 0
#define MACKRO_NAND_0()
#define MACKRO_NAND_1()
#define MACKRO_NAND_()
#define MACKRO_NOR(x, y) MACKRO_NOR_IMP(x, y)
#define MACKRO_NOR_IMP(x, y) MACKRO_CAT(MACKRO_CAT(MACKRO_NOR_, x), y)()
#define MACKRO_NOR_00() 1
#define MACKRO_NOR_01() 0
#define MACKRO_NOR_10() 0
#define MACKRO_NOR_11() 0
#define MACKRO_NOR_0()
#define MACKRO_NOR_1()
#define MACKRO_NOR_()
#define MACKRO_XOR(x, y) MACKRO_XOR(x, y)
#define MACKRO_XOR_IMP(x, y) MACKRO_CAT(MACKRO_CAT(MACKRO_XOR_, x), y)()
#define MACKRO_XOR_00() 0
#define MACKRO_XOR_01() 1
#define MACKRO_XOR_10() 1
#define MACKRO_XOR_11() 0
#define MACKRO_XOR_0()
#define MACKRO_XOR_1()
#define MACKRO_XOR_()
#define MACKRO_XNOR(x, y) MACKRO_XNOR_IMP(x, y)
#define MACKRO_XNOR_IMP(x, y) MACKRO_CAT(MACKRO_CAT(MACKRO_XNOR_, x), y)()
#define MACKRO_XNOR_00() 1
#define MACKRO_XNOR_01() 0
#define MACKRO_XNOR_10() 0
#define MACKRO_XNOR_11() 1
#define MACKRO_XNOR_0()
#define MACKRO_XNOR_1()
#define MACKRO_XNOR_()
#define MACKRO_IF(COND, ...) MACKRO_CAT(MACKRO_IF_, COND) (__VA_ARGS__)
#define MACKRO_IF_0(...)
#define MACKRO_IF_1(...) __VA_ARGS__
#define MACKRO_IF_(...)
#define MACKRO_HEAD(x, ...) x
#define MACKRO_TAIL(x, ...) __VA_ARGS__
#define MACKRO_FIRST(a, ...) a
#define MACKRO_SECOND(a, b, ...) b
#define MACKRO_THIRD(a, b, c, ...) c
#define MACKRO_FOURTH(a, b, c, d, ...) d
#define MACKRO_FIFTH(a, b, c, d, e, ...) e
#define MACKRO_PACK(...) ( __VA_ARGS__ )
//Returns 0 if only one argument is given, 1 otherwise.
//All 0,1, of course!
#define MACKRO_IS_PACK(...) MACKRO_IS_PACK_IN(__VA_ARGS__, )
#define MACKRO_IS_PACK_IN(x, y, ...) MACKRO_CAT(MACKRO_IS_PACK_IN_, y)()
#define MACKRO_IS_PACK_IN_0() 1
#define MACKRO_IS_PACK_IN_1() 1
#define MACKRO_IS_PACK_IN_() 0
#define MACKRO_IF_ELSE(COND, ...) MACKRO_CAT(MACKRO_IF_ELSE_, COND) (__VA_ARGS__)
#define MACKRO_IF_ELSE_1(EFF, ...) EFF
#define MACKRO_IF_ELSE_0(EFF, ...) __VA_ARGS__
#define MACKRO_IF_ELSE_(EFF, ...)
//Expects something of the form <COND1>, EFFECT1, <COND2>, EFFECT2...
//Will expand to the first true condition,
//so it's like a series of else-if.
//Unfortunately, no support for a final else,
//unless we do MACKRO_BRANCH(..., 1, ELSE_EFFECT).
#define MACKRO_BRANCH(...) MACKRO_BRANCH_IN(__VA_ARGS__, , )
#define MACKRO_BRANCH_IN(C1, EFF, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_BRANCH_H_, C1)) () (EFF, __VA_ARGS__)
#define MACKRO_BRANCH_H_0() MACKRO_BRANCH_CONT
#define MACKRO_BRANCH_H_1() MACKRO_BRANCH_STOP
#define MACKRO_BRANCH_H_() MACKRO_ABSORB
#define MACKRO_BRANCH_H_() MACKRO_ABSORB
#define MACKRO_BRANCH_CONT(EFF, ...) MACKRO_BRANCH_IN(__VA_ARGS__)
#define MACKRO_BRANCH_STOP(EFF, ...) EFF
#define MACKRO_BIT_ADD(A, B, C)\
MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_BIT_ADD_, A), B), C)()
//Gives (carry, result)
#define MACKRO_BIT_ADD_000() (0, 0)
#define MACKRO_BIT_ADD_001() (0, 1)
#define MACKRO_BIT_ADD_010() (0, 1)
#define MACKRO_BIT_ADD_011() (1, 0)
#define MACKRO_BIT_ADD_100() (0, 1)
#define MACKRO_BIT_ADD_101() (1, 0)
#define MACKRO_BIT_ADD_110() (1, 0)
#define MACKRO_BIT_ADD_111() (1, 1)
#define MACKRO_BIT_SUB(A, B, C)\
MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_BIT_SUB_, A), B), C)()
//Gives (borrowed, result)
#define MACKRO_BIT_SUB_000() (0, 0)
#define MACKRO_BIT_SUB_001() (1, 1)
#define MACKRO_BIT_SUB_010() (1, 1)
#define MACKRO_BIT_SUB_011() (1, 0)
#define MACKRO_BIT_SUB_100() (0, 1)
#define MACKRO_BIT_SUB_101() (0, 0)
#define MACKRO_BIT_SUB_110() (0, 0)
#define MACKRO_BIT_SUB_111() (1, 1)
#define MACKRO_BIT_ADD_C(A, B, C)\
MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_BIT_ADD_C_, A), B), C)()
//Gives carry
#define MACKRO_BIT_ADD_C_000() 0
#define MACKRO_BIT_ADD_C_001() 0
#define MACKRO_BIT_ADD_C_010() 0
#define MACKRO_BIT_ADD_C_011() 1
#define MACKRO_BIT_ADD_C_100() 0
#define MACKRO_BIT_ADD_C_101() 1
#define MACKRO_BIT_ADD_C_110() 1
#define MACKRO_BIT_ADD_C_111() 1
#define MACKRO_BIT_SUB_C(A, B, C)\
MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_BIT_SUB_C_, A), B), C)()
//Gives borrowed
#define MACKRO_BIT_SUB_C_000() 0
#define MACKRO_BIT_SUB_C_001() 1
#define MACKRO_BIT_SUB_C_010() 1
#define MACKRO_BIT_SUB_C_011() 1
#define MACKRO_BIT_SUB_C_100() 0
#define MACKRO_BIT_SUB_C_101() 0
#define MACKRO_BIT_SUB_C_110() 0
#define MACKRO_BIT_SUB_C_111() 1
#define MACKRO_BIT_ADD_R(A, B, C)\
MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_BIT_ADD_R_, A), B), C)()
//Gives result
#define MACKRO_BIT_ADD_R_000() 0
#define MACKRO_BIT_ADD_R_001() 1
#define MACKRO_BIT_ADD_R_010() 1
#define MACKRO_BIT_ADD_R_011() 0
#define MACKRO_BIT_ADD_R_100() 1
#define MACKRO_BIT_ADD_R_101() 0
#define MACKRO_BIT_ADD_R_110() 0
#define MACKRO_BIT_ADD_R_111() 1
#define MACKRO_BIT_SUB_R(A, B, C)\
MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_BIT_SUB_R_, A), B), C)()
//Gives result
#define MACKRO_BIT_SUB_R_000() 0
#define MACKRO_BIT_SUB_R_001() 1
#define MACKRO_BIT_SUB_R_010() 1
#define MACKRO_BIT_SUB_R_011() 0
#define MACKRO_BIT_SUB_R_100() 1
#define MACKRO_BIT_SUB_R_101() 0
#define MACKRO_BIT_SUB_R_110() 0
#define MACKRO_BIT_SUB_R_111() 1
//The macros that follow always input in the form (NEXT_FUNCTION, NEXT_ARG, N_1, N_2, ...)
//where the N_i are either 0, 1 or empty
//and NEXT_FUNCTION is a function-like macro
//that will be called with NEXT_ARG and the remaining arguments
//(This is to allow chaining of operations
// without creating unsplittable tokens)
//This assumes something of the form , , , ... , N_1, N_2, ..., N_n;
//it will not eat until all the empty values are exhausted,
//only the set of empty values before the numbers begin.
#define MACKRO_CHAIN_EAT_INITIAL_SEP(NEXT, ARG, ...) MACKRO_EAT_INITIAL_SEP_IN(NEXT, ARG, , , , , __VA_ARGS__)
#define MACKRO_EAT_INITIAL_SEP_IN(NEXT, ARG, N, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_EAT_INITIAL_SEP_, N)) () (NEXT, ARG, N, __VA_ARGS__)
#define MACKRO_EAT_INITIAL_SEP_0() MACKRO_EAT_INITIAL_SEP_STOP
#define MACKRO_EAT_INITIAL_SEP_1() MACKRO_EAT_INITIAL_SEP_STOP
#define MACKRO_EAT_INITIAL_SEP_() MACKRO_EAT_INITIAL_SEP_CONT
#define MACKRO_EAT_INITIAL_SEP_CONT(NEXT, ARG, N, ...) MACKRO_EAT_INITIAL_SEP_IN(NEXT, ARG, __VA_ARGS__)
#define MACKRO_EAT_INITIAL_SEP_STOP(NEXT, ARG, N, ...) NEXT(ARG, N, __VA_ARGS__)
//This assumes something of the form N_1, N_2, ..., N_n, , , ... ,
//it will not eat until all the empty values are exhausted,
//only the set of empty values after the first set of numbers.
#define MACKRO_CHAIN_EAT_FINAL_SEP(NEXT, ARG, ...) MACKRO_EAT_FINAL_SEP_IN(NEXT, ARG, __VA_ARGS__, , ,)
#define MACKRO_EAT_FINAL_SEP_IN(NEXT, ARG, N, D, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_EAT_FINAL_SEP_, D)) () (NEXT, ARG, N, D, __VA_ARGS__)
#define MACKRO_EAT_FINAL_SEP_0() MACKRO_EAT_FINAL_SEP_CONT
#define MACKRO_EAT_FINAL_SEP_1() MACKRO_EAT_FINAL_SEP_CONT
#define MACKRO_EAT_FINAL_SEP_() MACKRO_EAT_FINAL_SEP_STOP
#define MACKRO_EAT_FINAL_SEP_CONT(NEXT, ARG, N, ...) MACKRO_EAT_FINAL_SEP_IN(NEXT, ARG, __VA_ARGS__, N)
#define MACKRO_EAT_FINAL_SEP_STOP(NEXT, ARG, N, ...) MACKRO_CHAIN_EAT_INITIAL_SEP(NEXT, ARG, __VA_ARGS__, N)
//This will invert any combination of binary values and empty spaces.
#define MACKRO_CHAIN_REVERSE(NEXT, ARG, ...) MACKRO_REVERSE_START(NEXT, ARG, __VA_ARGS__, x, z )
#define MACKRO_REVERSE_START(NEXT, ARG, N1, ...) \
MACKRO_CAT(MACKRO_REVERSE_CHECK_ , N1) () (NEXT, ARG, N1, __VA_ARGS__)
#define MACKRO_REVERSE_CHECK_z() MACKRO_REVERSE_END
#define MACKRO_REVERSE_CHECK_x() MACKRO_REVERSE_END
#define MACKRO_REVERSE_CHECK_1() MACKRO_REVERSE_A_IN
#define MACKRO_REVERSE_CHECK_0() MACKRO_REVERSE_A_IN
#define MACKRO_REVERSE_CHECK_() MACKRO_REVERSE_A_IN
#define MACKRO_REVERSE_A_IN(NEXT, ARG, N1, N2, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_REVERSE_A_, N2))() (NEXT, ARG, N1, N2, __VA_ARGS__)
#define MACKRO_REVERSE_A_x() MACKRO_REVERSE_A_STOP
#define MACKRO_REVERSE_A_1() MACKRO_REVERSE_A_CONT
#define MACKRO_REVERSE_A_0() MACKRO_REVERSE_A_CONT
#define MACKRO_REVERSE_A_() MACKRO_REVERSE_A_CONT
#define MACKRO_REVERSE_A_CONT(NEXT, ARG, N1, N2, ...) MACKRO_REVERSE_A_IN(NEXT, ARG, N1, __VA_ARGS__, N2)
#define MACKRO_REVERSE_A_STOP(NEXT, ARG, N1, N2, ...) MACKRO_REVERSE_B_IN(NEXT, ARG, N2, N1, __VA_ARGS__)
#define MACKRO_REVERSE_B_IN(NEXT, ARG, N, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_REVERSE_B_, N))() (NEXT, ARG, N, __VA_ARGS__)
#define MACKRO_REVERSE_B_z() MACKRO_REVERSE_B_STOP
#define MACKRO_REVERSE_B_x() MACKRO_REVERSE_B_CONT
#define MACKRO_REVERSE_B_1() MACKRO_REVERSE_B_CONT
#define MACKRO_REVERSE_B_0() MACKRO_REVERSE_B_CONT
#define MACKRO_REVERSE_B_() MACKRO_REVERSE_B_CONT
#define MACKRO_REVERSE_B_CONT(NEXT, ARG, N, ...) MACKRO_REVERSE_B_IN(NEXT, ARG, __VA_ARGS__, N)
#define MACKRO_REVERSE_B_STOP(NEXT, ARG, N, ...) MACKRO_REVERSE_START(NEXT, ARG, __VA_ARGS__, N)
#define MACKRO_REVERSE_END(NEXT, ARG, IGNORE, ...) MACKRO_REVERSE_CLEAR(NEXT, ARG, __VA_ARGS__)
//This strips the x in front.
#define MACKRO_REVERSE_CLEAR(NEXT, ARG, N, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_REVERSE_CLEAR_, N))() (NEXT, ARG, N, __VA_ARGS__)
#define MACKRO_REVERSE_CLEAR_z() MACKRO_REVERSE_CLEAR_STOP
#define MACKRO_REVERSE_CLEAR_1() MACKRO_REVERSE_CLEAR_CONT
#define MACKRO_REVERSE_CLEAR_0() MACKRO_REVERSE_CLEAR_CONT
#define MACKRO_REVERSE_CLEAR_() MACKRO_REVERSE_CLEAR_CONT
#define MACKRO_REVERSE_CLEAR_CONT(NEXT, ARG, N, ...) MACKRO_REVERSE_CLEAR(NEXT, ARG, __VA_ARGS__, N)
#define MACKRO_REVERSE_CLEAR_STOP(NEXT, ARG, N, ...) NEXT(ARG, __VA_ARGS__)
//And this strips the z in the back.
#define MACKRO_CHAIN_EAT_INITIAL_ZEROS(NEXT, ARG, ...) MACKRO_EAT_INITIAL_ZEROS_IN(NEXT, ARG, 0, __VA_ARGS__, , ,)
#define MACKRO_EAT_INITIAL_ZEROS_IN(NEXT, ARG, N, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_EAT_INITIAL_ZEROS_, N))() (NEXT, ARG, N, __VA_ARGS__)
#define MACKRO_EAT_INITIAL_ZEROS_0() MACKRO_EAT_INITIAL_ZEROS_CONT
#define MACKRO_EAT_INITIAL_ZEROS_1() MACKRO_EAT_INITIAL_ZEROS_STOP
#define MACKRO_EAT_INITIAL_ZEROS_() MACKRO_EAT_INITIAL_ZEROS_EMPTY
#define MACKRO_EAT_INITIAL_ZEROS_CONT(NEXT, ARG, N, ...) MACKRO_EAT_INITIAL_ZEROS_IN(NEXT, ARG, __VA_ARGS__)
#define MACKRO_EAT_INITIAL_ZEROS_STOP(NEXT, ARG, ...) MACKRO_CHAIN_EAT_FINAL_SEP(NEXT, ARG, __VA_ARGS__)
#define MACKRO_EAT_INITIAL_ZEROS_EMPTY(NEXT, ARG, ...) NEXT(ARG, 0)
#define MACKRO_CHAIN_EAT_FINAL_ZEROS(NEXT, ARG, ...) \
MACKRO_CHAIN_REVERSE(MACKRO_EAT_FINAL_ZEROS_D1, (NEXT, ARG), __VA_ARGS__)
#define MACKRO_EAT_FINAL_ZEROS_D1(N_A_PAIR, ...) MACKRO_CHAIN_EAT_INITIAL_ZEROS(MACKRO_EAT_FINAL_ZEROS_D2, N_A_PAIR, __VA_ARGS__)
#define MACKRO_EAT_FINAL_ZEROS_D2(N_A_PAIR, ...) MACKRO_CHAIN_REVERSE(MACKRO_HEAD N_A_PAIR, MACKRO_TAIL N_A_PAIR, __VA_ARGS__)
#define MACKRO_CHAIN_IS_ZERO(NEXT, ARG, ...) MACKRO_CHAIN_IS_ZERO_IN(NEXT, ARG, __VA_ARGS__, , , ,)
#define MACKRO_CHAIN_IS_ZERO_IN(NEXT, ARG, N, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_CHAIN_IS_ZERO_, N))() (NEXT, ARG, N, __VA_ARGS__)
#define MACKRO_CHAIN_IS_ZERO_0() MACKRO_CHAIN_IS_ZERO_CONT
#define MACKRO_CHAIN_IS_ZERO_1() MACKRO_CHAIN_IS_ZERO_FAIL
#define MACKRO_CHAIN_IS_ZERO_() MACKRO_CHAIN_IS_ZERO_PASS
#define MACKRO_CHAIN_IS_ZERO_CONT(NEXT, ARG, N, ...) MACKRO_CHAIN_IS_ZERO_IN(NEXT, ARG, __VA_ARGS__)
#define MACKRO_CHAIN_IS_ZERO_FAIL(NEXT, ARG, ...) NEXT(ARG, 0)
#define MACKRO_CHAIN_IS_ZERO_PASS(NEXT, ARG, ...) NEXT(ARG, 1)
//Adds bits in a A1, B1, A2, B2, ... pattern.
#define MACKRO_CHAIN_BITS(NEXT, ARG, OP, ...) MACKRO_BITS_IN(NEXT, ARG, OP, 0, __VA_ARGS__, , , , )
#define MACKRO_BITS_IN(NEXT, ARG, OP, C1, A1, B1, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_CAT(MACKRO_BITS_H_, A1), B1)) () \
(NEXT, ARG, OP, C1, A1, B1, __VA_ARGS__)
#define MACKRO_BITS_H_00() MACKRO_BITS_OP
#define MACKRO_BITS_H_01() MACKRO_BITS_OP
#define MACKRO_BITS_H_10() MACKRO_BITS_OP
#define MACKRO_BITS_H_11() MACKRO_BITS_OP
#define MACKRO_BITS_H_0() MACKRO_BITS_END
#define MACKRO_BITS_H_1() MACKRO_BITS_END
#define MACKRO_BITS_H_() MACKRO_BITS_END
#define MACKRO_BITS_OP(NEXT, ARG, OP, C1, A1, B1, ...)\
MACKRO_BITS_IN(NEXT, ARG, OP, MACKRO_CAT(OP, _C) (A1, B1, C1), __VA_ARGS__, MACKRO_CAT(OP, _R) (A1, B1, C1) )
#define MACKRO_BITS_END(NEXT, ARG, OP, C1, ...) MACKRO_CAT(MACKRO_BITS_END_, C1) (NEXT, ARG, OP, __VA_ARGS__)
#define MACKRO_BITS_END_0(NEXT, ARG, OP, ...) MACKRO_BITS_OUT(NEXT, ARG, __VA_ARGS__)
#define MACKRO_BITS_END_(NEXT, ARG, OP, ...) MACKRO_BITS_OUT(NEXT, ARG, __VA_ARGS__)
#define MACKRO_BITS_END_1(NEXT, ARG, OP, ...) MACKRO_CAT(MACKRO_BITS_END_1_, OP) (NEXT, ARG, __VA_ARGS__)
#define MACKRO_BITS_END_1_MACKRO_BIT_ADD(NEXT, ARG, ...) MACKRO_BITS_OUT(NEXT, ARG, __VA_ARGS__, 1)
#define MACKRO_BITS_END_1_MACKRO_BIT_SUB(NEXT, ARG, ...) NEXT(ARG, 0)
#define MACKRO_BITS_OUT(NEXT, ARG, ...) MACKRO_CHAIN_EAT_INITIAL_SEP(MACKRO_BITS_OUT_D, (NEXT, ARG), __VA_ARGS__)
#define MACKRO_BITS_OUT_D(N_A_PAIR, ...) MACKRO_CHAIN_EAT_FINAL_ZEROS(MACKRO_HEAD N_A_PAIR, MACKRO_TAIL N_A_PAIR, __VA_ARGS__)
//Puts 0 to the argument list if there are any bit differences
//and 1 if all the bits match. Takes as arguments each pair of bits,
//that it, A1, B1, A2, B2, ...
#define MACKRO_CHAIN_COMPARE(NEXT, ARG, ...) MACKRO_COMPARE_IN(NEXT, ARG, __VA_ARGS__, , ,)
#define MACKRO_COMPARE_IN(NEXT, ARG, A1, B1, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_COMPARE_, A1), a), B1))() (NEXT, ARG, __VA_ARGS__)
#define MACKRO_COMPARE_0a0() MACKRO_COMPARE_CONT
#define MACKRO_COMPARE_0a1() MACKRO_COMPARE_FAIL
#define MACKRO_COMPARE_1a0() MACKRO_COMPARE_FAIL
#define MACKRO_COMPARE_1a1() MACKRO_COMPARE_CONT
#define MACKRO_COMPARE_0a() MACKRO_COMPARE_PASS
#define MACKRO_COMPARE_1a() MACKRO_COMPARE_PASS
#define MACKRO_COMPARE_a0() MACKRO_COMPARE_PASS
#define MACKRO_COMPARE_a1() MACKRO_COMPARE_PASS
#define MACKRO_COMPARE_a() MACKRO_COMPARE_PASS
#define MACKRO_COMPARE_CONT(NEXT, ARG, ...) MACKRO_COMPARE_IN(NEXT, ARG, __VA_ARGS__)
#define MACKRO_COMPARE_FAIL(NEXT, ARG, ...) NEXT(ARG, 0)
#define MACKRO_COMPARE_PASS(NEXT, ARG, ...) NEXT(ARG, 1)
//For convenience, these macros take as arguments two tuples,
//since it's unfeasible to split the variable arguments...
#define MACKRO_CHAIN_INTERLEAVE(NEXT, ARG, N1, N2) \
MACKRO_INTERLEAVE_H(NEXT, ARG, (MACKRO_EXPAND N1, , ,), (MACKRO_EXPAND N2, , ,), , ,)
#define MACKRO_INTERLEAVE_H(NEXT, ARG, N1, N2, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_CAT(MACKRO_CAT(MACKRO_INTERLEAVE_H_,\
MACKRO_EXPAND(MACKRO_HEAD N1)),a),\
MACKRO_EXPAND(MACKRO_HEAD N2)))() (NEXT, ARG, N1, N2, __VA_ARGS__)
#define MACKRO_INTERLEAVE_H_0a0() MACKRO_INTERLEAVE_CONT
#define MACKRO_INTERLEAVE_H_0a1() MACKRO_INTERLEAVE_CONT
#define MACKRO_INTERLEAVE_H_1a0() MACKRO_INTERLEAVE_CONT
#define MACKRO_INTERLEAVE_H_1a1() MACKRO_INTERLEAVE_CONT
#define MACKRO_INTERLEAVE_H_a() MACKRO_INTERLEAVE_STOP
#define MACKRO_INTERLEAVE_H_a0() MACKRO_INTERLEAVE_FNONE
#define MACKRO_INTERLEAVE_H_a1() MACKRO_INTERLEAVE_FNONE
#define MACKRO_INTERLEAVE_H_0a() MACKRO_INTERLEAVE_SNONE
#define MACKRO_INTERLEAVE_H_1a() MACKRO_INTERLEAVE_SNONE
#define MACKRO_INTERLEAVE_FNONE(NEXT, ARG, N1, N2, ...) \
MACKRO_INTERLEAVE_H(NEXT, ARG, (,), (MACKRO_TAIL N2), __VA_ARGS__, 0, MACKRO_HEAD N2)
#define MACKRO_INTERLEAVE_SNONE(NEXT, ARG, N1, N2, ...) \
MACKRO_INTERLEAVE_H(NEXT, ARG, (MACKRO_TAIL N1), (,), __VA_ARGS__, MACKRO_HEAD N1, 0)
#define MACKRO_INTERLEAVE_STOP(NEXT, ARG, N1, N2, ...) \
MACKRO_CHAIN_EAT_INITIAL_SEP(NEXT, ARG, __VA_ARGS__)
#define MACKRO_INTERLEAVE_CONT(NEXT, ARG, N1, N2, ...) \
MACKRO_INTERLEAVE_H(NEXT, ARG, (MACKRO_TAIL N1), (MACKRO_TAIL N2), __VA_ARGS__, MACKRO_HEAD N1, MACKRO_HEAD N2)
#define MACKRO_CHAIN_OPERATE(NEXT, ARG, OP, N1, N2) MACKRO_CHAIN_INTERLEAVE(MACKRO_CHAIN_OPERATE_D1, (NEXT, ARG, OP), N1, N2)
#define MACKRO_CHAIN_OPERATE_D1(N_A_O_TUPLE, ...) \
MACKRO_CHAIN_BITS(MACKRO_FIRST N_A_O_TUPLE, MACKRO_SECOND N_A_O_TUPLE, MACKRO_THIRD N_A_O_TUPLE, __VA_ARGS__)
#define MACKRO_CHAIN_ADD(NEXT, ARG, N1, N2) MACKRO_CHAIN_OPERATE(NEXT, ARG, MACKRO_BIT_ADD, N1, N2)
#define MACKRO_CHAIN_SUB(NEXT, ARG, N1, N2) MACKRO_CHAIN_OPERATE(NEXT, ARG, MACKRO_BIT_SUB, N1, N2)
#define MACKRO_CHAIN_INCREMENT(NEXT, ARG, N) MACKRO_CHAIN_ADD(NEXT, ARG, N, (1))
#define MACKRO_CHAIN_DECREMENT(NEXT, ARG, N) MACKRO_CHAIN_SUB(NEXT, ARG, N, (1))
#define MACKRO_CHAIN_IS_LESSER_EQUAL(NEXT, ARG, A, B) MACKRO_CHAIN_SUB(MACKRO_IS_LESSER_EQUAL_D1, (NEXT, ARG), A, B)
#define MACKRO_IS_LESSER_EQUAL_D1(N_A_PAIR, ...) MACKRO_CHAIN_IS_ZERO(MACKRO_HEAD N_A_PAIR, MACKRO_TAIL N_A_PAIR, __VA_ARGS__)
//Due to the subtraction being cut at zero, A - B == 0 means A <= B
#define MACKRO_CHAIN_IS_GREATER_EQUAL(NEXT, ARG, A, B) MACKRO_CHAIN_SUB(MACKRO_IS_GREATER_EQUAL_D1, (NEXT, ARG), B, A)
#define MACKRO_IS_GREATER_EQUAL_D1(N_A_PAIR, ...) MACKRO_CHAIN_IS_ZERO(MACKRO_HEAD N_A_PAIR, MACKRO_TAIL N_A_PAIR, __VA_ARGS__)
//Due to the subtraction being cut at zero, B - A == 0 means B <= A <-> A >= B
#define MACKRO_CHAIN_IS_EQUAL(NEXT, ARG, A, B) MACKRO_CHAIN_INTERLEAVE(MACKRO_IS_EQUAL_D1, (NEXT, ARG), A, B)
#define MACKRO_IS_EQUAL_D1(N_A_PAIR, ...) MACKRO_CHAIN_COMPARE(MACKRO_HEAD N_A_PAIR, MACKRO_TAIL N_A_PAIR, __VA_ARGS__)
#define MACKRO_CHAIN_IS_LESSER(NEXT, ARG, A, B) MACKRO_CHAIN_IS_GREATER_EQUAL(MACKRO_IS_LESSER_D1, (NEXT, ARG), A, B)
#define MACKRO_IS_LESSER_D1(N_A_PAIR, VAL) MACKRO_IS_LESSER_IN(MACKRO_HEAD N_A_PAIR, MACKRO_TAIL N_A_PAIR, MACKRO_NOT(VAL))
#define MACKRO_IS_LESSER_IN(NEXT, ARG, NOT_VAL) NEXT(ARG, NOT_VAL)
#define MACKRO_CHAIN_IS_GREATER(NEXT, ARG, A, B) MACKRO_CHAIN_IS_LESSER_EQUAL(MACKRO_IS_GREATER_D1, (NEXT, ARG), A, B)
#define MACKRO_IS_GREATER_D1(N_A_PAIR, VAL) MACKRO_IS_GREATER_IN(MACKRO_HEAD N_A_PAIR, MACKRO_TAIL N_A_PAIR, MACKRO_NOT(VAL))
#define MACKRO_IS_GREATER_IN(NEXT, ARG, NOT_VAL) NEXT(ARG, NOT_VAL)
//And the versions that follow take a tuple of numbers
//and spit out a tuple of numbers. Hopefully.
#define MACKRO_PACK_TO_NUMBER(IGNORE, ...) (__VA_ARGS__)
#define MACKRO_EAT_INITIAL_SEP(N) MACKRO_CHAIN_EAT_INITIAL_SEP(MACKRO_PACK_TO_NUMBER, 0, MACKRO_HEAD N, MACKRO_TAIL N)
#define MACKRO_EAT_FINAL_SEP(N) MACKRO_CHAIN_EAT_FINAL_SEP(MACKRO_PACK_TO_NUMBER, 0, MACKRO_HEAD N, MACKRO_TAIL N)
#define MACKRO_REVERSE(N) MACKRO_CHAIN_REVERSE(MACKRO_PACK_TO_NUMBER, 0, MACKRO_HEAD N, MACKRO_TAIL N)
#define MACKRO_EAT_INITIAL_ZEROS(N) MACKRO_CHAIN_EAT_INITIAL_ZEROS(MACKRO_PACK_TO_NUMBER, 0, MACKRO_HEAD N, MACKRO_TAIL N)
#define MACKRO_EAT_FINAL_ZEROS(N) MACKRO_CHAIN_EAT_FINAL_ZEROS(MACKRO_PACK_TO_NUMBER, 0, MACKRO_HEAD N, MACKRO_TAIL N)
#define MACKRO_INTERLEAVE(N1, N2) MACKRO_CHAIN_INTERLEAVE(MACKRO_PACK_TO_NUMBER, 0, N1, N2)
#define MACKRO_OPERATE(OP, N1, N2) MACKRO_CHAIN_OPERATE(MACKRO_PACK_TO_NUMBER, 0, OP, N1, N2)
#define MACKRO_ADD(N1, N2) MACKRO_CHAIN_ADD(MACKRO_PACK_TO_NUMBER, 0, N1, N2)
#define MACKRO_SUB(N1, N2) MACKRO_CHAIN_SUB(MACKRO_PACK_TO_NUMBER, 0, N1, N2)
#define MACKRO_INCREMENT(N) MACKRO_ADD(N, (1))
#define MACKRO_DECREMENT(N) MACKRO_SUB(N, (1))
#define MACKRO_IS_ZERO(N) MACKRO_IS_ZERO_IN((MACKRO_HEAD N, MACKRO_TAIL N, , ,))
#define MACKRO_IS_ZERO_IN(N) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_IS_ZERO_, MACKRO_HEAD N))() ((MACKRO_TAIL N))
#define MACKRO_IS_ZERO_0() MACKRO_IS_ZERO_CONT
#define MACKRO_IS_ZERO_1() MACKRO_IS_ZERO_FAIL
#define MACKRO_IS_ZERO_() MACKRO_IS_ZERO_PASS
#define MACKRO_IS_ZERO_CONT(N) MACKRO_IS_ZERO_IN(N)
#define MACKRO_IS_ZERO_FAIL(...) (0)
#define MACKRO_IS_ZERO_PASS(...) (1)
#define MACKRO_IS_LESSER_EQUAL(A, B) MACKRO_CHAIN_IS_LESSER_EQUAL(MACKRO_PACK_TO_NUMBER, 0, A, B)
#define MACKRO_IS_GREATER_EQUAL(A, B) MACKRO_CHAIN_IS_GREATER_EQUAL(MACKRO_PACK_TO_NUMBER, 0, A, B)
#define MACKRO_IS_EQUAL(A, B) MACKRO_CHAIN_IS_EQUAL(MACKRO_PACK_TO_NUMBER, 0, A, B)
#define MACKRO_IS_GREATER(A, B) MACKRO_CHAIN_IS_GREATER(MACKRO_PACK_TO_NUMBER, 0, A, B)
#define MACKRO_IS_LESSER(A, B) MACKRO_CHAIN_IS_LESSER(MACKRO_PACK_TO_NUMBER, 0, A, B)
//MACKRO_EVAL(MACKRO_IS_EQUAL((0,1),(1,1)))
//And now, the crown of glory: a preprocessor-based cycle.
//For simplicity, we only allow increments,
//but, if needed, it could be generalized.
//Basically equivalent to a "for (i = START; i <= END; i += STEP) { FUNC(ARG, i); }"
#define MACKRO_CYCLE(FUNC, ARG, START, STEP, END) \
MACKRO_CHAIN_ADD(MACKRO_CYCLE_D1, (FUNC, ARG, STEP, END), START, (0))
#define MACKRO_CYCLE_D1(PARAMS, ...) \
MACKRO_CYCLE_IN(MACKRO_FIRST PARAMS, MACKRO_SECOND PARAMS, MACKRO_THIRD PARAMS, MACKRO_FOURTH PARAMS, (__VA_ARGS__))
#define MACKRO_CYCLE_IN(FUNC, ARG, STEP, END, CURRENT, ...) \
MACKRO_CHAIN_IS_LESSER_EQUAL(MACKRO_CYCLE_D2, (FUNC, ARG, STEP, END, CURRENT), CURRENT, END)
#define MACKRO_CYCLE_D2(PARAMS, VAL) \
MACKRO_CAT(MACKRO_CYCLE_DECIDE_, VAL) \
(MACKRO_FIRST PARAMS, MACKRO_SECOND PARAMS, MACKRO_THIRD PARAMS, MACKRO_FOURTH PARAMS, MACKRO_FIFTH PARAMS)
#define MACKRO_CYCLE_DECIDE_1(FUNC, ARG, STEP, END, CURRENT) \
FUNC(ARG, CURRENT) MACKRO_CHAIN_ADD(MACKRO_CYCLE_D1, (FUNC, ARG, STEP, END), CURRENT, STEP)
#define MACKRO_CYCLE_DECIDE_0(...)
#define MACKRO_NUM_TO_VALUE(NUM) MACKRO_NUM_TO_VALUE_IN((MACKRO_HEAD NUM, MACKRO_TAIL NUM, , , ,))
#define MACKRO_NUM_TO_VALUE_IN(NUM) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_NUM_TO_VALUE_, MACKRO_HEAD NUM))() (NUM)
#define MACKRO_NUM_TO_VALUE_0() MACKRO_NUM_TO_VALUE_CONT
#define MACKRO_NUM_TO_VALUE_1() MACKRO_NUM_TO_VALUE_CONT
#define MACKRO_NUM_TO_VALUE_() MACKRO_NUM_TO_VALUE_STOP
#define MACKRO_NUM_TO_VALUE_CONT(NUM) MACKRO_HEAD NUM + 2 * ( MACKRO_NUM_TO_VALUE_IN((MACKRO_TAIL NUM)) )
#define MACKRO_NUM_TO_VALUE_STOP(...) 0
#define MACKRO_NUM_TO_TOKEN(NUM) MACKRO_NUM_TO_TOKEN_IN((MACKRO_HEAD NUM, MACKRO_TAIL NUM, , , ,), x)
#define MACKRO_NUM_TO_TOKEN_IN(NUM, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_NUM_TO_TOKEN_, MACKRO_HEAD NUM))() (NUM, __VA_ARGS__)
#define MACKRO_NUM_TO_TOKEN_0() MACKRO_NUM_TO_TOKEN_CONT
#define MACKRO_NUM_TO_TOKEN_1() MACKRO_NUM_TO_TOKEN_CONT
#define MACKRO_NUM_TO_TOKEN_() MACKRO_NUM_TO_TOKEN_STOP
#define MACKRO_NUM_TO_TOKEN_CONT(NUM, ...) MACKRO_NUM_TO_TOKEN_IN((MACKRO_TAIL NUM), __VA_ARGS__, MACKRO_HEAD NUM)
#define MACKRO_NUM_TO_TOKEN_STOP(NUM, ...) MACKRO_NUM_TO_TOKEN_CONCAT(__VA_ARGS__, z, z)
#define MACKRO_NUM_TO_TOKEN_CONCAT(F, ...) MACKRO_NUM_TO_TOKEN_CONCAT_IN( , __VA_ARGS__)
#define MACKRO_NUM_TO_TOKEN_CONCAT_IN(TOK, F, ...) \
MACKRO_DEFER(MACKRO_CAT(MACKRO_NUM_TO_TOKEN_CONCAT_, F))() (TOK, F, __VA_ARGS__)
#define MACKRO_NUM_TO_TOKEN_CONCAT_0() MACKRO_NUM_TO_TOKEN_CONCAT_CONT
#define MACKRO_NUM_TO_TOKEN_CONCAT_1() MACKRO_NUM_TO_TOKEN_CONCAT_CONT
#define MACKRO_NUM_TO_TOKEN_CONCAT_z() MACKRO_NUM_TO_TOKEN_CONCAT_STOP
#define MACKRO_NUM_TO_TOKEN_CONCAT_CONT(TOK, F, ...) MACKRO_NUM_TO_TOKEN_CONCAT_IN(MACKRO_CAT(F, TOK), __VA_ARGS__)
#define MACKRO_NUM_TO_TOKEN_CONCAT_STOP(TOK, ...) MACKRO_CAT(x, TOK)
#endif