2 * Image Library -- multidimensional Hilbert curves
4 * (c) 2006 Pavel Charvat <pchar@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
11 * - http://www.dcs.bbk.ac.uk/~jkl/mapping.c
13 * - J.K. Lawder. Calculation of Mappings between One and n-dimensional Values
14 * Using the Hilbert Space-Filling Curve. Technical Report JL1/00, Birkbeck
15 * College, University of London, 2000.
18 * - the algorithm fails for some combinations of HILBERT_DIM and HILBERT_ORDER,
19 * but it should be safe for HILBERT_DIM = 2..8, HILBERT_ORDER = 8..32
20 * - clean and optimize the code
23 #ifndef HILBERT_PREFIX
24 # error Undefined HILBERT_PREFIX
27 #define P(x) HILBERT_PREFIX(x)
30 * HILBERT_DIM is the number of dimensions in space through which the
31 * Hilbert Curve passes.
32 * Don't use this implementation with values for HILBERT_DIM of > 31!
33 * Also, make sure you use a 32 bit compiler!
36 # define HILBERT_DIM 2
40 # define HILBERT_TYPE u32
44 # define HILBERT_ORDER (8 * sizeof(HILBERT_TYPE))
47 typedef HILBERT_TYPE P(t);
50 * retained for historical reasons: the number of bits in an attribute value:
51 * effectively the order of a curve
53 #define NUMBITS HILBERT_ORDER
56 * the number of bits in a word used to store an hcode (or in an element of
57 * an array that's used)
59 #define WORDBITS HILBERT_ORDER
61 #ifdef HILBERT_WANT_ENCODE
63 * given the coordinates of a point, it finds the sequence number of the point
64 * on the Hilbert Curve
67 P(encode) (P(t) *dest, P(t) *src)
69 P(t) mask = (P(t))1 << WORDBITS - 1, element, temp1, temp2,
70 A, W = 0, S, tS, T, tT, J, P = 0, xJ;
71 uns i = NUMBITS * HILBERT_DIM - HILBERT_DIM, j;
73 for (j = 0; j < HILBERT_DIM; j++)
75 for (j = A = 0; j < HILBERT_DIM; j++)
77 A |= (1 << HILBERT_DIM - 1 - j);
81 P |= S & (1 << HILBERT_DIM - 1);
82 for (j = 1; j < HILBERT_DIM; j++)
83 if( S & (1 << HILBERT_DIM - 1 - j) ^ (P >> 1) & (1 << HILBERT_DIM - 1 - j))
84 P |= (1 << HILBERT_DIM - 1 - j);
86 /* add in HILBERT_DIM bits to hcode */
87 element = i / WORDBITS;
88 if (i % WORDBITS > WORDBITS - HILBERT_DIM)
90 dest[element] |= P << i % WORDBITS;
91 dest[element + 1] |= P >> WORDBITS - i % WORDBITS;
94 dest[element] |= P << i - element * WORDBITS;
97 for (j = 1; j < HILBERT_DIM; j++)
98 if ((P >> j & 1) == (P & 1))
102 if (j != HILBERT_DIM)
110 T = (P - 1) ^ (P - 1) / 2;
112 T = (P - 2) ^ (P - 2) / 2;
115 for (i -= HILBERT_DIM, mask >>= 1; (int)i >= 0; i -= HILBERT_DIM, mask >>= 1)
117 for (j = A = 0; j < HILBERT_DIM; j++)
119 A |= (1 << HILBERT_DIM - 1 - j);
123 if (xJ % HILBERT_DIM != 0)
125 temp1 = tS << xJ % HILBERT_DIM;
126 temp2 = tS >> HILBERT_DIM - xJ % HILBERT_DIM;
128 S &= ((P(t))1 << HILBERT_DIM) - 1;
133 P = S & (1 << HILBERT_DIM - 1);
134 for (j = 1; j < HILBERT_DIM; j++)
135 if( S & (1 << HILBERT_DIM - 1 - j) ^ (P >> 1) & (1 << HILBERT_DIM - 1 - j))
136 P |= (1 << HILBERT_DIM - 1 - j);
138 /* add in HILBERT_DIM bits to hcode */
139 element = i / WORDBITS;
140 if (i % WORDBITS > WORDBITS - HILBERT_DIM)
142 dest[element] |= P << i % WORDBITS;
143 dest[element + 1] |= P >> WORDBITS - i % WORDBITS;
146 dest[element] |= P << i - element * WORDBITS;
154 T = (P - 1) ^ (P - 1) / 2;
156 T = (P - 2) ^ (P - 2) / 2;
158 if (xJ % HILBERT_DIM != 0)
160 temp1 = T >> xJ % HILBERT_DIM;
161 temp2 = T << HILBERT_DIM - xJ % HILBERT_DIM;
163 tT &= ((P(t))1 << HILBERT_DIM) - 1;
169 for (j = 1; j < HILBERT_DIM; j++)
170 if ((P >> j & 1) == (P & 1))
174 if (j != HILBERT_DIM)
178 /* J %= HILBERT_DIM; */
181 for (j = 0; j < HILBERT_DIM; j++)
182 dest[j] &= ~(P(t))0 >> (8 * sizeof(P(t)) - WORDBITS);
186 #ifdef HILBERT_WANT_DECODE
188 * given the sequence number of a point, it finds the coordinates of the point
189 * on the Hilbert Curve
192 P(decode) (P(t) *dest, P(t) *src)
194 P(t) mask = (P(t))1 << WORDBITS - 1, element, temp1, temp2,
195 A, W = 0, S, tS, T, tT, J, P = 0, xJ;
196 uns i = NUMBITS * HILBERT_DIM - HILBERT_DIM, j;
198 for (j = 0; j < HILBERT_DIM; j++)
202 element = i / WORDBITS;
204 if (i % WORDBITS > WORDBITS - HILBERT_DIM)
206 temp1 = src[element + 1];
208 temp1 <<= WORDBITS - i % WORDBITS;
212 P >>= i % WORDBITS; /* P is a HILBERT_DIM bit hcode */
214 /* the & masks out spurious highbit values */
215 if (HILBERT_DIM < WORDBITS)
216 P &= (1 << HILBERT_DIM) -1;
220 for (j = 1; j < HILBERT_DIM; j++)
221 if ((P >> j & 1) == (P & 1))
225 if (j != HILBERT_DIM)
230 A = S = tS = P ^ P / 2;
238 T = (P - 1) ^ (P - 1) / 2;
240 T = (P - 2) ^ (P - 2) / 2;
245 /*--- distrib bits to coords ---*/
246 for (j = HILBERT_DIM - 1; P > 0; P >>=1, j--)
251 for (i -= HILBERT_DIM, mask >>= 1; (int)i >= 0; i -= HILBERT_DIM, mask >>= 1)
254 element = i / WORDBITS;
256 if (i % WORDBITS > WORDBITS - HILBERT_DIM)
258 temp1 = src[element + 1];
260 temp1 <<= WORDBITS - i % WORDBITS;
264 P >>= i % WORDBITS; /* P is a HILBERT_DIM bit hcode */
266 /* the & masks out spurious highbit values */
267 if (HILBERT_DIM < WORDBITS)
268 P &= (1 << HILBERT_DIM) -1;
274 if (xJ % HILBERT_DIM != 0)
276 temp1 = S >> xJ % HILBERT_DIM;
277 temp2 = S << HILBERT_DIM - xJ % HILBERT_DIM;
279 tS &= ((P(t))1 << HILBERT_DIM) - 1;
290 /*--- distrib bits to coords ---*/
291 for (j = HILBERT_DIM - 1; A > 0; A >>=1, j--)
302 T = (P - 1) ^ (P - 1) / 2;
304 T = (P - 2) ^ (P - 2) / 2;
307 if (xJ % HILBERT_DIM != 0)
309 temp1 = T >> xJ % HILBERT_DIM;
310 temp2 = T << HILBERT_DIM - xJ % HILBERT_DIM;
312 tT &= ((P(t))1 << HILBERT_DIM) - 1;
319 for (j = 1; j < HILBERT_DIM; j++)
320 if ((P >> j & 1) == (P & 1))
324 if (j != HILBERT_DIM)
333 #undef HILBERT_PREFIX
337 #undef HILBERT_WANT_DECODE
338 #undef HILBERT_WANT_ENCODE