Skip to content

Commit

Permalink
benchmark (#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
ciscorn authored Feb 19, 2025
1 parent 8ea4ca3 commit 085b5fc
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 26 deletions.
53 changes: 27 additions & 26 deletions pmtiles/tile_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,52 @@ import (
"math/bits"
)

func rotate(n uint64, x *uint64, y *uint64, rx uint64, ry uint64) {
func rotate(n uint32, x uint32, y uint32, rx uint32, ry uint32) (uint32, uint32) {
if ry == 0 {
if rx == 1 {
*x = n - 1 - *x
*y = n - 1 - *y
if rx != 0 {
x = n - 1 - x
y = n - 1 - y
}
*x, *y = *y, *x
return y, x
}
return x, y
}

// ZxyToID converts (Z,X,Y) tile coordinates to a Hilbert TileID.
func ZxyToID(z uint8, x uint32, y uint32) uint64 {
var acc uint64 = ((1 << (z * 2)) - 1) / 3
var tx, ty uint64 = uint64(x), uint64(y)
for a := int32(z - 1); a >= 0; a-- {
var rx uint64 = (tx >> a) & 1
var ry uint64 = (ty >> a) & 1
var s uint64 = (1 << a)
rotate(s, &tx, &ty, rx, ry)
acc += s * s * ((3 * rx) ^ ry)
var acc uint64 = (1<<(z*2) - 1) / 3
n := uint32(z - 1)
for s := uint32(1 << n); s > 0; s >>= 1 {
var rx = s & x
var ry = s & y
acc += uint64((3*rx)^ry) << n
x, y = rotate(s, x, y, rx, ry)
n--
}
return acc
}

// IDToZxy converts a Hilbert TileID to (Z,X,Y) tile coordinates.
func IDToZxy(i uint64) (uint8, uint32, uint32) {
var z uint8 = uint8((64 - bits.LeadingZeros64(3*i+1) - 1) / 2)
var acc uint64 = (1<<(z*2) - 1) / 3
var pos uint64 = i - acc
var tx, ty uint64 = 0, 0
var z = uint8(bits.Len64(3*i+1)-1) / 2
var acc = (uint64(1)<<(z*2) - 1) / 3
var t = i - acc
var tx, ty uint32
for a := uint8(0); a < z; a++ {
var rx uint64 = (pos / 2) & 1
var ry uint64 = (pos ^ rx) & 1
var s uint64 = 1 << a
rotate(s, &tx, &ty, rx, ry)
tx += s * rx
ty += s * ry
pos /= 4
var s = uint32(1) << a
var rx = 1 & (uint32(t) >> 1)
var ry = 1 & (uint32(t) ^ rx)
tx, ty = rotate(s, tx, ty, rx, ry)
tx += rx << a
ty += ry << a
t >>= 2
}
return z, uint32(tx), uint32(ty)
return uint8(z), tx, ty
}

// ParentID efficiently finds a parent Hilbert TileID without converting to (Z,X,Y).
func ParentID(i uint64) uint64 {
var z uint8 = uint8((64 - bits.LeadingZeros64(3*i+1) - 1) / 2)
var z = uint8(64-bits.LeadingZeros64(3*i+1)-1) / 2
var acc uint64 = (1<<(z*2) - 1) / 3
var parentAcc uint64 = (1<<((z-1)*2) - 1) / 3
return parentAcc + (i-acc)/4
Expand Down
33 changes: 33 additions & 0 deletions pmtiles/tile_id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,36 @@ func TestParent(t *testing.T) {
assert.Equal(t, ZxyToID(18, 1, 500), ParentID(ZxyToID(19, 3, 1000)))
assert.Equal(t, ZxyToID(18, 2, 500), ParentID(ZxyToID(19, 4, 1000)))
}

func BenchmarkZxyToId(b *testing.B) {
for n := 0; n < b.N; n++ {
for z := uint8(0); z < 15; z += 1 {
s := uint32(1 << z)
for x := uint32(0); x < s; x += 13 {
for y := uint32(0); y < s; y += 13 {
_ = ZxyToID(z, x, y)
}
}
}
}
}

func BenchmarkIdToZxy(b *testing.B) {
end := ZxyToID(15, 0, 0)
b.ResetTimer()
for n := 0; n < b.N; n++ {
for i := uint64(0); i < end; i += 13 {
_, _, _ = IDToZxy(i)
}
}
}

func BenchmarkParentId(b *testing.B) {
end := ZxyToID(15, 0, 0)
b.ResetTimer()
for n := 0; n < b.N; n++ {
for i := uint64(1); i < end; i += 13 {
_ = ParentID(i)
}
}
}

0 comments on commit 085b5fc

Please sign in to comment.