p99_for.h 47.2 KB
Newer Older
(no author)'s avatar
(no author) committed
1
2
/* This may look like nonsense, but it really is -*- mode: C -*-              */
/*                                                                            */
3
/* Except for parts copied from previous work and as explicitly stated below, */
(no author)'s avatar
(no author) committed
4
/* the authors and copyright holders for this work are as follows:            */
5
/* (C) copyright  2010-2013 Jens Gustedt, INRIA, France                       */
(no author)'s avatar
(no author) committed
6
7
8
9
10
11
12
13
/* (C) copyright  2012 William Morris                                         */
/*                                                                            */
/* This file is free software; it is part of the P99 project.                 */
/* You can redistribute it and/or modify it under the terms of the QPL as     */
/* given in the file LICENSE. It is distributed without any warranty;         */
/* without even the implied warranty of merchantability or fitness for a      */
/* particular purpose.                                                        */
/*                                                                            */
(no author)'s avatar
(no author) committed
14
15
#ifndef     P99_FOR_H_
# define    P99_FOR_H_
16

Jens Gustedt's avatar
Jens Gustedt committed
17
18
/**
 ** @file
19
 ** @brief A preprocessor for loop implementation and some derived
Jens Gustedt's avatar
Jens Gustedt committed
20
21
22
23
 ** list handling macros.
 ** @see P99_FOR
 **/

24
#include "p99_block.h"
25
26
27



28
/** @addtogroup preprocessor_for Preprocessor FOR loops
29
 ** @{
30
31
 **/

32
33
#define P00_FOR0(NAME, OP, FUNC, ...)
#define P00_FOR1(NAME, OP, FUNC, ...) FUNC(NAME, P00_PRE1(__VA_ARGS__,), 0)
34

Jens Gustedt's avatar
Jens Gustedt committed
35
#ifdef P00_DOXYGEN
36
/**
37
 ** @brief A preprocessor pseudo iterator.
38
 **
39
40
41
42
43
 ** @param NAME a name or other data that is visible to all iterations
 ** @param N the number of times the iteration is to be done
 ** @param OP an operation that is performed to glue the different
 **        results of the individual iterations together
 ** @param FUNC a function that is applied in each iteration
44
 **
45
 ** In each iteration, @a FUNC will be called as @c FUNC(NAME, X, I).
46
 ** Here @a NAME is the same as the argument to ::P99_FOR. @c I is the
47
48
 ** ordinal number of this iteration step, starting from 0. @c X is
 ** the @c Ith argument from the remaining argument list of this
49
 ** invocation of ::P99_FOR.
50
 **
51
52
53
54
55
 ** @a OP is called for iterations 1 to @a N - 1 to glue the results
 ** of the @a N iterations together. It is called in the form @a
 ** OP(NAME, I, REC, RES), where @a NAME and @c I are as before. @c
 ** REC is the result of all iterations with index less than @c I, @c
 ** RES is the result of the current iteration.
56
57
 **
 ** @code
58
59
 ** #define P00_SEP(NAME, I, REC, RES) REC; RES
 ** #define P00_VASSIGN(NAME, X, I) X = (NAME)[I]
60
 **
61
 ** P99_FOR(A, 2, P00_SEP, P00_VASSIGN, toto, tutu);
62
63
 ** @endcode
 **
64
 ** Will result in
65
 ** @code
Jens Gustedt's avatar
Jens Gustedt committed
66
 ** toto = (A)[0]; tutu = (A)[1];
67
68
 ** @endcode
 **
(no author)'s avatar
(no author) committed
69
 ** To understand the associativity of the @a OP argument
70
 ** @code
71
72
 ** #define P00_SUM(NAME, I, REC, RES) ((REC) + (RES))
 ** #define P00_IDT(NAME, X, I) X
73
 **
74
 ** P99_FOR(A, 2, P00_SUM, P00_IDT, a, b, c)
75
 ** @endcode
76
 ** Will result in
77
 ** @code
78
 ** ((((a) + (b))) + (c))
79
80
 ** @endcode
 **/
81
82
83
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_FOR, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_FOR, 1)
P00_DOCUMENT_MACRO_ARGUMENT(P99_FOR, 3)
Jens Gustedt's avatar
Jens Gustedt committed
84
85
86
87
88
#define P99_FOR(NAME, N, OP, FUNC, ...)
#else
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_FOR, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_FOR, 1)
P00_DOCUMENT_MACRO_ARGUMENT(P99_FOR, 3)
89
#define P99_FOR(NAME, N, OP, FUNC, ...) P99_PASTE2(P00_FOR, N)(NAME, OP, FUNC, __VA_ARGS__)
Jens Gustedt's avatar
Jens Gustedt committed
90
#endif
91

92
93
94
95
#define P00_IGN(NAME, X, I)
#define P00_IDT(NAME, X, I) X
#define P00_POS(NAME, X, I) I
#define P00_NAM(NAME, X, I) NAME
Jens Gustedt's avatar
Jens Gustedt committed
96
#define P00_NAME_I(NAME, X, I) P99_PASTE2(NAME, I)
97
#define P00_STR(NAME, X, I) P99_STRINGIFY(X)
98
#define P00_ISIT(WHAT, X, I) (X) WHAT
99

100
101
102
103
104
105
106
107
#define P00_SUM(NAME, I, X, Y) ((X) + (Y))
#define P00_PROD(NAME, I, X, Y) ((X) * (Y))
#define P00_QUOT(NAME, I, X, Y) ((X) / (Y))
#define P00_XOR(NAME, I, X, Y) ((X) ^ (Y))
#define P00_BOR(NAME, I, X, Y) ((X) | (Y))
#define P00_BAND(NAME, I, X, Y) ((X) & (Y))
#define P00_OR(NAME, I, X, Y) ((X) || (Y))
#define P00_AND(NAME, I, X, Y) ((X) && (Y))
108
#define P00_TOKJOIN(NAME, I, X, Y) X NAME Y
109

110
111
112
113
#define P00_SEQ(NAME, I, REC, X) REC, X
#define P00_SEP(NAME, I, REC, X) REC; X
#define P00_SER(NAME, I, REC, X) REC X
#define P00_REV(NAME, I, REC, X) X, REC
114
115
#define P00_PES(NAME, I, REC, X) X; REC
#define P00_RES(NAME, I, REC, X) X REC
116

Jens Gustedt's avatar
Jens Gustedt committed
117
/**
Jens Gustedt's avatar
Jens Gustedt committed
118
119
 ** @brief generate lists of names of the form <code>NAME0, NAME1, ...</code>
 **/
120
P00_DOCUMENT_NUMBER_ARGUMENT(P99_NAME, 0)
Jens Gustedt's avatar
Jens Gustedt committed
121
122
#define P99_NAME(N, NAME) P99_FOR(NAME, N, P00_SEQ, P00_NAME_I, P99_REP(N,))

123
#define P00_FUNC(NAME, I, REC, X) NAME(REC, X)
124

125
/**
126
 ** @brief Realize the right associative operation @a OP of all the arguments.
127
128
129
130
131
132
133
134
 **
 ** Here @a OP should receive four arguments <code>NAME, X, N,
 ** REC</code> out of which @c NAME and @c N are ignored and @c X and
 ** @c REC should be interpreted as the left and right hand of the
 ** operator action, respectively.
 **
 ** @a M is the length of the list that follows it.
 **/
135
P00_DOCUMENT_NUMBER_ARGUMENT(P99_BIGOP, 1)
136
#define P99_BIGOP(OP, M, ...) P99_FOR( , M, OP, P00_IDT, __VA_ARGS__)
137
138
139
140
141
142
143
144

/**
 ** @brief Realize the right associative call of binary function @a FUNC of all the arguments.
 **
 ** Here @a FUNC should be a function of two arguments.
 **
 ** @a M is the length of the list that follows it.
 **/
145
P00_DOCUMENT_NUMBER_ARGUMENT(P99_BIGFUNC, 1)
146
#define P99_BIGFUNC(FUNC, M, ...) P99_FOR(FUNC, M, P00_FUNC, P00_IDT, __VA_ARGS__)
147

148
149
150
151
152
153
154
155
156
157
158

#define P00_REPEAT(MACRO, X, I) MACRO(I)

