From 49c601c3ad0d4c401b7b5a021700d33000e6d8ca Mon Sep 17 00:00:00 2001 From: Matt Hinrichsen Date: Thu, 16 Oct 2025 21:38:21 -0500 Subject: [PATCH 1/4] Hilbert encode/decode 35% and 53% faster respectively --- numerics/hilbert/hilbert.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/numerics/hilbert/hilbert.go b/numerics/hilbert/hilbert.go index a84c707..0a1ce8b 100644 --- a/numerics/hilbert/hilbert.go +++ b/numerics/hilbert/hilbert.go @@ -44,17 +44,18 @@ func boolToInt(value bool) int32 { return int32(0) } -func rotate(n, rx, ry int32, x, y *int32) { +func rotate(n, rx, ry int32, x, y int32) (int32, int32) { if ry == 0 { if rx == 1 { - *x = n - 1 - *x - *y = n - 1 - *y + x = n - 1 - x + y = n - 1 - y } - t := *x - *x = *y - *y = t + t := x + x = y + y = t } + return x, y } // Encode will encode the provided x and y coordinates into a Hilbert @@ -62,11 +63,11 @@ func rotate(n, rx, ry int32, x, y *int32) { func Encode(x, y int32) int64 { var rx, ry int32 var d int64 - for s := int32(n / 2); s > 0; s /= 2 { + for s := int32(n >> 1); s > 0; s = s >> 1 { rx = boolToInt(x&s > 0) ry = boolToInt(y&s > 0) d += int64(int64(s) * int64(s) * int64(((3 * rx) ^ ry))) - rotate(s, rx, ry, &x, &y) + x, y = rotate(s, rx, ry, x, y) } return d @@ -82,7 +83,7 @@ func Decode(h int64) (int32, int32) { for s := int64(1); s < int64(n); s *= 2 { rx = 1 & (t / 2) ry = 1 & (t ^ rx) - rotate(int32(s), int32(rx), int32(ry), &x, &y) + x, y = rotate(int32(s), int32(rx), int32(ry), x, y) x += int32(s * rx) y += int32(s * ry) t /= 4 From 9971cb5b067ef6ae9d129fe1f1107d04f07beb1d Mon Sep 17 00:00:00 2001 From: Matt Hinrichsen Date: Thu, 16 Oct 2025 21:59:40 -0500 Subject: [PATCH 2/4] Decode is now 65% faster --- numerics/hilbert/hilbert.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/numerics/hilbert/hilbert.go b/numerics/hilbert/hilbert.go index 0a1ce8b..987381c 100644 --- a/numerics/hilbert/hilbert.go +++ b/numerics/hilbert/hilbert.go @@ -51,9 +51,7 @@ func rotate(n, rx, ry int32, x, y int32) (int32, int32) { y = n - 1 - y } - t := x - x = y - y = t + x, y = y, x } return x, y } @@ -63,7 +61,7 @@ func rotate(n, rx, ry int32, x, y int32) (int32, int32) { func Encode(x, y int32) int64 { var rx, ry int32 var d int64 - for s := int32(n >> 1); s > 0; s = s >> 1 { + for s := int32(n >> 1); s > 0; s >>= 1 { rx = boolToInt(x&s > 0) ry = boolToInt(y&s > 0) d += int64(int64(s) * int64(s) * int64(((3 * rx) ^ ry))) @@ -80,13 +78,13 @@ func Decode(h int64) (int32, int32) { var x, y int32 t := h - for s := int64(1); s < int64(n); s *= 2 { + for s := int64(1); s < int64(n); s <<= 1 { rx = 1 & (t / 2) ry = 1 & (t ^ rx) x, y = rotate(int32(s), int32(rx), int32(ry), x, y) x += int32(s * rx) y += int32(s * ry) - t /= 4 + t >>= 2 } return x, y From 5b371120d3e5a4e4ea6412500d79462cf32ae145 Mon Sep 17 00:00:00 2001 From: Matt Hinrichsen Date: Thu, 16 Oct 2025 22:08:12 -0500 Subject: [PATCH 3/4] Minor improvement to Encode and Decode now 71.7% faster --- numerics/hilbert/hilbert.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numerics/hilbert/hilbert.go b/numerics/hilbert/hilbert.go index 987381c..9872cde 100644 --- a/numerics/hilbert/hilbert.go +++ b/numerics/hilbert/hilbert.go @@ -64,7 +64,7 @@ func Encode(x, y int32) int64 { for s := int32(n >> 1); s > 0; s >>= 1 { rx = boolToInt(x&s > 0) ry = boolToInt(y&s > 0) - d += int64(int64(s) * int64(s) * int64(((3 * rx) ^ ry))) + d += int64(int64(s) * int64(s) * int64(rx<<1|(rx^ry))) x, y = rotate(s, rx, ry, x, y) } @@ -79,7 +79,7 @@ func Decode(h int64) (int32, int32) { t := h for s := int64(1); s < int64(n); s <<= 1 { - rx = 1 & (t / 2) + rx = 1 & (t >> 1) ry = 1 & (t ^ rx) x, y = rotate(int32(s), int32(rx), int32(ry), x, y) x += int32(s * rx) From 150f628020632fcdaf8f63349aabeb9672085150 Mon Sep 17 00:00:00 2001 From: Matt Hinrichsen Date: Thu, 16 Oct 2025 22:15:26 -0500 Subject: [PATCH 4/4] Updates the benchmark comment --- numerics/hilbert/hilbert.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numerics/hilbert/hilbert.go b/numerics/hilbert/hilbert.go index 9872cde..647d28f 100644 --- a/numerics/hilbert/hilbert.go +++ b/numerics/hilbert/hilbert.go @@ -26,8 +26,8 @@ This expects coordinates in the range [0, 0] to [MaxInt32, MaxInt32]. Using negative values for x and y will have undefinied behavior. Benchmarks: -BenchmarkEncode-8 10000000 181 ns/op -BenchmarkDecode-8 10000000 191 ns/op +BenchmarkEncode-10 23791095 50.66 ns/op +BenchmarkDecode-10 32430058 36.99 ns/op */ package hilbert