Encode f32 embeddings using spherical coordinate transformation + lz4. Input: flat array of f32 values, `vectors * dims` total elements. Each consecutive `dims` values form one embedding vector.
(data: &[f32], dims: usize, vectors: usize)
| 26 | /// Input: flat array of f32 values, `vectors * dims` total elements. |
| 27 | /// Each consecutive `dims` values form one embedding vector. |
| 28 | pub fn encode(data: &[f32], dims: usize, vectors: usize) -> Result<Vec<u8>, CodecError> { |
| 29 | if data.is_empty() || dims == 0 { |
| 30 | return Ok(build_header(dims as u32, 0, 0, &[])); |
| 31 | } |
| 32 | |
| 33 | if data.len() != vectors * dims { |
| 34 | return Err(CodecError::Corrupt { |
| 35 | detail: format!( |
| 36 | "expected {} elements ({vectors} vectors × {dims} dims), got {}", |
| 37 | vectors * dims, |
| 38 | data.len() |
| 39 | ), |
| 40 | }); |
| 41 | } |
| 42 | |
| 43 | // Transform each vector from Cartesian to spherical coordinates. |
| 44 | let mut transformed = Vec::with_capacity(data.len()); |
| 45 | for v in 0..vectors { |
| 46 | let start = v * dims; |
| 47 | let vec_data = &data[start..start + dims]; |
| 48 | let spherical = cartesian_to_spherical(vec_data); |
| 49 | transformed.extend_from_slice(&spherical); |
| 50 | } |
| 51 | |
| 52 | // Convert f32 to bytes and compress with lz4. |
| 53 | let raw_bytes: Vec<u8> = transformed.iter().flat_map(|f| f.to_le_bytes()).collect(); |
| 54 | let compressed = crate::lz4::encode(&raw_bytes); |
| 55 | |
| 56 | Ok(build_header( |
| 57 | dims as u32, |
| 58 | vectors as u32, |
| 59 | 1, // spherical transform |
| 60 | &compressed, |
| 61 | )) |
| 62 | } |
| 63 | |
| 64 | /// Encode f32 embeddings without transformation (raw + lz4). |
| 65 | /// |