From 626df79eb0f0a5f8b79c06689b8a874fae5cf4d1 Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Tue, 28 Apr 2026 08:03:19 -0700 Subject: [PATCH 1/4] remove alignedslice and replace with direct poly calls --- Cargo.toml | 1 - .../benchmarks/aligned_file_reader_bench.rs | 4 +- .../aligned_file_reader_bench_iai.rs | 4 +- diskann-disk/src/search/pq/pq_scratch.rs | 38 ++--- .../src/search/provider/disk_sector_graph.rs | 18 ++- .../provider/disk_vertex_provider_factory.rs | 10 +- .../linux_aligned_file_reader.rs | 8 +- .../storage_provider_aligned_file_reader.rs | 4 +- .../windows_aligned_file_reader.rs | 6 +- diskann-quantization/src/alloc/aligned.rs | 13 ++ .../src/alloc/aligned_slice.rs | 76 ---------- diskann-quantization/src/alloc/mod.rs | 2 - diskann-quantization/src/num.rs | 139 ++++++++++++++++++ 13 files changed, 194 insertions(+), 129 deletions(-) delete mode 100644 diskann-quantization/src/alloc/aligned_slice.rs diff --git a/Cargo.toml b/Cargo.toml index eabbcbc1a..6f31a1ae2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,6 @@ iai-callgrind = "0.14.0" itertools = "0.13.0" num-traits = "0.2.15" num_cpus = "1.16.0" -once_cell = "1.19.0" opentelemetry = "0.30.0" opentelemetry_sdk = "0.30.0" paste = "1.0.15" diff --git a/diskann-disk/benches/benchmarks/aligned_file_reader_bench.rs b/diskann-disk/benches/benchmarks/aligned_file_reader_bench.rs index d301af5a0..e8099d40d 100644 --- a/diskann-disk/benches/benchmarks/aligned_file_reader_bench.rs +++ b/diskann-disk/benches/benchmarks/aligned_file_reader_bench.rs @@ -9,7 +9,7 @@ use diskann_disk::utils::aligned_file_reader::{ traits::{AlignedFileReader, AlignedReaderFactory}, AlignedFileReaderFactory, AlignedRead, }; -use diskann_quantization::{alloc::aligned_slice, num::PowerOfTwo}; +use diskann_quantization::alloc::{AlignedAllocator, Poly}; pub const TEST_INDEX_PATH: &str = "../test_data/disk_index_misc/disk_index_siftsmall_learn_256pts_R4_L50_A1.2_aligned_reader_test.index"; @@ -34,7 +34,7 @@ pub fn benchmark_aligned_file_reader(c: &mut Criterion) { let read_length = 512; let num_read = MAX_IO_CONCURRENCY * 100; // The LinuxAlignedFileReader batches reads according to MAX_IO_CONCURRENCY. Make sure we have many batches to handle. let mut aligned_mem = - aligned_slice::(read_length * num_read, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_read, AlignedAllocator::A512).unwrap(); // create and add AlignedReads to the vector let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); diff --git a/diskann-disk/benches/benchmarks_iai/aligned_file_reader_bench_iai.rs b/diskann-disk/benches/benchmarks_iai/aligned_file_reader_bench_iai.rs index 8ff50f167..8c9c1f880 100644 --- a/diskann-disk/benches/benchmarks_iai/aligned_file_reader_bench_iai.rs +++ b/diskann-disk/benches/benchmarks_iai/aligned_file_reader_bench_iai.rs @@ -7,7 +7,7 @@ use diskann_disk::utils::aligned_file_reader::{ traits::{AlignedFileReader, AlignedReaderFactory}, AlignedFileReaderFactory, AlignedRead, }; -use diskann_quantization::{alloc::aligned_slice, num::PowerOfTwo}; +use diskann_quantization::alloc::{AlignedAllocator, Poly}; pub const TEST_INDEX_PATH: &str = "../test_data/disk_index_misc/disk_index_siftsmall_learn_256pts_R4_L50_A1.2_aligned_reader_test.index"; @@ -25,7 +25,7 @@ pub fn benchmark_aligned_file_reader_iai() { let read_length = 512; let num_read = MAX_IO_CONCURRENCY * 100; // The LinuxAlignedFileReader batches reads according to MAX_IO_CONCURRENCY. Make sure we have many batches to handle. let mut aligned_mem = - aligned_slice::(read_length * num_read, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_read, AlignedAllocator::A512).unwrap(); // create and add AlignedReads to the vector let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); diff --git a/diskann-disk/src/search/pq/pq_scratch.rs b/diskann-disk/src/search/pq/pq_scratch.rs index bd7a8dfc3..e7c103724 100644 --- a/diskann-disk/src/search/pq/pq_scratch.rs +++ b/diskann-disk/src/search/pq/pq_scratch.rs @@ -6,25 +6,22 @@ use diskann::{error::IntoANNResult, utils::VectorRepr, ANNError, ANNResult}; -use diskann_quantization::{ - alloc::{aligned_slice, AlignedSlice}, - num::PowerOfTwo, -}; +use diskann_quantization::alloc::{AlignedAllocator, Poly}; #[derive(Debug)] /// PQ scratch pub struct PQScratch { /// Aligned pq table distance scratch, the length must be at least [256 * NCHUNKS]. 256 is the number of PQ centroids. /// This is used to store the distance between each chunk in the query vector to each centroid, which is why the length is num of centroids * num of chunks - pub aligned_pqtable_dist_scratch: AlignedSlice, + pub aligned_pqtable_dist_scratch: Poly<[f32], AlignedAllocator>, /// Aligned dist scratch, must be at least diskann MAX_DEGREE /// This is used to temporarily save the pq distance between query vector to the candidate vectors. - pub aligned_dist_scratch: AlignedSlice, + pub aligned_dist_scratch: Poly<[f32], AlignedAllocator>, /// Aligned pq coord scratch, must be at least [N_CHUNKS * MAX_DEGREE] /// This is used to store the pq coordinates of the candidate vectors. - pub aligned_pq_coord_scratch: AlignedSlice, + pub aligned_pq_coord_scratch: Poly<[u8], AlignedAllocator>, /// Query scratch buffer stored as `f32`. `set` initializes it by copying/converting the /// raw query values; `PQTable.PreprocessQuery` can then rotate or otherwise preprocess it. @@ -32,12 +29,6 @@ pub struct PQScratch { } impl PQScratch { - /// 128 bytes alignment to optimize for the L2 Adjacent Cache Line Prefetcher. - const ALIGNED_ALLOC_128: PowerOfTwo = match PowerOfTwo::new(128) { - Ok(v) => v, - Err(_) => unreachable!(), - }; - /// Create a new pq scratch pub fn new( graph_degree: usize, @@ -46,13 +37,11 @@ impl PQScratch { num_centers: usize, ) -> ANNResult { let aligned_pq_coord_scratch = - aligned_slice(graph_degree * num_pq_chunks, PQScratch::ALIGNED_ALLOC_128) - .map_err(ANNError::log_index_error)?; + Poly::broadcast(0u8, graph_degree * num_pq_chunks, AlignedAllocator::A128).unwrap(); let aligned_pqtable_dist_scratch = - aligned_slice(num_centers * num_pq_chunks, PQScratch::ALIGNED_ALLOC_128) - .map_err(ANNError::log_index_error)?; - let aligned_dist_scratch = aligned_slice(graph_degree, PQScratch::ALIGNED_ALLOC_128) - .map_err(ANNError::log_index_error)?; + Poly::broadcast(0f32, num_centers * num_pq_chunks, AlignedAllocator::A128).unwrap(); + let aligned_dist_scratch = + Poly::broadcast(0f32, graph_degree, AlignedAllocator::A128).unwrap(); let rotated_query = vec![0.0f32; dim]; Ok(Self { @@ -94,6 +83,7 @@ impl PQScratch { #[cfg(test)] mod tests { + use diskann_quantization::num::PowerOfTwo; use rstest::rstest; use super::PQScratch; @@ -110,20 +100,16 @@ mod tests { let mut pq_scratch: PQScratch = PQScratch::new(graph_degree, dim, num_pq_chunks, num_centers).unwrap(); - // Check alignment of the remaining AlignedSlice buffers. assert_eq!( - (pq_scratch.aligned_pqtable_dist_scratch.as_ptr() as usize) - % PQScratch::ALIGNED_ALLOC_128.raw(), + (pq_scratch.aligned_pqtable_dist_scratch.as_ptr() as usize) % PowerOfTwo::V128.raw(), 0 ); assert_eq!( - (pq_scratch.aligned_dist_scratch.as_ptr() as usize) - % PQScratch::ALIGNED_ALLOC_128.raw(), + (pq_scratch.aligned_dist_scratch.as_ptr() as usize) % PowerOfTwo::V128.raw(), 0 ); assert_eq!( - (pq_scratch.aligned_pq_coord_scratch.as_ptr() as usize) - % PQScratch::ALIGNED_ALLOC_128.raw(), + (pq_scratch.aligned_pq_coord_scratch.as_ptr() as usize) % PowerOfTwo::V128.raw(), 0 ); diff --git a/diskann-disk/src/search/provider/disk_sector_graph.rs b/diskann-disk/src/search/provider/disk_sector_graph.rs index cd3412b57..cc78e6c2d 100644 --- a/diskann-disk/src/search/provider/disk_sector_graph.rs +++ b/diskann-disk/src/search/provider/disk_sector_graph.rs @@ -9,7 +9,7 @@ use std::ops::Deref; use diskann::{ANNError, ANNResult}; use diskann_quantization::{ - alloc::{aligned_slice, AlignedSlice}, + alloc::{AlignedAllocator, Poly}, num::PowerOfTwo, }; @@ -37,7 +37,7 @@ pub struct DiskSectorGraph { /// index info for multi-sector nodes /// node `i` is in sector: [i * max_node_len.div_ceil(block_size)] /// offset in sector: [0] - sectors_data: AlignedSlice, + sectors_data: Poly<[u8], AlignedAllocator>, /// Current sector index into which the next read reads data cur_sector_idx: u64, @@ -76,11 +76,12 @@ impl DiskSectorGraph { Ok(Self { sector_reader, - sectors_data: aligned_slice( + sectors_data: Poly::broadcast( + 0u8, max_n_batch_sector_read * num_sectors_per_node * block_size, - PowerOfTwo::new(block_size).map_err(ANNError::log_index_error)?, + AlignedAllocator::new(PowerOfTwo::new(block_size).unwrap()), ) - .map_err(ANNError::log_index_error)?, + .unwrap(), cur_sector_idx: 0, num_nodes_per_sector, node_len, @@ -94,9 +95,10 @@ impl DiskSectorGraph { pub fn reconfigure(&mut self, max_n_batch_sector_read: usize) -> ANNResult<()> { if max_n_batch_sector_read > self.max_n_batch_sector_read { self.max_n_batch_sector_read = max_n_batch_sector_read; - self.sectors_data = aligned_slice( + self.sectors_data = Poly::broadcast( + 0u8, max_n_batch_sector_read * self.num_sectors_per_node * self.block_size, - PowerOfTwo::new(self.block_size).map_err(ANNError::log_index_error)?, + AlignedAllocator::new(PowerOfTwo::new(self.block_size).unwrap()), ) .map_err(ANNError::log_index_error)?; } @@ -220,7 +222,7 @@ mod disk_sector_graph_test { ) -> DiskSectorGraph<::AlignedReaderType> { DiskSectorGraph { - sectors_data: aligned_slice(512, PowerOfTwo::new(512).unwrap()).unwrap(), + sectors_data: Poly::broadcast(0u8, 512, AlignedAllocator::A512).unwrap(), sector_reader, cur_sector_idx: 0, num_nodes_per_sector, diff --git a/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs b/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs index 7b5647b87..b07fe8d1d 100644 --- a/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs +++ b/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs @@ -6,7 +6,10 @@ use std::{cmp::min, collections::VecDeque, sync::Arc, time::Instant}; use crate::data_model::GraphDataType; use diskann::{graph::AdjacencyList, utils::TryIntoVectorId, ANNError, ANNResult}; -use diskann_quantization::{alloc::aligned_slice, num::PowerOfTwo}; +use diskann_quantization::{ + alloc::{AlignedAllocator, Poly}, + num::PowerOfTwo, +}; use hashbrown::HashSet; use tracing::info; @@ -52,9 +55,10 @@ where // since this is the implementation for the disk vertex provider, there're only two kinds of sector lengths: 4096 and 512. // it's okay to hardcoded at this place. let buffer_len = GraphHeader::get_size().next_multiple_of(DEFAULT_DISK_SECTOR_LEN); - let mut read_buf = aligned_slice::( + let mut read_buf = Poly::broadcast( + 0u8, buffer_len, - PowerOfTwo::new(buffer_len).map_err(ANNError::log_index_error)?, + AlignedAllocator::new(PowerOfTwo::new(buffer_len).unwrap()), ) .map_err(ANNError::log_index_error)?; let aligned_read = AlignedRead::new(0_u64, &mut read_buf)?; diff --git a/diskann-disk/src/utils/aligned_file_reader/linux_aligned_file_reader.rs b/diskann-disk/src/utils/aligned_file_reader/linux_aligned_file_reader.rs index 9ad5dba16..b9c649b7c 100644 --- a/diskann-disk/src/utils/aligned_file_reader/linux_aligned_file_reader.rs +++ b/diskann-disk/src/utils/aligned_file_reader/linux_aligned_file_reader.rs @@ -135,7 +135,7 @@ mod tests { use serde::{Deserialize, Serialize}; use super::*; - use diskann_quantization::{alloc::aligned_slice, num::PowerOfTwo}; + use diskann_quantization::alloc::{AlignedAllocator, Poly}; pub const TEST_INDEX_PATH: &str = "../test_data/disk_index_misc/disk_index_siftsmall_learn_256pts_R4_L50_A1.2_aligned_reader_test.index"; pub const TRUTH_NODE_DATA_PATH: &str = @@ -171,7 +171,7 @@ mod tests { let read_length = 512; // adjust according to your logic let num_read = 10; let mut aligned_mem = - aligned_slice::(read_length * num_read, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_read, AlignedAllocator::A512).unwrap(); // create and add AlignedReads to the vector let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); @@ -215,7 +215,7 @@ mod tests { let read_length = 512; let num_read = MAX_IO_CONCURRENCY * 100; // The LinuxAlignedFileReader batches reads according to MAX_IO_CONCURRENCY. Make sure we have many batches to handle. let mut aligned_mem = - aligned_slice::(read_length * num_read, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_read, AlignedAllocator::A512).unwrap(); // create and add AlignedReads to the vector let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); @@ -255,7 +255,7 @@ mod tests { let read_length = 512; // adjust according to your logic let num_sector = 10; let mut aligned_mem = - aligned_slice::(read_length * num_sector, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_sector, AlignedAllocator::A512).unwrap(); // Each slice will be used as the buffer for a read request of a sector. let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); diff --git a/diskann-disk/src/utils/aligned_file_reader/storage_provider_aligned_file_reader.rs b/diskann-disk/src/utils/aligned_file_reader/storage_provider_aligned_file_reader.rs index 2e296eaf7..8bc6a7e54 100644 --- a/diskann-disk/src/utils/aligned_file_reader/storage_provider_aligned_file_reader.rs +++ b/diskann-disk/src/utils/aligned_file_reader/storage_provider_aligned_file_reader.rs @@ -54,7 +54,7 @@ mod tests { use diskann_utils::test_data_root; use super::*; - use diskann_quantization::{alloc::aligned_slice, num::PowerOfTwo}; + use diskann_quantization::alloc::{AlignedAllocator, Poly}; fn test_index_path() -> String { "/disk_index_misc/disk_index_siftsmall_learn_256pts_R4_L50_A1.2_aligned_reader_test.index" @@ -79,7 +79,7 @@ mod tests { let read_length = 512; let num_read = 10; let mut aligned_mem = - aligned_slice::(read_length * num_read, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_read, AlignedAllocator::A512).unwrap(); // create and add AlignedReads to the vector let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); diff --git a/diskann-disk/src/utils/aligned_file_reader/windows_aligned_file_reader.rs b/diskann-disk/src/utils/aligned_file_reader/windows_aligned_file_reader.rs index 0ac6887f5..468d8a1ff 100644 --- a/diskann-disk/src/utils/aligned_file_reader/windows_aligned_file_reader.rs +++ b/diskann-disk/src/utils/aligned_file_reader/windows_aligned_file_reader.rs @@ -123,7 +123,7 @@ mod tests { use super::*; use crate::utils::aligned_file_reader::AlignedRead; - use diskann_quantization::{alloc::aligned_slice, num::PowerOfTwo}; + use diskann_quantization::alloc::{AlignedAllocator, Poly}; fn test_index_path() -> String { test_data_root() @@ -170,7 +170,7 @@ mod tests { let read_length = 512; // adjust according to your logic let num_read = 10; let mut aligned_mem = - aligned_slice::(read_length * num_read, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_read, AlignedAllocator::A512).unwrap(); // create and add AlignedReads to the vector let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); @@ -209,7 +209,7 @@ mod tests { let read_length = DEFAULT_DISK_SECTOR_LEN; // adjust according to your logic let num_sector = 10; let mut aligned_mem = - aligned_slice::(read_length * num_sector, PowerOfTwo::new(512).unwrap()).unwrap(); + Poly::broadcast(0u8, read_length * num_sector, AlignedAllocator::A512).unwrap(); // Each slice will be used as the buffer for a read request of a sector. let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect(); diff --git a/diskann-quantization/src/alloc/aligned.rs b/diskann-quantization/src/alloc/aligned.rs index 3a3d3f6fd..40dea03ab 100644 --- a/diskann-quantization/src/alloc/aligned.rs +++ b/diskann-quantization/src/alloc/aligned.rs @@ -20,6 +20,19 @@ pub struct AlignedAllocator { } impl AlignedAllocator { + /// Aligned allocators for commonly specified boundaries in the codebase (4..4096) + pub const A4: Self = Self::new(PowerOfTwo::V4); + pub const A8: Self = Self::new(PowerOfTwo::V8); + pub const A16: Self = Self::new(PowerOfTwo::V16); + pub const A32: Self = Self::new(PowerOfTwo::V32); + pub const A64: Self = Self::new(PowerOfTwo::V64); + pub const A128: Self = Self::new(PowerOfTwo::V128); + pub const A256: Self = Self::new(PowerOfTwo::V256); + pub const A512: Self = Self::new(PowerOfTwo::V512); + pub const A1024: Self = Self::new(PowerOfTwo::V1024); + pub const A2048: Self = Self::new(PowerOfTwo::V2048); + pub const A4096: Self = Self::new(PowerOfTwo::V4096); + /// Construct a new allocator that uses the given alignment. #[inline] pub const fn new(alignment: PowerOfTwo) -> Self { diff --git a/diskann-quantization/src/alloc/aligned_slice.rs b/diskann-quantization/src/alloc/aligned_slice.rs deleted file mode 100644 index 4e15f114f..000000000 --- a/diskann-quantization/src/alloc/aligned_slice.rs +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT license. - */ - -use super::Poly; -use crate::alloc::{AlignedAllocator, AllocatorError}; - -use crate::num::PowerOfTwo; - -/// Type alias for an aligned, heap-allocated slice -/// -/// Shorthand for `Poly<[T], AlignedAllocator>` which is intended -/// for allocations requiring specific alignment (e.g. cache-line or disk-sector alignment) -pub type AlignedSlice = Poly<[T], AlignedAllocator>; - -/// Create a new [`AlignedSlice`] with the given capacity and alignment -/// initialized to `T::default()` -pub fn aligned_slice( - capacity: usize, - alignment: PowerOfTwo, -) -> Result, AllocatorError> { - let allocator = AlignedAllocator::new(alignment); - Poly::from_iter((0..capacity).map(|_| T::default()), allocator) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn aligned_slice_alignment_32() { - let data = aligned_slice::(1000, PowerOfTwo::new(32).unwrap()).unwrap(); - assert_eq!(data.len(), 1000); - assert_eq!(data.as_ptr() as usize % 32, 0); - } - - #[test] - fn aligned_slice_alignment_256() { - let data = aligned_slice::(500, PowerOfTwo::new(256).unwrap()).unwrap(); - assert_eq!(data.len(), 500); - assert_eq!(data.as_ptr() as usize % 256, 0); - } - - #[test] - fn aligned_slice_alignment_512() { - let data = aligned_slice::(4096, PowerOfTwo::new(512).unwrap()).unwrap(); - assert_eq!(data.len(), 4096); - assert_eq!(data.as_ptr() as usize % 512, 0); - } - - #[test] - fn aligned_slice_zero_length() { - // Zero-length aligned slices should succeed: `Poly::from_iter` - // special-cases empty iterators and returns an empty slice. - let data = aligned_slice::(0, PowerOfTwo::new(16).unwrap()).unwrap(); - assert!(data.is_empty()); - assert_eq!(data.len(), 0); - } - - #[test] - fn aligned_slice_default_initialized() { - let data = aligned_slice::(100, PowerOfTwo::new(64).unwrap()).unwrap(); - for &val in data.iter() { - assert_eq!(val, 0.0); - } - } - - #[test] - fn aligned_slice_deref_mut() { - let mut data = aligned_slice::(4, PowerOfTwo::new(32).unwrap()).unwrap(); - data[0] = 1.0; - data[1] = 2.0; - assert_eq!(&data[..2], &[1.0, 2.0]); - } -} diff --git a/diskann-quantization/src/alloc/mod.rs b/diskann-quantization/src/alloc/mod.rs index e4aaae317..da58f8b77 100644 --- a/diskann-quantization/src/alloc/mod.rs +++ b/diskann-quantization/src/alloc/mod.rs @@ -6,13 +6,11 @@ use std::{alloc::Layout, ptr::NonNull}; mod aligned; -mod aligned_slice; mod bump; mod poly; mod traits; pub use aligned::{AlignedAllocator, NotPowerOfTwo}; -pub use aligned_slice::{AlignedSlice, aligned_slice}; pub use bump::BumpAllocator; pub use poly::{CompoundError, Poly, TrustedIter, poly}; pub use traits::{Allocator, AllocatorCore, AllocatorError}; diff --git a/diskann-quantization/src/num.rs b/diskann-quantization/src/num.rs index 17a632ac1..e6eebd942 100644 --- a/diskann-quantization/src/num.rs +++ b/diskann-quantization/src/num.rs @@ -60,7 +60,146 @@ pub struct PowerOfTwo(NonZeroUsize); #[non_exhaustive] pub struct NotPowerOfTwo(usize); +/// PowerOfTwo constants for all valid exponents (0..64) +/// +/// # Safety +/// +/// 1 << N is a power of two for all N in 0..64. +#[allow(clippy::undocumented_unsafe_blocks)] impl PowerOfTwo { + pub const P0: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 0).unwrap()) }; + pub const P1: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 1).unwrap()) }; + pub const P2: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 2).unwrap()) }; + pub const P3: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 3).unwrap()) }; + pub const P4: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 4).unwrap()) }; + pub const P5: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 5).unwrap()) }; + pub const P6: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 6).unwrap()) }; + pub const P7: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 7).unwrap()) }; + pub const P8: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 8).unwrap()) }; + pub const P9: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 9).unwrap()) }; + pub const P10: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 10).unwrap()) }; + pub const P11: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 11).unwrap()) }; + pub const P12: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 12).unwrap()) }; + pub const P13: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 13).unwrap()) }; + pub const P14: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 14).unwrap()) }; + pub const P15: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 15).unwrap()) }; + pub const P16: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 16).unwrap()) }; + pub const P17: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 17).unwrap()) }; + pub const P18: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 18).unwrap()) }; + pub const P19: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 19).unwrap()) }; + pub const P20: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 20).unwrap()) }; + pub const P21: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 21).unwrap()) }; + pub const P22: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 22).unwrap()) }; + pub const P23: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 23).unwrap()) }; + pub const P24: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 24).unwrap()) }; + pub const P25: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 25).unwrap()) }; + pub const P26: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 26).unwrap()) }; + pub const P27: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 27).unwrap()) }; + pub const P28: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 28).unwrap()) }; + pub const P29: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 29).unwrap()) }; + pub const P30: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 30).unwrap()) }; + pub const P31: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 31).unwrap()) }; + pub const P32: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 32).unwrap()) }; + pub const P33: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 33).unwrap()) }; + pub const P34: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 34).unwrap()) }; + pub const P35: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 35).unwrap()) }; + pub const P36: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 36).unwrap()) }; + pub const P37: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 37).unwrap()) }; + pub const P38: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 38).unwrap()) }; + pub const P39: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 39).unwrap()) }; + pub const P40: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 40).unwrap()) }; + pub const P41: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 41).unwrap()) }; + pub const P42: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 42).unwrap()) }; + pub const P43: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 43).unwrap()) }; + pub const P44: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 44).unwrap()) }; + pub const P45: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 45).unwrap()) }; + pub const P46: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 46).unwrap()) }; + pub const P47: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 47).unwrap()) }; + pub const P48: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 48).unwrap()) }; + pub const P49: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 49).unwrap()) }; + pub const P50: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 50).unwrap()) }; + pub const P51: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 51).unwrap()) }; + pub const P52: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 52).unwrap()) }; + pub const P53: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 53).unwrap()) }; + pub const P54: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 54).unwrap()) }; + pub const P55: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 55).unwrap()) }; + pub const P56: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 56).unwrap()) }; + pub const P57: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 57).unwrap()) }; + pub const P58: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 58).unwrap()) }; + pub const P59: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 59).unwrap()) }; + pub const P60: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 60).unwrap()) }; + pub const P61: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 61).unwrap()) }; + pub const P62: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 62).unwrap()) }; + pub const P63: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 63).unwrap()) }; +} + +impl PowerOfTwo { + /// V values for some of the equivalent P(owersOfTwo)'s + pub const V1: Self = Self::P0; + pub const V2: Self = Self::P1; + pub const V4: Self = Self::P2; + pub const V8: Self = Self::P3; + pub const V16: Self = Self::P4; + pub const V32: Self = Self::P5; + pub const V64: Self = Self::P6; + pub const V128: Self = Self::P7; + pub const V256: Self = Self::P8; + pub const V512: Self = Self::P9; + pub const V1024: Self = Self::P10; + pub const V2048: Self = Self::P11; + pub const V4096: Self = Self::P12; + pub const V8192: Self = Self::P13; + pub const V16384: Self = Self::P14; + pub const V32768: Self = Self::P15; + pub const V65536: Self = Self::P16; + pub const V131072: Self = Self::P17; + pub const V262144: Self = Self::P18; + pub const V524288: Self = Self::P19; + pub const V1048576: Self = Self::P20; + pub const V2097152: Self = Self::P21; + pub const V4194304: Self = Self::P22; + pub const V8388608: Self = Self::P23; + pub const V16777216: Self = Self::P24; + pub const V33554432: Self = Self::P25; + pub const V67108864: Self = Self::P26; + pub const V134217728: Self = Self::P27; + pub const V268435456: Self = Self::P28; + pub const V536870912: Self = Self::P29; + pub const V1073741824: Self = Self::P30; + pub const V2147483648: Self = Self::P31; + pub const V4294967296: Self = Self::P32; + pub const V8589934592: Self = Self::P33; + pub const V17179869184: Self = Self::P34; + pub const V34359738368: Self = Self::P35; + pub const V68719476736: Self = Self::P36; + pub const V137438953472: Self = Self::P37; + pub const V274877906944: Self = Self::P38; + pub const V549755813888: Self = Self::P39; + pub const V1099511627776: Self = Self::P40; + pub const V2199023255552: Self = Self::P41; + pub const V4398046511104: Self = Self::P42; + pub const V8796093022208: Self = Self::P43; + pub const V17592186044416: Self = Self::P44; + pub const V35184372088832: Self = Self::P45; + pub const V70368744177664: Self = Self::P46; + pub const V140737488355328: Self = Self::P47; + pub const V281474976710656: Self = Self::P48; + pub const V562949953421312: Self = Self::P49; + pub const V1125899906842624: Self = Self::P50; + pub const V2251799813685248: Self = Self::P51; + pub const V4503599627370496: Self = Self::P52; + pub const V9007199254740992: Self = Self::P53; + pub const V18014398509481984: Self = Self::P54; + pub const V36028797018963968: Self = Self::P55; + pub const V72057594037927936: Self = Self::P56; + pub const V144115188075855872: Self = Self::P57; + pub const V288230376151711744: Self = Self::P58; + pub const V576460752303423488: Self = Self::P59; + pub const V1152921504606846976: Self = Self::P60; + pub const V2305843009213693952: Self = Self::P61; + pub const V4611686018427387904: Self = Self::P62; + pub const V9223372036854775808: Self = Self::P63; + /// Create a new `PowerOfTwo` if the given value is greater a power of two. pub const fn new(value: usize) -> Result { let v = match NonZeroUsize::new(value) { From afa3f89843319eb6fac83b6f5fbca6b52b220b98 Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Tue, 28 Apr 2026 08:52:43 -0700 Subject: [PATCH 2/4] add back error propagation and gate 64 bit definitions behind a config --- diskann-disk/src/search/pq/pq_scratch.rs | 10 ++++++---- .../src/search/provider/disk_sector_graph.rs | 10 +++++++--- .../provider/disk_vertex_provider_factory.rs | 2 +- diskann-quantization/src/num.rs | 20 +++++++++++++++++-- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/diskann-disk/src/search/pq/pq_scratch.rs b/diskann-disk/src/search/pq/pq_scratch.rs index e7c103724..0707fae3a 100644 --- a/diskann-disk/src/search/pq/pq_scratch.rs +++ b/diskann-disk/src/search/pq/pq_scratch.rs @@ -37,11 +37,13 @@ impl PQScratch { num_centers: usize, ) -> ANNResult { let aligned_pq_coord_scratch = - Poly::broadcast(0u8, graph_degree * num_pq_chunks, AlignedAllocator::A128).unwrap(); + Poly::broadcast(0u8, graph_degree * num_pq_chunks, AlignedAllocator::A128) + .map_err(ANNError::log_index_error)?; let aligned_pqtable_dist_scratch = - Poly::broadcast(0f32, num_centers * num_pq_chunks, AlignedAllocator::A128).unwrap(); - let aligned_dist_scratch = - Poly::broadcast(0f32, graph_degree, AlignedAllocator::A128).unwrap(); + Poly::broadcast(0f32, num_centers * num_pq_chunks, AlignedAllocator::A128) + .map_err(ANNError::log_index_error)?; + let aligned_dist_scratch = Poly::broadcast(0f32, graph_degree, AlignedAllocator::A128) + .map_err(ANNError::log_index_error)?; let rotated_query = vec![0.0f32; dim]; Ok(Self { diff --git a/diskann-disk/src/search/provider/disk_sector_graph.rs b/diskann-disk/src/search/provider/disk_sector_graph.rs index cc78e6c2d..def525712 100644 --- a/diskann-disk/src/search/provider/disk_sector_graph.rs +++ b/diskann-disk/src/search/provider/disk_sector_graph.rs @@ -79,9 +79,11 @@ impl DiskSectorGraph { sectors_data: Poly::broadcast( 0u8, max_n_batch_sector_read * num_sectors_per_node * block_size, - AlignedAllocator::new(PowerOfTwo::new(block_size).unwrap()), + AlignedAllocator::new( + PowerOfTwo::new(block_size).map_err(ANNError::log_index_error)?, + ), ) - .unwrap(), + .map_err(ANNError::log_index_error)?, cur_sector_idx: 0, num_nodes_per_sector, node_len, @@ -98,7 +100,9 @@ impl DiskSectorGraph { self.sectors_data = Poly::broadcast( 0u8, max_n_batch_sector_read * self.num_sectors_per_node * self.block_size, - AlignedAllocator::new(PowerOfTwo::new(self.block_size).unwrap()), + AlignedAllocator::new( + PowerOfTwo::new(self.block_size).map_err(ANNError::log_index_error)?, + ), ) .map_err(ANNError::log_index_error)?; } diff --git a/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs b/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs index b07fe8d1d..e5567c373 100644 --- a/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs +++ b/diskann-disk/src/search/provider/disk_vertex_provider_factory.rs @@ -58,7 +58,7 @@ where let mut read_buf = Poly::broadcast( 0u8, buffer_len, - AlignedAllocator::new(PowerOfTwo::new(buffer_len).unwrap()), + AlignedAllocator::new(PowerOfTwo::new(buffer_len).map_err(ANNError::log_index_error)?), ) .map_err(ANNError::log_index_error)?; let aligned_read = AlignedRead::new(0_u64, &mut read_buf)?; diff --git a/diskann-quantization/src/num.rs b/diskann-quantization/src/num.rs index e6eebd942..f813b47e1 100644 --- a/diskann-quantization/src/num.rs +++ b/diskann-quantization/src/num.rs @@ -60,11 +60,11 @@ pub struct PowerOfTwo(NonZeroUsize); #[non_exhaustive] pub struct NotPowerOfTwo(usize); -/// PowerOfTwo constants for all valid exponents (0..64) +/// PowerOfTwo constants for all valid exponents (0..Usize::BITS-1) for 32 bit architectures /// /// # Safety /// -/// 1 << N is a power of two for all N in 0..64. +/// 1 << N is a power of two for all N in 0..Usize::BITS-1. #[allow(clippy::undocumented_unsafe_blocks)] impl PowerOfTwo { pub const P0: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 0).unwrap()) }; @@ -99,6 +99,16 @@ impl PowerOfTwo { pub const P29: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 29).unwrap()) }; pub const P30: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 30).unwrap()) }; pub const P31: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 31).unwrap()) }; +} + +/// PowerOfTwo constants for all valid exponents (32..Usize::BITS-1) for 64 bit architectures +/// +/// # Safety +/// +/// 1 << N is a power of two for all N in 0..Usize::BITS-1. +#[cfg(target_pointer_width = "64")] +#[allow(clippy::undocumented_unsafe_blocks)] +impl PowerOfTwo { pub const P32: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 32).unwrap()) }; pub const P33: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 33).unwrap()) }; pub const P34: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 34).unwrap()) }; @@ -167,6 +177,10 @@ impl PowerOfTwo { pub const V536870912: Self = Self::P29; pub const V1073741824: Self = Self::P30; pub const V2147483648: Self = Self::P31; +} + +#[cfg(target_pointer_width = "64")] +impl PowerOfTwo { pub const V4294967296: Self = Self::P32; pub const V8589934592: Self = Self::P33; pub const V17179869184: Self = Self::P34; @@ -199,7 +213,9 @@ impl PowerOfTwo { pub const V2305843009213693952: Self = Self::P61; pub const V4611686018427387904: Self = Self::P62; pub const V9223372036854775808: Self = Self::P63; +} +impl PowerOfTwo { /// Create a new `PowerOfTwo` if the given value is greater a power of two. pub const fn new(value: usize) -> Result { let v = match NonZeroUsize::new(value) { From 9f81eaeaedd12e825487c29e9f0ec430eecff3e3 Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Tue, 28 Apr 2026 10:21:38 -0700 Subject: [PATCH 3/4] use macro instead --- diskann-quantization/src/num.rs | 225 ++++++++++++-------------------- 1 file changed, 80 insertions(+), 145 deletions(-) diff --git a/diskann-quantization/src/num.rs b/diskann-quantization/src/num.rs index f813b47e1..d91dfa977 100644 --- a/diskann-quantization/src/num.rs +++ b/diskann-quantization/src/num.rs @@ -60,159 +60,94 @@ pub struct PowerOfTwo(NonZeroUsize); #[non_exhaustive] pub struct NotPowerOfTwo(usize); -/// PowerOfTwo constants for all valid exponents (0..Usize::BITS-1) for 32 bit architectures -/// -/// # Safety -/// -/// 1 << N is a power of two for all N in 0..Usize::BITS-1. -#[allow(clippy::undocumented_unsafe_blocks)] -impl PowerOfTwo { - pub const P0: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 0).unwrap()) }; - pub const P1: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 1).unwrap()) }; - pub const P2: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 2).unwrap()) }; - pub const P3: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 3).unwrap()) }; - pub const P4: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 4).unwrap()) }; - pub const P5: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 5).unwrap()) }; - pub const P6: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 6).unwrap()) }; - pub const P7: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 7).unwrap()) }; - pub const P8: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 8).unwrap()) }; - pub const P9: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 9).unwrap()) }; - pub const P10: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 10).unwrap()) }; - pub const P11: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 11).unwrap()) }; - pub const P12: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 12).unwrap()) }; - pub const P13: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 13).unwrap()) }; - pub const P14: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 14).unwrap()) }; - pub const P15: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 15).unwrap()) }; - pub const P16: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 16).unwrap()) }; - pub const P17: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 17).unwrap()) }; - pub const P18: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 18).unwrap()) }; - pub const P19: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 19).unwrap()) }; - pub const P20: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 20).unwrap()) }; - pub const P21: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 21).unwrap()) }; - pub const P22: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 22).unwrap()) }; - pub const P23: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 23).unwrap()) }; - pub const P24: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 24).unwrap()) }; - pub const P25: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 25).unwrap()) }; - pub const P26: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 26).unwrap()) }; - pub const P27: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 27).unwrap()) }; - pub const P28: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 28).unwrap()) }; - pub const P29: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 29).unwrap()) }; - pub const P30: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 30).unwrap()) }; - pub const P31: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 31).unwrap()) }; -} +macro_rules! constants { + (($pow:ident, $value:ident) => $shift:literal) => { + pub const $pow: Self = match Self::new(1 << $shift) { + Ok(v) => v, + Err(_) => panic!("not a power of two"), + }; -/// PowerOfTwo constants for all valid exponents (32..Usize::BITS-1) for 64 bit architectures -/// -/// # Safety -/// -/// 1 << N is a power of two for all N in 0..Usize::BITS-1. -#[cfg(target_pointer_width = "64")] -#[allow(clippy::undocumented_unsafe_blocks)] -impl PowerOfTwo { - pub const P32: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 32).unwrap()) }; - pub const P33: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 33).unwrap()) }; - pub const P34: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 34).unwrap()) }; - pub const P35: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 35).unwrap()) }; - pub const P36: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 36).unwrap()) }; - pub const P37: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 37).unwrap()) }; - pub const P38: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 38).unwrap()) }; - pub const P39: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 39).unwrap()) }; - pub const P40: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 40).unwrap()) }; - pub const P41: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 41).unwrap()) }; - pub const P42: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 42).unwrap()) }; - pub const P43: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 43).unwrap()) }; - pub const P44: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 44).unwrap()) }; - pub const P45: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 45).unwrap()) }; - pub const P46: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 46).unwrap()) }; - pub const P47: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 47).unwrap()) }; - pub const P48: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 48).unwrap()) }; - pub const P49: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 49).unwrap()) }; - pub const P50: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 50).unwrap()) }; - pub const P51: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 51).unwrap()) }; - pub const P52: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 52).unwrap()) }; - pub const P53: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 53).unwrap()) }; - pub const P54: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 54).unwrap()) }; - pub const P55: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 55).unwrap()) }; - pub const P56: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 56).unwrap()) }; - pub const P57: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 57).unwrap()) }; - pub const P58: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 58).unwrap()) }; - pub const P59: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 59).unwrap()) }; - pub const P60: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 60).unwrap()) }; - pub const P61: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 61).unwrap()) }; - pub const P62: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 62).unwrap()) }; - pub const P63: Self = unsafe { Self::new_unchecked(NonZeroUsize::new(1 << 63).unwrap()) }; + pub const $value: Self = Self::$pow; + }; + ($(($pow:ident, $value:ident) => $shift:literal),+ $(,)?) => { + $(constants!(($pow, $value) => $shift);)+ + }; } impl PowerOfTwo { - /// V values for some of the equivalent P(owersOfTwo)'s - pub const V1: Self = Self::P0; - pub const V2: Self = Self::P1; - pub const V4: Self = Self::P2; - pub const V8: Self = Self::P3; - pub const V16: Self = Self::P4; - pub const V32: Self = Self::P5; - pub const V64: Self = Self::P6; - pub const V128: Self = Self::P7; - pub const V256: Self = Self::P8; - pub const V512: Self = Self::P9; - pub const V1024: Self = Self::P10; - pub const V2048: Self = Self::P11; - pub const V4096: Self = Self::P12; - pub const V8192: Self = Self::P13; - pub const V16384: Self = Self::P14; - pub const V32768: Self = Self::P15; - pub const V65536: Self = Self::P16; - pub const V131072: Self = Self::P17; - pub const V262144: Self = Self::P18; - pub const V524288: Self = Self::P19; - pub const V1048576: Self = Self::P20; - pub const V2097152: Self = Self::P21; - pub const V4194304: Self = Self::P22; - pub const V8388608: Self = Self::P23; - pub const V16777216: Self = Self::P24; - pub const V33554432: Self = Self::P25; - pub const V67108864: Self = Self::P26; - pub const V134217728: Self = Self::P27; - pub const V268435456: Self = Self::P28; - pub const V536870912: Self = Self::P29; - pub const V1073741824: Self = Self::P30; - pub const V2147483648: Self = Self::P31; + constants! { + (P0, V1) => 0, + (P1, V2) => 1, + (P2, V4) => 2, + (P3, V8) => 3, + (P4, V16) => 4, + (P5, V32) => 5, + (P6, V64) => 6, + (P7, V128) => 7, + (P8, V256) => 8, + (P9, V512) => 9, + (P10, V1024) => 10, + (P11, V2048) => 11, + (P12, V4096) => 12, + (P13, V8192) => 13, + (P14, V16384) => 14, + (P15, V32768) => 15, + (P16, V65536) => 16, + (P17, V131072) => 17, + (P18, V262144) => 18, + (P19, V524288) => 19, + (P20, V1048576) => 20, + (P21, V2097152) => 21, + (P22, V4194304) => 22, + (P23, V8388608) => 23, + (P24, V16777216) => 24, + (P25, V33554432) => 25, + (P26, V67108864) => 26, + (P27, V134217728) => 27, + (P28, V268435456) => 28, + (P29, V536870912) => 29, + (P30, V1073741824) => 30, + (P31, V2147483648) => 31, + } } #[cfg(target_pointer_width = "64")] +#[allow(clippy::undocumented_unsafe_blocks)] impl PowerOfTwo { - pub const V4294967296: Self = Self::P32; - pub const V8589934592: Self = Self::P33; - pub const V17179869184: Self = Self::P34; - pub const V34359738368: Self = Self::P35; - pub const V68719476736: Self = Self::P36; - pub const V137438953472: Self = Self::P37; - pub const V274877906944: Self = Self::P38; - pub const V549755813888: Self = Self::P39; - pub const V1099511627776: Self = Self::P40; - pub const V2199023255552: Self = Self::P41; - pub const V4398046511104: Self = Self::P42; - pub const V8796093022208: Self = Self::P43; - pub const V17592186044416: Self = Self::P44; - pub const V35184372088832: Self = Self::P45; - pub const V70368744177664: Self = Self::P46; - pub const V140737488355328: Self = Self::P47; - pub const V281474976710656: Self = Self::P48; - pub const V562949953421312: Self = Self::P49; - pub const V1125899906842624: Self = Self::P50; - pub const V2251799813685248: Self = Self::P51; - pub const V4503599627370496: Self = Self::P52; - pub const V9007199254740992: Self = Self::P53; - pub const V18014398509481984: Self = Self::P54; - pub const V36028797018963968: Self = Self::P55; - pub const V72057594037927936: Self = Self::P56; - pub const V144115188075855872: Self = Self::P57; - pub const V288230376151711744: Self = Self::P58; - pub const V576460752303423488: Self = Self::P59; - pub const V1152921504606846976: Self = Self::P60; - pub const V2305843009213693952: Self = Self::P61; - pub const V4611686018427387904: Self = Self::P62; - pub const V9223372036854775808: Self = Self::P63; + constants! { + (P32, V4294967296) => 32, + (P33, V8589934592) => 33, + (P34, V17179869184) => 34, + (P35, V34359738368) => 35, + (P36, V68719476736) => 36, + (P37, V137438953472) => 37, + (P38, V274877906944) => 38, + (P39, V549755813888) => 39, + (P40, V1099511627776) => 40, + (P41, V2199023255552) => 41, + (P42, V4398046511104) => 42, + (P43, V8796093022208) => 43, + (P44, V17592186044416) => 44, + (P45, V35184372088832) => 45, + (P46, V70368744177664) => 46, + (P47, V140737488355328) => 47, + (P48, V281474976710656) => 48, + (P49, V562949953421312) => 49, + (P50, V1125899906842624) => 50, + (P51, V2251799813685248) => 51, + (P52, V4503599627370496) => 52, + (P53, V9007199254740992) => 53, + (P54, V18014398509481984) => 54, + (P55, V36028797018963968) => 55, + (P56, V72057594037927936) => 56, + (P57, V144115188075855872) => 57, + (P58, V288230376151711744) => 58, + (P59, V576460752303423488) => 59, + (P60, V1152921504606846976) => 60, + (P61, V2305843009213693952) => 61, + (P62, V4611686018427387904) => 62, + (P63, V9223372036854775808) => 63, + } } impl PowerOfTwo { From 4a2b598e8a99d3a4006ab9cf0707dd3838ce0a46 Mon Sep 17 00:00:00 2001 From: Jordan Maples Date: Tue, 28 Apr 2026 10:35:24 -0700 Subject: [PATCH 4/4] remove unneeded clippy suppression --- diskann-quantization/src/num.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/diskann-quantization/src/num.rs b/diskann-quantization/src/num.rs index d91dfa977..7881c45e7 100644 --- a/diskann-quantization/src/num.rs +++ b/diskann-quantization/src/num.rs @@ -112,7 +112,6 @@ impl PowerOfTwo { } #[cfg(target_pointer_width = "64")] -#[allow(clippy::undocumented_unsafe_blocks)] impl PowerOfTwo { constants! { (P32, V4294967296) => 32,