/**
 ** @brief Apply the macro @a MACRO @a N times
 **
 ** The macro is called with the numbers <code>0, ..., N-1</code> and
 ** the @a N results are separated by a comma.
 **
 ** In the following example we define an adhoc macro that initializes
 ** an array element with a certain structure type. The array @c P is
159
 ** an array of 10 pairs, each containing their index in the @c index
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
 ** field and a different pointer in their @c aPos field.
 ** @code
 ** typedef struct pair pair;
 ** struct pair {
 **   size_t index;
 **   double* aPos;
 ** };
 ** #define ASIZE 10
 ** double A[] = { P99_DUPL(ASIZE, 1.7) };
 ** #define INIT_PAIR(I) [I] = {                               \
 **   .index = I,                                              \
 **   .aPos = &A[I],                                           \
 **   }
 ** pair P[] = { P99_REPEAT(INIT_PAIR, ASIZE) };
 ** @endcode
 ** @see P99_UNROLL for a macro that separates the parts by @c ;
 ** @see P99_SEQ for a similar macro that applies @a MACRO to a list of items
 ** @see P99_FOR for a more generic and flexible utility
 **/
P00_DOCUMENT_MACRO_ARGUMENT(P99_REPEAT, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_REPEAT, 1)
#define P99_REPEAT(MACRO, N) P99_FOR(MACRO, N, P00_SEQ, P00_REPEAT, P99_DUPL(N,))

/**
 ** @brief Apply the macro @a MACRO @a N times
 **
 ** The macro is called with the numbers <code>0, ..., N-1</code> and
 ** the @a N results are separated by a semicolon.
 **
 ** In the following example we define an adhoc macro that copies an array element
 ** of an array @c A to the elements of another array B.
 **
 ** @code
 ** #define ASIZE 3
 ** double A[] = { P99_DUPL(ASIZE, 1.7) };
 ** double B[] = { P99_DUPL(ASIZE, 371) };
 ** #define COPY_A2B(I) B[I] = A[I]
 ** P99_UNROLL(COPY_A2B, ASIZE);
 ** @endcode
 **
 ** This will expand to
 ** @code
202
 ** B[0] = A[0]; B[1] = A[1]; B[2] = A[2];
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
 ** @endcode
 **
 ** Observe that the first two @c ; are inserted automatically as
 ** separators by the ::P99_UNROLL macro.  The final one is inserted
 ** directly in the program, right after the macro invocation.
 **
 ** @see P99_REPEAT for a macro that separates the parts by @c ,
 ** @see P99_SEQ for a similar macro that applies @a MACRO to a list of items
 ** @see P99_FOR for a more generic and flexible utility
 **/
P00_DOCUMENT_MACRO_ARGUMENT(P99_UNROLL, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_UNROLL, 1)
#define P99_UNROLL(MACRO, N) P99_FOR(MACRO, N, P00_SEP, P00_REPEAT, P99_DUPL(N,))

#define P00_MAP(MACRO, X, I) MACRO(X)
/**
 ** @brief Apply the macro @a MACRO to the rest of the argument list.
 **
 ** The macro is called with each of the other arguments and
 ** the results are separated by commas.
 **
 ** Suppose you have an enumeration type with three values:
 ** @code
 ** enum { one, two, three } ;
 ** #define ENUM_INIT(X) [X] = P99_STRINGIFY(X)
 ** char const* names[] = { P99_SEQ(ENUM_INIT, one, two, three) };
 ** @endcode
 **
 ** This will result in the following expansion
 **
 ** @code
 ** char const* names[] = { [one] = "one", [two] = "two", [three] = "three" };
 ** @endcode
 ** @see P99_REPEAT for a similar macro that applies @a MACRO a fixed number of times
 ** @see P99_SEP for a similar macro that separates the different parts with a @c ;
238
 ** @see P99_SER for a similar macro that separates the different parts with a space token
239
240
241
 ** @see P99_FOR for a more generic and flexible utility
 **/
P00_DOCUMENT_MACRO_ARGUMENT(P99_SEQ, 0)
242
#define P99_SEQ(MACRO, ...) P00_MAP_(P99_NARG(__VA_ARGS__), MACRO, (,), __VA_ARGS__)
243
244
245
246
247

/**
 ** @brief Apply the macro @a MACRO to the rest of the argument list.
 **
 ** The macro is called with each of the other arguments and
248
 ** the results are separated by a space token.
249
250
251
 **
 ** @see P99_UNROLL for a similar macro that applies @a MACRO a fixed number of times
 ** @see P99_SEQ for a similar macro that separates the different parts with a @c ,
252
 ** @see P99_SER for a similar macro that separates the different parts with a space token
253
254
255
 ** @see P99_FOR for a more generic and flexible utility
 **/
P00_DOCUMENT_MACRO_ARGUMENT(P99_SER, 0)
256
#define P99_SER(MACRO, ...) P00_MAP_(P99_NARG(__VA_ARGS__), MACRO, ( ), __VA_ARGS__)
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

/**
 ** @brief Apply the macro @a MACRO to the rest of the argument list.
 **
 ** The macro is called with each of the other arguments and
 ** the results are separated by semicolon.
 **
 ** Suppose you want to create a @c struct that has several fields of
 ** similar name and type.
 **
 ** @code
 ** #define FIELD_DECL(X) P99_PASTE2(type_, X) P99_PASTE2(X, _flag)
 ** struct bits {
 **    P99_SEP(FIELD_DECL, chaos, sat, grey);
 ** };
 ** @endcode
 **
 ** This will result in the following expansion
 **
 ** @code
 ** struct bits {
 **    type_chaos chaos_flag;
 **    type_sat sat_flag;
 **    type_grey grey_flag;
 ** };
 ** @endcode
 ** @see P99_UNROLL for a similar macro that applies @a MACRO a fixed number of times
 ** @see P99_SEQ for a similar macro that separates the different parts with a @c ,
285
 ** @see P99_SER for a similar macro that separates the different parts with a space token
286
287
288
 ** @see P99_FOR for a more generic and flexible utility
 **/
P00_DOCUMENT_MACRO_ARGUMENT(P99_SEP, 0)
289
#define P99_SEP(MACRO, ...) P00_MAP_(P99_NARG(__VA_ARGS__), MACRO, (;), __VA_ARGS__)
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
/**
 ** @brief Apply the macro @a MACRO to the rest of the argument list.
 **
 ** The macro is called with each of the other arguments and
 ** the results are joined by a <code>+</code> token.
 **
 ** @see P99_UNROLL for a similar macro that applies @a MACRO a fixed number of times
 ** @see P99_SEQ for a similar macro that separates the different parts with a @c ,
 ** @see P99_SER for a similar macro that separates the different parts with a space token
 ** @see P99_FOR for a more generic and flexible utility
 **/
P00_DOCUMENT_MACRO_ARGUMENT(P99_SEA, 0)
#define P99_SEA(MACRO, ...) P00_MAP_(P99_NARG(__VA_ARGS__), MACRO, (+), __VA_ARGS__)

/**
 ** @brief Apply the macro @a MACRO to the rest of the argument list.
 **
 ** The macro is called with each of the other arguments and
 ** the results are joined by a <code>*</code> token.
 **
 ** @see P99_UNROLL for a similar macro that applies @a MACRO a fixed number of times
 ** @see P99_SEQ for a similar macro that separates the different parts with a @c ,
 ** @see P99_SER for a similar macro that separates the different parts with a space token
 ** @see P99_FOR for a more generic and flexible utility
 **/
P00_DOCUMENT_MACRO_ARGUMENT(P99_SEM, 0)
#define P99_SEM(MACRO, ...) P00_MAP_(P99_NARG(__VA_ARGS__), MACRO, (*), __VA_ARGS__)
318
319


320
321
322
323
324
325
326
327
328
/**
 ** @}
 **/



/** @addtogroup statement_lists
 ** @{
 **/
329
330

/**
331
 ** @brief Realize the right associative sum of all the arguments.
332
 **/
333
#define P99_SUMS(...) P99_BIGOP(P00_SUM, P99_NARG(__VA_ARGS__),__VA_ARGS__)
334
/**
335
 ** @brief Realize the right associative product of all the arguments.
336
 **/
337
#define P99_PRODS(...) P99_BIGOP(P00_PROD, P99_NARG(__VA_ARGS__),__VA_ARGS__)
338
/**
339
 ** @brief Realize the right associative quotient of all the arguments.
340
 **/
341
#define P99_QUOTS(...) P99_BIGOP(P00_QUOT, P99_NARG(__VA_ARGS__),__VA_ARGS__)
342
/**
343
 ** @brief Realize the right associative bitwise exclusive or of all the arguments.
344
 **/
