ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/hilbert.c
Revision: 3.1
Committed: Fri Feb 18 00:40:25 2011 UTC (13 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Major code reorg, moving mgflib to common and introducing BSDF material

File Contents

# User Rev Content
1 greg 3.1 /* See LICENSE below for information on rights to use, modify and distribute
2     this code. */
3    
4     /*
5     * hilbert.c - Computes Hilbert space-filling curve coordinates, without
6     * recursion, from integer index, and vice versa, and other Hilbert-related
7     * calculations. Also known as Pi-order or Peano scan.
8     *
9     * Author: Doug Moore
10     * Dept. of Computational and Applied Math
11     * Rice University
12     * http://www.caam.rice.edu/~dougm
13     * Date: Sun Feb 20 2000
14     * Copyright (c) 1998-2000, Rice University
15     *
16     * Acknowledgement:
17     * This implementation is based on the work of A. R. Butz ("Alternative
18     * Algorithm for Hilbert's Space-Filling Curve", IEEE Trans. Comp., April,
19     * 1971, pp 424-426) and its interpretation by Spencer W. Thomas, University
20     * of Michigan (http://www-personal.umich.edu/~spencer/Home.html) in his widely
21     * available C software. While the implementation here differs considerably
22     * from his, the first two interfaces and the style of some comments are very
23     * much derived from his work. */
24    
25    
26     #include "hilbert.h"
27    
28     /* implementation of the hilbert functions */
29    
30     #define adjust_rotation(rotation,nDims,bits) \
31     do { \
32     /* rotation = (rotation + 1 + ffs(bits)) % nDims; */ \
33     bits &= -bits & nd1Ones; \
34     while (bits) \
35     bits >>= 1, ++rotation; \
36     if ( ++rotation >= nDims ) \
37     rotation -= nDims; \
38     } while (0)
39    
40     #define ones(T,k) ((((T)2) << (k-1)) - 1)
41    
42     #define rdbit(w,k) (((w) >> (k)) & 1)
43    
44     #define rotateRight(arg, nRots, nDims) \
45     ((((arg) >> (nRots)) | ((arg) << ((nDims)-(nRots)))) & ones(bitmask_t,nDims))
46    
47     #define rotateLeft(arg, nRots, nDims) \
48     ((((arg) << (nRots)) | ((arg) >> ((nDims)-(nRots)))) & ones(bitmask_t,nDims))
49    
50     #define DLOGB_BIT_TRANSPOSE
51     static bitmask_t
52     bitTranspose(unsigned nDims, unsigned nBits, bitmask_t inCoords)
53     #if defined(DLOGB_BIT_TRANSPOSE)
54     {
55     unsigned const nDims1 = nDims-1;
56     unsigned inB = nBits;
57     unsigned utB;
58     bitmask_t inFieldEnds = 1;
59     bitmask_t inMask = ones(bitmask_t,inB);
60     bitmask_t coords = 0;
61    
62     while ((utB = inB >> 1))
63     {
64     unsigned const shiftAmt = nDims1 * utB;
65     bitmask_t const utFieldEnds =
66     inFieldEnds | (inFieldEnds << (shiftAmt+utB));
67     bitmask_t const utMask =
68     (utFieldEnds << utB) - utFieldEnds;
69     bitmask_t utCoords = 0;
70     unsigned d;
71     if (inB & 1)
72     {
73     bitmask_t const inFieldStarts = inFieldEnds << (inB-1);
74     unsigned oddShift = 2*shiftAmt;
75     for (d = 0; d < nDims; ++d)
76     {
77     bitmask_t in = inCoords & inMask;
78     inCoords >>= inB;
79     coords |= (in & inFieldStarts) << oddShift++;
80     in &= ~inFieldStarts;
81     in = (in | (in << shiftAmt)) & utMask;
82     utCoords |= in << (d*utB);
83     }
84     }
85     else
86     {
87     for (d = 0; d < nDims; ++d)
88     {
89     bitmask_t in = inCoords & inMask;
90     inCoords >>= inB;
91     in = (in | (in << shiftAmt)) & utMask;
92     utCoords |= in << (d*utB);
93     }
94     }
95     inCoords = utCoords;
96     inB = utB;
97     inFieldEnds = utFieldEnds;
98     inMask = utMask;
99     }
100     coords |= inCoords;
101     return coords;
102     }
103     #else
104     {
105     bitmask_t coords = 0;
106     unsigned d;
107     for (d = 0; d < nDims; ++d)
108     {
109     unsigned b;
110     bitmask_t in = inCoords & ones(bitmask_t,nBits);
111     bitmask_t out = 0;
112     inCoords >>= nBits;
113     for (b = nBits; b--;)
114     {
115     out <<= nDims;
116     out |= rdbit(in, b);
117     }
118     coords |= out << d;
119     }
120     return coords;
121     }
122     #endif
123    
124     /*****************************************************************
125     * hilbert_i2c
126     *
127     * Convert an index into a Hilbert curve to a set of coordinates.
128     * Inputs:
129     * nDims: Number of coordinate axes.
130     * nBits: Number of bits per axis.
131     * index: The index, contains nDims*nBits bits
132     * (so nDims*nBits must be <= 8*sizeof(bitmask_t)).
133     * Outputs:
134     * coord: The list of nDims coordinates, each with nBits bits.
135     * Assumptions:
136     * nDims*nBits <= (sizeof index) * (bits_per_byte)
137     */
138     void
139     hilbert_i2c(unsigned nDims, unsigned nBits, bitmask_t index, bitmask_t coord[])
140     {
141     if (nDims > 1)
142     {
143     bitmask_t coords;
144     halfmask_t const nbOnes = ones(halfmask_t,nBits);
145     unsigned d;
146    
147     if (nBits > 1)
148     {
149     unsigned const nDimsBits = nDims*nBits;
150     halfmask_t const ndOnes = ones(halfmask_t,nDims);
151     halfmask_t const nd1Ones= ndOnes >> 1; /* for adjust_rotation */
152     unsigned b = nDimsBits;
153     unsigned rotation = 0;
154     halfmask_t flipBit = 0;
155     bitmask_t const nthbits = ones(bitmask_t,nDimsBits) / ndOnes;
156     index ^= (index ^ nthbits) >> 1;
157     coords = 0;
158     do
159     {
160     halfmask_t bits = (index >> (b-=nDims)) & ndOnes;
161     coords <<= nDims;
162     coords |= rotateLeft(bits, rotation, nDims) ^ flipBit;
163     flipBit = (halfmask_t)1 << rotation;
164     adjust_rotation(rotation,nDims,bits);
165     } while (b);
166     for (b = nDims; b < nDimsBits; b *= 2)
167     coords ^= coords >> b;
168     coords = bitTranspose(nBits, nDims, coords);
169     }
170     else
171     coords = index ^ (index >> 1);
172    
173     for (d = 0; d < nDims; ++d)
174     {
175     coord[d] = coords & nbOnes;
176     coords >>= nBits;
177     }
178     }
179     else
180     coord[0] = index;
181     }
182    
183     /*****************************************************************
184     * hilbert_c2i
185     *
186     * Convert coordinates of a point on a Hilbert curve to its index.
187     * Inputs:
188     * nDims: Number of coordinates.
189     * nBits: Number of bits/coordinate.
190     * coord: Array of n nBits-bit coordinates.
191     * Outputs:
192     * index: Output index value. nDims*nBits bits.
193     * Assumptions:
194     * nDims*nBits <= (sizeof bitmask_t) * (bits_per_byte)
195     */
196     bitmask_t
197     hilbert_c2i(unsigned nDims, unsigned nBits, bitmask_t const coord[])
198     {
199     if (nDims > 1)
200     {
201     unsigned const nDimsBits = nDims*nBits;
202     bitmask_t index;
203     unsigned d;
204     bitmask_t coords = 0;
205     for (d = nDims; d--; )
206     {
207     coords <<= nBits;
208     coords |= coord[d];
209     }
210    
211     if (nBits > 1)
212     {
213     halfmask_t const ndOnes = ones(halfmask_t,nDims);
214     halfmask_t const nd1Ones= ndOnes >> 1; /* for adjust_rotation */
215     unsigned b = nDimsBits;
216     unsigned rotation = 0;
217     halfmask_t flipBit = 0;
218     bitmask_t const nthbits = ones(bitmask_t,nDimsBits) / ndOnes;
219     coords = bitTranspose(nDims, nBits, coords);
220     coords ^= coords >> nDims;
221     index = 0;
222     do
223     {
224     halfmask_t bits = (coords >> (b-=nDims)) & ndOnes;
225     bits = rotateRight(flipBit ^ bits, rotation, nDims);
226     index <<= nDims;
227     index |= bits;
228     flipBit = (halfmask_t)1 << rotation;
229     adjust_rotation(rotation,nDims,bits);
230     } while (b);
231     index ^= nthbits >> 1;
232     }
233     else
234     index = coords;
235     for (d = 1; d < nDimsBits; d *= 2)
236     index ^= index >> d;
237     return index;
238     }
239     else
240     return coord[0];
241     }
242    
243     /*****************************************************************
244     * Readers and writers of bits
245     */
246    
247     typedef bitmask_t (*BitReader) (unsigned nDims, unsigned nBytes,
248     char const* c, unsigned y);
249     typedef void (*BitWriter) (unsigned d, unsigned nBytes,
250     char* c, unsigned y, int fold);
251    
252    
253     #if defined(sparc)
254     #define __BIG_ENDIAN__
255     #endif
256    
257     #if defined(__BIG_ENDIAN__)
258     #define whichByte(nBytes,y) (nBytes-1-y/8)
259     #define setBytes(dst,pos,nBytes,val) \
260     memset(&dst[pos+1],val,nBytes-pos-1)
261     #else
262     #define whichByte(nBytes,y) (y/8)
263     #define setBytes(dst,pos,nBytes,val) \
264     memset(&dst[0],val,pos)
265     #endif
266    
267     static bitmask_t
268     getIntBits(unsigned nDims, unsigned nBytes, char const* c, unsigned y)
269     {
270     unsigned const bit = y%8;
271     unsigned const offs = whichByte(nBytes,y);
272     unsigned d;
273     bitmask_t bits = 0;
274     c += offs;
275     for (d = 0; d < nDims; ++d)
276     {
277     bits |= rdbit(*c, bit) << d;
278     c += nBytes;
279     }
280     return bits;
281     }
282    
283     #include <string.h>
284     static void
285     propogateIntBits(unsigned d, unsigned nBytes,
286     char* c, unsigned y, int fold)
287     {
288     unsigned const byteId = whichByte(nBytes,y);
289     unsigned const b = y%8;
290     char const bthbit = 1 << b;
291     char* const target = &c[d*nBytes];
292     target[byteId] ^= bthbit;
293     if (!fold)
294     {
295     char notbit = ((target[byteId] >> b) & 1) - 1;
296     if (notbit)
297     target[byteId] |= bthbit-1;
298     else
299     target[byteId] &= -bthbit;
300     setBytes(target,byteId,nBytes,notbit);
301     }
302     }
303    
304     /* An IEEE double is treated as a 2100 bit number. In particular, 0 is treated
305     as a 1 followed by 2099 zeroes, and negative 0 as a 0 followed by 2099 ones.
306     Only 53 bits differ between a number and a zero of the same sign, with the
307     position of the 53 determined by the exponent, and the values of the 53 by
308     the significand (with implicit leading 1 bit). Although IEEE 754 uses the
309     maximum exponent for NaN's and infinities, this implementation ignores that
310     decision, so that infinities and NaN's are treated as very large numbers.
311     Note that we do not explicitly construct a 2100 bit bitmask in the IEEE
312     routines below. */
313    
314     enum { IEEEexpBits = 11 };
315     enum { IEEEsigBits = 52 };
316     enum { IEEErepBits = (1 << IEEEexpBits) + IEEEsigBits };
317    
318     typedef union ieee754_double
319     {
320     double d;
321    
322     /* This is the IEEE 754 double-precision format. */
323     struct
324     {
325     #if defined(__BIG_ENDIAN__)
326     unsigned int negative:1;
327     unsigned int exponent:11;
328     /* Together these comprise the mantissa. */
329     unsigned int mantissa0:20;
330     unsigned int mantissa1:32;
331     #else /* Big endian. */
332     /* Together these comprise the mantissa. */
333     unsigned int mantissa1:32;
334     unsigned int mantissa0:20;
335     unsigned int exponent:11;
336     unsigned int negative:1;
337     #endif /* Little endian. */
338     } ieee;
339     } ieee754_double;
340    
341     static bitmask_t
342     getIEEESignBits(unsigned nDims, double const* c)
343     {
344     unsigned d;
345     ieee754_double x;
346     bitmask_t bits = 0;
347     for (d = 0; d < nDims; ++d)
348     {
349     x.d = c[d];
350     bits |= x.ieee.negative << d;
351     }
352     return bits;
353     }
354    
355     static bitmask_t
356     getIEEEBits(unsigned nDims,
357     unsigned ignoreMe, /* ignored */
358     char const* cP,
359     unsigned y)
360     /* retrieve bits y of elements of double array c, where an expanded IEEE
361     double has 2100 bits. */
362     {
363     unsigned d;
364     double const* c = (double const*) cP;
365     ieee754_double x;
366     bitmask_t bits = 0;
367     for (x.d = c[d=0]; d < nDims; x.d = c[++d])
368     {
369     bitmask_t bit = x.ieee.negative;
370     unsigned normalized = (x.ieee.exponent != 0);
371     unsigned diff = y - (x.ieee.exponent - normalized);
372     if (diff <= 52)
373     bit ^= 1 & ((diff < 32)? x.ieee.mantissa1 >> diff:
374     (diff < 52)? x.ieee.mantissa0 >> (diff - 32):
375     /* else */ normalized);
376     else
377     bit ^= (y == IEEErepBits-1);
378    
379     bits |= bit << d;
380     }
381     return bits;
382     }
383    
384     static void
385     propogateIEEEBits(unsigned d, unsigned nBytes,
386     char* cP, unsigned y, int fold)
387     {
388     ieee754_double* x = d + (ieee754_double*) cP;
389     unsigned normalized = (x->ieee.exponent != 0);
390     unsigned diff = y - (x->ieee.exponent - normalized);
391     if (diff < 32)
392     {
393     unsigned b = 1 << diff;
394     unsigned bit = x->ieee.mantissa1 & b;
395     x->ieee.mantissa1 &= ~(b-1);
396     x->ieee.mantissa1 |= b;
397     if (bit)
398     --x->ieee.mantissa1;
399     }
400     else if (diff < 52)
401     {
402     unsigned b = 1 << (diff - 32);
403     unsigned bit = x->ieee.mantissa0 & b;
404     x->ieee.mantissa0 &= ~(b-1);
405     x->ieee.mantissa0 |= b;
406     if (bit)
407     --x->ieee.mantissa0;
408     x->ieee.mantissa1 = bit?-1: 0;
409     }
410     else if (diff == 52) /* "flip" the implicit 1 bit */
411     {
412     if (normalized)
413     --x->ieee.exponent;
414     else
415     x->ieee.exponent = 1;
416     x->ieee.mantissa0 = -normalized;
417     x->ieee.mantissa1 = -normalized;
418     }
419     else if (diff < IEEErepBits)
420     {
421     if (y == IEEErepBits-1)
422     {
423     x->ieee.negative ^= 1;
424     x->ieee.exponent = 0;
425     }
426     else
427     x->ieee.exponent = y - 51;
428     x->ieee.mantissa0 = 0;
429     x->ieee.mantissa1 = 0;
430     }
431     }
432    
433     static unsigned
434     getIEEEexptMax(unsigned nDims, double const* c)
435     {
436     unsigned max = 0;
437     unsigned d;
438     for (d = 0; d < nDims; ++d)
439     {
440     ieee754_double x;
441     x.d = c[d];
442     if (max < x.ieee.exponent)
443     max = x.ieee.exponent;
444     }
445     if (max) --max;
446     return max;
447     }
448    
449     static void
450     getIEEEinitValues(double const* c1,
451     unsigned y,
452     unsigned nDims,
453     unsigned* rotation,
454     bitmask_t* bits,
455     bitmask_t* index)
456     {
457     bitmask_t const one = 1;
458     unsigned d;
459     bitmask_t signBits = getIEEESignBits(nDims, c1);
460     unsigned signParity, leastZeroBit, strayBit;
461    
462     /* compute the odd/evenness of the number of sign bits */
463     {
464     bitmask_t signPar = signBits;
465     for (d = 1; d < nDims; d *= 2)
466     signPar ^= signPar >> d;
467     signParity = signPar & 1;
468     }
469    
470     /* find the position of the least-order 0 bit in among signBits and adjust it
471     if necessary */
472     for (leastZeroBit = 0; leastZeroBit < nDims; ++leastZeroBit)
473     if (rdbit(signBits, leastZeroBit) == 0)
474     break;
475     strayBit = 0;
476     if (leastZeroBit == nDims-2)
477     strayBit = 1;
478     else if (leastZeroBit == nDims)
479     leastZeroBit = nDims-1;
480    
481     if (y % 2 == 1)
482     {
483     *rotation = (IEEErepBits - y + 1 + leastZeroBit) % nDims;
484     if (y < IEEErepBits-1)
485     {
486     *bits = signBits ^ (one << ((*rotation + strayBit) % nDims));
487     *index = signParity;
488     }
489     else /* y == IEEErepBits-1 */
490     {
491     *bits = signBits ^ (ones(bitmask_t,nDims) &~ 1);
492     *index = signParity ^ (nDims&1);
493     }
494     }
495     else /* y % 2 == 0 */
496     if (y < IEEErepBits)
497     {
498     unsigned shift_amt = (IEEErepBits - y + leastZeroBit) % nDims;
499     *rotation = (shift_amt + 2 + strayBit) % nDims;
500     *bits = signBits ^ (one << shift_amt);
501     *index = signParity ^ 1;
502     }
503     else /* y == IEEErepBits */
504     {
505     *rotation = 0;
506     *bits = one << (nDims-1);
507     *index = 1;
508     }
509     }
510    
511     /*****************************************************************
512     * hilbert_cmp, hilbert_ieee_cmp
513     *
514     * Determine which of two points lies further along the Hilbert curve
515     * Inputs:
516     * nDims: Number of coordinates.
517     * nBytes: Number of bytes of storage/coordinate (hilbert_cmp only)
518     * nBits: Number of bits/coordinate. (hilbert_cmp only)
519     * coord1: Array of nDims nBytes-byte coordinates (or doubles for ieee_cmp).
520     * coord2: Array of nDims nBytes-byte coordinates (or doubles for ieee_cmp).
521     * Return value:
522     * -1, 0, or 1 according to whether
523     coord1<coord2, coord1==coord2, coord1>coord2
524     * Assumptions:
525     * nBits <= (sizeof bitmask_t) * (bits_per_byte)
526     */
527    
528     static int
529     hilbert_cmp_work(unsigned nDims, unsigned nBytes, unsigned nBits,
530     unsigned max, unsigned y,
531     char const* c1, char const* c2,
532     unsigned rotation,
533     bitmask_t bits,
534     bitmask_t index,
535     BitReader getBits)
536     {
537     bitmask_t const one = 1;
538     bitmask_t const nd1Ones = ones(bitmask_t,nDims) >> 1; /* used in adjust_rotation macro */
539     while (y-- > max)
540     {
541     bitmask_t reflection = getBits(nDims, nBytes, c1, y);
542     bitmask_t diff = reflection ^ getBits(nDims, nBytes, c2, y);
543     bits ^= reflection;
544     bits = rotateRight(bits, rotation, nDims);
545     if (diff)
546     {
547     unsigned d;
548     diff = rotateRight(diff, rotation, nDims);
549     for (d = 1; d < nDims; d *= 2)
550     {
551     index ^= index >> d;
552     bits ^= bits >> d;
553     diff ^= diff >> d;
554     }
555     return (((index ^ y ^ nBits) & 1) == (bits < (bits^diff)))? -1: 1;
556     }
557     index ^= bits;
558     reflection ^= one << rotation;
559     adjust_rotation(rotation,nDims,bits);
560     bits = reflection;
561     }
562     return 0;
563     }
564    
565     int
566     hilbert_cmp(unsigned nDims, unsigned nBytes, unsigned nBits,
567     void const* c1, void const* c2)
568     {
569     bitmask_t const one = 1;
570     bitmask_t bits = one << (nDims-1);
571     return hilbert_cmp_work(nDims, nBytes, nBits, 0, nBits,
572     (char const*)c1, (char const*)c2,
573     0, bits, bits, getIntBits);
574     }
575    
576     int
577     hilbert_ieee_cmp(unsigned nDims, double const* c1, double const* c2)
578     {
579     unsigned rotation, max;
580     bitmask_t bits, index;
581     if (getIEEESignBits(nDims, c1) != getIEEESignBits(nDims, c2))
582     max = 2047;
583     else
584     {
585     unsigned max1 = getIEEEexptMax(nDims, c1);
586     unsigned max2 = getIEEEexptMax(nDims, c2);
587     max = (max1 > max2)? max1: max2;
588     }
589    
590     getIEEEinitValues(c1, max+53, nDims, &rotation, &bits, &index);
591     return hilbert_cmp_work(nDims, 8, 64, max, max+53,
592     (char const*)c1, (char const*)c2,
593     rotation, bits, index, getIEEEBits);
594     }
595    
596     /*****************************************************************
597     * hilbert_box_vtx
598     *
599     * Determine the first or last vertex of a box to lie on a Hilbert curve
600     * Inputs:
601     * nDims: Number of coordinates.
602     * nBytes: Number of bytes/coordinate.
603     * nBits: Number of bits/coordinate.
604     * findMin: Is it the least vertex sought?
605     * coord1: Array of nDims nBytes-byte coordinates - one corner of box
606     * coord2: Array of nDims nBytes-byte coordinates - opposite corner
607     * Output:
608     * c1 and c2 modified to refer to selected corner
609     * value returned is log2 of size of largest power-of-two-aligned box that
610     * contains the selected corner and no other corners
611     * Assumptions:
612     * nBits <= (sizeof bitmask_t) * (bits_per_byte)
613     */
614    
615    
616     static unsigned
617     hilbert_box_vtx_work(unsigned nDims, unsigned nBytes, unsigned nBits,
618     int findMin,
619     unsigned max, unsigned y,
620     char* c1, char* c2,
621     unsigned rotation,
622     bitmask_t bits,
623     bitmask_t index,
624     BitReader getBits)
625     {
626     bitmask_t const one = 1;
627     bitmask_t const ndOnes = ones(bitmask_t,nDims);
628     bitmask_t const nd1Ones= ndOnes >> 1;
629     bitmask_t bitsFolded = 0;
630    
631     while (y--)
632     {
633     bitmask_t reflection = getBits(nDims, nBytes, c1, y);
634     bitmask_t diff = reflection ^ getBits(nDims, nBytes, c2, y);
635     if (diff)
636     {
637     unsigned d;
638     bitmask_t smear = rotateRight(diff, rotation, nDims) >> 1;
639     bitmask_t digit = rotateRight(bits ^ reflection, rotation, nDims);
640     for (d = 1; d < nDims; d *= 2)
641     {
642     index ^= index >> d;
643     digit ^= (digit >> d) &~ smear;
644     smear |= smear >> d;
645     }
646     index &= 1;
647     if ((index ^ y ^ findMin) & 1)
648     digit ^= smear+1;
649     digit = rotateLeft(digit, rotation, nDims) & diff;
650     reflection ^= digit;
651    
652     for (d = 0; d < nDims; ++d)
653     if (rdbit(diff, d))
654     {
655     int way = rdbit(digit, d);
656     char* target = d*nBytes + (way? c1: c2);
657     char* const source = 2*d*nBytes + c1 - target + c2;
658     memcpy(target, source, nBytes);
659     }
660    
661     bitsFolded |= diff;
662     if (bitsFolded == ndOnes)
663     return y;
664     }
665    
666     bits ^= reflection;
667     bits = rotateRight(bits, rotation, nDims);
668     index ^= bits;
669     reflection ^= one << rotation;
670     adjust_rotation(rotation,nDims,bits);
671     bits = reflection;
672     }
673     return y;
674     }
675    
676     unsigned
677     hilbert_box_vtx(unsigned nDims, unsigned nBytes, unsigned nBits,
678     int findMin, void* c1, void* c2)
679     {
680     bitmask_t const one = 1;
681     bitmask_t bits = one << (nDims-1);
682     return hilbert_box_vtx_work(nDims, nBytes, nBits, findMin,
683     0, nBits, (char*)c1, (char*)c2,
684     0, bits, bits, getIntBits);
685     }
686    
687     unsigned
688     hilbert_ieee_box_vtx(unsigned nDims,
689     int findMin, double* c1, double* c2)
690     {
691     unsigned rotation, max;
692     bitmask_t bits, index;
693     if (getIEEESignBits(nDims, c1) != getIEEESignBits(nDims, c2))
694     max = 2047;
695     else
696     {
697     unsigned max1 = getIEEEexptMax(nDims, c1);
698     unsigned max2 = getIEEEexptMax(nDims, c2);
699     max = (max1 > max2)? max1: max2;
700     }
701    
702     getIEEEinitValues(c1, max+53, nDims, &rotation, &bits, &index);
703    
704     return hilbert_box_vtx_work(nDims, 8, 64, findMin,
705     max, max+53, (char *)c1, (char *)c2,
706     rotation, bits, index, getIEEEBits);
707     }
708    
709     /*****************************************************************
710     * hilbert_box_pt
711     *
712     * Determine the first or last point of a box to lie on a Hilbert curve
713     * Inputs:
714     * nDims: Number of coordinates.
715     * nBytes: Number of bytes/coordinate.
716     * nBits: Number of bits/coordinate.
717     * findMin: Is it the least vertex sought?
718     * coord1: Array of nDims nBytes-byte coordinates - one corner of box
719     * coord2: Array of nDims nBytes-byte coordinates - opposite corner
720     * Output:
721     * c1 and c2 modified to refer to least point
722     * Assumptions:
723     * nBits <= (sizeof bitmask_t) * (bits_per_byte)
724     */
725     unsigned
726     hilbert_box_pt_work(unsigned nDims, unsigned nBytes, unsigned nBits,
727     int findMin,
728     unsigned max, unsigned y,
729     char* c1, char* c2,
730     unsigned rotation,
731     bitmask_t bits,
732     bitmask_t index,
733     BitReader getBits,
734     BitWriter propogateBits)
735     {
736     bitmask_t const one = 1;
737     bitmask_t const nd1Ones = ones(bitmask_t,nDims) >> 1;
738     bitmask_t fold1 = 0, fold2 = 0;
739     unsigned smearSum = 0;
740    
741     while (y-- > max)
742     {
743     bitmask_t reflection = getBits(nDims, nBytes, c1, y);
744     bitmask_t diff = reflection ^ getBits(nDims, nBytes, c2, y);
745     if (diff)
746     {
747     bitmask_t smear = rotateRight(diff, rotation, nDims) >> 1;
748     bitmask_t digit = rotateRight(bits ^ reflection, rotation, nDims);
749     unsigned d;
750     for (d = 1; d < nDims; d *= 2)
751     {
752     index ^= index >> d;
753     digit ^= (digit >> d) &~ smear;
754     smear |= smear >> d;
755     }
756     smearSum += smear;
757     index &= 1;
758     if ((index ^ y ^ findMin) & 1)
759     digit ^= smear+1;
760     digit = rotateLeft(digit, rotation, nDims) & diff;
761     reflection ^= digit;
762    
763     for (d = 0; d < nDims; ++d)
764     if (rdbit(diff, d))
765     {
766     int way = rdbit(digit, d);
767     char* c = way? c1: c2;
768     bitmask_t fold = way? fold1: fold2;
769     propogateBits(d, nBytes, c, y, rdbit(fold, d));
770     }
771     diff ^= digit;
772     fold1 |= digit;
773     fold2 |= diff;
774     }
775    
776     bits ^= reflection;
777     bits = rotateRight(bits, rotation, nDims);
778     index ^= bits;
779     reflection ^= one << rotation;
780     adjust_rotation(rotation,nDims,bits);
781     bits = reflection;
782     }
783     return smearSum;
784     }
785    
786     unsigned
787     hilbert_box_pt(unsigned nDims, unsigned nBytes, unsigned nBits,
788     int findMin, void* c1, void* c2)
789     {
790     bitmask_t const one = 1;
791     bitmask_t bits = one << (nDims-1);
792     return hilbert_box_pt_work(nDims, nBytes, nBits, findMin,
793     0, nBits, (char*)c1, (char*)c2,
794     0, bits, bits,
795     getIntBits, propogateIntBits);
796     }
797    
798     unsigned
799     hilbert_ieee_box_pt(unsigned nDims,
800     int findMin, double* c1, double* c2)
801     {
802     unsigned rotation, max;
803     bitmask_t bits, index;
804     bitmask_t c1Signs = getIEEESignBits(nDims, c1);
805     bitmask_t c2Signs = getIEEESignBits(nDims, c2);
806     if (c1Signs != c2Signs)
807     {
808     rotation = 0;
809     bits = (bitmask_t)1 << (nDims-1);
810     index = 1;
811     hilbert_box_pt_work(nDims, 8, 64, findMin,
812     IEEErepBits-1, IEEErepBits, (char *)c1, (char *)c2,
813     rotation, bits, index,
814     getIEEEBits, propogateIEEEBits);
815     }
816    
817     /* having put everything in the same orthant, start */
818     {
819     unsigned max1 = getIEEEexptMax(nDims, c1);
820     unsigned max2 = getIEEEexptMax(nDims, c2);
821     max = (max1 > max2)? max1: max2;
822     }
823    
824     getIEEEinitValues(c1, max+53, nDims, &rotation, &bits, &index);
825    
826     return hilbert_box_pt_work(nDims, 8, 64, findMin,
827     max, max+53, (char *)c1, (char *)c2,
828     rotation, bits, index,
829     getIEEEBits, propogateIEEEBits);
830     }
831    
832     /*****************************************************************
833     * hilbert_nextinbox
834     *
835     * Determine the first point of a box after or before a given point to lie on
836     * a Hilbert curve
837     * Inputs:
838     * nDims: Number of coordinates.
839     * nBytes: Number of bytes/coordinate.
840     * nBits: Number of bits/coordinate.
841     * findPrev: Is it a previous point that you want?
842     * coord1: Array of nDims nBytes-byte coordinates - one corner of box
843     * coord2: Array of nDims nBytes-byte coordinates - opposite corner
844     * point: Array of nDims nBytes-byte coordinates - lower bound on point returned
845     *
846     * Output:
847     if returns 1:
848     * c1 and c2 modified to refer to least point after "point" in box
849     else returns 0:
850     arguments unchanged; "point" is beyond the last point of the box
851     * Assumptions:
852     * nBits <= (sizeof bitmask_t) * (bits_per_byte)
853     */
854     int
855     hilbert_nextinbox(unsigned nDims, unsigned nBytes, unsigned nBits,
856     int findPrev, void* c1V, void* c2V, void const* ptV)
857     {
858     bitmask_t const one = 1;
859     unsigned y = nBits;
860     bitmask_t const ndOnes = ones(bitmask_t,nDims);
861     bitmask_t const nd1Ones = ndOnes >> 1;
862     unsigned rotation = 0;
863     bitmask_t bits = 0;
864     bitmask_t index = 0;
865     bitmask_t fold1 = 0, fold2 = 0;
866     bitmask_t valu1 = 0, valu2 = 0;
867     unsigned p_y;
868     bitmask_t p_separator = 0, p_firstSeparator;
869     bitmask_t p_cornerdiff, p_reflection;
870     bitmask_t p_fold1, p_fold2, p_valu1, p_valu2;
871    
872     char* c1 = (char*)c1V;
873     char* c2 = (char*)c2V;
874     char const* pt = (const char*)ptV;
875    
876     while (y-- > 0)
877     {
878     bitmask_t reflection = getIntBits(nDims, nBytes, pt, y);
879     bitmask_t diff = reflection ^ /* planes that separate box and point */
880     ((getIntBits(nDims, nBytes, c1, y) &~ fold1) | valu1);
881    
882     if (diff)
883     /* some coordinate planes separate point from box or
884     dividing box or both; smear the bits of diff to reflect that
885     after the first diff dimension, they might as well all be
886     diffing; adjust the diff to reflect the fact that diffed
887     dimensions don't matter. */
888     {
889     /* compute (the complement of) a "digit" in the integer index of this
890     point */
891     bitmask_t cornerdiff = (diff ^ reflection) ^ /* separate box crnrs */
892     ((getIntBits(nDims, nBytes, c2, y) &~ fold2) | valu2);
893     bitmask_t separator = diff & ~cornerdiff;
894     /* eventually, the most significant separating cutting plane */
895     bitmask_t firstSeparator;
896     /* bits less significant than the msb of separator are irrelevant;
897     for convenience, call them all separators too */
898     bitmask_t rotSep = rotateRight(separator, rotation, nDims);
899     /* compute the (complement of the) digit of the hilbert code
900     assoc with point */
901     bitmask_t digit = rotateRight(bits ^ reflection, rotation, nDims);
902     unsigned d;
903     for (d = 1; d < nDims; d *= 2)
904     {
905     index ^= index >> d;
906     digit ^= digit >> d;
907     rotSep |= rotSep >> d;
908     }
909     index &= 1;
910     digit &= rotSep;
911     if ((index ^ y ^ findPrev) & 1)
912     digit ^= rotSep;
913    
914     separator = rotateLeft(rotSep, rotation, nDims);
915     rotSep -= rotSep >> 1;
916     firstSeparator = rotateLeft(rotSep, rotation, nDims);
917     /* forget about all the planes that split the box, except those that
918     are more significant than the most significant separator. */
919     cornerdiff &= ~separator;
920    
921     if (cornerdiff && digit)
922     /* some coordinate planes divide the box. Call the part of the
923     box in the same orthant as the point "here" and the part of
924     the box in the next (or previous) orthant "there". Remember
925     what the "there" orthant of the box looks like in case it
926     turns out that the curve doesn't reenter the box "here" after
927     (before) passing thru point. Continue working with the
928     "here" part. If there is no "there" there, skip it */
929     {
930     p_firstSeparator = digit & -digit;
931     p_separator = 2*p_firstSeparator-1;
932     p_separator = rotateLeft(p_separator, rotation, nDims);
933     p_firstSeparator = rotateLeft(p_firstSeparator, rotation, nDims);
934     p_cornerdiff = cornerdiff &~ (p_separator ^ p_firstSeparator);
935     p_y = y;
936     p_reflection = reflection ^ p_firstSeparator;
937     p_fold1 = fold1;
938     p_fold2 = fold2;
939     p_valu1 = valu1;
940     p_valu2 = valu2;
941     }
942    
943     if (digit < rotSep)
944    
945     /* use next box */
946     {
947     if (!p_separator) return 0; /* no next point */
948     separator = p_separator;
949     firstSeparator = p_firstSeparator;
950     y = p_y;
951     cornerdiff = p_cornerdiff;
952     reflection = p_reflection;
953     fold1 = p_fold1;
954     fold2 = p_fold2;
955     valu1 = p_valu1;
956     valu2 = p_valu2;
957     }
958    
959     if (cornerdiff)
960     {
961     /* reduce currbox */
962     bitmask_t corner = diff & cornerdiff;
963     cornerdiff ^= corner;
964     fold1 |= corner;
965     fold2 |= cornerdiff;
966     valu1 |= ~reflection & corner;
967     valu2 |= ~reflection & cornerdiff;
968     }
969    
970     separator ^= firstSeparator;
971     if (firstSeparator)
972     /* we have completely separated the point from a part of the box
973     ahead of it on the curve; almost done */
974     {
975     unsigned byteId = whichByte(nBytes,y);
976     bitmask_t bthbit = one << y%8;
977     for (d = 0; d < nDims; ++d)
978     {
979     char lo1, lo2;
980     char* cc1 = &c1[d*nBytes];
981     char* cc2 = &c2[d*nBytes];
982     char const* pnt = &pt[d*nBytes];
983     char hibits = -bthbit;
984     char hipart = pnt[byteId] & hibits;
985     memcpy(cc1, pnt, byteId);
986     memcpy(cc2, pnt, byteId);
987    
988     if (rdbit(separator, d))
989     hibits ^= bthbit;
990     if (rdbit(firstSeparator, d))
991     hipart ^= bthbit;
992    
993     if (rdbit(fold1, d))
994     {
995     lo1 = -rdbit(valu1, d);
996     setBytes(cc1,byteId,nBytes,lo1);
997     }
998     else lo1 = cc1[byteId];
999     cc1[byteId] = hipart | (lo1 &~ hibits);
1000    
1001     if (rdbit(fold2, d))
1002     {
1003     lo2 = -rdbit(valu2, d);
1004     setBytes(cc2,byteId,nBytes,lo2);
1005     }
1006     else lo2 = cc2[byteId];
1007     cc2[byteId] = hipart | (lo2 &~ hibits);
1008     }
1009    
1010     hilbert_box_pt(nDims, nBytes, nBits, !findPrev, c1V, c2V);
1011     return 1;
1012     }
1013     }
1014    
1015     bits ^= reflection;
1016     bits = rotateRight(bits, rotation, nDims);
1017     index ^= bits;
1018     reflection ^= one << rotation;
1019     adjust_rotation(rotation,nDims,bits);
1020     bits = reflection;
1021     }
1022    
1023     /* point is in box */
1024     {
1025     unsigned d;
1026     for (d = 0; d < nDims; ++d)
1027     ((char*)c1)[d] = ((char*)c2)[d] = ((char*)pt)[d];
1028     }
1029     return 1;
1030     }
1031    
1032    
1033    
1034     /*****************************************************************
1035     * hilbert_incr
1036     *
1037     * Advance from one point to its successor on a Hilbert curve
1038     * Inputs:
1039     * nDims: Number of coordinates.
1040     * nBits: Number of bits/coordinate.
1041     * coord: Array of nDims nBits-bit coordinates.
1042     * Output:
1043     * coord: Next point on Hilbert curve
1044     * Assumptions:
1045     * nBits <= (sizeof bitmask_t) * (bits_per_byte)
1046     */
1047    
1048     void
1049     hilbert_incr(unsigned nDims, unsigned nBits, bitmask_t coord[])
1050     {
1051     bitmask_t const one = 1;
1052     bitmask_t const ndOnes = ones(bitmask_t,nDims);
1053     bitmask_t const nd1Ones= ndOnes >> 1;
1054     unsigned b, d;
1055     unsigned rotation = 0;
1056     bitmask_t reflection = 0;
1057     bitmask_t index = 0;
1058     unsigned rb = nBits-1;
1059     bitmask_t rd = ndOnes;
1060    
1061     for (b = nBits; b--;)
1062     {
1063     bitmask_t bits = reflection;
1064     reflection = 0;
1065     for (d = 0; d < nDims; ++d)
1066     reflection |= rdbit(coord[d], b) << d;
1067     bits ^= reflection;
1068     bits = rotateRight(bits, rotation, nDims);
1069     index ^= bits;
1070     for (d = 1; d < nDims; d *= 2)
1071     index ^= index >> d;
1072     if (index++ != ndOnes)
1073     {
1074     rb = b;
1075     rd = index & -index;
1076     rd = rotateLeft(rd, rotation, nDims);
1077    
1078     }
1079     index &= 1;
1080     index <<= nDims-1;
1081    
1082     reflection ^= one << rotation;
1083     adjust_rotation(rotation,nDims,bits);
1084     }
1085     for (d = 0; !rdbit(rd, d); ++d) {}
1086     coord[d] ^= (2 << rb) - 1;
1087     }
1088    
1089    
1090     /* LICENSE
1091     *
1092     * This software is copyrighted by Rice University. It may be freely copied,
1093     * modified, and redistributed, provided that the copyright notice is
1094     * preserved on all copies.
1095     *
1096     * There is no warranty or other guarantee of fitness for this software,
1097     * it is provided solely "as is". Bug reports or fixes may be sent
1098     * to the author, who may or may not act on them as he desires.
1099     *
1100     * You may include this software in a program or other software product,
1101     * but must display the notice:
1102     *
1103     * Hilbert Curve implementation copyright 1998, Rice University
1104     *
1105     * in any place where the end-user would see your own copyright.
1106     *
1107     * If you modify this software, you should include a notice giving the
1108     * name of the person performing the modification, the date of modification,
1109     * and the reason for such modification.
1110     */
1111    
1112    
1113    
1114     /* Revision history:
1115    
1116     July 1998: Initial release
1117    
1118     Sept 1998: Second release
1119    
1120     Dec 1998: Fixed bug in hilbert_c2i that allowed a shift by number of bits in
1121     bitmask to vaporize index, in last bit of the function. Implemented
1122     hilbert_incr.
1123    
1124     August 1999: Added argument to hilbert_nextinbox so that you can, optionally,
1125     find the previous point along the curve to intersect the box, rather than the
1126     next point.
1127    
1128     Nov 1999: Defined fast bit-transpose function (fast, at least, if the number
1129     of bits is large), and reimplemented i2c and c2i in terms of it. Collapsed
1130     loops in hilbert_cmp, with the intention of reusing the cmp code to compare
1131     more general bitstreams.
1132    
1133     Feb 2000: Implemented almost all the floating point versions of cmp, etc, so
1134     that coordinates expressed in terms of double-precision IEEE floating point
1135     can be ordered. Still have to do next-in-box, though.
1136    
1137     Oct 2001: Learned that some arbitrary coding choices caused some routines
1138     to fail in one dimension, and changed those choices.
1139    
1140     version 2001-10-20-05:34
1141    
1142     */
1143    
1144     /* What remains is test code that won't be compiled unless you define the
1145     TEST_HILBERT preprocessor symbol */
1146    
1147     #ifdef TEST_HILBERT
1148     #include <stdio.h>
1149     #define abs(x) (((x)>=0)?(x):(-(x)))
1150    
1151     int main()
1152     {
1153     #define maxDim (8*sizeof(bitmask_t))
1154     bitmask_t coord[maxDim], coordPrev[maxDim];
1155     unsigned nDims, nBits, nPrints, orderCheck, i;
1156     bitmask_t r, r1;
1157    
1158     for (;;)
1159     {
1160     printf( "Enter nDims, nBits, nPrints, orderCheck: " );
1161     scanf( "%d", &nDims);
1162     if ( nDims == 0 )
1163     break;
1164     scanf( "%d%d%d", &nBits, &nPrints, &orderCheck);
1165     while ( (i = getchar()) != '\n' && i != EOF )
1166     ;
1167     if ( i == EOF )
1168     break;
1169    
1170     if (nDims*nBits > 8*sizeof(r))
1171     {
1172     printf("Product of nDims and nBits not exceed %d.\n", 8*sizeof(r));
1173     break;
1174     }
1175    
1176     if (nBits == 0)
1177     {
1178     printf("nBits must be positive.\n");
1179     break;
1180     }
1181    
1182     if (nPrints > (1ULL << (nDims*nBits)))
1183     nPrints = 1ULL << (nDims*nBits);
1184    
1185     for (r = 0; r < nPrints; ++r)
1186     {
1187     bitmask_t coord1[maxDim];
1188     int miscount = 0;
1189     hilbert_i2c( nDims, nBits, r, coord );
1190     printf("%d: ", (unsigned)r);
1191     for (i = 0; i < nDims; ++i)
1192     {
1193     int diff = (int)(coord[i] - coordPrev[i]);
1194     miscount += abs(diff);
1195     coordPrev[i] = coord[i];
1196     printf(" %d", (unsigned)coord[i]);
1197     }
1198     if (r > 0 && miscount != 1)
1199     printf(".....error");
1200     printf("\n");
1201     r1 = hilbert_c2i( nDims, nBits, coord );
1202     if ( r != r1 )
1203     printf( "r = 0x%x; r1 = 0x%x\n", (unsigned)r, (unsigned)r1);
1204     for (i = 0; i < nDims; ++i)
1205     coord[i] = coordPrev[i];
1206    
1207     if (! orderCheck)
1208     continue;
1209    
1210     for (r1 = 0; r1 < r; ++r1 )
1211     {
1212     unsigned ans;
1213     hilbert_i2c( nDims, nBits, r1, coord1 );
1214     ans = hilbert_cmp( nDims, sizeof(coord[0]), nBits, coord, coord1);
1215     if (ans != 1)
1216     {
1217     int width = (nDims*nBits + 3) / 4;
1218     printf( "cmp r = 0x%0*x; r1 = 0x%0*x, ans = %2d\n",
1219     width, (unsigned)r,
1220     width, (unsigned)r1, ans );
1221     }
1222     }
1223     hilbert_i2c( nDims, nBits, r1, coord1 );
1224     if (hilbert_cmp( nDims, sizeof(coord[0]), nBits, coord, coord1) != 0)
1225     printf( "cmp r = 0x%0*x; r1 = 0x%0*x\n", (nDims*nBits+3)/4, (unsigned)r,
1226     (nDims*nBits+3)/4, (unsigned)r1 );
1227    
1228     }
1229     }
1230     return 0;
1231     }
1232    
1233     #endif
1234    
1235     #ifdef TEST_IEEE
1236     #include <stdio.h>
1237     #include <stdlib.h>
1238     #include <math.h>
1239    
1240     int cmp(const void* xv, const void* yv)
1241     {
1242     double const* x = xv;
1243     double const* y = yv;
1244     /* return hilbert_cmp(2, 8, 64, x, y); */
1245     return hilbert_ieee_cmp(2, x, y);
1246     }
1247    
1248     int main()
1249     {
1250     double *a;
1251     unsigned i;
1252     unsigned n;
1253     printf("How many points? ");
1254     scanf("%d", &n);
1255     a = (double*) malloc(2*n*sizeof(double));
1256     for (i = 0; i < n; ++i)
1257     a[2*i] = drand48()-0.5, a[2*i+1] = drand48()-0.5;
1258    
1259     qsort(a, n, 2*sizeof(double), cmp);
1260    
1261     for (i = 0; i < n; ++i)
1262     printf("%8g %8g\n", a[2*i], a[2*i+1]);
1263     free(a);
1264     return 0;
1265     }
1266    
1267     #endif
1268    
1269     #ifdef TEST_CMP
1270     #include <stdio.h>
1271    
1272     #define maxDim (8*sizeof(bitmask_t))
1273     int main()
1274     {
1275     double coord[maxDim];
1276     unsigned nDims, i, k;
1277    
1278     printf( "Enter nDims: " );
1279     scanf( "%d", &nDims);
1280     if ( nDims == 0 )
1281     return 0;
1282     while ( (i = getchar()) != '\n' && i != EOF )
1283     ;
1284     if ( i == EOF )
1285     return 0;
1286    
1287     for (k = 0; k < (1<<nDims); ++k)
1288     {
1289     printf("Orth %2d\n", k);
1290     for (i = 0; i < nDims; ++i)
1291     coord[i] = ((k>>i)&1)? -1.: 1.;
1292    
1293    
1294     hilbert_ieee_cmp( nDims, coord, coord);
1295     }
1296     return 0;
1297     }
1298    
1299     #endif
1300    
1301     #ifdef TEST_VTX
1302     #include <stdio.h>
1303     #include <stdlib.h>
1304    
1305     #define maxDim (8*sizeof(bitmask_t))
1306    
1307     unsigned g_nDims;
1308    
1309     int cmp(void const* c1p, void const* c2p)
1310     {
1311     return hilbert_cmp(g_nDims, sizeof(unsigned), 8*sizeof(unsigned), c1p, c2p);
1312     }
1313    
1314     int main()
1315     {
1316     unsigned corner0[maxDim], corner1[maxDim];
1317     unsigned cornerlo[maxDim], cornerhi[maxDim], work[maxDim];
1318     typedef unsigned array_t[maxDim];
1319     array_t* array;
1320    
1321     unsigned nDims, i, k;
1322    
1323     printf( "Enter nDims: " );
1324     scanf( "%d", &nDims);
1325     if ( nDims == 0 )
1326     return 0;
1327     while ( (i = getchar()) != '\n' && i != EOF )
1328     ;
1329     if ( i == EOF )
1330     return 0;
1331    
1332     printf("Enter one corner (%d coordinates): ", nDims);
1333     for (k = 0; k < nDims; ++k)
1334     scanf("%d", &corner0[k]);
1335    
1336     printf("Enter other corner (%d coordinates): ", nDims);
1337     for (k = 0; k < nDims; ++k)
1338     scanf("%d", &corner1[k]);
1339    
1340    
1341     /* find first corner */
1342     for (k = 0; k < nDims; ++k)
1343     {
1344     cornerlo[k] = corner0[k];
1345     work[k] = corner1[k];
1346     }
1347    
1348     hilbert_box_vtx(nDims, sizeof(unsigned), 8*sizeof(unsigned),
1349     1, cornerlo, work);
1350     printf("Predicted lo corner: ");
1351     for (k = 0; k < nDims; ++k)
1352     printf("%4u", cornerlo[k]);
1353     printf("\n");
1354    
1355    
1356     /* find last corner */
1357     for (k = 0; k < nDims; ++k)
1358     {
1359     work[k] = corner0[k];
1360     cornerhi[k] = corner1[k];
1361     }
1362    
1363     hilbert_box_vtx(nDims, sizeof(unsigned), 8*sizeof(unsigned),
1364     0, work, cornerhi);
1365     printf("Predicted hi corner: ");
1366     for (k = 0; k < nDims; ++k)
1367     printf("%4u", cornerhi[k]);
1368     printf("\n");
1369    
1370     array = (array_t*) malloc(maxDim*sizeof(unsigned) << nDims);
1371     for (k = 0; k < (1<<nDims); ++k)
1372     {
1373     unsigned j;
1374     unsigned* eltk = &array[k][0];
1375     for (j = 0; j < nDims; ++j)
1376     {
1377     unsigned* src = ((k>>j)&1)? corner1: corner0;
1378     eltk[j] = src[j];
1379     }
1380     }
1381    
1382     g_nDims = nDims;
1383     qsort(array, (1<<nDims), maxDim*sizeof(unsigned), cmp);
1384    
1385     printf("Result of sort\n");
1386     for (k = 0; k < (1<<nDims); k += (1 << nDims) - 1)
1387     {
1388     unsigned j;
1389     unsigned* eltk = &array[k][0];
1390     for (j = 0; j < nDims; ++j)
1391     printf("%4u", eltk[j]);
1392     printf("\n");
1393     }
1394     free((char*)array);
1395     return 0;
1396     }
1397    
1398     #endif
1399    
1400     #ifdef TEST_IEEE_VTX
1401     #include <stdio.h>
1402     #include <stdlib.h>
1403     #include <assert.h>
1404    
1405     #define maxDim (8*sizeof(bitmask_t))
1406     typedef double key_t;
1407    
1408     unsigned g_nDims;
1409    
1410     int cmp(void const* c1p, void const* c2p)
1411     {
1412     return hilbert_ieee_cmp(g_nDims, c1p, c2p);
1413     }
1414    
1415     int main()
1416     {
1417     key_t corner0[maxDim], corner1[maxDim];
1418     key_t cornerlo[maxDim], cornerhi[maxDim], work[maxDim];
1419     typedef key_t array_t[maxDim];
1420     array_t* array;
1421    
1422     unsigned nDims, i, k;
1423    
1424     printf( "Enter nDims: " );
1425     scanf( "%d", &nDims);
1426     if ( nDims == 0 )
1427     return 0;
1428    
1429     for (i = 0; i < 10000; ++i)
1430     {
1431     for (k = 0; k < nDims; ++k)
1432     {
1433     corner0[k] = 2.*drand48() - 1.;
1434     corner1[k] = 2.*drand48() - 1.;
1435     }
1436    
1437     /* find first corner */
1438     for (k = 0; k < nDims; ++k)
1439     {
1440     cornerlo[k] = corner0[k];
1441     work[k] = corner1[k];
1442     }
1443    
1444     hilbert_ieee_box_vtx(nDims, 1, cornerlo, work);
1445    
1446     /* find last corner */
1447     for (k = 0; k < nDims; ++k)
1448     {
1449     work[k] = corner0[k];
1450     cornerhi[k] = corner1[k];
1451     }
1452    
1453     hilbert_ieee_box_vtx(nDims, 0, work, cornerhi);
1454    
1455     array = (array_t*) malloc(maxDim*sizeof(key_t) << nDims);
1456     for (k = 0; k < (1<<nDims); ++k)
1457     {
1458     unsigned j;
1459     key_t* eltk = &array[k][0];
1460     for (j = 0; j < nDims; ++j)
1461     {
1462     key_t* src = ((k>>j)&1)? corner1: corner0;
1463     eltk[j] = src[j];
1464     }
1465     }
1466    
1467     g_nDims = nDims;
1468     qsort(array, (1<<nDims), maxDim*sizeof(key_t), cmp);
1469    
1470     for (k = 0; k < (1<<nDims); k += (1 << nDims) - 1)
1471     {
1472     unsigned j;
1473     int mismatch = 0;
1474     key_t* eltk = &array[k][0];
1475     for (j = 0; j < nDims & !mismatch; ++j)
1476     {
1477     mismatch = (eltk[j] != ((k==0)? cornerlo: cornerhi)[j]);
1478     }
1479     assert (!mismatch);
1480     }
1481     free((char*)array);
1482     }
1483     return 0;
1484     }
1485    
1486     #endif
1487    
1488     #ifdef TEST_PT
1489     #include <stdio.h>
1490     #include <stdlib.h>
1491    
1492     #define maxDim (8*sizeof(bitmask_t))
1493    
1494     unsigned g_nDims;
1495    
1496     int cmp(void const* c1p, void const* c2p)
1497     {
1498     return hilbert_cmp(g_nDims, sizeof(unsigned), 8*sizeof(unsigned), c1p, c2p);
1499     }
1500    
1501     int main()
1502     {
1503     unsigned point0[maxDim], point1[maxDim];
1504     unsigned pointlo[maxDim], pointhi[maxDim], work[maxDim];
1505     typedef unsigned array_t[maxDim];
1506     array_t* array;
1507    
1508     unsigned nDims, i, k, outvolume = 1, involume = 1;
1509     unsigned nextItem;
1510    
1511     printf( "Enter nDims: " );
1512     scanf( "%d", &nDims);
1513     if ( nDims == 0 )
1514     return 0;
1515     while ( (i = getchar()) != '\n' && i != EOF )
1516     ;
1517     if ( i == EOF )
1518     return 0;
1519    
1520     printf("Enter one point (%d coordinates): ", nDims);
1521     for (k = 0; k < nDims; ++k)
1522     scanf("%d", &point0[k]);
1523    
1524     printf("Enter other point (%d coordinates, strictly greater): ", nDims);
1525     for (k = 0; k < nDims; ++k)
1526     {
1527     unsigned diff;
1528     scanf("%d", &point1[k]);
1529     diff = point1[k] - point0[k];
1530     outvolume *= diff + 1;
1531     involume *= diff - 1;
1532     }
1533    
1534    
1535     /* find first point */
1536     for (k = 0; k < nDims; ++k)
1537     {
1538     pointlo[k] = point0[k];
1539     work[k] = point1[k];
1540     }
1541    
1542     hilbert_box_pt(nDims, sizeof(unsigned), 8*sizeof(unsigned),
1543     1, pointlo, work);
1544     printf("Predicted lo point: ");
1545     for (k = 0; k < nDims; ++k)
1546     printf("%4u", pointlo[k]);
1547     printf("\n");
1548    
1549    
1550     /* find last point */
1551     for (k = 0; k < nDims; ++k)
1552     {
1553     work[k] = point0[k];
1554     pointhi[k] = point1[k];
1555     }
1556    
1557     hilbert_box_pt(nDims, sizeof(unsigned), 8*sizeof(unsigned),
1558     0, work, pointhi);
1559     printf("Predicted hi point: ");
1560     for (k = 0; k < nDims; ++k)
1561     printf("%4u", pointhi[k]);
1562     printf("\n");
1563    
1564    
1565    
1566     array = (array_t*) malloc(maxDim*sizeof(unsigned) * (outvolume-involume));
1567     if (array == 0)
1568     {
1569     fprintf(stderr, "Out of memory.\n");
1570     exit(-1);
1571     }
1572     nextItem = 0;
1573     for (k = 0; k < outvolume; ++k)
1574     {
1575     unsigned kk = k;
1576     unsigned j;
1577     unsigned* eltk = &array[nextItem][0];
1578     int boundary = 0;
1579    
1580     for (j = 0; j < nDims; ++j)
1581     {
1582     unsigned diff1 = point1[j] - point0[j] + 1;
1583     unsigned pos = point0[j] + (kk % diff1);
1584     boundary |= (point0[j] == pos || pos == point1[j]);
1585     eltk[j] = pos;
1586     kk /= diff1;
1587     }
1588     if (boundary)
1589     ++nextItem;
1590     }
1591    
1592     g_nDims = nDims;
1593     qsort(array, outvolume-involume, maxDim*sizeof(unsigned), cmp);
1594    
1595     printf("Result of sort\n");
1596     for (k = 0; k < outvolume-involume; k += outvolume-involume-1)
1597     {
1598     unsigned j;
1599     unsigned* eltk = &array[k][0];
1600     for (j = 0; j < nDims; ++j)
1601     printf("%4u", eltk[j]);
1602     printf("\n");
1603     }
1604     free((char*)array);
1605     return 0;
1606     }
1607    
1608     #endif
1609    
1610     #ifdef TEST_IEEE_PT
1611     #include <stdio.h>
1612     #include <stdlib.h>
1613    
1614     #define maxDim (8*sizeof(bitmask_t))
1615    
1616     int main()
1617     {
1618     double point0[maxDim], point1[maxDim];
1619     double pointlo[maxDim], pointhi[maxDim], work[maxDim];
1620    
1621     unsigned nDims, k, i;
1622    
1623     printf( "Enter nDims: " );
1624     scanf( "%d", &nDims);
1625     if ( nDims == 0 )
1626     return 0;
1627     while ( (i = getchar()) != '\n' && i != EOF )
1628     ;
1629     if ( i == EOF )
1630     return 0;
1631    
1632     printf("Enter one point (%d coordinates): ", nDims);
1633     for (k = 0; k < nDims; ++k)
1634     scanf("%lf", &point0[k]);
1635    
1636     printf("Enter other point (%d coordinates, strictly greater): ", nDims);
1637     for (k = 0; k < nDims; ++k)
1638     scanf("%lf", &point1[k]);
1639    
1640     /* find last point */
1641     for (k = 0; k < nDims; ++k)
1642     {
1643     work[k] = point0[k];
1644     pointhi[k] = point1[k];
1645     }
1646    
1647     hilbert_ieee_box_pt(nDims, 0, work, pointhi);
1648     printf("Predicted hi point: ");
1649     for (k = 0; k < nDims; ++k)
1650     printf("%10lg", pointhi[k]);
1651     printf("\n");
1652    
1653     /* find first point */
1654     for (k = 0; k < nDims; ++k)
1655     {
1656     pointlo[k] = point0[k];
1657     work[k] = point1[k];
1658     }
1659    
1660     hilbert_ieee_box_pt(nDims, 1, pointlo, work);
1661     printf("Predicted lo point: ");
1662     for (k = 0; k < nDims; ++k)
1663     printf("%10lg", pointlo[k]);
1664     printf("\n");
1665    
1666     /* validate by sorting random boundary points */
1667     #define nPts 1000000
1668     assert(hilbert_ieee_cmp(nDims, pointlo, pointhi) < 0);
1669     for (i = 0; i < nPts; ++i)
1670     {
1671     double pt1[maxDim], pt2[maxDim];
1672     for (k = 0; k < nDims; ++k)
1673     {
1674     if (i % nDims == k)
1675     pt1[k] = point0[k];
1676     else
1677     pt1[k] = point0[k] + drand48()*(point1[k]-point0[k]);
1678     }
1679     for (k = 0; k < nDims; ++k)
1680     {
1681     if (i % nDims == k)
1682     pt2[k] = point1[k];
1683     else
1684     pt2[k] = point0[k] + drand48()*(point1[k]-point0[k]);
1685     }
1686     if (hilbert_ieee_cmp(nDims, pt1, pt2) < 0)
1687     {
1688     if (hilbert_ieee_cmp(nDims, pt1, pointlo) < 0)
1689     memcpy(pointlo, pt1, maxDim*sizeof(double));
1690     if (hilbert_ieee_cmp(nDims, pointhi, pt2) < 0)
1691     memcpy(pointhi, pt2, maxDim*sizeof(double));
1692     }
1693     else
1694     {
1695     if (hilbert_ieee_cmp(nDims, pt2, pointlo) < 0)
1696     memcpy(pointlo, pt2, maxDim*sizeof(double));
1697     if (hilbert_ieee_cmp(nDims, pointhi, pt1) < 0)
1698     memcpy(pointhi, pt1, maxDim*sizeof(double));
1699     }
1700     }
1701    
1702     printf("Sorted hi and lo:\n");
1703     for (k = 0; k < nDims; ++k)
1704     printf("%10lg", pointhi[k]);
1705     printf("\n");
1706     for (k = 0; k < nDims; ++k)
1707     printf("%10lg", pointlo[k]);
1708     printf("\n");
1709    
1710     return 0;
1711     }
1712    
1713     #endif
1714    
1715     #ifdef TEST_NEXT
1716     #include <stdio.h>
1717    
1718     int main()
1719     {
1720     unsigned i;
1721     unsigned c1[100], c2[100], pt[100];
1722     unsigned nDims, nBytes = 4;
1723     int stat, findPrev;
1724     printf("Enter nDims: " );
1725     scanf("%u", &nDims);
1726    
1727     printf("Enter 1st box corner: ");
1728     for (i = 0; i < nDims; ++i)
1729     scanf("%u", &c1[i]);
1730     printf("Enter 2nd box corner: ");
1731     for (i = 0; i < nDims; ++i)
1732     scanf("%u", &c2[i]);
1733     printf("Enter point: ");
1734     for (i = 0; i < nDims; ++i)
1735     scanf("%u", &pt[i]);
1736     printf("Find prev?: ");
1737     scanf("%d", &findPrev);
1738    
1739     stat = hilbert_nextinbox(nDims, nBytes, 8*nBytes, findPrev, c1, c2, pt);
1740    
1741     if (stat)
1742     for (i = 0; i < nDims; ++i)
1743     printf("%u ", c1[i]);
1744     else
1745     printf("No such point");
1746    
1747     printf("\n");
1748     return 0;
1749     }
1750     #endif