diskann_quantization/multi_vector/distance/
max_sim.rs1use thiserror::Error;
7
8#[derive(Clone, Debug, Copy, Error)]
10pub enum MaxSimError {
11 #[error("Trying to access score in index {0} for output of size {1}")]
12 IndexOutOfBounds(usize, usize),
13 #[error("Invalid buffer length {0} for query size {1}")]
14 InvalidBufferLength(usize, usize),
15}
16
17#[derive(Debug)]
38pub struct MaxSim<'a> {
39 pub(crate) scores: &'a mut [f32],
40}
41
42impl<'a> MaxSim<'a> {
43 pub fn new(scores: &'a mut [f32]) -> Self {
45 Self { scores }
46 }
47
48 #[inline]
50 pub fn size(&self) -> usize {
51 self.scores.len()
52 }
53
54 #[inline(always)]
56 pub fn get(&self, i: usize) -> Result<f32, MaxSimError> {
57 self.scores
58 .get(i)
59 .copied()
60 .ok_or_else(|| MaxSimError::IndexOutOfBounds(i, self.size()))
61 }
62
63 #[inline(always)]
65 pub fn set(&mut self, i: usize, x: f32) -> Result<(), MaxSimError> {
66 let size = self.size();
67
68 let s = self
69 .scores
70 .get_mut(i)
71 .ok_or(MaxSimError::IndexOutOfBounds(i, size))?;
72
73 *s = x;
74 Ok(())
75 }
76
77 pub fn scores_mut(&mut self) -> &mut [f32] {
82 self.scores
83 }
84}
85
86#[derive(Debug, Clone, Copy)]
101pub struct Chamfer;
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 struct TestFixture {
109 buffer: Vec<f32>,
110 }
111
112 impl TestFixture {
113 fn new(size: usize) -> Self {
114 Self {
115 buffer: vec![0.0; size],
116 }
117 }
118
119 fn with_values(values: &[f32]) -> Self {
120 Self {
121 buffer: values.to_vec(),
122 }
123 }
124
125 fn max_sim(&mut self) -> MaxSim<'_> {
126 MaxSim::new(&mut self.buffer)
127 }
128 }
129
130 mod max_sim_new {
131 use super::*;
132
133 #[test]
134 fn returns_correct_size() {
135 let sizes = [1, 2, 5, 100, 1000];
136 for size in sizes {
137 let mut fixture = TestFixture::new(size);
138 let mut max_sim = fixture.max_sim();
139 assert_eq!(max_sim.size(), size, "size mismatch for buffer of {}", size);
140
141 let scores = max_sim.scores_mut();
142 assert_eq!(scores.len(), max_sim.size());
143 }
144 }
145 }
146
147 mod max_sim_get {
148 use super::*;
149
150 #[test]
151 fn returns_value_at_valid_index() {
152 let mut fixture = TestFixture::with_values(&[1.0, 2.0, 3.0]);
153 let max_sim = fixture.max_sim();
154
155 assert_eq!(max_sim.get(0).unwrap(), 1.0);
156 assert_eq!(max_sim.get(1).unwrap(), 2.0);
157 assert_eq!(max_sim.get(2).unwrap(), 3.0);
158 }
159
160 #[test]
161 fn fails_at_out_of_bounds_index() {
162 let mut fixture = TestFixture::new(3);
163 let max_sim = fixture.max_sim();
164
165 let result = max_sim.get(3);
166 assert!(matches!(result, Err(MaxSimError::IndexOutOfBounds(3, 3))));
167
168 let result = max_sim.get(100);
169 assert!(matches!(result, Err(MaxSimError::IndexOutOfBounds(100, 3))));
170 }
171 }
172
173 mod max_sim_set {
174 use super::*;
175
176 #[test]
177 fn sets_value_at_valid_index() {
178 let mut fixture = TestFixture::new(3);
179 let mut max_sim = fixture.max_sim();
180
181 max_sim.set(0, 10.0).unwrap();
182 max_sim.set(1, 20.0).unwrap();
183 max_sim.set(2, 30.0).unwrap();
184
185 assert_eq!(max_sim.get(0).unwrap(), 10.0);
186 assert_eq!(max_sim.get(1).unwrap(), 20.0);
187 assert_eq!(max_sim.get(2).unwrap(), 30.0);
188 }
189
190 #[test]
191 fn fails_at_out_of_bounds_index() {
192 let mut fixture = TestFixture::new(3);
193 let mut max_sim = fixture.max_sim();
194
195 let result = max_sim.set(3, 999.0);
196 assert!(matches!(result, Err(MaxSimError::IndexOutOfBounds(3, 3))));
197 }
198
199 #[test]
200 fn overwrites_existing_value() {
201 let mut fixture = TestFixture::with_values(&[1.0, 2.0, 3.0]);
202 let mut max_sim = fixture.max_sim();
203
204 max_sim.set(1, 99.0).unwrap();
205
206 assert_eq!(max_sim.get(0).unwrap(), 1.0); assert_eq!(max_sim.get(1).unwrap(), 99.0); assert_eq!(max_sim.get(2).unwrap(), 3.0); }
210
211 #[test]
212 fn handles_special_float_values() {
213 let mut fixture = TestFixture::new(4);
214 let mut max_sim = fixture.max_sim();
215
216 max_sim.set(0, f32::INFINITY).unwrap();
217 max_sim.set(1, f32::NEG_INFINITY).unwrap();
218 max_sim.set(2, f32::NAN).unwrap();
219 max_sim.set(3, -0.0).unwrap();
220
221 assert_eq!(max_sim.get(0).unwrap(), f32::INFINITY);
222 assert_eq!(max_sim.get(1).unwrap(), f32::NEG_INFINITY);
223 assert!(max_sim.get(2).unwrap().is_nan());
224 assert!(max_sim.get(3).unwrap().is_sign_negative());
225 }
226
227 #[test]
228 fn writes_through_to_underlying_buffer() {
229 let mut buffer = vec![0.0f32; 3];
230 {
231 let mut max_sim = MaxSim::new(&mut buffer);
232 max_sim.set(0, 1.0).unwrap();
233 max_sim.set(1, 2.0).unwrap();
234 }
235 assert_eq!(buffer, vec![1.0, 2.0, 0.0]);
237 }
238 }
239}