345
#define P99_XORS(...) P99_BIGOP(P00_XOR, P99_NARG(__VA_ARGS__),__VA_ARGS__)
346
/**
347
 ** @brief Realize the right associative bitwise or of all the arguments.
348
 **/
349
#define P99_BORS(...) P99_BIGOP(P00_BOR, P99_NARG(__VA_ARGS__),__VA_ARGS__)
350
/**
351
 ** @brief Realize the right associative bitwise and of all the arguments.
352
 **/
353
#define P99_BANDS(...) P99_BIGOP(P00_BAND, P99_NARG(__VA_ARGS__),__VA_ARGS__)
354
/**
355
 ** @brief Realize the right associative logical or of all the arguments.
356
 **/
357
#define P99_ORS(...) P99_BIGOP(P00_OR, P99_NARG(__VA_ARGS__),__VA_ARGS__)
358
/**
359
 ** @brief Realize the right associative logical and of all the arguments.
360
 **/
361
#define P99_ANDS(...) P99_BIGOP(P00_AND, P99_NARG(__VA_ARGS__),__VA_ARGS__)
362

363
364
365
366
367

/**
 ** @brief Check if argument @a FIRST is equal to one of the other
 ** elements in the list
 **
368
 ** Use this as follows:
369
370
371
372
373
374
375
376
377
378
379
380
381
382
 ** @code
 ** if (P99_IS_ONE(23, b, c, d, e, f)) {
 **   // one of the guys is 23, do something special
 ** } else {
 **   // handle the base case
 ** }
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_IS_ONE, 0)
#define P99_IS_ONE(FIRST, ...) P99_FOR(== (FIRST), P99_NARG(__VA_ARGS__), P00_OR, P00_ISIT, __VA_ARGS__)

/**
 ** @brief Check if the arguments in the list are all equal
 **
383
 ** Use this as follows:
384
385
386
387
388
389
390
391
392
393
394
395
396
397
 ** @code
 ** if (P99_ARE_EQ(a, b, c, d, e, f)) {
 **   // all are equal, do something special
 ** } else {
 **   // handle the base case
 ** }
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_ARE_EQ, 0)
#define P99_ARE_EQ(FIRST, ...) P99_FOR(== (FIRST), P99_NARG(__VA_ARGS__), P00_AND, P00_ISIT, __VA_ARGS__)

/**
 ** @brief Check if argument @a FIRST is less than the other elements in the list
 **
398
 ** Use this as follows:
399
400
401
402
403
404
405
406
407
408
409
410
 ** @code
 ** if (P99_IS_MIN(a, b, c, d, e, f)) {
 **   // a is smallest, do something special
 ** } else {
 **   // handle the base case
 ** }
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_IS_MIN, 0)
#define P99_IS_MIN(FIRST, ...) P99_FOR(>= (FIRST), P99_NARG(__VA_ARGS__), P00_AND, P00_ISIT, __VA_ARGS__)

/**
411
412
 ** @brief Check if argument @a FIRST is less than or equal to the other
 ** elements in the list
413
 **
414
 ** Use this as follows:
415
416
417
418
419
420
421
422
423
424
425
426
427
428
 ** @code
 ** if (P99_IS_INF(a, b, c, d, e, f)) {
 **   // a is smallest, do something special
 ** } else {
 **   // handle the base case
 ** }
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_IS_INF, 0)
#define P99_IS_INF(FIRST, ...) P99_FOR(> (FIRST), P99_NARG(__VA_ARGS__), P00_AND, P00_ISIT, __VA_ARGS__)

/**
 ** @brief Check if argument @a FIRST is strictly greater than the other elements in the list
 **
429
 ** Use this as follows:
430
431
432
433
434
435
436
437
438
439
440
441
 ** @code
 ** if (P99_IS_MAX(a, b, c, d, e, f)) {
 **   // a is largest, do something special
 ** } else {
 **   // handle the base case
 ** }
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_IS_MAX, 0)
#define P99_IS_MAX(FIRST, ...) P99_FOR(<= (FIRST), P99_NARG(__VA_ARGS__), P00_AND, P00_ISIT, __VA_ARGS__)

/**
442
443
 ** @brief Check if argument @a FIRST is greater than or equal to the other
 ** elements in the list
444
 **
445
 ** Use this as follows:
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
 ** @code
 ** if (P99_IS_SUP(a, b, c, d, e, f)) {
 **   // a is largest, do something special
 ** } else {
 **   // handle the base case
 ** }
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_IS_SUP, 0)
#define P99_IS_SUP(FIRST, ...) P99_FOR(< (FIRST), P99_NARG(__VA_ARGS__), P00_AND, P00_ISIT, __VA_ARGS__)

/**
 ** @brief Check if the arguments in the list are ordered according to
 ** the operation @a OP.
 **
461
 ** Use this as follows:
462
463
464
465
466
467
468
469
470
471
472
473
474
 ** @code
 ** if (P99_ARE_ORDERED(<=, a, b, c, d, e, f)) {
 **   // all are in order, do something special
 ** } else {
 **   // handle the base case
 ** }
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_ARE_ORDERED, 0)
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_ARE_ORDERED, 1)
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_ARE_ORDERED, 2)
#define P99_ARE_ORDERED(OP, ...) P00_ARE_ORDERED(OP, P99_NARG(__VA_ARGS__), __VA_ARGS__)

475
476
477
#define P00_ARE_ORDERED(OP, N, ...)                            \
P99_IF_LT(N, 3)                                                \
(P00_ARE_ORDERED2(OP,__VA_ARGS__))                             \
478
479
480
481
(P00_ARE_ORDERED3(OP, P99_PRED(N), __VA_ARGS__))

#define P00_ARE_ORDERED2(OP, X, Y) (X) OP (Y)

482
483
484
#define P00_ARE_ORDERED3(OP, N, ...)                           \
((P99_SUB(0, 1, __VA_ARGS__))                                  \
 OP P00_ARE_ORDERED_MID(OP, P99_PRED(N), __VA_ARGS__)          \
485
486
 OP (P99_SUB(N, 1, __VA_ARGS__)))

487
#define P00_ARE_ORDERED_MID(OP, N, ...)                                             \
488
489
490
491
492
493
494
P99_FOR(OP, N, P00_ARE_ORDERED_OP, P00_ARE_ORDERED_AND, P99_SUB(1, N, __VA_ARGS__))

#define P00_ARE_ORDERED_AND(_0, X, _2) (X)) && ((X)
#define P00_ARE_ORDERED_OP(OP, _1, X, Y) X OP Y



495
/**
496
497
498
 ** @}
 **/

499
/**
500
 ** @brief join a list with a specific token given as the first argument
501
502
503
504
505
506
507
508
 **
 ** Examples
 ** @code
 ** P99_TOKJOIN(+, 1, 2, 3)  ->  1+2+3
 ** P99_TOKJOIN(., f(), a, length)  ->  f().a.length
 ** @endcode
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_TOKJOIN, 0)
509
510
511
#define P99_TOKJOIN(TOK, ...)                                            \
P99_IF_LT(P99_NARG(__VA_ARGS__), 2)                                      \
(__VA_ARGS__)                                                            \
512
(P99_FOR(TOK, P99_NARG(__VA_ARGS__), P00_TOKJOIN, P00_IDT, __VA_ARGS__))
513
514
515

/**
 ** @ingroup preprocessor_for
516
517
 ** @brief Revert the argument list
 **/
518
#define P99_REVS(...) P00_REVS(P99_NARG(__VA_ARGS__),__VA_ARGS__)
519

520
#define P00_REVS(N, ...) P99_PASTE2(P00_REVS_, P99_IS_LT(N, 2))(N, __VA_ARGS__)
Jens Gustedt's avatar
Jens Gustedt committed
521

522
523
#define P00_REVS_0(N, ...) P00_REVS_(N,__VA_ARGS__)
#define P00_REVS_1(N, ...) __VA_ARGS__
524

525
/* the general case for an argument list of at least two elements */
526
#define P00_REVS_(N, ...) P99_FOR(,N, P00_REV, P00_IDT, __VA_ARGS__)
527

528
529
530
531
/**
 ** @}
 **/

Jens Gustedt's avatar
Jens Gustedt committed
532
/**
533
 ** @ingroup preprocessor_arithmetic
Jens Gustedt's avatar
Jens Gustedt committed
534
 ** @brief Generate the quotient of non-negative decimal numbers @a A and @a B at
Jens Gustedt's avatar
Jens Gustedt committed
535
536
 ** preprocessing time.
 **
Jens Gustedt's avatar
Jens Gustedt committed
537
 ** @warning Both arguments must be less than the maximum argument list number that
Jens Gustedt's avatar
Jens Gustedt committed
538
539
 ** is supported, currently 64.
 **/
