1use crate::{
2 vector::vector_types::{Vector, VectorType},
3 Result,
4};
5
6pub fn vector_convert(v: Vector, target_type: VectorType) -> Result<Vector> {
7 if v.vector_type == target_type {
8 return Ok(v);
9 }
10 match (v.vector_type, target_type) {
11 (VectorType::Float32Dense, VectorType::Float64Dense) => Ok(Vector::from_f64(
12 v.as_f32_slice().iter().map(|&x| x as f64).collect(),
13 )),
14 (VectorType::Float64Dense, VectorType::Float32Dense) => Ok(Vector::from_f32(
15 v.as_f64_slice().iter().map(|&x| x as f32).collect(),
16 )),
17 (VectorType::Float32Dense, VectorType::Float32Sparse) => {
18 let (mut idx, mut values) = (Vec::new(), Vec::new());
19 for (i, &value) in v.as_f32_slice().iter().enumerate() {
20 if value == 0.0 {
21 continue;
22 }
23 idx.push(i as u32);
24 values.push(value);
25 }
26 Ok(Vector::from_f32_sparse(v.dims, values, idx))
27 }
28 (VectorType::Float64Dense, VectorType::Float32Sparse) => {
29 let (mut idx, mut values) = (Vec::new(), Vec::new());
30 for (i, &value) in v.as_f64_slice().iter().enumerate() {
31 if value == 0.0 {
32 continue;
33 }
34 idx.push(i as u32);
35 values.push(value as f32);
36 }
37 Ok(Vector::from_f32_sparse(v.dims, values, idx))
38 }
39 (VectorType::Float32Sparse, VectorType::Float32Dense) => {
40 let sparse = v.as_f32_sparse();
41 let mut data = vec![0f32; v.dims];
42 for (&i, &value) in sparse.idx.iter().zip(sparse.values.iter()) {
43 data[i as usize] = value;
44 }
45 Ok(Vector::from_f32(data))
46 }
47 (VectorType::Float32Sparse, VectorType::Float64Dense) => {
48 let sparse = v.as_f32_sparse();
49 let mut data = vec![0f64; v.dims];
50 for (&i, &value) in sparse.idx.iter().zip(sparse.values.iter()) {
51 data[i as usize] = value as f64;
52 }
53 Ok(Vector::from_f64(data))
54 }
55 (VectorType::Float32Dense, VectorType::Float1Bit) => {
57 let dims = v.dims;
58 let byte_count = dims.div_ceil(8);
59 let mut bits = vec![0u8; byte_count];
60 for (i, &val) in v.as_f32_slice().iter().enumerate() {
61 if val > 0.0 {
62 bits[i / 8] |= 1 << (i & 7);
63 }
64 }
65 Ok(Vector::from_1bit(dims, bits))
66 }
67 (VectorType::Float64Dense, VectorType::Float1Bit) => {
68 let dims = v.dims;
69 let byte_count = dims.div_ceil(8);
70 let mut bits = vec![0u8; byte_count];
71 for (i, &val) in v.as_f64_slice().iter().enumerate() {
72 if val > 0.0 {
73 bits[i / 8] |= 1 << (i & 7);
74 }
75 }
76 Ok(Vector::from_1bit(dims, bits))
77 }
78 (VectorType::Float1Bit, VectorType::Float32Dense) => {
79 let data = v.as_1bit_data();
80 let floats: Vec<f32> = (0..v.dims)
81 .map(|i| {
82 if (data[i / 8] >> (i & 7)) & 1 == 1 {
83 1.0
84 } else {
85 -1.0
86 }
87 })
88 .collect();
89 Ok(Vector::from_f32(floats))
90 }
91 (VectorType::Float1Bit, VectorType::Float64Dense) => {
92 let data = v.as_1bit_data();
93 let floats: Vec<f64> = (0..v.dims)
94 .map(|i| {
95 if (data[i / 8] >> (i & 7)) & 1 == 1 {
96 1.0
97 } else {
98 -1.0
99 }
100 })
101 .collect();
102 Ok(Vector::from_f64(floats))
103 }
104 (VectorType::Float32Dense, VectorType::Float8) => {
106 convert_floats_to_f8(v.as_f32_slice().iter().copied(), v.dims)
107 }
108 (VectorType::Float64Dense, VectorType::Float8) => {
109 convert_floats_to_f8(v.as_f64_slice().iter().map(|&x| x as f32), v.dims)
110 }
111 (VectorType::Float8, VectorType::Float32Dense) => {
112 let (quantized, alpha, shift) = v.as_f8_data();
113 let floats: Vec<f32> = quantized
114 .iter()
115 .map(|&q| alpha * q as f32 + shift)
116 .collect();
117 Ok(Vector::from_f32(floats))
118 }
119 (VectorType::Float8, VectorType::Float64Dense) => {
120 let (quantized, alpha, shift) = v.as_f8_data();
121 let floats: Vec<f64> = quantized
122 .iter()
123 .map(|&q| alpha as f64 * q as f64 + shift as f64)
124 .collect();
125 Ok(Vector::from_f64(floats))
126 }
127 (VectorType::Float1Bit, VectorType::Float8) => {
129 let f32_vec = vector_convert(v, VectorType::Float32Dense)?;
130 vector_convert(f32_vec, VectorType::Float8)
131 }
132 (VectorType::Float8, VectorType::Float1Bit) => {
133 let f32_vec = vector_convert(v, VectorType::Float32Dense)?;
134 vector_convert(f32_vec, VectorType::Float1Bit)
135 }
136 (VectorType::Float1Bit, VectorType::Float32Sparse)
137 | (VectorType::Float8, VectorType::Float32Sparse)
138 | (VectorType::Float32Sparse, VectorType::Float1Bit)
139 | (VectorType::Float32Sparse, VectorType::Float8) => {
140 let f32_vec = vector_convert(v, VectorType::Float32Dense)?;
141 vector_convert(f32_vec, target_type)
142 }
143 _ => unreachable!(
144 "unexpected conversion: {:?} -> {:?}",
145 v.vector_type, target_type
146 ),
147 }
148}
149
150fn convert_floats_to_f8(
151 values: impl Iterator<Item = f32> + Clone,
152 dims: usize,
153) -> Result<Vector<'static>> {
154 if dims == 0 {
155 return Ok(Vector::from_f8(0, Vec::new(), 0.0, 0.0));
156 }
157 let mut min_val = f32::INFINITY;
158 let mut max_val = f32::NEG_INFINITY;
159 for val in values.clone() {
160 if val < min_val {
161 min_val = val;
162 }
163 if val > max_val {
164 max_val = val;
165 }
166 }
167 let alpha = (max_val - min_val) / 255.0;
168 let shift = min_val;
169 let mut quantized = Vec::with_capacity(dims);
170 for val in values {
171 let q = if alpha == 0.0 {
172 0u8
173 } else {
174 let v = (val - shift) / alpha + 0.5;
175 (v as i32).clamp(0, 255) as u8
176 };
177 quantized.push(q);
178 }
179 Ok(Vector::from_f8(dims, quantized, alpha, shift))
180}
181
182#[cfg(clt_turso_tests)]
183mod tests {
184 use crate::vector::{
185 operations::convert::vector_convert,
186 vector_types::{tests::ArbitraryVector, Vector, VectorType},
187 };
188 use quickcheck_macros::quickcheck;
189
190 fn concat<const N: usize>(data: &[[u8; N]]) -> Vec<u8> {
191 data.iter().flatten().cloned().collect::<Vec<u8>>()
192 }
193
194 fn assert_vectors(v1: &Vector, v2: &Vector) {
195 assert_eq!(v1.vector_type, v2.vector_type);
196 assert_eq!(v1.dims, v2.dims);
197 assert_eq!(v1.bin_data(), v2.bin_data());
198 }
199
200 fn clone_vector(v: &Vector) -> Vector<'static> {
201 Vector {
202 vector_type: v.vector_type,
203 dims: v.dims,
204 owned: Some(v.bin_data().to_vec()),
205 refer: None,
206 }
207 }
208
209 #[test]
210 pub fn test_vector_convert() {
211 let vf32 = Vector {
212 vector_type: VectorType::Float32Dense,
213 dims: 3,
214 owned: Some(concat(&[
215 1.0f32.to_le_bytes(),
216 0.0f32.to_le_bytes(),
217 2.0f32.to_le_bytes(),
218 ])),
219 refer: None,
220 };
221 let vf64 = Vector {
222 vector_type: VectorType::Float64Dense,
223 dims: 3,
224 owned: Some(concat(&[
225 1.0f64.to_le_bytes(),
226 0.0f64.to_le_bytes(),
227 2.0f64.to_le_bytes(),
228 ])),
229 refer: None,
230 };
231 let vf32_sparse = Vector {
232 vector_type: VectorType::Float32Sparse,
233 dims: 3,
234 owned: Some(concat(&[
235 1.0f32.to_le_bytes(),
236 2.0f32.to_le_bytes(),
237 0u32.to_le_bytes(),
238 2u32.to_le_bytes(),
239 ])),
240 refer: None,
241 };
242
243 let vectors = [vf32, vf64, vf32_sparse];
244 for v1 in &vectors {
245 for v2 in &vectors {
246 println!("{:?} -> {:?}", v1.vector_type, v2.vector_type);
247 let v_copy = Vector {
248 vector_type: v1.vector_type,
249 dims: v1.dims,
250 owned: v1.owned.clone(),
251 refer: None,
252 };
253 assert_vectors(&vector_convert(v_copy, v2.vector_type).unwrap(), v2);
254 }
255 }
256 }
257
258 #[test]
260 pub fn test_vector_convert_all_types() {
261 let source = Vector::from_f32(vec![1.0, 0.5, 2.0]);
262
263 let all_types = [
264 VectorType::Float32Dense,
265 VectorType::Float64Dense,
266 VectorType::Float32Sparse,
267 VectorType::Float1Bit,
268 VectorType::Float8,
269 ];
270
271 for &src_type in &all_types {
272 let src = vector_convert(clone_vector(&source), src_type).unwrap();
273 for &dst_type in &all_types {
274 let result = vector_convert(clone_vector(&src), dst_type);
275 assert!(
276 result.is_ok(),
277 "conversion {:?} -> {:?} failed: {:?}",
278 src_type,
279 dst_type,
280 result.err()
281 );
282 let converted = result.unwrap();
283 assert_eq!(converted.vector_type, dst_type);
284 assert_eq!(converted.dims, 3);
285 }
286 }
287 }
288
289 #[test]
291 pub fn test_vector_convert_lossless_roundtrip() {
292 let vf32 = Vector::from_f32(vec![1.0, 0.0, 2.0]);
293
294 let via_f64 = vector_convert(
296 vector_convert(clone_vector(&vf32), VectorType::Float64Dense).unwrap(),
297 VectorType::Float32Dense,
298 )
299 .unwrap();
300 assert_eq!(vf32.bin_data(), via_f64.bin_data());
301
302 let via_sparse = vector_convert(
304 vector_convert(clone_vector(&vf32), VectorType::Float32Sparse).unwrap(),
305 VectorType::Float32Dense,
306 )
307 .unwrap();
308 assert_eq!(vf32.bin_data(), via_sparse.bin_data());
309 }
310
311 #[quickcheck]
313 fn prop_vector_convert_1bit_roundtrip(v: ArbitraryVector<100>) -> bool {
314 let v_f32 = vector_convert(v.into(), VectorType::Float32Dense).unwrap();
315 let orig_slice = v_f32.as_f32_slice().to_vec();
316 let v_1bit = vector_convert(v_f32, VectorType::Float1Bit).unwrap();
317 let v_back = vector_convert(v_1bit, VectorType::Float32Dense).unwrap();
318 let back_slice = v_back.as_f32_slice();
319
320 for i in 0..100 {
321 let expected = if orig_slice[i] > 0.0 { 1.0f32 } else { -1.0f32 };
322 if back_slice[i] != expected {
323 return false;
324 }
325 }
326 true
327 }
328
329 #[quickcheck]
331 fn prop_vector_convert_f8_roundtrip(v: ArbitraryVector<100>) -> bool {
332 let v_f32 = vector_convert(v.into(), VectorType::Float32Dense).unwrap();
333 let orig_slice = v_f32.as_f32_slice().to_vec();
334 let v_f8 = vector_convert(v_f32, VectorType::Float8).unwrap();
335 let v_back = vector_convert(v_f8, VectorType::Float32Dense).unwrap();
336 let back_slice = v_back.as_f32_slice();
337
338 let min_val = orig_slice.iter().cloned().fold(f32::INFINITY, f32::min);
339 let max_val = orig_slice.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
340 let alpha = (max_val - min_val) / 255.0;
341 let tolerance = alpha + 1e-6;
342
343 for i in 0..100 {
344 if (orig_slice[i] - back_slice[i]).abs() > tolerance {
345 return false;
346 }
347 }
348 true
349 }
350
351 #[quickcheck]
353 fn prop_vector_convert_all_pairs(v: ArbitraryVector<16>) -> bool {
354 let v: Vector = v.into();
355 let all_types = [
356 VectorType::Float32Dense,
357 VectorType::Float64Dense,
358 VectorType::Float32Sparse,
359 VectorType::Float1Bit,
360 VectorType::Float8,
361 ];
362
363 for &target_type in &all_types {
364 if vector_convert(clone_vector(&v), target_type).is_err() {
365 return false;
366 }
367 }
368 true
369 }
370
371 #[test]
372 fn test_vector_convert_empty_to_f8() {
373 let empty_f32 = Vector::from_f32(vec![]);
374 let f8 = vector_convert(empty_f32, VectorType::Float8).unwrap();
375 assert_eq!(f8.dims, 0);
376 assert_eq!(f8.vector_type, VectorType::Float8);
377 let (quantized, alpha, shift) = f8.as_f8_data();
378 assert!(quantized.is_empty());
379 assert_eq!(alpha, 0.0);
380 assert_eq!(shift, 0.0);
381 }
382
383 #[test]
384 fn test_vector_convert_empty_f8_to_f32() {
385 let empty_f8 = Vector::from_f8(0, Vec::new(), 0.0, 0.0);
386 let f32_vec = vector_convert(empty_f8, VectorType::Float32Dense).unwrap();
387 assert_eq!(f32_vec.dims, 0);
388 assert!(f32_vec.as_f32_slice().is_empty());
389 }
390}