#include
#include
#include
/*
Given the "order" n of a Hilbert curve and (x, y) coordinates, this
program computes the distance s along the curve to the point (x, y).
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 bits then append and enter
state is of x and y are to s state
----------------------------------------------------------
A (0, 0) 00 B
A (0, 1) 01 A
A (1, 0) 11 D
A (1, 1) 10 A
B (0, 0) 00 A
B (0, 1) 11 C
B (1, 0) 01 B
B (1, 1) 10 B
C (0, 0) 10 D
C (0, 1) 11 B
C (1, 0) 01 C
C (1, 1) 00 D
D (0, 0) 10 C
D (0, 1) 01 D
D (1, 0) 11 A
D (1, 1) 00 C
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 (x, y) are (0, 0), then output 00 and
enter state B. Then, advance to the next bits of (x, y). The third row
means that if the current state is A and the scanned bits are (1, 0),
then output 11 and stay in state D.
If the output is accumulated in left-to-right order, then when the
end of x and y is reached, the output quantity will contain the length s
of the curve from its beginning to (x, y).
For example, suppose the order is 3 and
(x, y) = (4, 3).
Then since the process starts in state A and the initial bits scanned
are (1, 0), the process outputs 11 and enters state D (third row). Then,
being in state D and scanning (0, 1), the process outputs 01 and stays in
state D. Lastly, the process outputs 01 and enters state D, although
the state is now immaterial.
Thus the output is 110101, i.e., decimal 53. */
// ------------------------- hil_s_from_xy -----------------------------
// Num ops: TBD
// ------------------------------ cut ----------------------------------
unsigned hil_s_from_xy(unsigned x, unsigned y, int n) {
int i;
unsigned state, s, row;
state = 0; // Initialize.
s = 0;
for (i = n - 1; i >= 0; i--) {
row = 4*state | 2*((x >> i) & 1) | (y >> i) & 1;
s = (s << 2) | (0x361E9CB4 >> 2*row) & 3;
state = (0x8FE65831 >> 2*row) & 3;
}
return s;
}
// ------------------------------ cut ----------------------------------
// ------------------------------ main ---------------------------------
int main(int argc, char *argv[]) {
unsigned n, N, x, y, s;
if (argc <= 1) {
printf("Need one parameter, the order of the curve.\n");
exit(1);
}
n = atoi(argv[1]);
N = 1 << n; // N = 2**n.
printf("Distance along the Hilbert curve of order %d\n", n);
printf(" x y s\n");
for (x = 0; x < N; x++) {
for (y = 0; y < N; y++) {
s = hil_s_from_xy(x, y, n);
printf("%5d %5d %5d\n", x, y, s);
}
}
return 0;
}