540
#define P99_DIV(A, B) P99_CHS(A, P99_FOR(B, 32, P00_SEQ, P00_IDI, P00_ALL_ONES()))
Jens Gustedt's avatar
Jens Gustedt committed
541

542
#define P00_IDI(B, X, I) P99_DUPL(B, I)
543
544


545
546
547
548
549
550
#define P00_CDIM_OP(NAME, I, REC, X) (X + ((NAME)[I] * REC))
#define P00_CDIM_FUNC(NAME, X, I) (X)
#define P00_CDIM(N, NAME, ...) P99_FOR(NAME, N, P00_CDIM_OP, P00_CDIM_FUNC, __VA_ARGS__)

/**
 ** @ingroup preprocessor_arithmetic
551
552
 ** @brief Compute an absolute index in a multidimensional array in
 ** the same way as C.
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
 **
 ** If we have @c N arguments after @a NAME, @a NAME must be an array
 ** of type
 ** @code
 ** size_t NAME[N];
 ** @endcode
 ** that hold the side lengths of an @c N dimensional cube. E.g
 ** @code
 ** size_t const D[] = { 3, 4, 7 };
 ** @endcode
 ** corresponds to a cube of side length 3 in dimension 0, 4 in
 ** dimension 1 and 7 in dimension 2, with in total 84 elements.
 ** With that, we get
 ** @code
 ** P99_CDIM(D, 1, 2, 3)  =>  ((3) + ((D)[2] * ((2) + ((D)[1] * (1)))))
 ** P99_CDIM(D, k0, k1, k2)  =>  ((k2) + ((D)[2] * ((k1) + ((D)[1] * (k0)))))
 ** @endcode
 **/
571
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_CDIM, 0)
572
573
#define P99_CDIM(NAME, ...) P00_CDIM(P99_NARG(__VA_ARGS__), NAME, __VA_ARGS__)

574

Jens Gustedt's avatar
Jens Gustedt committed
575
576
577
578
579
/**
 ** @addtogroup VLA Variable Length Arrays
 ** @{
 **/

580
#define P00_SUBSCRIPT(X) [X]
Jens Gustedt's avatar
Jens Gustedt committed
581
582

/**
Jens Gustedt's avatar
Jens Gustedt committed
583
584
 ** @brief Transform the list of arguments <code>x0, x1, ...</code> to array
 ** subscripts <code>[x0][x1]...</code>
Jens Gustedt's avatar
Jens Gustedt committed
585
 **/
586
#define P99_SUBSCRIPT(...) P99_SER(P00_SUBSCRIPT, __VA_ARGS__)
Jens Gustedt's avatar
Jens Gustedt committed
587
588
589

#define P99_ARRAY(ARR, ...) (ARR)P99_SUBSCRIPT(__VA_ARGS__)
#define P99_AREF(T, ARR, ...) T P99_ARRAY(*const ARR, __VA_ARGS__)
590
#define P99_AREF1(T, ARR, ...) T P99_ARRAY(ARR, static const 1, __VA_ARGS__)
Jens Gustedt's avatar
Jens Gustedt committed
591

592
593
594
595
#define P00_ALEN0(NAME)                                         \
  ((sizeof(NAME)/sizeof((NAME)[0]))                             \
   /sizeof(char[((!(sizeof(NAME) % sizeof((NAME)[0])))<<1)-1]))

Jens Gustedt's avatar
Jens Gustedt committed
596
#define P00_ALEN(NAME, _1, I) P99_IF_EQ_0(I)(P00_ALEN0(NAME))(P00_ALEN0((NAME)P99_REP(I,[0])))
597
598
#define P00_ALEN2_(NAME, I, ...) P00_ALEN(NAME,,I)
#define P00_ALEN2(NAME, ...) P00_ALEN2_(NAME, __VA_ARGS__,)
Jens Gustedt's avatar
Jens Gustedt committed
599
600
601

#define P00_ALENS0(NAME, I, REC, _3) REC, P00_ALEN(NAME,,I)
/**
602
603
 ** @brief Produce a list of the lengths of the argument array @a ARR in terms
 ** of the number of elements in the first @a N dimensions.
Jens Gustedt's avatar
Jens Gustedt committed
604
 **/
605
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_ALENS, 0)
606
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ALENS, 1)
607
#define P99_ALENS(ARR, N) P99_FOR(ARR, N, P00_ALENS0, P00_ALEN, P99_REP(N,))
Jens Gustedt's avatar
Jens Gustedt committed
608

609

610
611
612
613
614
615
616
/**
 ** @brief Declare a new matrix @a A of base type @a T and with @a N
 ** dimensions as given by @a B
 **/
#define P99_ATYPE(T, A, B, N) P99_AREF(T, A, P99_ALENS(*B, N))


617
618
619
620
621
622
#define P00_AALLOC(...) ((__VA_ARGS__)malloc(sizeof *(__VA_ARGS__){ 0 }))

/**
 ** @brief Allocate a new matrix of base type @a T and with @a N
 ** dimensions as given by @a VB
 **/
623
624
P00_DOCUMENT_TYPE_ARGUMENT(P99_AALLOC, 0)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_AALLOC, 1)
625
#define P99_AALLOC(T, VB, N) P00_AALLOC(P99_ATYPE(T, , VB, N))
626

627
628
629
630
631
632
#define P00_ACALL1(ARR) P99_ALENS(*ARR, 1), (ARR)
#define P00_ACALL2(ARR, N) P99_ALENS(*ARR, N), (ARR)
/* The three argument form asserts that pointers to the elements of
   the matrix are assignment compatible to pointers of the indicated type.
   Then we do the cast to the pointer to matrix type that would
   otherwise be dangerous and could hide incompatibilities. */
633
#define P00_ACALL3(ARR, N, TYPE) P99_ALENS(*ARR, N), ((TYPE (*const)P99_SUBSCRIPT(P99_ALENS(*ARR, N)))(TYPE*const){ &((*ARR)P99_REP(N,[0])) })
Jens Gustedt's avatar
Jens Gustedt committed
634
635

/* transform a list of names into size_t declarations */
636
637
#define P00_AARG_DECL(X) size_t const X
#define P00_AARG_LIST(N, ...) P99_SEQ(P00_AARG_DECL, __VA_ARGS__)
Jens Gustedt's avatar
Jens Gustedt committed
638
639
640

/* generate a list of size_t's and the declaration of the array
   pointer */
641
#define P00_AARG_0(T, ARR, DIM, ...) P00_AARG_LIST(DIM, __VA_ARGS__), P99_AREF1(T, ARR, __VA_ARGS__)
Jens Gustedt's avatar
Jens Gustedt committed
642
643
644
645
646
647
#define P00_AARG(T, ARR, DIM, INAME) P00_AARG_0(T, ARR, DIM, P99_NAME(DIM, INAME))

/* capture the special cases do implement default arguments */
#define P00_AARG_3(T, ARR, DIM) P00_AARG(T, ARR, DIM, P99_PASTE(p00_aarg_, ARR))
#define P00_AARG_2(T, ARR) P00_AARG_3(T, ARR, 1)

648
649
650
651
652
653
654
655
656
/* generate a list of size_t's and the declaration of the array
   pointer */
#define P00_ANAME_0(ARR, DIM, ...) __VA_ARGS__, ARR
#define P00_ANAME(ARR, DIM, INAME) P00_ANAME_0(ARR, DIM, P99_NAME(DIM, INAME))

/* capture the special cases do implement default arguments */
#define P00_ANAME_2(ARR, DIM) P00_ANAME(ARR, DIM, P99_PASTE(p00_aarg_, ARR))
#define P00_ANAME_1(ARR) P00_ANAME_2(ARR, 1)

657
#ifdef P00_DOXYGEN
Jens Gustedt's avatar
Jens Gustedt committed
658
659
660
661
662
663
664
665
666
667
/**
 ** @brief Produce the length of the argument array @a ARR in terms of number
 ** of elements.
 **
 ** If a second argument @a N is given, it refers to the size of the
 ** Nth dimension of the array.
 **
 ** If @a ARR is actually just a pointer to an array, P99_ALEN(ARR, 0)
 ** is meaningless.
 **/
668
669
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_ALEN, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ALEN, 1)
Jens Gustedt's avatar
Jens Gustedt committed
670
671
672
673
674
#define P99_ALEN(ARR, N)

