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