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