1 #ifndef IMDI_UTL_H
2 #define IMDI_UTL_H
3 
4 /* Integer Multi-Dimensional Interpolation */
5 
6 /*
7  * Copyright 2000 - 2007 Graeme W. Gill
8  * All rights reserved.
9  *
10  * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
11  * see the License.txt file for licencing details.
12  */
13 
14 #include <limits.h>
15 
16 /* Common utility definitions used at both generation and runtime. */
17 
18 #define IXDI 10		/* maximum input channels/dimensions allowed */
19 #define IXDO 10		/* maximum output channels/dimensions allowed */
20 
21 #if IXDI > IXDO		/* Maximum of either DI or DO */
22 # define IXDIDO IXDI
23 #else
24 # define IXDIDO IXDO
25 #endif
26 
27 #define ALLOW64		/* Allow declarations but not use of 64 bit types */
28 
29 #ifndef FORCE64
30 # undef FORCE64		/* Use 64 bit, even on architectures where it's */
31 					/* not a native size. ALLOW64 must be defined */
32 #endif
33 
34 /* ------------------------------------------------------ */
35 
36 #if defined(ALLOW64) && (ULONG_MAX == 0xffffffffffffffffUL || defined(FORCE64))
37 #ifndef USE64
38 #pragma message("Using 64 bit integer color kernel")
39 #endif /* USE64 */
40 #define USE64		/* Use 64 bits if it's natural or forced */
41 #endif
42 
43 /* ------------------------------------------------------- */
44 /* Macros combination counter */
45 /* Declare the counter name nn, combinations out of total */
46 /* Maximum combinations is DI+2 */
47 
48 #define COMBO(nn, comb, total) 				\
49 	int nn[IXDI+2];			/* counter value */				\
50 	int nn##_cmb = (comb);	/* number of combinations*/		\
51 	int nn##_tot = (total);	/* out of total possible */		\
52 	int nn##_e				/* dimension index */
53 
54 /* Set total to new setting */
55 #define CB_SETT(nn, total)					 		\
56 	nn##_tot = (total)	/* total possible */
57 
58 /* Set combinations to new setting */
59 #define CB_SETC(nn, comb)					 		\
60 	nn##_cmb = (comb)	/* number of combinations*/
61 
62 /* Set the counter to its initial value */
63 #define CB_INIT(nn) 								\
64 {													\
65 	for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++)	\
66 		nn[nn##_e] = nn##_cmb-nn##_e-1;				\
67 	nn##_e = 0;										\
68 }
69 
70 /* Increment the counter value */
71 #define CB_INC(nn)									\
72 {													\
73 	for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) {	\
74 		nn[nn##_e]++;								\
75 		if (nn[nn##_e] < (nn##_tot-nn##_e)) {		\
76 			int nn##_ee;		/* No carry */		\
77 			for (nn##_ee = nn##_e-1; nn##_ee >= 0; nn##_ee--)	\
78 				nn[nn##_ee] = nn[nn##_ee+1] + 1;	\
79 			break;									\
80 		}											\
81 	}												\
82 }
83 
84 /* After increment, expression is TRUE if counter is done */
85 #define CB_DONE(nn)									\
86 	(nn##_e >= nn##_cmb)
87 
88 
89 /* ------------------------------------------------------- */
90 /* Macros simplex combination counter. */
91 /* Based on COMBO, but skips invalid simplex combinations */
92 
93 #define XCOMBO(nn, comb, total) 						\
94 		 COMBO(nn, comb, total)
95 
96 /* Set total to new setting */
97 #define XCB_SETT(nn, total)					 			\
98          CB_SETT(nn, total)
99 
100 /* Set combinations to new setting */
101 #define XCB_SETC(nn, comb)					 			\
102          CB_SETC(nn, comb)
103 
104 
105 /* Set the counter to its initial value */
106 #define XCB_INIT(nn) 									\
107 {														\
108 	int nn##_ii;										\
109 														\
110 	for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++)		\
111 		nn[nn##_e] = nn##_cmb-nn##_e-1;					\
112 	for (nn##_ii = 1; nn##_ii < nn##_cmb; nn##_ii++) {	\
113 		if ((nn[nn##_ii-1] ^ nn[nn##_ii]) & nn[nn##_ii])\
114 			break;	/* Went from 0 to 1 */				\
115 	}													\
116 	if (nn##_ii < nn##_cmb)	{ /* Fix invalid combination */	\
117 		XCB_INC(nn);									\
118 	}													\
119 	nn##_e = 0;											\
120 }
121 
122 /* Increment the counter value */
123 #define XCB_INC(nn)										\
124 {														\
125 	int nn##_ii = 0;									\
126 														\
127 	while (nn##_ii < nn##_cmb) {						\
128 		for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) {	\
129 			nn[nn##_e]++;								\
130 			if (nn[nn##_e] < (nn##_tot-nn##_e)) {		\
131 				int nn##_ee;		/* No carry */		\
132 				for (nn##_ee = nn##_e-1; nn##_ee >= 0; nn##_ee--)	\
133 					nn[nn##_ee] = nn[nn##_ee+1] + 1;	\
134 				break;									\
135 			}											\
136 		}												\
137 		if (nn##_e >= nn##_cmb)							\
138 			break;		/* Done */						\
139 														\
140 		/* Reject invalid combinations */				\
141 		for (nn##_ii = 1; nn##_ii < nn##_cmb; nn##_ii++) {		\
142 			if ((nn[nn##_ii-1] ^ nn[nn##_ii]) & nn[nn##_ii]) 	\
143 				break;	/* Went from 0 to 1 */			\
144 		}												\
145 	}													\
146 }
147 
148 /* After increment, expression is TRUE if counter is done */
149 #define XCB_DONE(nn)									\
150          CB_DONE(nn)
151 
152 /* ------------------------------------------------------- */
153 /* Macro pseudo-hilbert counter */
154 /* This multi-dimensional count sequence is a distributed */
155 /* Gray code sequence, with direction reversal on every */
156 /* alternate power of 2 scale. */
157 /* It is intended to aid cache coherence in multi-dimensional */
158 /* regular sampling. It approximates the Hilbert curve sequence. */
159 
160 #define PHILBERT(nn) 									\
161 	int      nn[IXDIDO];/* counter value */				\
162 	int      nn##di;	/* Dimensionality */			\
163 	unsigned nn##res;	/* Resolution per coordinate */	\
164 	unsigned nn##bits;	/* Bits per coordinate */		\
165 	unsigned nn##ix;	/* Current binary index */		\
166 	unsigned nn##tmask;	/* Total 2^n count mask */		\
167 	unsigned nn##count;	/* Usable count */
168 
169 /* Init counter for dimenion di, resolution res */
170 #define PH_INIT(nn, pdi, pres) 									\
171 {																\
172 	int nn##e;													\
173 																\
174 	nn##di  = pdi;												\
175 	nn##res = (unsigned)pres;									\
176 																\
177 	/* Compute bits */											\
178 	for (nn##bits = 0; (1u << nn##bits) < nn##res; nn##bits++)	\
179 		;														\
180 																\
181 	/* Compute the total count mask */							\
182 	nn##tmask = ((1u << (nn##bits * nn##di))-1);				\
183 																\
184 	/* Compute usable count */									\
185 	nn##count = 1;												\
186 	for (nn##e = 0; nn##e < nn##di; nn##e++)					\
187 		nn##count *= nn##res;									\
188 																\
189 	nn##ix = 0;													\
190 	for (nn##e = 0; nn##e < nn##di; nn##e++)					\
191 		nn[nn##e] = 0;											\
192 }
193 
194 /* Increment the counter value */
195 #define PH_INC(nn)												\
196 {																\
197 	int nn##e;													\
198 	do {														\
199 		unsigned int nn##b;										\
200 		int nn##gix;	/* Gray code index */					\
201 																\
202 		nn##ix = (nn##ix + 1) & nn##tmask;						\
203 																\
204 		/* Convert to gray code index */						\
205 		nn##gix = nn##ix ^ (nn##ix >> 1);						\
206 																\
207 		for (nn##e = 0; nn##e < nn##di; nn##e++) 				\
208 			nn[nn##e] = 0;										\
209 																\
210 		/* Distribute bits */									\
211 		for (nn##b = 0; nn##b < nn##bits; nn##b++) {			\
212 			if (nn##b & 1) {	/* In reverse order */			\
213 				for (nn##e = nn##di-1; nn##e >= 0; nn##e--)  {	\
214 					nn[nn##e] |= (nn##gix & 1) << nn##b;		\
215 					nn##gix >>= 1;								\
216 				}												\
217 			} else {	/* In normal order */					\
218 				for (nn##e = 0; nn##e < nn##di; nn##e++)  {		\
219 					nn[nn##e] |= (nn##gix & 1) << nn##b;		\
220 					nn##gix >>= 1;								\
221 				}												\
222 			}													\
223 		}														\
224 																\
225 		/* Convert from Gray to binary coordinates */			\
226 		for (nn##e = 0; nn##e < nn##di; nn##e++)  {				\
227 			unsigned nn##sh, nn##tv;							\
228 																\
229 			for(nn##sh = 1, nn##tv = nn[nn##e];; nn##sh <<= 1) {	\
230 				unsigned nn##ptv = nn##tv;						\
231 				nn##tv ^= (nn##tv >> nn##sh);					\
232 				if (nn##ptv <= 1 || nn##sh == 16)				\
233 					break;										\
234 			}													\
235 			/* Filter - increment again if outside cube range */	\
236 			if (nn##tv >= nn##res)								\
237 				break;											\
238 			nn[nn##e] = nn##tv;									\
239 		}														\
240 																\
241 	} while (nn##e < nn##di);									\
242 																\
243 }
244 
245 /* After increment, expression is TRUE if counter has looped back to start. */
246 #define PH_LOOPED(nn)									\
247 	(nn##ix == 0)										\
248 
249 /* ------------------------------------------------------- */
250 
251 #endif /* IMDI_UTL_H */
252 
253 
254 
255 
256 
257 
258 
259 
260 
261 
262 
263