pub struct BucketedAxis<const N: usize, const B: usize> { /* private fields */ }Expand description
An axis of N stored knots with a static index of B buckets.
The index turns an irregular axis into a bounded local problem: one division
selects a bucket, the bucket names the first knot that can hold the answer,
and a short scan finishes the job. It is the strategy to reach for when an
axis is long and unevenly spaced and a few index bytes are worth a smaller
search bound; UniformAxis is better when the spacing
is regular, and BinaryAxis when no extra bytes are
wanted.
The index is built at compile time by bucket_index and re-derived by
BucketedAxis::new, so a stale or hand-written table fails to compile.
Nothing is constructed, cached, or mutated at runtime.
§Cost
2*N stored knot bytes plus 2*B index bytes. After the endpoint checks,
the strategy reads one bucket and then performs at most
max_local_comparisons knot comparisons — a figure exact for these knots,
which never grows when B is raised to a multiple of itself.
§Examples
use ph_surfaces::{BilinearSurface, BinaryAxis, BucketedAxis, bucket_index, max_local_comparisons};
// Tightly clustered at the bottom, then a long tail.
static X: [u16; 6] = [0, 1, 2, 3, 400, 1_000];
static X_INDEX: [u16; 8] = bucket_index(&X);
static Y: [u16; 2] = [0, 10];
static VALUES: [[i32; 6]; 2] = [[0, 1, 2, 3, 400, 1_000], [10, 11, 12, 13, 410, 1_010]];
static SURFACE: BilinearSurface<6, 2, BucketedAxis<6, 8>, BinaryAxis<2>> =
BilinearSurface::from_axes(BucketedAxis::new(&X, &X_INDEX), BinaryAxis::new(&Y), &VALUES);
// The same answers as the default binary surface over the same tables.
static DEFAULT: BilinearSurface<6, 2> = BilinearSurface::new(&X, &Y, &VALUES);
assert_eq!(SURFACE.evaluate(700, 5), DEFAULT.evaluate(700, 5));
// Three comparisons at worst, on an axis a plain scan could take five to
// walk: the index paid two bytes a bucket to bound the walk.
assert_eq!(max_local_comparisons(&X, &X_INDEX), 3);A bucket table that does not match its knots does not compile:
use ph_surfaces::BucketedAxis;
static X: [u16; 6] = [0, 1, 2, 3, 400, 1_000];
static WRONG: [u16; 4] = [0, 0, 0, 0];
static AXIS: BucketedAxis<6, 4> = BucketedAxis::new(&X, &WRONG);Implementations§
Source§impl<const N: usize, const B: usize> BucketedAxis<N, B>
impl<const N: usize, const B: usize> BucketedAxis<N, B>
Sourcepub const fn new(knots: &'static [u16; N], index: &'static [u16; B]) -> Self
pub const fn new(knots: &'static [u16; N], index: &'static [u16; B]) -> Self
Declares a bucketed axis over static knots and a static bucket index.
§Panics
Panics unless the axis declares at least two strictly increasing knots,
N <= 65_536 so every knot index is representable in the table,
1 <= B <= 65_536, and every entry of index equals the entry
bucket_index derives for the same knots. In a constant or static
definition that panic is a compile error, so an axis cannot reach runtime
with an index that disagrees with its knots.
Examples found in repository?
More examples
Sourcepub const fn knots(&self) -> &'static [u16; N]
pub const fn knots(&self) -> &'static [u16; N]
Returns the declared knots.
The same array as KnotArray::knots, available in a constant context.
Sourcepub const fn max_local_comparisons(&self) -> u32
pub const fn max_local_comparisons(&self) -> u32
Returns the exact worst-case local scan for this axis, in knot
comparisons: max_local_comparisons over its knots and index.
Trait Implementations§
Source§impl<const N: usize, const B: usize> AxisLookup<N> for BucketedAxis<N, B>
impl<const N: usize, const B: usize> AxisLookup<N> for BucketedAxis<N, B>
Source§const KNOT_BYTES: usize
const KNOT_BYTES: usize
Source§const INDEX_BYTES: usize
const INDEX_BYTES: usize
Source§const MAX_SEARCH_COMPARISONS: u32
const MAX_SEARCH_COMPARISONS: u32
Source§impl<const N: usize, const B: usize> Clone for BucketedAxis<N, B>
impl<const N: usize, const B: usize> Clone for BucketedAxis<N, B>
Source§fn clone(&self) -> BucketedAxis<N, B>
fn clone(&self) -> BucketedAxis<N, B>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more