pub struct UniformAxis<const N: usize, const ORIGIN: u16, const STEP: u16>(/* private fields */);Expand description
An axis of N evenly spaced knots, described by ORIGIN and STEP rather
than stored.
Knot i is ORIGIN + i * STEP, so the whole axis is ORIGIN, STEP, and
N — all three in the type. The value is zero-sized: an evenly spaced axis
costs no static bytes, adds nothing to the surface handle, and needs no knot
array to walk or probe. Because the descriptor is a compile-time constant,
the division that locates a cell is a division by a constant in every
instantiation.
This is the one strategy that cannot describe an arbitrary axis. If the
spacing is irregular, use BinaryAxis, or
BucketedAxis when a smaller search bound is worth
index bytes.
§Cost
No stored bytes, no index, and no strategy-specific knot comparison after
the endpoint checks: one subtraction and one division locate the cell
regardless of N.
§Examples
use ph_surfaces::{BilinearSurface, BinaryAxis, UniformAxis};
// Five knots at 0, 25, 50, 75, 100 — declared, not stored.
static Y: [u16; 2] = [0, 10];
static VALUES: [[i32; 5]; 2] = [[0, 25, 50, 75, 100], [10, 35, 60, 85, 110]];
static SURFACE: BilinearSurface<5, 2, UniformAxis<5, 0, 25>, BinaryAxis<2>> =
BilinearSurface::from_axes(UniformAxis::new(), BinaryAxis::new(&Y), &VALUES);
assert_eq!(SURFACE.x_knot(3), 75);
assert_eq!(SURFACE.evaluate(60, 0), Ok(60));
assert_eq!(SURFACE.evaluate(100, 10), Ok(110));The same surface with the knots spelled out and located binarily returns the same values:
use ph_surfaces::{BilinearSurface, BinaryAxis, UniformAxis};
static X: [u16; 5] = [0, 25, 50, 75, 100];
static Y: [u16; 2] = [0, 10];
static VALUES: [[i32; 5]; 2] = [[0, 25, 50, 75, 100], [10, 35, 60, 85, 110]];
static UNIFORM: BilinearSurface<5, 2, UniformAxis<5, 0, 25>, BinaryAxis<2>> =
BilinearSurface::from_axes(UniformAxis::new(), BinaryAxis::new(&Y), &VALUES);
static STORED: BilinearSurface<5, 2> = BilinearSurface::new(&X, &Y, &VALUES);
for x in [0u16, 1, 37, 50, 99, 100] {
assert_eq!(UNIFORM.evaluate(x, 5), STORED.evaluate(x, 5));
}A single-knot axis does not compile:
use ph_surfaces::UniformAxis;
static AXIS: UniformAxis<1, 0, 25> = UniformAxis::new();Nor does a zero step, which would declare N copies of one knot:
use ph_surfaces::UniformAxis;
static AXIS: UniformAxis<5, 0, 0> = UniformAxis::new();Nor does a descriptor whose last knot leaves u16:
use ph_surfaces::UniformAxis;
static AXIS: UniformAxis<5, 60_000, 2_000> = UniformAxis::new();The descriptor cannot bypass UniformAxis::new; its zero-sized field is
private:
use ph_surfaces::UniformAxis;
static AXIS: UniformAxis<5, 0, 25> = UniformAxis(());Implementations§
Source§impl<const N: usize, const ORIGIN: u16, const STEP: u16> UniformAxis<N, ORIGIN, STEP>
impl<const N: usize, const ORIGIN: u16, const STEP: u16> UniformAxis<N, ORIGIN, STEP>
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Declares an evenly spaced axis.
§Panics
Panics unless the descriptor names at least two strictly increasing knots
that are all representable: N >= 2, STEP >= 1, and
N <= 65_536, and ORIGIN + (N - 1) * STEP <= u16::MAX. In a constant
or static definition that panic is a compile error, so an unrepresentable
axis cannot be declared.
Examples found in repository?
More examples
63 static SURFACE: UniformPair =
64 BilinearSurface::from_axes(UniformAxis::new(), UniformAxis::new(), &VALUES);
65
66 assert_eq!(SURFACE.evaluate(100, 200), Ok(0));
67 assert_eq!(SURFACE.x_knot(16), 1_600);
68 assert_eq!(SURFACE.y_knot(8), 1_600);
69
70 assert_eq!(UniformPair::VALUE_BYTES, 612);
71 assert_eq!(UniformPair::PAYLOAD_BYTES, 612);
72 assert_eq!(AllBinary::PAYLOAD_BYTES, 664);
73 assert_eq!(UniformPair::PAYLOAD_BYTES + 52, AllBinary::PAYLOAD_BYTES);
74 assert_eq!(<UniformAxis<17, 0, 100>>::KNOT_BYTES, 0);
75 assert_eq!(<UniformAxis<17, 0, 100>>::MAX_SEARCH_COMPARISONS, 0);
76 assert_eq!(<UniformAxis<9, 0, 200>>::MAX_SEARCH_COMPARISONS, 0);
77 assert_eq!(UniformPair::SUCCESS_INTERPOLATIONS, 3);
78 assert_eq!(UniformPair::SUCCESS_GRID_READS, 4);
79 assert_eq!(
80 UniformPair::HANDLE_BYTES,
81 core::mem::size_of::<UniformPair>()
82 );
83}
84
85fn mixed_bucketed_uniform_17x9() {
86 static X: [u16; 17] = [
87 0, 100, 210, 300, 405, 500, 610, 700, 805, 900, 1_010, 1_100, 1_205, 1_300, 1_410, 1_500,
88 1_600,
89 ];
90 static X_INDEX: [u16; 8] = bucket_index(&X);
91 static VALUES: [[i32; 17]; 9] = [[0; 17]; 9];
92
93 type Mixed = BilinearSurface<17, 9, BucketedAxis<17, 8>, UniformAxis<9, 0, 200>>;
94 type AllBinary = BilinearSurface<17, 9>;
95
96 static MIXED: Mixed =
97 BilinearSurface::from_axes(BucketedAxis::new(&X, &X_INDEX), UniformAxis::new(), &VALUES);Sourcepub const fn origin(&self) -> u16
pub const fn origin(&self) -> u16
Returns the first knot, ORIGIN.
The same value as AxisLookup::first, available in a constant context.
Sourcepub const fn knot(&self, index: usize) -> u16
pub const fn knot(&self, index: usize) -> u16
Returns the knot at index, computed from the descriptor.
The same value as AxisLookup::knot, available in a constant
context.
§Panics
Panics if index >= N.
Sourcepub const fn last(&self) -> u16
pub const fn last(&self) -> u16
Returns the last knot, ORIGIN + (N - 1) * STEP.
The same value as AxisLookup::last, available in a constant
context. inline(always) because the body folds to one constant; an
outlined copy would be all call overhead.
Trait Implementations§
Source§impl<const N: usize, const ORIGIN: u16, const STEP: u16> AxisLookup<N> for UniformAxis<N, ORIGIN, STEP>
impl<const N: usize, const ORIGIN: u16, const STEP: u16> AxisLookup<N> for UniformAxis<N, ORIGIN, STEP>
Source§const KNOT_BYTES: usize = 0
const KNOT_BYTES: usize = 0
Source§const INDEX_BYTES: usize = 0
const INDEX_BYTES: usize = 0
Source§const MAX_SEARCH_COMPARISONS: u32 = 0
const MAX_SEARCH_COMPARISONS: u32 = 0
Source§impl<const N: usize, const ORIGIN: u16, const STEP: u16> Clone for UniformAxis<N, ORIGIN, STEP>
impl<const N: usize, const ORIGIN: u16, const STEP: u16> Clone for UniformAxis<N, ORIGIN, STEP>
Source§fn clone(&self) -> UniformAxis<N, ORIGIN, STEP>
fn clone(&self) -> UniformAxis<N, ORIGIN, STEP>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl<const N: usize, const ORIGIN: u16, const STEP: u16> Copy for UniformAxis<N, ORIGIN, STEP>
Source§impl<const N: usize, const ORIGIN: u16, const STEP: u16> Debug for UniformAxis<N, ORIGIN, STEP>
impl<const N: usize, const ORIGIN: u16, const STEP: u16> Debug for UniformAxis<N, ORIGIN, STEP>
Source§impl<const N: usize, const ORIGIN: u16, const STEP: u16> Default for UniformAxis<N, ORIGIN, STEP>
impl<const N: usize, const ORIGIN: u16, const STEP: u16> Default for UniformAxis<N, ORIGIN, STEP>
Source§fn default() -> Self
fn default() -> Self
Returns UniformAxis::new, validating the descriptor.
It is written out rather than derived on purpose: a derived Default
would hand back an axis whose descriptor had never been checked, and the
rest of the crate relies on every axis having been.