MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / encode_inner

Method encode_inner

nodedb-codec/src/vector_quant/rabitq.rs:217–280  ·  view source on GitHub ↗

Encode a single vector into a [`UnifiedQuantizedVector`] with `QuantMode::RaBitQ`. The header fields populated are: - `global_scale` = `residual_norm` (‖v−c‖); both store the same value so that consumers that use either field without context still have the magnitude available. - `residual_norm` = ‖v−c‖. - `dot_quantized` = ⟨residual, dequantised_sign_vector⟩ / ‖v−c‖; used for IP-bias correction w

(&self, v: &[f32])

Source from the content-addressed store, hash-verified

215 /// - `dot_quantized` = ⟨residual, dequantised_sign_vector⟩ / ‖v−c‖;
216 /// used for IP-bias correction when `bias_correct = true`.
217 fn encode_inner(&self, v: &[f32]) -> UnifiedQuantizedVector {
218 let dim = self.dim;
219
220 // Step 1: residual = v - centroid
221 let residual: Vec<f32> = v
222 .iter()
223 .zip(self.centroid.iter())
224 .map(|(&vi, &ci)| vi - ci)
225 .collect();
226
227 // Step 2: ‖residual‖
228 let residual_norm = residual.iter().map(|x| x * x).sum::<f32>().sqrt();
229
230 // Step 3: rotate
231 let rotated = self.apply_rotation(&residual);
232
233 // Step 4: sign-pack → 1-bit code
234 let packed = sign_pack(&rotated, dim);
235
236 // Step 5: compute dot_quantized = ⟨residual, R⁻¹·sign(rotated)⟩ / ‖residual‖
237 // Inverse rotation of the sign vector, then dot with original residual.
238 let signs_fp = sign_unpack(&packed, dim);
239 // Inverse WHT rotation: apply WHT again then re-apply D⁻¹ = D (since D² = I).
240 let pow2 = next_pow2(dim);
241 let mut sign_buf = vec![0.0f32; pow2];
242 for (i, &s) in signs_fp.iter().enumerate() {
243 sign_buf[i] = s;
244 }
245 wht_inplace(&mut sign_buf);
246 // Re-apply signed diagonal (D is its own inverse since flips are ±1)
247 let mut seed = self.rotation_seed;
248 #[allow(clippy::needless_range_loop)]
249 for i in 0..dim {
250 let flip = if xorshift64(&mut seed) & 1 == 0 {
251 1.0f32
252 } else {
253 -1.0f32
254 };
255 sign_buf[i] *= flip;
256 }
257 let dot_raw: f32 = residual
258 .iter()
259 .zip(sign_buf.iter().take(dim))
260 .map(|(&r, &s)| r * s)
261 .sum();
262 let dot_quantized = if residual_norm > 0.0 {
263 dot_raw / residual_norm
264 } else {
265 0.0
266 };
267
268 let header = QuantHeader {
269 quant_mode: QuantMode::RaBitQ as u16,
270 dim: dim as u16,
271 global_scale: residual_norm,
272 residual_norm,
273 dot_quantized,
274 outlier_bitmask: 0,

Callers 1

encodeMethod · 0.45

Calls 11

sign_packFunction · 0.85
sign_unpackFunction · 0.85
next_pow2Function · 0.85
wht_inplaceFunction · 0.85
xorshift64Function · 0.85
collectMethod · 0.80
sumMethod · 0.80
iterMethod · 0.45
apply_rotationMethod · 0.45
takeMethod · 0.45
expectMethod · 0.45

Tested by

no test coverage detected