pub struct BinaryCode {
pub words: Vec<u64>,
pub norm: f32,
pub dim: usize,
}Expand description
A packed binary code representing one vector (D bits).
Fields§
§words: Vec<u64>Packed u64 words (ceil(D/64) words).
norm: f32Original L2 norm before normalisation (needed for the IP estimator).
dim: usizeNumber of dimensions.
Implementations§
Source§impl BinaryCode
impl BinaryCode
Sourcepub fn encode(rotated: &[f32], norm: f32) -> Self
pub fn encode(rotated: &[f32], norm: f32) -> Self
Encode a (possibly rotated) vector into a binary code.
norm should be the L2 norm of the pre-rotation vector so the estimator
can rescale correctly.
Sourcepub fn xnor_popcount(&self, other: &Self) -> u32
pub fn xnor_popcount(&self, other: &Self) -> u32
Raw XNOR-popcount across all stored bits. Do not use when
D % 64 != 0 — the padding bits in the last word are zero in every
code and XNOR-popcount counts them as matches, biasing the estimator.
Retained as a fast path for the aligned case (D multiple of 64).
Sourcepub fn masked_xnor_popcount(&self, other: &Self) -> u32
pub fn masked_xnor_popcount(&self, other: &Self) -> u32
Padding-safe XNOR-popcount. Masks the trailing
64·n_words − D bits of the last word so padding zeros don’t inflate
the agreement count. Correct at any D ≥ 1; same cost as the raw
version up to one extra AND on the last word.
Sourcepub fn estimated_sq_distance(&self, query_code: &Self) -> f32
pub fn estimated_sq_distance(&self, query_code: &Self) -> f32
Symmetric angular estimator (Charikar-style) — both operands are 1-bit codes of rotated unit vectors.
For normalized database x̂ (self.norm holds the original ‖x‖) and
normalized query q̂ (query_code.norm holds the original ‖q‖):
E[B/D] = 1 − θ/π where θ = arccos(⟨x̂, q̂⟩) ⟹ est cos(θ) = cos(π · (1 − B/D)) ⟹ est ⟨q, x⟩ = ‖q‖ · ‖x‖ · est cos(θ)
Returns estimated squared-L2: ‖q − x‖² = ‖q‖² + ‖x‖² − 2⟨q, x⟩.
Sourcepub fn estimated_sq_distance_asymmetric(
&self,
q_rotated_unit: &[f32],
q_norm: f32,
) -> f32
pub fn estimated_sq_distance_asymmetric( &self, q_rotated_unit: &[f32], q_norm: f32, ) -> f32
Asymmetric inner-product estimator (RaBitQ-style, keeps the query in f32). More accurate than the symmetric path, at the cost of O(D) arithmetic per candidate instead of O(D/64) popcount.
Given the rotated-unit query q_rot (‖q_rot‖ = 1) and the stored 1-bit
code b_x ∈ {−1/√D, +1/√D}ᴰ, the unbiased inner-product estimate is:
⟨q̂_rot, u_x⟩ ≈ (1/√D) · Σᵢ sign(x_rot,i) · q_rot,i
where u_x is the rotated unit vector and b_x,i = sign(x_rot,i)/√D.
The unbiasing factor accounts for the concentration of
Σ|q_rot,i| on a Haar-uniform rotation of q (which preserves norm).
Returns estimated squared-L2: ‖q − x‖² = ‖q‖² + ‖x‖² − 2‖q‖·‖x‖·ŝ
where ŝ = ⟨q̂_rot, u_x⟩ is the unit-sphere IP estimate above.
q_rotated must be length self.dim; caller pre-normalises and
pre-rotates the query once per search (amortised across n candidates).
Trait Implementations§
Source§impl Clone for BinaryCode
impl Clone for BinaryCode
Source§fn clone(&self) -> BinaryCode
fn clone(&self) -> BinaryCode
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for BinaryCode
impl Debug for BinaryCode
Source§impl<'de> Deserialize<'de> for BinaryCode
impl<'de> Deserialize<'de> for BinaryCode
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for BinaryCode
impl RefUnwindSafe for BinaryCode
impl Send for BinaryCode
impl Sync for BinaryCode
impl Unpin for BinaryCode
impl UnsafeUnpin for BinaryCode
impl UnwindSafe for BinaryCode
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more