pub struct Slice<T, M> { /* private fields */ }Expand description
A wrapper for a traditional Rust slice that provides the addition of arbitrary metadata.
§Examples
The Slice has several named variants that should be used instead of Slice directly:
PolySlice: An owning, independently allocatedSlice.SliceMut: A mutable, reference-like type.SliceRef: A const, reference-like type.
use diskann_quantization::{
alloc::GlobalAllocator,
meta::slice,
bits::Unsigned,
};
use diskann_utils::{Reborrow, ReborrowMut};
#[derive(Debug, Default, Clone, Copy, PartialEq)]
struct Metadata {
value: f32,
}
// Create a new heap-allocated Vector for 4-bit compressions capable of
// holding 3 elements.
//
// In this case, the associated m
let mut v = slice::PolySlice::new_in(3, GlobalAllocator).unwrap();
// We can inspect the underlying bitslice.
let data = v.vector();
assert_eq!(&data, &[0, 0, 0]);
assert_eq!(*v.meta(), Metadata::default(), "expected default metadata value");
// If we want, we can mutably borrow the bitslice and mutate its components.
let mut data = v.vector_mut();
assert_eq!(data.len(), 3);
data[0] = 1;
data[1] = 2;
data[2] = 3;
// Setting the underlying compensation will be visible in the original allocation.
*v.meta_mut() = Metadata { value: 10.5 };
// Check that the changes are visible.
assert_eq!(v.meta().value, 10.5);
assert_eq!(&v.vector(), &[1, 2, 3]);§Constructing a SliceMut From Components
The following example shows how to assemble a SliceMut from raw parts.
use diskann_quantization::meta::slice;
// For exposition purposes, we will use a slice of `u8` and `f32` as the metadata.
let mut data = vec![0u8; 4];
let mut metadata: f32 = 0.0;
{
let mut v = slice::SliceMut::new(data.as_mut_slice(), &mut metadata);
// Through `v`, we can set all the components in `slice` and the compensation.
*v.meta_mut() = 123.4;
let mut data = v.vector_mut();
data[0] = 1;
data[1] = 2;
data[2] = 3;
data[3] = 4;
}
// Now we can check that the changes made internally are visible.
assert_eq!(&data, &[1, 2, 3, 4]);
assert_eq!(metadata, 123.4);§Canonical Layout
When the slice element type T and metadata type M are both
bytemuck::Pod, SliceRef
and SliceMut support layout canonicalization, where a raw slice can be used as the
backing store for such vectors, enabling inline storage.
The layout is specified by:
- A base alignment of the maximum alignments of
TandM. - The first
Mbytes contain the metadata. - Padding if necessary to reach the alignment of
T. - The values of type
Tstored contiguously.
The canonical layout needs the following properties:
T: bytemuck::Podand `M: bytemuck::Pod: For safely storing and retrieving.- The length for a vector with
Ndimensions must be equal to the value returned fromSliceRef::canonical_bytes. - The alignment of the base pointer must be equal to
SliceRef::canonical_align().
The following functions can be used to construct slices from raw slices:
An example is shown below.
use diskann_quantization::{
alloc::{AlignedAllocator, Poly},
meta::slice,
num::PowerOfTwo,
};
let dim = 3;
// Since we don't control the alignment of the returned pointer, we need to oversize it.
let bytes = slice::SliceRef::<u16, f32>::canonical_bytes(dim);
let align = slice::SliceRef::<u16, f32>::canonical_align();
let mut data = Poly::broadcast(
0u8,
bytes,
AlignedAllocator::new(align)
).unwrap();
// Construct a mutable compensated vector over the slice.
let mut v = slice::SliceMut::<u16, f32>::from_canonical_mut(&mut data, dim).unwrap();
*v.meta_mut() = 1.0;
v.vector_mut().copy_from_slice(&[1, 2, 3]);
// Reconstruct a constant CompensatedVector.
let cv = slice::SliceRef::<u16, f32>::from_canonical(&data, dim).unwrap();
assert_eq!(*cv.meta(), 1.0);
assert_eq!(&cv.vector(), &[1, 2, 3]);Implementations§
Source§impl<T, M> Slice<T, M>
impl<T, M> Slice<T, M>
Source§impl<T, M, U, V> Slice<T, M>
impl<T, M, U, V> Slice<T, M>
Sourcepub fn vector_mut(&mut self) -> &mut [U]where
T: DerefMut,
pub fn vector_mut(&mut self) -> &mut [U]where
T: DerefMut,
Borrow the integer compressed vector.
Sourcepub const fn canonical_align() -> PowerOfTwo
pub const fn canonical_align() -> PowerOfTwo
Return the necessary alignment for the base pointer required for
SliceRef::from_canonical and SliceMut::from_canonical_mut.
The return value is guaranteed to be a power of two.
Sourcepub const fn canonical_bytes(count: usize) -> usize
pub const fn canonical_bytes(count: usize) -> usize
Return the number of bytes required to store count elements plus metadata in a
canonical layout.
See: SliceRef::from_canonical, SliceMut::from_canonical_mut.
Source§impl<T, A, M> Slice<Poly<[T], A>, Owned<M>>
impl<T, A, M> Slice<Poly<[T], A>, Owned<M>>
Sourcepub fn new_in(len: usize, allocator: A) -> Result<Self, AllocatorError>
pub fn new_in(len: usize, allocator: A) -> Result<Self, AllocatorError>
Create a new owned VectorBase with its metadata default initialized.
Source§impl<'a, T, M> Slice<&'a [T], Ref<'a, M>>
impl<'a, T, M> Slice<&'a [T], Ref<'a, M>>
Sourcepub fn from_canonical(data: &'a [u8], dim: usize) -> Result<Self, NotCanonical>
pub fn from_canonical(data: &'a [u8], dim: usize) -> Result<Self, NotCanonical>
Construct an instance of Self viewing data as the canonical layout for a vector.
The canonical layout is as follows:
std::mem::size_of::<T>().max(std::mem::size_of::<M>())for the metadata.- Necessary additional padding to achieve the alignment requirements for
T. std::mem::size_of::<T>() * dimfor the slice.
Returns an error if:
datais not aligned toSelf::canonical_align().data.len() !=Self::canonical_bytes(dim)`.
Sourcepub unsafe fn from_canonical_unchecked(data: &'a [u8], dim: usize) -> Self
pub unsafe fn from_canonical_unchecked(data: &'a [u8], dim: usize) -> Self
Construct a VectorRef from the raw data.
§Safety
data.as_ptr()must be aligned toSelf::canonical_align().data.len()must be equal toSelf::canonical_bytes(dim).
This invariant is checked in debug builds and will panic if not satisfied.
Source§impl<'a, T, M> Slice<&'a mut [T], Mut<'a, M>>
impl<'a, T, M> Slice<&'a mut [T], Mut<'a, M>>
Sourcepub fn from_canonical_mut(
data: &'a mut [u8],
dim: usize,
) -> Result<Self, NotCanonical>
pub fn from_canonical_mut( data: &'a mut [u8], dim: usize, ) -> Result<Self, NotCanonical>
Construct an instance of Self viewing data as the canonical layout for a vector.
The canonical layout is as follows:
std::mem::size_of::<T>().max(std::mem::size_of::<M>())for the metadata.- Necessary additional padding to achieve the alignment requirements for
T. std::mem::size_of::<T>() * dimfor the slice.
Returns an error if:
datais not aligned toSelf::canonical_align().data.len() !=Self::canonical_bytes(dim)`.
Trait Implementations§
Source§impl<'a, T> CompressInto<&[T], Slice<&'a mut [f32], Mut<'a, FullQueryMeta>>> for MinMaxQuantizer
impl<'a, T> CompressInto<&[T], Slice<&'a mut [f32], Mut<'a, FullQueryMeta>>> for MinMaxQuantizer
Source§fn compress_into(
&self,
from: &[T],
to: FullQueryMut<'a>,
) -> Result<(), Self::Error>
fn compress_into( &self, from: &[T], to: FullQueryMut<'a>, ) -> Result<(), Self::Error>
Compress the input vector from into a FullQueryMut to.
This method simply applies the transformation to the input without any compression.
§Error
Returns an error if the input contains NaN.
§Panics
Panics if:
from.len() != self.dim(): Vector to be compressed must have the same dimensionality as the quantizer.to.len() != self.output_dim(): Compressed vector must have the same dimensionality as the quantizer.
Source§type Error = InputContainsNaN
type Error = InputContainsNaN
Source§impl<A> CompressIntoWith<&[f32], Slice<&mut [f32], Mut<'_, FullQueryMeta>>, ScopedAllocator<'_>> for SphericalQuantizer<A>where
A: Allocator,
impl<A> CompressIntoWith<&[f32], Slice<&mut [f32], Mut<'_, FullQueryMeta>>, ScopedAllocator<'_>> for SphericalQuantizer<A>where
A: Allocator,
Source§fn compress_into_with(
&self,
from: &[f32],
into: FullQueryMut<'_>,
allocator: ScopedAllocator<'_>,
) -> Result<(), Self::Error>
fn compress_into_with( &self, from: &[f32], into: FullQueryMut<'_>, allocator: ScopedAllocator<'_>, ) -> Result<(), Self::Error>
Compress the input vector from into the bitslice into.
§Error
Returns an error if
- The input contains
NaN. from.len() != self.dim(): Vector to be compressed must have the same dimensionality as the quantizer.into.len() != self.output_dim(): Compressed vector must have the same dimensionality as the output of the distance-preserving transform. Importantely, this may be different thanself.dim()and should be retrieved fromself.output_dim().
Source§type Error = CompressionError
type Error = CompressionError
Source§impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<MathematicalValue<f32>, UnequalLengths>> for MinMaxIPwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<MathematicalValue<f32>, UnequalLengths>> for MinMaxIPwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
fn evaluate( x: FullQueryRef<'_>, y: DataRef<'_, NBITS>, ) -> MathematicalResult<f32>
Source§impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<MathematicalValue<f32>, UnequalLengths>> for MinMaxL2Squaredwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<MathematicalValue<f32>, UnequalLengths>> for MinMaxL2Squaredwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
fn evaluate( x: FullQueryRef<'_>, y: DataRef<'_, NBITS>, ) -> MathematicalResult<f32>
Source§impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxCosinewhere
Unsigned: Representation<NBITS>,
MinMaxIP: for<'a, 'b> PureDistanceFunction<FullQueryRef<'a>, DataRef<'b, NBITS>, MathematicalResult<f32>>,
impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxCosinewhere
Unsigned: Representation<NBITS>,
MinMaxIP: for<'a, 'b> PureDistanceFunction<FullQueryRef<'a>, DataRef<'b, NBITS>, MathematicalResult<f32>>,
Source§impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxCosineNormalizedwhere
Unsigned: Representation<NBITS>,
MinMaxIP: for<'a, 'b> PureDistanceFunction<FullQueryRef<'a>, DataRef<'b, NBITS>, MathematicalResult<f32>>,
impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxCosineNormalizedwhere
Unsigned: Representation<NBITS>,
MinMaxIP: for<'a, 'b> PureDistanceFunction<FullQueryRef<'a>, DataRef<'b, NBITS>, MathematicalResult<f32>>,
Source§impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxIPwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxIPwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
Source§impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxL2Squaredwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
impl<const NBITS: usize> PureDistanceFunction<Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, MinMaxCompensation>>, Result<f32, UnequalLengths>> for MinMaxL2Squaredwhere
Unsigned: Representation<NBITS>,
InnerProduct: for<'a, 'b> PureDistanceFunction<&'a [f32], BitSlice<'b, NBITS, Unsigned>, MathematicalResult<f32>>,
Source§impl<'a, T, A, M> Reborrow<'a> for Slice<Poly<[T], A>, Owned<M>>where
A: AllocatorCore,
M: 'static,
impl<'a, T, A, M> Reborrow<'a> for Slice<Poly<[T], A>, Owned<M>>where
A: AllocatorCore,
M: 'static,
Source§impl<'a, T, A, M> ReborrowMut<'a> for Slice<Poly<[T], A>, Owned<M>>where
A: AllocatorCore,
M: 'static,
impl<'a, T, A, M> ReborrowMut<'a> for Slice<Poly<[T], A>, Owned<M>>where
A: AllocatorCore,
M: 'static,
Source§impl<A, const NBITS: usize> Target2<A, Result<MathematicalValue<f32>, UnequalLengths>, Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, DataMeta>>> for CompensatedIPwhere
A: Architecture,
Unsigned: Representation<NBITS>,
InnerProduct: for<'a> Target2<A, MathematicalResult<f32>, &'a [f32], BitSlice<'a, NBITS, Unsigned>>,
Compute the inner product between a full-precision query and a spherically quantized
data vector.
impl<A, const NBITS: usize> Target2<A, Result<MathematicalValue<f32>, UnequalLengths>, Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, DataMeta>>> for CompensatedIPwhere
A: Architecture,
Unsigned: Representation<NBITS>,
InnerProduct: for<'a> Target2<A, MathematicalResult<f32>, &'a [f32], BitSlice<'a, NBITS, Unsigned>>,
Compute the inner product between a full-precision query and a spherically quantized data vector.
Returns an error if the arguments have different lengths.
Source§fn run(
self,
arch: A,
x: FullQueryRef<'_>,
y: DataRef<'_, NBITS>,
) -> MathematicalResult<f32>
fn run( self, arch: A, x: FullQueryRef<'_>, y: DataRef<'_, NBITS>, ) -> MathematicalResult<f32>
Architecture.Source§impl<A, const NBITS: usize> Target2<A, Result<MathematicalValue<f32>, UnequalLengths>, Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, DataMeta>>> for CompensatedSquaredL2where
A: Architecture,
Unsigned: Representation<NBITS>,
InnerProduct: for<'a> Target2<A, MathematicalResult<f32>, &'a [f32], BitSlice<'a, NBITS, Unsigned>>,
Compute the inner product between a full-precision query and a spherically quantized
data vector.
impl<A, const NBITS: usize> Target2<A, Result<MathematicalValue<f32>, UnequalLengths>, Slice<&[f32], Ref<'_, FullQueryMeta>>, VectorBase<NBITS, Unsigned, SlicePtr<'_, u8>, Ref<'_, DataMeta>>> for CompensatedSquaredL2where
A: Architecture,
Unsigned: Representation<NBITS>,
InnerProduct: for<'a> Target2<A, MathematicalResult<f32>, &'a [f32], BitSlice<'a, NBITS, Unsigned>>,
Compute the inner product between a full-precision query and a spherically quantized data vector.
Returns an error if the arguments have different lengths.
Source§fn run(
self,
arch: A,
x: FullQueryRef<'_>,
y: DataRef<'_, NBITS>,
) -> MathematicalResult<f32>
fn run( self, arch: A, x: FullQueryRef<'_>, y: DataRef<'_, NBITS>, ) -> MathematicalResult<f32>
Architecture.impl<T: Copy, M: Copy> Copy for Slice<T, M>
Auto Trait Implementations§
impl<T, M> Freeze for Slice<T, M>
impl<T, M> RefUnwindSafe for Slice<T, M>where
T: RefUnwindSafe,
M: RefUnwindSafe,
impl<T, M> Send for Slice<T, M>
impl<T, M> Sync for Slice<T, M>
impl<T, M> Unpin for Slice<T, M>
impl<T, M> UnsafeUnpin for Slice<T, M>where
T: UnsafeUnpin,
M: UnsafeUnpin,
impl<T, M> UnwindSafe for Slice<T, M>where
T: UnwindSafe,
M: UnwindSafe,
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