-
Notifications
You must be signed in to change notification settings - Fork 847
Faster hilbert.Encode and hilbert.Decode #234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
49c601c
9971cb5
5b37112
150f628
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
|
||
|
|
@@ -44,29 +44,28 @@ 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 | ||
| x, y = y, x | ||
| } | ||
| return x, y | ||
| } | ||
|
|
||
| // Encode will encode the provided x and y coordinates into a Hilbert | ||
| // distance. | ||
| 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 >>= 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) | ||
| d += int64(int64(s) * int64(s) * int64(rx<<1|(rx^ry))) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📖 There's a lot magic bitwise stuff happening in this file (there was before!). Especially since this is OSS, perhaps we could add comments to the code describing the intent of what's happening (and why we're doing it the obscure way, not the clear way). |
||
| x, y = rotate(s, rx, ry, x, y) | ||
| } | ||
|
|
||
| return d | ||
|
|
@@ -79,13 +78,13 @@ func Decode(h int64) (int32, int32) { | |
| var x, y int32 | ||
| t := h | ||
|
|
||
| for s := int64(1); s < int64(n); s *= 2 { | ||
| rx = 1 & (t / 2) | ||
| for s := int64(1); s < int64(n); s <<= 1 { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🌵 I wonder what the impact is to cast const (
n = int32(1 << 31)
n_64 = int64(n)
) |
||
| rx = 1 & (t >> 1) | ||
| 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) | ||
|
Comment on lines
85
to
86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔮 I don't know definitively, but aren't if rx {
x += int32(s)
} else {
y += int32(s)
}be faster than a multiplication? Or maybe they're not mutually exclusive: is a bool check still faster than a mult? if rx {
x += int32(s)
}
if ry {
y += int32(s)
} |
||
| t /= 4 | ||
| t >>= 2 | ||
| } | ||
|
|
||
| return x, y | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🌵