/**
 ** @brief Pass a pointer to an @a N dimensional array @a ARR to a function.
 **
675
676
 ** This is not supposed to be used directly but instead is for defining a
 ** macro interface to a function:
Jens Gustedt's avatar
Jens Gustedt committed
677
 ** @code
678
679
680
 ** double dotproductFunc(P99_AARG(double const, A, 1),
 **                       P99_AARG(double const, B, 1));
 **
681
682
 ** #define dotproduct(VA, VB)                                 \
 **   dotproductFunc(P99_ACALL(VA, 1, double const),           \
683
 **                  P99_ACALL(VB, 1, double const))
Jens Gustedt's avatar
Jens Gustedt committed
684
685
686
687
688
689
690
691
692
693
694
 ** .
 ** double Ar[5];
 ** double Br[5];
 ** .
 ** double result = dotproduct(&Ar, &Br);
 ** @endcode
 ** Here the expression with @c dotproduct in the last line will
 ** first result in a macro expansion that will place the pointers as
 ** well as the array sizes to a call of the function @c
 ** dotproductFunc.
 **
695
696
697
698
 ** If the argument @a N is omitted it will default to 1, indicating
 ** that the array is just one dimensional. If N is greater than 1, a
 ** list of the @a N lengths in the first @a N dimensions of @a ARR is
 ** passed to the function call.
699
700
701
 **
 ** @a TYPE can be omitted in which case no attempt to conform types
 ** will be made. Specifying @a TYPE is particularly helpful if the
702
703
704
 ** type is qualified, that is it has a @c const or @c volatile
 ** qualification as in the example above. If you don't use this macro,
 ** ensuring <code>const</code>ness of multidimensional
705
706
707
708
709
710
711
 ** arrays is particularly tedious.
 **
 ** To be more precise, the three argument form asserts that pointers
 ** to the elements of the matrix are assignment compatible to
 ** pointers of the indicated type.  Then we do the cast to the
 ** pointer to matrix type that would otherwise be dangerous and could
 ** hide incompatibilities.
Jens Gustedt's avatar
Jens Gustedt committed
712
713
 ** @see P99_AARG
 **/
714
715
716
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_ACALL, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ACALL, 1)
P00_DOCUMENT_TYPE_ARGUMENT(P99_ACALL, 2)
717
#define P99_ACALL(ARR, N, TYPE)
Jens Gustedt's avatar
Jens Gustedt committed
718
719
720
721
722
723

/**
 ** @brief Declare a pointer to array function argument of basetype @a
 ** TYPE, with name @a NAME, dimension @a DIM and naming scheme for
 ** the length variables @a VAR{0}, ... @a VAR{@a DIM - 1}.
 **
724
725
726
727
728
729
 ** Parameter @a VAR may be omitted such that you will not have access
 ** to the length variables. But you most probably don't need them
 ** since you may use ::P99_ALEN to have these values.
 **
 ** @a DIM defaults to @c 1.
 **
730
731
 ** @warning A pointer so declared has the @c const attribute
 ** and thus may not be modified.
732
733
734
735
736
 **
 ** If @a TYPE has qualifiers (@c const, @c volatile, @c restrict or
 ** @c _Atomic), the corresponding call to ::P99_ACALL @em must
 ** contain the same qualifiers in the 3rd argument.
 **
Jens Gustedt's avatar
Jens Gustedt committed
737
 ** @see P99_ACALL
738
 ** @see P99_ALEN
Jens Gustedt's avatar
Jens Gustedt committed
739
 **/
740
741
P00_DOCUMENT_TYPE_ARGUMENT(P99_AARG, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_AARG, 2)
Jens Gustedt's avatar
Jens Gustedt committed
742
743
#define P99_AARG(TYPE, NAME, DIM, VAR)

744
745
746
747
748
749
750
751
752
753
754
755
756
757
/**
 ** @brief Declare list of variable names as produced by ::P99_AARG
 **
 ** Parameter @a VAR may be omitted as for :P99_AARG.
 **
 ** @a DIM defaults to @c 1.
 **
 ** @see P99_ACALL
 ** @see P99_ALEN
 **/
P00_DOCUMENT_TYPE_ARGUMENT(P99_ANAME, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ANAME, 2)
#define P99_ANAME(NAME, DIM, VAR)

Jens Gustedt's avatar
Jens Gustedt committed
758
#else
759
760
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_ALEN, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ALEN, 1)
Jens Gustedt's avatar
Jens Gustedt committed
761
#define P99_ALEN(...) P99_IF_EQ_1(P99_NARG(__VA_ARGS__))(P00_ALEN(__VA_ARGS__, ,0))(P00_ALEN2(__VA_ARGS__))
762
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_ACALL, 0)
763
764
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ACALL, 1)
P00_DOCUMENT_TYPE_ARGUMENT(P99_ACALL, 2)
765
#define P99_ACALL(...)  P99_PASTE2(P00_ACALL, P99_NARG(__VA_ARGS__))(__VA_ARGS__)
766
767
P00_DOCUMENT_TYPE_ARGUMENT(P99_AARG, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_AARG, 2)
768
#define P99_AARG(...) P99_IF_GT(P99_NARG(__VA_ARGS__),3)(P00_AARG(__VA_ARGS__))(P99_PASTE2(P00_AARG_, P99_NARG(__VA_ARGS__))(__VA_ARGS__))
769
770
771
P00_DOCUMENT_TYPE_ARGUMENT(P99_ANAME, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ANAME, 2)
#define P99_ANAME(...) P99_IF_GT(P99_NARG(__VA_ARGS__),2)(P00_ANAME(__VA_ARGS__))(P99_PASTE2(P00_ANAME_, P99_NARG(__VA_ARGS__))(__VA_ARGS__))
Jens Gustedt's avatar
Jens Gustedt committed
772
773
774

#endif

775
776
777
778
779
780
781
782
/**
 ** @example test-p99-pow.c
 ** @brief an example for computations with large matrices
 **
 ** This uses the VLA array passing macros, ::P99_DO and ::P99_PARALLEL_DO
 **/


Jens Gustedt's avatar
Jens Gustedt committed
783
784
785
786
/** @}
 **/


787
/**
Jens Gustedt's avatar
Jens Gustedt committed
788
 ** @ingroup preprocessor_blocks
789
790
791
792
793
794
795
796
797
798
799
800
801
802
 ** @brief Declare a @c for loop for which all iterations can be run
 ** independently and out of order.
 **
 ** This can be used syntactically exactly as the keyword @c for,
 ** except that the programmer asserts with this that the depending
 ** statement or block can be executed independently and out of order for all instances.
 **
 ** @code
 ** P99_PARALLEL_FOR (unsigned i = 0; i < limit; ++i) {
 **    unsigned sum = a[i] + b[i];
 **    a[i] *= sum;
 ** }
 ** @endcode
 **
803
 ** The resulting code may then be parallelized and (if the platform
804
805
806
807
808
809
810
811
 ** supports this) multiple threads may be used to speed up the
 ** execution.
 ** @see P99_PARALLEL_PRAGMA for the conditions under which this will
 ** result in a parallel execution.
 **/
#define P99_PARALLEL_FOR _Pragma(P99_PARALLEL_PRAGMA) for


Jens Gustedt's avatar
Jens Gustedt committed
812
813
#define P00_PRAGMA_DO(PRAG, TYPE, VAR, LOW, LEN, INCR)                           \
P00_BLK_START                                                                    \
Jens Gustedt's avatar
Jens Gustedt committed
814
P00_BLK_BEFORE(const TYPE                                                        \
Jens Gustedt's avatar
Jens Gustedt committed
815
               P99_PASTE2(p00_start_, VAR) = (LOW),                              \
816
               P99_PASTE2(p00_stop_, VAR) = P99_PASTE2(p00_start_, VAR) + (LEN), \
Jens Gustedt's avatar
Jens Gustedt committed
817
818
               P99_PASTE2(p00_incr_, VAR) = (INCR))                              \
P99_PRAGMA(PRAG)                                                                 \
Jens Gustedt's avatar
Jens Gustedt committed
819
     for (register TYPE P99_PASTE2(p00_i_, VAR) = P99_PASTE2(p00_start_, VAR);   \
Jens Gustedt's avatar
Jens Gustedt committed
820
          P99_PASTE2(p00_i_, VAR) < P99_PASTE2(p00_stop_, VAR);                  \
Jens Gustedt's avatar
Jens Gustedt committed
821
822
          P99_PASTE2(p00_i_, VAR) += P99_PASTE2(p00_incr_, VAR))                 \
       P00_BLK_START                                                             \
