Skip to content

Commit b2a5a70

Browse files
connortsui20lwwmanningclaude
authored
TurboQuant encoding for Vectors (#7269)
Continuation of #7167, authored by @lwwmanning ## Summary Lossy quantization for vector data (e.g., embeddings) based on TurboQuant (https://arxiv.org/abs/2504.19874). Implements the MSE-only variant (Stage 1 of RFC 0033) at 1-8 bits per coordinate (0 for empty arrays), defaulting to 8-bit near-lossless compression (but still a small amount because we use SRHT instead of random orthogonal rotation matrix, something about not satisfying the Haar assumption?). Key components: - TurboQuant array encoding with 4 slots: quantized codes, norms, centroids, and rotation signs. Note that we should probably abstract the codes and centroids as a dictionary encoded thing so we don't have to duplicate pushdown rules, and we might want to make a matrix multiplication `ScalarFn` expression for the rotations. - Structured Random Hadamard Transform (SRHT) for `O(d log d)` rotation, fully self-contained with no external linear algebra library. This is what claude came up with, but we can see in testing that while this is practical and more efficient, we lose some of the assumptions that a Haar-random orthogonal matrix gives us. I think this is something we can play around with because it's abstracted into a discrete step of the algorithm. - Max-Lloyd centroid computation on the Beta distribution for the given dimension. - Approximate cosine similarity and dot product computed directly on quantized arrays without full decompression. - Pluggable `TurboQuantScheme` for the cascading compressor. - Minimum dimension of 128 (`TurboQuant::MIN_DIMENSION`) for SRHT quality guarantees. - Default 8-bit encoding (MSE ~4e-5, exact 4x compression on `f32`). - Adds `vortex_tensor::initialize()` for session registration of tensor types, encodings, and scalar functions. ## API Changes - Adds `TurboQuant` encoding in `vortex-tensor` with `turboquant_encode()` and `TurboQuantConfig`, and new types `TurboQuantData` and `TurboQuantArray`. - Adds `TurboQuantScheme` for compressor integration. - Adds `TurboQuant::MIN_DIMENSION` (128) constant. - Adds `float_from_f32<T: Float + FromPrimitive>` shared helper for infallible f32-to-float conversion. ## Testing (claude-generated) - Roundtrip tests across bit widths (1-8) and dimensions (128, 256, 768, 1024). - MSE quality bounds verified against the theoretical bound from Theorem 1. - Edge cases: empty arrays, single-row arrays, all-zero vectors, dimension rejection below 128. - Float type coverage: f16, f32, f64 input encoding and roundtrip. - Nullable vector support: validity propagation through encode, decode, slice, take, L2 norm readthrough. - Quantized-domain cosine similarity and dot product accuracy tests. - Serde roundtrip (serialize/deserialize). - Compute pushdown tests: slice, take, scalar_at. - Compression ratio estimates for typical embedding dimensions. - Centroid correctness: count, sorted, symmetric, within bounds, caching, boundary rejection. - SRHT rotation: determinism, roundtrip, norm preservation, sign export/import roundtrip. --------- Signed-off-by: Connor Tsui <connor.tsui20@gmail.com> Co-authored-by: Will Manning <will@willmanning.io> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e3c7401 commit b2a5a70

32 files changed

+3780
-17
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

_typos.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[default]
2-
extend-ignore-identifiers-re = ["ffor", "FFOR", "FoR", "typ", "ratatui"]
2+
extend-ignore-identifiers-re = ["ffor", "FFOR", "FoR", "typ", "ratatui", "wht", "WHT"]
33
# We support a few common special comments to tell the checker to ignore sections of code
44
extend-ignore-re = [
55
"(#|//)\\s*spellchecker:ignore-next-line\\n.*", # Ignore the next line

vortex-btrblocks/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ vortex-pco = { workspace = true, optional = true }
3535
vortex-runend = { workspace = true }
3636
vortex-sequence = { workspace = true }
3737
vortex-sparse = { workspace = true }
38+
vortex-tensor = { workspace = true, optional = true }
3839
vortex-utils = { workspace = true }
3940
vortex-zigzag = { workspace = true }
4041
vortex-zstd = { workspace = true, optional = true }
@@ -47,7 +48,7 @@ vortex-array = { workspace = true, features = ["_test-harness"] }
4748

4849
[features]
4950
# This feature enabled unstable encodings for which we don't guarantee stability.
50-
unstable_encodings = ["vortex-zstd?/unstable_encodings"]
51+
unstable_encodings = ["dep:vortex-tensor", "vortex-zstd?/unstable_encodings"]
5152
pco = ["dep:pco", "dep:vortex-pco"]
5253
zstd = ["dep:vortex-zstd"]
5354

vortex-btrblocks/src/builder.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,22 @@ impl BtrBlocksCompressorBuilder {
138138
builder
139139
}
140140

141+
/// Adds the TurboQuant lossy vector quantization scheme.
142+
///
143+
/// When enabled, [`Vector`] extension arrays are compressed using the TurboQuant algorithm
144+
/// with MSE-optimal scalar quantization.
145+
///
146+
/// # Panics
147+
///
148+
/// Panics if the TurboQuant scheme is already present.
149+
///
150+
/// [`Vector`]: vortex_tensor::vector::Vector
151+
#[cfg(feature = "unstable_encodings")]
152+
pub fn with_turboquant(self) -> Self {
153+
use vortex_tensor::encodings::turboquant::TurboQuantScheme;
154+
self.with_new_scheme(&TurboQuantScheme)
155+
}
156+
141157
/// Excludes schemes without CUDA kernel support and adds Zstd for string compression.
142158
///
143159
/// With the `unstable_encodings` feature, buffer-level Zstd compression is used which

vortex-file/src/strategy.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ use vortex_pco::Pco;
5656
use vortex_runend::RunEnd;
5757
use vortex_sequence::Sequence;
5858
use vortex_sparse::Sparse;
59+
#[cfg(feature = "unstable_encodings")]
60+
use vortex_tensor::encodings::turboquant::TurboQuant;
5961
use vortex_utils::aliases::hash_map::HashMap;
6062
use vortex_zigzag::ZigZag;
6163
#[cfg(feature = "zstd")]
@@ -104,6 +106,8 @@ pub static ALLOWED_ENCODINGS: LazyLock<ArrayRegistry> = LazyLock::new(|| {
104106
session.register(RunEnd);
105107
session.register(Sequence);
106108
session.register(Sparse);
109+
#[cfg(feature = "unstable_encodings")]
110+
session.register(TurboQuant);
107111
session.register(ZigZag);
108112

109113
#[cfg(feature = "zstd")]

vortex-tensor/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@ workspace = true
1919
[dependencies]
2020
vortex-array = { workspace = true }
2121
vortex-buffer = { workspace = true }
22+
vortex-compressor = { workspace = true }
2223
vortex-error = { workspace = true }
24+
vortex-fastlanes = { workspace = true }
2325
vortex-session = { workspace = true }
26+
vortex-utils = { workspace = true }
2427

28+
half = { workspace = true }
2529
itertools = { workspace = true }
2630
num-traits = { workspace = true }
2731
prost = { workspace = true }
32+
rand = { workspace = true }
2833

2934
[dev-dependencies]
35+
rand_distr = { workspace = true }
3036
rstest = { workspace = true }
31-
vortex-buffer = { workspace = true }

vortex-tensor/public-api.lock

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,166 @@ pub mod vortex_tensor
22

33
pub mod vortex_tensor::encodings
44

5+
pub mod vortex_tensor::encodings::turboquant
6+
7+
pub struct vortex_tensor::encodings::turboquant::TurboQuant
8+
9+
impl vortex_tensor::encodings::turboquant::TurboQuant
10+
11+
pub const vortex_tensor::encodings::turboquant::TurboQuant::ID: vortex_array::array::ArrayId
12+
13+
pub const vortex_tensor::encodings::turboquant::TurboQuant::MIN_DIMENSION: u32
14+
15+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::try_new_array(dtype: vortex_array::dtype::DType, codes: vortex_array::array::erased::ArrayRef, norms: vortex_array::array::erased::ArrayRef, centroids: vortex_array::array::erased::ArrayRef, rotation_signs: vortex_array::array::erased::ArrayRef) -> vortex_error::VortexResult<vortex_tensor::encodings::turboquant::TurboQuantArray>
16+
17+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::validate_dtype(dtype: &vortex_array::dtype::DType) -> vortex_error::VortexResult<&vortex_array::dtype::extension::erased::ExtDTypeRef>
18+
19+
impl core::clone::Clone for vortex_tensor::encodings::turboquant::TurboQuant
20+
21+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::clone(&self) -> vortex_tensor::encodings::turboquant::TurboQuant
22+
23+
impl core::fmt::Debug for vortex_tensor::encodings::turboquant::TurboQuant
24+
25+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
26+
27+
impl vortex_array::array::vtable::VTable for vortex_tensor::encodings::turboquant::TurboQuant
28+
29+
pub type vortex_tensor::encodings::turboquant::TurboQuant::ArrayData = vortex_tensor::encodings::turboquant::TurboQuantData
30+
31+
pub type vortex_tensor::encodings::turboquant::TurboQuant::OperationsVTable = vortex_tensor::encodings::turboquant::TurboQuant
32+
33+
pub type vortex_tensor::encodings::turboquant::TurboQuant::ValidityVTable = vortex_array::array::vtable::validity::ValidityVTableFromChild
34+
35+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::array_eq(array: &vortex_tensor::encodings::turboquant::TurboQuantData, other: &vortex_tensor::encodings::turboquant::TurboQuantData, precision: vortex_array::hash::Precision) -> bool
36+
37+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::array_hash<H: core::hash::Hasher>(array: &vortex_tensor::encodings::turboquant::TurboQuantData, state: &mut H, precision: vortex_array::hash::Precision)
38+
39+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::buffer(_array: vortex_array::array::view::ArrayView<'_, Self>, idx: usize) -> vortex_array::buffer::BufferHandle
40+
41+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::buffer_name(_array: vortex_array::array::view::ArrayView<'_, Self>, _idx: usize) -> core::option::Option<alloc::string::String>
42+
43+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::deserialize(&self, dtype: &vortex_array::dtype::DType, len: usize, metadata: &[u8], _buffers: &[vortex_array::buffer::BufferHandle], children: &dyn vortex_array::serde::ArrayChildren, _session: &vortex_session::VortexSession) -> vortex_error::VortexResult<Self::ArrayData>
44+
45+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::execute(array: vortex_array::array::typed::Array<Self>, ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::executor::ExecutionResult>
46+
47+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::execute_parent(array: vortex_array::array::view::ArrayView<'_, Self>, parent: &vortex_array::array::erased::ArrayRef, child_idx: usize, ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::array::erased::ArrayRef>>
48+
49+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::id(&self) -> vortex_array::array::ArrayId
50+
51+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::nbuffers(_array: vortex_array::array::view::ArrayView<'_, Self>) -> usize
52+
53+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::reduce_parent(array: vortex_array::array::view::ArrayView<'_, Self>, parent: &vortex_array::array::erased::ArrayRef, child_idx: usize) -> vortex_error::VortexResult<core::option::Option<vortex_array::array::erased::ArrayRef>>
54+
55+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::serialize(array: vortex_array::array::view::ArrayView<'_, Self>) -> vortex_error::VortexResult<core::option::Option<alloc::vec::Vec<u8>>>
56+
57+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::slot_name(_array: vortex_array::array::view::ArrayView<'_, Self>, idx: usize) -> alloc::string::String
58+
59+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::slots(array: vortex_array::array::view::ArrayView<'_, Self>) -> &[core::option::Option<vortex_array::array::erased::ArrayRef>]
60+
61+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::validate(&self, data: &Self::ArrayData, dtype: &vortex_array::dtype::DType, len: usize) -> vortex_error::VortexResult<()>
62+
63+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::with_slots(array: &mut vortex_tensor::encodings::turboquant::TurboQuantData, slots: alloc::vec::Vec<core::option::Option<vortex_array::array::erased::ArrayRef>>) -> vortex_error::VortexResult<()>
64+
65+
impl vortex_array::array::vtable::operations::OperationsVTable<vortex_tensor::encodings::turboquant::TurboQuant> for vortex_tensor::encodings::turboquant::TurboQuant
66+
67+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::scalar_at(array: vortex_array::array::view::ArrayView<'_, vortex_tensor::encodings::turboquant::TurboQuant>, index: usize, ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::scalar::Scalar>
68+
69+
impl vortex_array::array::vtable::validity::ValidityChild<vortex_tensor::encodings::turboquant::TurboQuant> for vortex_tensor::encodings::turboquant::TurboQuant
70+
71+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::validity_child(array: &vortex_tensor::encodings::turboquant::TurboQuantData) -> &vortex_array::array::erased::ArrayRef
72+
73+
impl vortex_array::arrays::dict::take::TakeExecute for vortex_tensor::encodings::turboquant::TurboQuant
74+
75+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::take(array: vortex_array::array::view::ArrayView<'_, vortex_tensor::encodings::turboquant::TurboQuant>, indices: &vortex_array::array::erased::ArrayRef, _ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<core::option::Option<vortex_array::array::erased::ArrayRef>>
76+
77+
impl vortex_array::arrays::slice::SliceReduce for vortex_tensor::encodings::turboquant::TurboQuant
78+
79+
pub fn vortex_tensor::encodings::turboquant::TurboQuant::slice(array: vortex_array::array::view::ArrayView<'_, vortex_tensor::encodings::turboquant::TurboQuant>, range: core::ops::range::Range<usize>) -> vortex_error::VortexResult<core::option::Option<vortex_array::array::erased::ArrayRef>>
80+
81+
pub struct vortex_tensor::encodings::turboquant::TurboQuantConfig
82+
83+
pub vortex_tensor::encodings::turboquant::TurboQuantConfig::bit_width: u8
84+
85+
pub vortex_tensor::encodings::turboquant::TurboQuantConfig::seed: core::option::Option<u64>
86+
87+
impl core::clone::Clone for vortex_tensor::encodings::turboquant::TurboQuantConfig
88+
89+
pub fn vortex_tensor::encodings::turboquant::TurboQuantConfig::clone(&self) -> vortex_tensor::encodings::turboquant::TurboQuantConfig
90+
91+
impl core::default::Default for vortex_tensor::encodings::turboquant::TurboQuantConfig
92+
93+
pub fn vortex_tensor::encodings::turboquant::TurboQuantConfig::default() -> Self
94+
95+
impl core::fmt::Debug for vortex_tensor::encodings::turboquant::TurboQuantConfig
96+
97+
pub fn vortex_tensor::encodings::turboquant::TurboQuantConfig::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
98+
99+
pub struct vortex_tensor::encodings::turboquant::TurboQuantData
100+
101+
impl vortex_tensor::encodings::turboquant::TurboQuantData
102+
103+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::bit_width(&self) -> u8
104+
105+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::centroids(&self) -> &vortex_array::array::erased::ArrayRef
106+
107+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::codes(&self) -> &vortex_array::array::erased::ArrayRef
108+
109+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::dimension(&self) -> u32
110+
111+
pub unsafe fn vortex_tensor::encodings::turboquant::TurboQuantData::new_unchecked(dtype: &vortex_array::dtype::DType, codes: vortex_array::array::erased::ArrayRef, norms: vortex_array::array::erased::ArrayRef, centroids: vortex_array::array::erased::ArrayRef, rotation_signs: vortex_array::array::erased::ArrayRef) -> Self
112+
113+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::norms(&self) -> &vortex_array::array::erased::ArrayRef
114+
115+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::padded_dim(&self) -> u32
116+
117+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::rotation_signs(&self) -> &vortex_array::array::erased::ArrayRef
118+
119+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::try_new(dtype: &vortex_array::dtype::DType, codes: vortex_array::array::erased::ArrayRef, norms: vortex_array::array::erased::ArrayRef, centroids: vortex_array::array::erased::ArrayRef, rotation_signs: vortex_array::array::erased::ArrayRef) -> vortex_error::VortexResult<Self>
120+
121+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::validate(dtype: &vortex_array::dtype::DType, codes: &vortex_array::array::erased::ArrayRef, norms: &vortex_array::array::erased::ArrayRef, centroids: &vortex_array::array::erased::ArrayRef, rotation_signs: &vortex_array::array::erased::ArrayRef) -> vortex_error::VortexResult<()>
122+
123+
impl core::clone::Clone for vortex_tensor::encodings::turboquant::TurboQuantData
124+
125+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::clone(&self) -> vortex_tensor::encodings::turboquant::TurboQuantData
126+
127+
impl core::fmt::Debug for vortex_tensor::encodings::turboquant::TurboQuantData
128+
129+
pub fn vortex_tensor::encodings::turboquant::TurboQuantData::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
130+
131+
pub struct vortex_tensor::encodings::turboquant::TurboQuantScheme
132+
133+
impl core::clone::Clone for vortex_tensor::encodings::turboquant::TurboQuantScheme
134+
135+
pub fn vortex_tensor::encodings::turboquant::TurboQuantScheme::clone(&self) -> vortex_tensor::encodings::turboquant::TurboQuantScheme
136+
137+
impl core::cmp::Eq for vortex_tensor::encodings::turboquant::TurboQuantScheme
138+
139+
impl core::cmp::PartialEq for vortex_tensor::encodings::turboquant::TurboQuantScheme
140+
141+
pub fn vortex_tensor::encodings::turboquant::TurboQuantScheme::eq(&self, other: &vortex_tensor::encodings::turboquant::TurboQuantScheme) -> bool
142+
143+
impl core::fmt::Debug for vortex_tensor::encodings::turboquant::TurboQuantScheme
144+
145+
pub fn vortex_tensor::encodings::turboquant::TurboQuantScheme::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
146+
147+
impl core::marker::Copy for vortex_tensor::encodings::turboquant::TurboQuantScheme
148+
149+
impl core::marker::StructuralPartialEq for vortex_tensor::encodings::turboquant::TurboQuantScheme
150+
151+
impl vortex_compressor::scheme::Scheme for vortex_tensor::encodings::turboquant::TurboQuantScheme
152+
153+
pub fn vortex_tensor::encodings::turboquant::TurboQuantScheme::compress(&self, compressor: &vortex_compressor::compressor::CascadingCompressor, data: &mut vortex_compressor::stats::cache::ArrayAndStats, _ctx: vortex_compressor::ctx::CompressorContext) -> vortex_error::VortexResult<vortex_array::array::erased::ArrayRef>
154+
155+
pub fn vortex_tensor::encodings::turboquant::TurboQuantScheme::expected_compression_ratio(&self, _compressor: &vortex_compressor::compressor::CascadingCompressor, data: &mut vortex_compressor::stats::cache::ArrayAndStats, _ctx: vortex_compressor::ctx::CompressorContext) -> vortex_error::VortexResult<f64>
156+
157+
pub fn vortex_tensor::encodings::turboquant::TurboQuantScheme::matches(&self, canonical: &vortex_array::canonical::Canonical) -> bool
158+
159+
pub fn vortex_tensor::encodings::turboquant::TurboQuantScheme::scheme_name(&self) -> &'static str
160+
161+
pub fn vortex_tensor::encodings::turboquant::turboquant_encode(ext: &vortex_array::arrays::extension::vtable::ExtensionArray, config: &vortex_tensor::encodings::turboquant::TurboQuantConfig, ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::array::erased::ArrayRef>
162+
163+
pub type vortex_tensor::encodings::turboquant::TurboQuantArray = vortex_array::array::typed::Array<vortex_tensor::encodings::turboquant::TurboQuant>
164+
5165
pub mod vortex_tensor::fixed_shape
6166

7167
pub struct vortex_tensor::fixed_shape::FixedShapeTensor
@@ -180,7 +340,7 @@ pub fn vortex_tensor::scalar_fns::inner_product::InnerProduct::arity(&self, _opt
180340

181341
pub fn vortex_tensor::scalar_fns::inner_product::InnerProduct::child_name(&self, _options: &Self::Options, child_idx: usize) -> vortex_array::scalar_fn::vtable::ChildName
182342

183-
pub fn vortex_tensor::scalar_fns::inner_product::InnerProduct::execute(&self, _options: &Self::Options, args: &dyn vortex_array::scalar_fn::vtable::ExecutionArgs, ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::array::erased::ArrayRef>
343+
pub fn vortex_tensor::scalar_fns::inner_product::InnerProduct::execute(&self, options: &Self::Options, args: &dyn vortex_array::scalar_fn::vtable::ExecutionArgs, ctx: &mut vortex_array::executor::ExecutionCtx) -> vortex_error::VortexResult<vortex_array::array::erased::ArrayRef>
184344

185345
pub fn vortex_tensor::scalar_fns::inner_product::InnerProduct::fmt_sql(&self, _options: &Self::Options, expr: &vortex_array::expr::expression::Expression, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
186346

@@ -236,6 +396,12 @@ pub vortex_tensor::scalar_fns::ApproxOptions::Approximate
236396

237397
pub vortex_tensor::scalar_fns::ApproxOptions::Exact
238398

399+
impl vortex_tensor::scalar_fns::ApproxOptions
400+
401+
pub fn vortex_tensor::scalar_fns::ApproxOptions::is_approx(&self) -> bool
402+
403+
pub fn vortex_tensor::scalar_fns::ApproxOptions::is_exact(&self) -> bool
404+
239405
impl core::clone::Clone for vortex_tensor::scalar_fns::ApproxOptions
240406

241407
pub fn vortex_tensor::scalar_fns::ApproxOptions::clone(&self) -> vortex_tensor::scalar_fns::ApproxOptions

vortex-tensor/src/encodings/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@
77
// pub mod norm; // Unit-normalized vectors.
88
// pub mod spherical; // Spherical transform on unit-normalized vectors.
99

10-
// TODO(will):
11-
// pub mod turboquant;
10+
pub mod turboquant;

0 commit comments

Comments
 (0)