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