#include #include #include /* Given the "order" n of a Hilbert curve and a distance s along the curve, this program computes the corresponding (x, y) coordinates. The square that the Hilbert curve traverses is of size 2**n by 2**n. The method is to employ the following state transition table: If the current And the next two then and enter state is bits of s are output state ---------------------------------------------------------- A 00 00 B A 01 01 A A 10 11 A A 11 10 D B 00 00 A B 01 10 B B 10 11 B B 11 01 C C 00 11 D C 01 10 C C 10 00 C C 11 01 B D 00 11 C D 01 01 D D 10 00 D D 11 10 A The states correspond to mappings, with state A denoting the map from binary 00 to 00, 01 to 01, 10 to 11, and 11 to 10, and similarly for states B, C, and D. To use the table, start in state A. Scan the bits of s in pairs from left to right. The first row means that if the current state is A and the currently scanned bits of s are 00, then output 00 and enter state B. Then, advance to the next two bits of s. The third row means that if the current state is A and the scanned bits are 10, then output 11 and stay in state A. If the outputs are accumulated in left-to-right order, then when the end of s is reached, the output quantity will contain x in the odd numbered bit positions, and y in the even numbered bit positions. For example, suppose s = 110100. Then since the process starts in state A and the initial bits scanned are 11, the process outputs 10 and enters state D (fourth row). Then, being in state D and scanning 01, the process outputs 01 and stays in state D. Lastly, the process outputs 11 and enters state C, although the state is now immaterial. Thus the output is 100111. From the odd and even bits respectively, this gives x = 101 and y = 011. Thus the (x, y) coordinates for s = 52 (110100) are (5, 3). */ // ------------------------- hil_xy_from_s ----------------------------- // Num ops: TBD // ------------------------------ cut ---------------------------------- void hil_xy_from_s(unsigned s, int n, unsigned *xp, unsigned *yp) { int i; unsigned state, x, y, row; state = 0; // Initialize. x = y = 0; for (i = 2*n - 2; i >= 0; i -= 2) { // Do n times. row = 4*state | (s >> i) & 3; // Row in table. x = (x << 1) | (0x936C >> row) & 1; y = (y << 1) | (0x39C6 >> row) & 1; state = (0x3E6B94C1 >> 2*row) & 3; // New state. } *xp = x; // Pass back *yp = y; // results. } // ------------------------------ cut ---------------------------------- // ------------------------------ main --------------------------------- int main(int argc, char *argv[]) { unsigned n, N, s, x, y; if (argc <= 1) { printf("Need one parameter, the order of the curve.\n"); exit(1); } n = atoi(argv[1]); N = 1 << 2*n; // N = 2**2n. printf("(x, y) coordinates along the Hilbert curve of order %d\n", n); printf(" s x y\n"); for (s = 0; s < N; s++) { hil_xy_from_s(s, n, &x, &y); printf("%5d %5d %5d\n", s, x, y); } return 0; }