823
         P00_BLK_BEFORE(TYPE const VAR = P99_PASTE2(p00_i_, VAR))
824

825
#ifdef P00_DOXYGEN
826
827
828
829
830
831
832
833
834
/**
 ** @ingroup preprocessor_blocks
 ** @brief A fortran like do-loop with bounds that are fixed at the
 ** beginning
 **
 ** @param TYPE is the type of the control variable. It must be an
 ** arithmetic type.
 **
 ** @param VAR is the name of the control variable. It is not mutable
835
 ** inside the loop, as if it were declared <code>TYPE const
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
 ** VAR</code>.
 **
 ** @param LOW is the start value of VAR for the first iteration. Only
 ** evaluated once before all iterations. Must be assignment
 ** compatible to type @a TYPE.
 **
 ** @param LEN is the length of the iteration and is
 ** non-inclusive. Only evaluated once before all iterations. Must be
 ** assignment compatible to type @a TYPE.
 **
 ** @param INCR is the increment of VAR after each iteration. Only
 ** evaluated once before all iterations. @a INCR defaults to @c 1 if
 ** omitted. Must be assignment compatible to type @a TYPE.
 **
 ** @code
 ** P99_DO(size_t, i, a, n, inc) {
 **   A[i] *= B[i-1]
 ** }
 ** @endcode
 ** would expand to something similar to
 ** @code
 ** for (size_t i = a; i < (a + n); i += inc) {
 **   A[i] *= B[i-1]
 ** }
 ** @endcode
 **
 ** only that
 ** -  the bounds of the loop (involving @c a and @c n) and the
 ** increment @c inc are fixed once when entering this construct
 ** - the loop variable @c i is not modifiable within the block
 **
867
868
869
 ** @warning Placing a @c #pragma directive directly in front of
 ** ::P99_DO will not work because of syntactic restrictions. Use
 ** ::P99_PRAGMA_DO instead.
870
 ** @see P99_PARALLEL_DO for a parallel variant of this
871
872
 ** @see P99_PRAGMA_DO for a variant of this that can be controlled
 ** with an arbitrary @c #pragma directive.
873
874
875
876
877
878
879
880
881
 **/
#define P99_DO(TYPE, VAR, LOW, LEN, INCR) for(;;)
/**
 ** @ingroup preprocessor_blocks
 ** @brief as ::P99_DO but performs the iterations out of order
 ** @see P99_DO for an explanation of the arguments
 ** @see P99_FOR for a more general parallel iteration construct
 **/
#define P99_PARALLEL_DO(TYPE, VAR, LOW, LEN, INCR) for(;;)
882
883
884
885
886
887
888
889
/**
 ** @brief as ::P99_DO but allows you to additionally place a pragma
 ** directive in front of the generated @c for loop
 **
 ** @warning Just placing a @c #pragma directive directly in front of
 ** ::P99_DO will not work because of syntactic restrictions
 **/
#define P99_PRAGMA_DO(PRAG, TYPE, VAR, LOW, LEN, INCR) for(;;)
890
#else
891
892
893
894
895
896
897
898
899
P00_DOCUMENT_TYPE_ARGUMENT(P99_DO, 0)
#define P99_DO(TYPE, VAR, ...) P99_PRAGMA_DO(, TYPE, VAR, __VA_ARGS__)
P00_DOCUMENT_TYPE_ARGUMENT(P99_PARALLEL_DO, 0)
#define P99_PARALLEL_DO(TYPE, VAR, ...) P99_PRAGMA_DO(P99_PARALLEL_PRAGMA, TYPE, VAR, __VA_ARGS__)
P00_DOCUMENT_TYPE_ARGUMENT(P99_PRAGMA_DO, 1)
#define P99_PRAGMA_DO(PRAG, TYPE, VAR, ...)                    \
P99_IF_EQ(P99_NARG(__VA_ARGS__), 2)                            \
(P00_PRAGMA_DO(PRAG, TYPE, VAR, __VA_ARGS__, 1))               \
(P00_PRAGMA_DO(PRAG, TYPE, VAR, __VA_ARGS__))
900
901
#endif

902
#define P00_FORALL_OP(NAME, I, REC, X) REC X
903
904
905

#define P00_FORALL_FUNC(NAME, X, I) P99_DO(size_t, X, 0, (NAME)[I])

906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
#define P00_FORALL(N, NAME, ...) P99_FOR(NAME, N, P00_FORALL_OP, P00_FORALL_FUNC, __VA_ARGS__)

/**
 ** @ingroup preprocessor_blocks
 ** @brief A multi-index @c for loop
 **
 ** Given the names of @c N identifiers after @a NAME, @a NAME must
 ** correspond to an array of lengths with dimension at least @c N.
 ** @code
 ** size_t NAME[N];
 ** @endcode
 ** For @c N = 3 this could e.g be
 ** @code
 ** size_t const D[] = { 3, 4, 7 };
 ** @endcode
 ** Then, the macro in the following
 ** @code
 ** P99_FORALL(D, i0, i1, i2) {
 **   A[i0][i1][i2] *= B[i0][i1][i2]
 ** }
 ** @endcode
 ** would expand to something similar to
 ** @code
929
930
931
 ** for (size_t i0 = 0; i0 < D[0]; ++i0)
 **   for (size_t i1 = 0; i1 < D[1]; ++i1)
 **     for (size_t i2 = 0; i2 < D[2]; ++i2) {
932
933
934
935
 **        A[i0][i1][i2] *= B[i0][i1][i2]
 **     }
 ** @endcode
 **
936
937
938
939
940
941
 ** only that
 ** - the bounds of the loops (involving @c D[0], @c D[1] and @c
 **    D[2]) are fixed once when entering this construct
 ** - the loop variables @c i0, @c i1 and @c i2 are not modifiable
 **    within the block
 **
942
 ** @see P99_PARALLEL_FORALL for a variant that uses OpenMp to parallelize the loop.
943
 ** @see P99_DO for a simple fortran like iteration
944
 ** @see P99_CDIM for a macro that computes the absolute position of an
945
946
 **   index N-tuple in a multi-dimensional array.
 **/
947
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_FORALL, 0)
948
949
#define P99_FORALL(NAME, ...) P00_FORALL(P99_NARG(__VA_ARGS__), NAME, __VA_ARGS__)

950
#define P00_PARALLEL_FORALL_FUNC(NAME, X, I)  P99_PARALLEL_DO(size_t, X, 0, (NAME)[I])
951
952
953
954
955
956
957
#define P00_PARALLEL_FORALL(N, NAME, ...) P99_FOR(NAME, N, P00_FORALL_OP, P00_PARALLEL_FORALL_FUNC, __VA_ARGS__)

/**
 ** @ingroup preprocessor_blocks
 ** @brief A multi-index @c for loop who's dependent statement or
 ** block may be executed out of order.
 **
958
959
960
 ** This has the same semantics as ::P99_FORALL except that it assumes
 ** the independence of each execution of the statement from every
 ** other.
961
962
963
 **
 ** @see P99_FORALL for a variant that doesn't need that assumption,
 ** i.e where the statements should be executed sequentially in order.
964
965
 ** @see P99_PARALLEL_DO for a simple fortran like parallel iteration
 ** @see P99_PARALLEL_FOR for a parallel replacement of @c for
966
 ** @see P99_CDIM for a macro that computes the absolute position of an
967
968
 **   index N-tuple in a multi-dimensional array.
 **/
969
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_PARALLEL_FORALL, 0)
970
971
#define P99_PARALLEL_FORALL(NAME, ...) P00_PARALLEL_FORALL(P99_NARG(__VA_ARGS__), NAME, __VA_ARGS__)

972

Jens Gustedt's avatar
Jens Gustedt committed
973
#define P00_CASERANGE0(NAME, X, I) case ((NAME)+I):
974
#define P00_CASERANGE3(START, LEN, LABEL)                          \
(no author)'s avatar
(no author) committed
975
976
977
978
if (0) {                                                           \
  /* Execution will only go here if one of the cases is chosen. */ \
  P99_FOR(START, LEN, P00_SEP, P00_CASERANGE0, P99_REP(LEN,))      \
    /* Then it just continues with the else part */                \
979
    goto LABEL;                                                    \
(no author)'s avatar
(no author) committed
980
981
982
 } else                                                            \
  /* execution will just fall through, here, if a previous case    \
     matched */                                                    \
983
984
985
986
  LABEL

