Usage

Quick Start

The simplest case - 2D data:

using BijectiveHilbert
encoder = Simple2D(Int)
h = encode_hilbert(encoder, [x, y])

Choose Your Encoder

2D data

Simple2D requires no setup - just specify the index type:

encoder = Simple2D(Int64)

N-D, same-size axes

SpaceGray is the fastest N-D encoder. All axes must be the same power-of-two size:

# 4D space, each axis 0-7 (3 bits = 2^3 = 8 values)
encoder = SpaceGray(Int64, 3, 4)

GlobalGray and FaceContinuous use the same interface but produce different curve patterns:

encoder = GlobalGray(Int64, 3, 4)
encoder = FaceContinuous(Int64, 3, 4)

N-D, different-size axes

Compact handles axes of different sizes (each must be a power of two):

# 3D space: axis 1 is 0-7 (3 bits), axis 2 is 0-3 (2 bits), axis 3 is 0-15 (4 bits)
encoder = Compact(Int64, [3, 2, 4])

Families of Hilbert curves

Beyond the single canonical curve shown above, Compact exposes a whole family of distinct curves over the same domain, while always keeping the curve lattice-continuous. You select a member with a catalog Gray code and a gluing path:

# a specific random-Gray-code curve with a catalogued gluing path
encoder = Compact([4, 4, 4, 3]; gray=:random, gray_index=3, path=:catalog, path_index=7)

Why does a family matter? For a given domain there are many distinct Hilbert curves, each with slightly different spatial-locality behavior. Being able to pick many different curves over the same points lets you build ensembles: run an algorithm across several curves and average the results, or randomize the curve to avoid systematic bias from any single ordering.

Encode and Decode

Convert a point to a Hilbert index and back:

point = [2, 1, 7, 3]
hilbert_index = encode_hilbert(encoder, point)

point_out = zeros(Int, 4)
decode_hilbert!(encoder, point_out, hilbert_index)
@assert point_out == point

For zero-based indexing, use the _zero variants:

point = [1, 0, 6, 2]
hilbert_index = encode_hilbert_zero(encoder, point)
decode_hilbert_zero!(encoder, point_out, hilbert_index)

Sorting

Sort a Vector{<:AbstractVector} according to a Hilbert curve:

points = [rand(3) for _ in 1:1000]
hilbertsort!(points)

Methods for matrix arguments are also supported:

points_mat = permutedims(reduce(hcat, points))
hilbertsort!(points_mat)

Performance Tips

  • Use StaticArrays.MVector for the point vector when encoding/decoding in a tight loop
  • The 1-based functions are thin wrappers around the 0-based implementations