1 
2 /*
3  * Argyll Color Correction System
4  * Multi-dimensional counter macros.
5  *
6  * Author: Graeme W. Gill
7  * Date:   28/9/96
8  *
9  * Copyright 1996 - 2006, Graeme W. Gill
10  * All rights reserved.
11  *
12  * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
13  * see the License.txt file for licencing details.
14  */
15 
16 #ifndef COUNTERS_H
17 
18 #ifdef __cplusplus
19 	extern "C" {
20 #endif
21 
22 /* ------------------------------------------------------- */
23 /* Macros for a multi-dimensional counter. */
24 /* Declare the counter name nn, maximum di mxdi, dimensions di, & count */
25 
26 #define DCOUNT(nn, mxdi, di, start, reset, endp1) 			\
27 	int nn[mxdi];			/* counter value */				\
28 	int nn##_di = (di);		/* Number of dimensions */		\
29 	int nn##_stt = (start);	/* start count value */			\
30 	int nn##_rst = (reset);	/* reset on carry value */		\
31 	int nn##_res = (endp1); /* last count +1 */				\
32 	int nn##_e				/* dimension index */
33 
34 #define DRECONF(nn, start, reset, endp1) 				\
35 	nn##_stt = (start);	/* start count value */			\
36 	nn##_rst = (reset);	/* reset on carry value */		\
37 	nn##_res = (endp1); /* last count +1 */
38 
39 /* Set the counter value to 0 */
40 #define DC_INIT(nn) 								\
41 {													\
42 	for (nn##_e = 0; nn##_e < nn##_di; nn##_e++)	\
43 		nn[nn##_e] = nn##_stt;						\
44 	nn##_e = 0;										\
45 }
46 
47 /* Increment the counter value */
48 #define DC_INC(nn)									\
49 {													\
50 	for (nn##_e = 0; nn##_e < nn##_di; nn##_e++) {	\
51 		nn[nn##_e]++;								\
52 		if (nn[nn##_e] < nn##_res)					\
53 			break;	/* No carry */					\
54 		nn[nn##_e] = nn##_rst;						\
55 	}												\
56 }
57 
58 /* After init or increment, expression is TRUE if counter is done */
59 #define DC_DONE(nn)									\
60 	(nn##_e >= nn##_di)
61 
62 /* Typical use:
63 
64 	DCOUNT(cc, 15, 3, -1, -1, 2);
65 
66 	DC_INIT(cc);
67    	while(!DC_DONE(cc)) {
68 
69 		DC_INC(cc);
70 	}
71  */
72 
73 /* (Do we need a version of the above that tracks the actual input coords ?) */
74 /* ------------------------------------------------------- */
75 /* Similar to abovem but each dimension range can be clipped. */
76 
77 #define FCOUNT(nn, mxdi, di) 				\
78 	int nn[mxdi];			/* counter value */				\
79 	int nn##_di = (di);		/* Number of dimensions */		\
80 	int nn##_stt[mxdi];		/* start count value */			\
81 	int nn##_res[mxdi]; 	/* last count +1 */				\
82 	int nn##_e				/* dimension index */
83 
84 #define FRECONF(nn, start, endp1) 							\
85 	for (nn##_e = 0; nn##_e < nn##_di; nn##_e++) {			\
86 		nn##_stt[nn##_e] = (start);	/* start count value */	\
87 		nn##_res[nn##_e] = (endp1); /* last count +1 */		\
88 	}
89 
90 /* Set the counter value to 0 */
91 #define FC_INIT(nn) 								\
92 {													\
93 	for (nn##_e = 0; nn##_e < nn##_di; nn##_e++)	\
94 		nn[nn##_e] = nn##_stt[nn##_e];				\
95 	nn##_e = 0;										\
96 }
97 
98 /* Increment the counter value */
99 #define FC_INC(nn)									\
100 {													\
101 	for (nn##_e = 0; nn##_e < nn##_di; nn##_e++) {	\
102 		nn[nn##_e]++;								\
103 		if (nn[nn##_e] < nn##_res[nn##_e])			\
104 			break;	/* No carry */					\
105 		nn[nn##_e] = nn##_stt[nn##_e];				\
106 	}												\
107 }
108 
109 /* After increment, expression is TRUE if counter is done */
110 #define FC_DONE(nn)								\
111 	(nn##_e >= nn##_di)
112 
113 /* ------------------------------------------------------- */
114 /* Same as above, but allows for variable resolution on each axis. */
115 /* End offset is added to count[] */
116 
117 #define ECOUNT(nn, mxdi, di, start, endp1, end_offst)		\
118 	int nn[mxdi];	/* counter value */						\
119 	int nn##_di = (di);		/* Number of dimensions */		\
120 	int nn##_start = (start);/* Start value*/				\
121 	int *nn##_res = (endp1);/* last count +1 */				\
122 	int nn##_endo = (end_offst);/* Count offset */			\
123 	int nn##_e				/* dimension index */
124 
125 /* Set the counter value to start */
126 #define EC_INIT(nn) 								\
127 {													\
128 	for (nn##_e = 0; nn##_e < nn##_di; nn##_e++)	\
129 		nn[nn##_e] = nn##_start;					\
130 	nn##_e = 0;										\
131 }
132 
133 /* Increment the counter value */
134 #define EC_INC(nn)											\
135 {															\
136 	for (nn##_e = 0; nn##_e < nn##_di; nn##_e++) {			\
137 		nn[nn##_e]++;										\
138 		if (nn[nn##_e] < (nn##_res[nn##_e] + nn##_endo))	\
139 			break;	/* No carry */							\
140 		nn[nn##_e] = nn##_start;							\
141 	}														\
142 }
143 
144 /* After increment, expression is TRUE if counter is done */
145 #define EC_DONE(nn)									\
146 	(nn##_e >= nn##_di)
147 
148 /* (Do we need a version of the above that tracks the actual input coords ?) */
149 
150 /* ------------------------------------------------------- */
151 /* Macros combination counter */
152 /* Declare the counter name nn, combinations out of total */
153 /* mxdi should be set to maximum combinations */
154 
155 /* e.g. if there are 8 objects, and we want all combinations */
156 /* of 4 out of the 8, we would use: COMBO(nn, 4, 4, 8) */
157 
158 #define COMBO(nn, mxdi, comb, total) 				\
159 	int nn[mxdi+2];			/* counter value */				\
160 	int nn##_cmb = (comb);	/* number of combinations */	\
161 	int nn##_tot = (total);	/* out of total possible */		\
162 	int nn##_e				/* dimension index */
163 
164 /* Set total to new setting */
165 #define CB_SETT(nn, total)					 		\
166 	nn##_tot = (total)	/* total possible */
167 
168 /* Set combinations to new setting */
169 #define CB_SETC(nn, comb)					 		\
170 	nn##_cmb = (comb)	/* number of combinations*/
171 
172 /* Set the counter to its initial value */
173 #define CB_INIT(nn) 								\
174 {													\
175 	for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++)	\
176 		nn[nn##_e] = nn##_cmb-nn##_e-1;				\
177 	nn##_e = 0;										\
178 }
179 
180 /* Increment the counter value */
181 #define CB_INC(nn)									\
182 {													\
183 	for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) {	\
184 		nn[nn##_e]++;								\
185 		if (nn[nn##_e] < (nn##_tot-nn##_e)) {		\
186 			int nn##_ee;		/* No carry */		\
187 			for (nn##_ee = nn##_e-1; nn##_ee >= 0; nn##_ee--)	\
188 				nn[nn##_ee] = nn[nn##_ee+1] + 1;	\
189 			break;									\
190 		}											\
191 	}												\
192 }
193 
194 /* After increment, expression is TRUE if counter is done */
195 #define CB_DONE(nn)									\
196 	(nn##_e >= nn##_cmb)
197 
198 /* ------------------------------------------------------- */
199 /* Macros simplex combination counter. */
200 /* Based on COMBO, but skips invalid simplex combinations */
201 
202 #define XCOMBO(nn, mxdi, comb, total) 						\
203 		 COMBO(nn, mxdi, comb, total)
204 
205 /* Set total to new setting */
206 #define XCB_SETT(nn, total)					 			\
207          CB_SETT(nn, total)
208 
209 /* Set combinations to new setting */
210 #define XCB_SETC(nn, comb)					 			\
211          CB_SETC(nn, comb)
212 
213 
214 /* Set the counter to its initial value */
215 #define XCB_INIT(nn) 									\
216 {														\
217 	int nn##_ii;										\
218 														\
219 	for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++)		\
220 		nn[nn##_e] = nn##_cmb-nn##_e-1;					\
221 	for (nn##_ii = 1; nn##_ii < nn##_cmb; nn##_ii++) {	\
222 		if ((nn[nn##_ii-1] ^ nn[nn##_ii]) & nn[nn##_ii])\
223 			break;	/* Went from 0 to 1 */				\
224 	}													\
225 	if (nn##_ii < nn##_cmb)	{ /* Fix invalid combination */	\
226 		XCB_INC(nn);									\
227 	}													\
228 	nn##_e = 0;											\
229 }
230 
231 /* Increment the counter value */
232 #define XCB_INC(nn)										\
233 {														\
234 	int nn##_ii = 0;									\
235 														\
236 	while (nn##_ii < nn##_cmb) {						\
237 		for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) {	\
238 			nn[nn##_e]++;								\
239 			if (nn[nn##_e] < (nn##_tot-nn##_e)) {		\
240 				int nn##_ee;		/* No carry */		\
241 				for (nn##_ee = nn##_e-1; nn##_ee >= 0; nn##_ee--)	\
242 					nn[nn##_ee] = nn[nn##_ee+1] + 1;	\
243 				break;									\
244 			}											\
245 		}												\
246 		if (nn##_e >= nn##_cmb)							\
247 			break;		/* Done */						\
248 														\
249 		/* Reject invalid combinations */				\
250 		for (nn##_ii = 1; nn##_ii < nn##_cmb; nn##_ii++) {		\
251 			if ((nn[nn##_ii-1] ^ nn[nn##_ii]) & nn[nn##_ii]) 	\
252 				break;	/* Went from 0 to 1 */			\
253 		}												\
254 	}													\
255 }
256 
257 /* After increment, expression is TRUE if counter is done */
258 #define XCB_DONE(nn)									\
259          CB_DONE(nn)
260 
261 /* - - - - - - - - - - - - - - - - - - - - - - - - - - */
262 
263 #ifdef __cplusplus
264 	}
265 #endif
266 
267 #define COUNTERS_H
268 #endif /* COUNTERS_H */
269