#define P00_CASERANGE1(START, LEN, ...) P00_CASERANGE3(START, LEN, P99_UNIQ(__VA_ARGS__, caselabel))
#define P00_CASERANGE2(START, LEN) P00_CASERANGE3(START, LEN, P99_UNIQ(caselabel))
Jens Gustedt's avatar
Jens Gustedt committed
987

988

989
#ifdef P00_DOXYGEN
Jens Gustedt's avatar
Jens Gustedt committed
990
991
992
993
994
995
996
997
/**
 ** @ingroup preprocessor_blocks
 ** @brief implement a range syntax for case labels.
 **
 ** gcc has an analogous extension to the C syntax. Something like
 ** @code
 ** case '0'..'9': return 23;
 ** @endcode
998
 ** This implementation uses macros and consequently should
Jens Gustedt's avatar
Jens Gustedt committed
999
1000
1001
1002
1003
 ** be more portable.
 ** @code
 ** switch (argv[0][0]) {
 **   P99_CASERANGE('\0', 0): return -1;
 **   P99_CASERANGE('0', 10): return 0;
1004
1005
1006
 **   P99_CASERANGE('A', 25): --argc;
 **   P99_CASERANGE('.', 0):  return -1;
 **   P99_CASERANGE('a', 25,  oioi): return 2;
Jens Gustedt's avatar
Jens Gustedt committed
1007
1008
1009
1010
1011
1012
1013
 **   default: return 3;
 ** }
 ** @endcode
 **
 ** @param START must evaluate to an expression that can be used as a case label
 **
 ** @param LEN must evaluate to a decimal number. If this is 0 the
1014
1015
 ** depending statement will never be reached as a direct jump to the
 ** "label". Depending on the flow for the other cases the statement
1016
1017
 ** may or may not be reachable when falling through from a previous
 ** case.  In the example above, for the first range @c '\0' is not
1018
1019
 ** reachable. But the range for @c '.' is reachable after the
 ** execution of the range starting with @c 'A'.
Jens Gustedt's avatar
Jens Gustedt committed
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
 **
 ** The additional variable argument list is optional and is used to
 ** "name" the range. This is only necessary if you have more than one
 ** P99_CASERANGE on the same logical line of code.
 **
 ** This is intended to have the same flow control rules as if there
 ** were just @em one case label in front of @em one statement. In
 ** particular, the dependent statement may just be a @c break to
 ** break out of the enclosing @c switch.
 **/
#define P99_CASERANGE(START, LEN, ...)
#else
1032
1033
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_CASERANGE, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_CASERANGE, 1)
1034
1035
1036
1037
#define P99_CASERANGE(START, ...)                              \
P99_IF_LT(P99_NARG(__VA_ARGS__), 2)                            \
(P00_CASERANGE2(START, __VA_ARGS__))                           \
(P00_CASERANGE1(START, __VA_ARGS__))
Jens Gustedt's avatar
Jens Gustedt committed
1038
1039
1040
#endif


1041
1042
1043
1044
1045
1046
#define P00_STRUCT_TYPENAME(BASE, DECL) P99_PASTE3(DECL, _P99_typedef_of_, BASE)
#define P00_STRUCT_TYPEDEF(BASE, DECL, I) typedef P00_STRUCT_TYPENAME(BASE, DECL)
#define P00_STRUCT_TYPEDEFS(NAME, ...) P99_FOR(NAME, P99_NARG(__VA_ARGS__), P00_SEP, P00_STRUCT_TYPEDEF, __VA_ARGS__)


/**
Jens Gustedt's avatar
Jens Gustedt committed
1047
 ** @ingroup types
1048
 ** @brief Declare a structure of name @a NAME composed of the
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
 ** field declarations that are given in the remaining arguments.
 **
 ** For this to work the argument list must contain the declaration of
 ** the fields, one per argument.
 **
 ** @remark The declarations must be such that the name of the field
 ** is at the end of the declaration.
 **
 ** @see P99_STRUCT_USE to see how to lift all or parts of the fields
 ** that are defined here as local variables on the stack of the
 ** current function.
 **/
#define P99_DEFINE_STRUCT(NAME, ...)                           \
struct NAME {                                                  \
  P99_SEP(P00_IDENT, __VA_ARGS__);                             \
};                                                             \
P00_STRUCT_TYPEDEFS(NAME, __VA_ARGS__)


#define P00_STRUCT_USE3(TYPE, VAR, NAME) P00_STRUCT_TYPENAME(TYPE, NAME) NAME = (VAR)->NAME
#define P00_STRUCT_USE2(PAIR, NAME) P00_STRUCT_USE3(PAIR, NAME)
#define P00_STRUCT_USE(PAIR, NAME, I) P00_STRUCT_USE2(P00_ROBUST PAIR, NAME)

/**
Jens Gustedt's avatar
Jens Gustedt committed
1073
 ** @ingroup types
1074
1075
1076
 ** @brief Use the fields of variable @a VAR of type @a TYPE
 **
 ** This "lifts" the fields of @a VAR as local variables onto the
1077
 ** local stack and copies their value into these local variables.
1078
1079
1080
1081
 **
 ** @see P99_STRUCT_UNUSE to restore changed values back into @a VAR.
 **/
P00_DOCUMENT_TYPE_IDENTIFIER_ARGUMENT(P99_STRUCT_USE, 0)
1082
1083
1084
1085
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_USE, 1)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_USE, 2)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_USE, 3)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_USE, 4)
1086
1087
1088
1089
1090
1091
1092
#define P99_STRUCT_USE(TYPE, VAR, ...) P99_FOR((TYPE, VAR), P99_NARG(__VA_ARGS__), P00_SEP, P00_STRUCT_USE, __VA_ARGS__)

#define P00_STRUCT_UNUSE3(TYPE, VAR, NAME) P00_STRUCT_TYPENAME(TYPE, NAME) (VAR)->NAME = NAME
#define P00_STRUCT_UNUSE2(PAIR, NAME) P00_STRUCT_UNUSE3(PAIR, NAME)
#define P00_STRUCT_UNUSE(PAIR, NAME, I) P00_STRUCT_UNUSE2(P00_ROBUST PAIR, NAME)

/**
Jens Gustedt's avatar
Jens Gustedt committed
1093
 ** @ingroup types
1094
1095
1096
1097
1098
 ** @brief Copy local variables back to the fields of variable @a VAR.
 **
 ** @see P99_STRUCT_USE
 **/
P00_DOCUMENT_TYPE_IDENTIFIER_ARGUMENT(P99_STRUCT_UNUSE, 0)
1099
1100
1101
1102
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_UNUSE, 1)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_UNUSE, 2)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_UNUSE, 3)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_UNUSE, 4)
1103
1104
#define P99_STRUCT_UNUSE(TYPE, VAR, ...) P99_FOR((TYPE, VAR), P99_NARG(__VA_ARGS__), P00_SEP, P00_STRUCT_UNUSE, __VA_ARGS__)

(no author)'s avatar
(no author) committed
1105
#define P00_LITERAL(NAME) .NAME = NAME
1106
1107

/**
Jens Gustedt's avatar
Jens Gustedt committed
1108
 ** @ingroup types
1109
1110
1111
1112
 ** @brief Copy local variables back to the fields of same name inside a literal.
 **
 ** @see P99_DEFINE_STRUCT
 **/
Jens Gustedt's avatar
Jens Gustedt committed
1113
1114
1115
1116
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_LITERAL, 0)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_LITERAL, 1)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_LITERAL, 2)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_LITERAL, 3)
1117
1118
1119
1120
#define P99_LITERAL(...) P99_SEQ(P00_LITERAL, __VA_ARGS__)


/**
Jens Gustedt's avatar
Jens Gustedt committed
1121
 ** @ingroup types
1122
1123
1124
1125
1126
 ** @brief Copy local variables back to the fields of same name inside
 ** a compound literal of type @a TYPE.
 **
 ** @see P99_DEFINE_STRUCT
 **/
Jens Gustedt's avatar
Jens Gustedt committed
1127
1128
1129
1130
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_LITERAL, 0)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_LITERAL, 1)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_LITERAL, 2)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_LITERAL, 3)
1131
1132
1133
1134
1135
#define P99_STRUCT_LITERAL(TYPE, ...) (TYPE){ P99_SEQ(P00_LITERAL, __VA_ARGS__) }

#define P00_STRUCT_TYPES(TYPE, NAME, I) P00_STRUCT_TYPENAME(TYPE, NAME)

