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