/**
Jens Gustedt's avatar
Jens Gustedt committed
1136
 ** @ingroup types
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
 ** @brief Transform the argument list into a list of field types for
 ** type @a TYPE.
 **
 ** @see P99_DEFINE_STRUCT
 **/
P00_DOCUMENT_TYPE_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPES, 0)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPES, 1)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPES, 2)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPES, 3)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPES, 4)
#define P99_STRUCT_TYPES(TYPE, ...) P99_FOR(TYPE, P99_NARG(__VA_ARGS__), P00_SEQ, P00_STRUCT_TYPES, __VA_ARGS__)

#define P00_STRUCT_TYPE0(TYPE, NAME, I) P99_0(P00_STRUCT_TYPENAME(TYPE, NAME))

/**
Jens Gustedt's avatar
Jens Gustedt committed
1152
 ** @ingroup types
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
 ** @brief Transform the argument list into a list of lvalue for the
 ** fields of type @a TYPE.
 **
 ** @see P99_DEFINE_STRUCT
 **/
P00_DOCUMENT_TYPE_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPE0, 0)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPE0, 1)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPE0, 2)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPE0, 3)
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_STRUCT_TYPE0, 4)
#define P99_STRUCT_TYPE0(TYPE, ...) P99_FOR(TYPE, P99_NARG(__VA_ARGS__), P00_SEQ, P00_STRUCT_TYPE0, __VA_ARGS__)


1166
1167
1168
#define P00_MAC_ARGS_TYPE_(NAME, EXP, QUAL, ...) __typeof__(EXP)
#define P00_MAC_ARGS_EXP_(NAME, EXP, QUAL, ...) (EXP)
#define P00_MAC_ARGS_QUAL_(NAME, EXP, QUAL, ...) QUAL
Jens Gustedt's avatar
Jens Gustedt committed
1169

1170
1171
1172
1173
1174
1175
1176
#define P00_MAC_ARGS_NAME(NAME, ...) NAME
#define P00_MAC_ARGS_TYPE(...) P00_MAC_ARGS_TYPE_(__VA_ARGS__,)

#define P00_MAC_ARGS_EXP(...) P00_MAC_ARGS_EXP_(__VA_ARGS__,)

#define P00_MAC_ARGS_QUAL(...) P00_MAC_ARGS_QUAL_(__VA_ARGS__,)

1177
1178
1179
1180
#define P00_MAC_ARGS_REAL0(_0, PAIR, I)                        \
P00_MAC_ARGS_TYPE PAIR                                         \
P00_MAC_ARGS_QUAL PAIR                                         \
P99_PASTE2(p00_mac_arg_, I)                                    \
1181
1182
= P00_MAC_ARGS_EXP PAIR

1183
1184
1185
1186
#define P00_MAC_ARGS_REAL1(_0, PAIR, I)                        \
P00_MAC_ARGS_TYPE PAIR                                         \
P00_MAC_ARGS_QUAL PAIR                                         \
P00_MAC_ARGS_NAME PAIR                                         \
1187
  = P99_PASTE2(p00_mac_arg_, I)
Jens Gustedt's avatar
Jens Gustedt committed
1188
1189
1190
1191
1192
1193
1194

/**
 ** @ingroup preprocessor_initialization
 **
 ** @brief Declare macro parameters as local variables as if the macro
 ** were declared as a type generic @c inline function.
 **
1195
 ** @remark This uses the @c __typeof__ extension implemented
Jens Gustedt's avatar
Jens Gustedt committed
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
 ** by gcc.
 **
 ** This receives parenthesized pairs of name and value that are to be
 ** promoted as local variables inside a macro expansion. Use this as
 ** follows:
 ** @code
 ** #define atomic_fetch_add_conditional(OBJP, OPERAND)        \
 ** ({                                                         \
 ** P99_MAC_ARGS((p00_objp, OBJP), (p00_op, OPERAND));         \
 ** ...                                                        \
 ** })
 ** @endcode
 **
 ** @remark The corresponding local variables have exactly the type of
1210
 ** the expressions that are passed as the 2nd element in each pair.
Jens Gustedt's avatar
Jens Gustedt committed
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
 **
 ** This achieves several objectives
 ** - Each macro parameter is evaluated exactly once.
 **
 ** - The values of the macro parameters are accessible through an
 **   ordinary identifier.
 **
 ** - Even if a variable with one of the names is passed through a
 **   macro parameter (e.g by calling
 **   <code>atomic_fetch_add_conditional(p00_op->next, 23)</code>)
 **   there will be no conflict.
 **
 ** This is done by evaluating all macro arguments first, as it would
 ** be for a function call, and then assigning it to fresh variables.
 **/
1226
1227
1228
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_MAC_ARGS, 0)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_MAC_ARGS, 1)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_MAC_ARGS, 2)
Jens Gustedt's avatar
Jens Gustedt committed
1229
1230
1231
1232
#define P99_MAC_ARGS(...)                                                   \
P99_FOR(, P99_NARG(__VA_ARGS__), P00_SEP, P00_MAC_ARGS_REAL0, __VA_ARGS__); \
P99_FOR(, P99_NARG(__VA_ARGS__), P00_SEP, P00_MAC_ARGS_REAL1, __VA_ARGS__)

1233
1234
#define P00_MACRO_VAR(NAME, EXP, ...)                                 \
__typeof__(EXP) __VA_ARGS__ P99_PASTE2(p00_macro_var_, NAME) = (EXP), \
1235
  NAME = P99_PASTE2(p00_macro_var_, NAME)
Jens Gustedt's avatar
Jens Gustedt committed
1236

1237
#define P00_MACRO_PVAR(NAME, EXP, ...)                                                \
1238
1239
__typeof__(*(EXP)) __VA_ARGS__* P99_PASTE2(p00_macro_var_, NAME) = (EXP), \
  * NAME = P99_PASTE2(p00_macro_var_, NAME)
1240

1241
1242
#ifdef DOXYGEN
/**
1243
 ** @brief Define a variable with @a NAME that has the type and value of
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
 ** @a EXPR.
 **
 ** If @a QUAL is given it must be a qualifier list that is added to
 ** the resulting type.
 **
 ** @remark Other than just redeclaring @a NAME this macro is safe
 ** even if @a EXPR contains the evaluation of a variable of the same
 ** name @a NAME.
 **
 ** This is achieved by declaring two variables, one with a dummy name
 ** that receives @a EXPR as an initializer (so there can't be a name
 ** conflict), and then @a NAME that is initialized with the
 ** first. Any normal optimizer should optimize that auxiliary
 ** variable out.
1258
 **/
1259
1260
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_MACRO_VAR, 0)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_MACRO_VAR, 1)
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
# define P99_MACRO_VAR(NAME, EXPR, QUAL)
/**
 ** @brief Define a variable with @a NAME that has the type and value of
 ** @a EXPR, where @a EXPR is of a pointer type.
 **
 ** If @a QUAL is given it must be a qualifier list that is
 ** added to the type @a EXPR is pointing to.
 **
 ** @remark Other than just redeclaring @a NAME this macro is safe
 ** even if @a EXPR contains the evaluation of a variable of the same
 ** name @a NAME.
 **
 ** This is achieved by declaring two variables, one with a dummy name
 ** that receives @a EXPR as an initializer (so there can't be a name
 ** conflict), and then @a NAME that is initialized with the
 ** first. Any normal optimizer should optimize that auxiliary
 ** variable out.
 **/
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_MACRO_PVAR, 0)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_MACRO_PVAR, 1)
# define P99_MACRO_PVAR(NAME, EXPR, QUAL)
1282
#else
1283
1284
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_MACRO_VAR, 0)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_MACRO_VAR, 1)
1285
1286
1287
1288
# define P99_MACRO_VAR(NAME, ...)                              \
P99_IF_EQ_1(P99_NARG(__VA_ARGS__))                             \
(P00_MACRO_VAR(NAME, __VA_ARGS__,))                            \
(P00_MACRO_VAR(NAME, __VA_ARGS__))
1289

1290
1291
P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_MACRO_PVAR, 0)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_MACRO_PVAR, 1)
1292
1293
1294
1295
# define P99_MACRO_PVAR(NAME, ...)                             \
P99_IF_EQ_1(P99_NARG(__VA_ARGS__))                             \
(P00_MACRO_PVAR(NAME, __VA_ARGS__,))                           \
(P00_MACRO_PVAR(NAME, __VA_ARGS__))
1296
#endif
1297

(no author)'s avatar
(no author) committed
1298
#endif      /* !P99_FOR_H_ */