Skip to main content

qualia_core_db/tensor/
bake_pipeline.rs

1//! Cold-path NQuin → Tensor10D baking (ingest / encode tier).
2//!
3//! Hot-path queries read baked SOA volumes; this module runs at ingest only.
4
5use crate::{q_hash, NQuin};
6
7use super::Tensor10D;
8
9pub const PRED_GEO_VERTEX: u64 = q_hash("geo:hasVertex");
10/// Bake-time link to mmap STFT/CQT sidecar (`spectral/audio/{hash}.bin`).
11pub const PRED_HAS_SPECTRAL_SHEET: u64 = q_hash("q42:hasSpectralSheet");
12
13/// Relative sidecar path under storage root — zero-heap (`spectral/audio/{hash:016x}.bin`).
14pub fn audio_sidecar_relpath(content_hash: u64, out: &mut [u8]) -> usize {
15    const PREFIX: &[u8] = b"spectral/audio/";
16    const SUFFIX: &[u8] = b".bin";
17    let hex = format_hash16(content_hash);
18    let need = PREFIX.len() + 16 + SUFFIX.len();
19    if out.len() < need {
20        return 0;
21    }
22    out[..PREFIX.len()].copy_from_slice(PREFIX);
23    out[PREFIX.len()..PREFIX.len() + 16].copy_from_slice(&hex);
24    out[PREFIX.len() + 16..need].copy_from_slice(SUFFIX);
25    need
26}
27
28#[inline]
29fn format_hash16(h: u64) -> [u8; 16] {
30    let mut buf = [b'0'; 16];
31    let nibbles = [
32        ((h >> 60) & 0xf) as u8,
33        ((h >> 56) & 0xf) as u8,
34        ((h >> 52) & 0xf) as u8,
35        ((h >> 48) & 0xf) as u8,
36        ((h >> 44) & 0xf) as u8,
37        ((h >> 40) & 0xf) as u8,
38        ((h >> 36) & 0xf) as u8,
39        ((h >> 32) & 0xf) as u8,
40        ((h >> 28) & 0xf) as u8,
41        ((h >> 24) & 0xf) as u8,
42        ((h >> 20) & 0xf) as u8,
43        ((h >> 16) & 0xf) as u8,
44        ((h >> 12) & 0xf) as u8,
45        ((h >> 8) & 0xf) as u8,
46        ((h >> 4) & 0xf) as u8,
47        (h & 0xf) as u8,
48    ];
49    for (i, n) in nibbles.iter().enumerate() {
50        buf[i] = match *n {
51            0..=9 => b'0' + *n,
52            _ => b'a' + (*n - 10),
53        };
54    }
55    buf
56}
57
58/// σ sheet index from baked NQuin object when `q42:hasSpectralSheet` is present.
59#[inline]
60pub fn sigma_sheet_index_from_nquin(nquin: &NQuin) -> Option<u32> {
61    let pred = nquin.predicate & 0x0FFF_FFFF_FFFF_FFFF;
62    if pred != (PRED_HAS_SPECTRAL_SHEET & 0x0FFF_FFFF_FFFF_FFFF) {
63        return None;
64    }
65    let idx = (nquin.object & 0x0FFF_FFFF_FFFF_FFFF) as u32;
66    Some(idx)
67}
68
69/// Decode `spatial_encode_wasm` packed coordinates from an object field.
70#[inline]
71pub fn decode_packed_coord(object: u64) -> (f32, f32, f32) {
72    let xi = sign_extend_20(((object >> 40) & 0xfffff) as u32);
73    let yi = sign_extend_20(((object >> 20) & 0xfffff) as u32);
74    let zi = sign_extend_20((object & 0xfffff) as u32);
75    (xi as f32 / 1000.0, yi as f32 / 1000.0, zi as f32 / 1000.0)
76}
77
78#[inline]
79fn sign_extend_20(v: u32) -> i32 {
80    let v = v & 0xfffff;
81    if v & 0x8_0000 != 0 {
82        (v | !0xfffff) as i32
83    } else {
84        v as i32
85    }
86}
87
88/// True when the Quin carries a baked geo vertex payload (not a hash-proxy xyz).
89#[inline]
90pub fn is_geo_vertex_quin(nquin: &NQuin) -> bool {
91    (nquin.predicate & 0x7FFF_FFFF_FFFF_FF00) == PRED_GEO_VERTEX
92        || (nquin.predicate & 0x0FFF_FFFF_FFFF_FFFF) == (PRED_GEO_VERTEX & 0x0FFF_FFFF_FFFF_FFFF)
93}
94
95/// Semantic xyz: packed geo coords when present, else legacy hash spread.
96#[inline]
97pub fn semantic_xyz_from_nquin(nquin: &NQuin) -> (f32, f32, f32) {
98    if is_geo_vertex_quin(nquin) && (nquin.object >> 63) == 0 {
99        return decode_packed_coord(nquin.object);
100    }
101    let hash = nquin.object & 0x0FFF_FFFF_FFFF_FFFF;
102    let x = (hash & 0xFFFF) as f32 / 65535.0;
103    let y = ((hash >> 16) & 0xFFFF) as f32 / 65535.0;
104    let z = ((hash >> 32) & 0xFFFF) as f32 / 65535.0;
105    (x, y, z)
106}
107
108/// Bake a single NQuin into a ground-truth Tensor10D node.
109#[inline]
110pub fn bake_quin_to_tensor(nquin: &NQuin) -> Tensor10D {
111    let q = if (nquin.metadata >> 60) & 0xF != 0 {
112        0.25
113    } else {
114        0.0
115    };
116    let v = ((nquin.context >> 32) & 0x7) as f32;
117    let w = ((nquin.context >> 40) & 0xF) as f32;
118    let (x, y, z) = semantic_xyz_from_nquin(nquin);
119    let t = ((nquin.metadata >> 32) & 0x1FFF_FFFF) as f32;
120    let payload = nquin.metadata & 0xFFFF_FFFF;
121    let alpha = (payload & 0xFF) as f32 / 255.0;
122    let mu = ((payload >> 8) & 0xFF) as f32 / 255.0;
123    let sigma = ((payload >> 16) & 0xFF) as f32 / 255.0;
124    if q > 0.0 {
125        Tensor10D::parallel_context(q, v, w, x, y, z, t, alpha.max(0.1), mu, sigma)
126    } else {
127        Tensor10D::ground_truth(v, w, x, y, z, t, alpha.max(0.1), mu, sigma)
128    }
129}
130
131/// Write baked tensors into caller buffer; returns count written.
132pub fn bake_quins_into(quins: &[NQuin], out: &mut [Tensor10D]) -> usize {
133    let n = quins.len().min(out.len());
134    for i in 0..n {
135        out[i] = bake_quin_to_tensor(&quins[i]);
136    }
137    n
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143    use crate::NQuin;
144
145    fn pack_coord(x: f32, y: f32, z: f32) -> u64 {
146        let xi = (x * 1000.0).round() as i64 & 0xfffff;
147        let yi = (y * 1000.0).round() as i64 & 0xfffff;
148        let zi = (z * 1000.0).round() as i64 & 0xfffff;
149        ((xi as u64) << 40) | ((yi as u64) << 20) | (zi as u64)
150    }
151
152    #[test]
153    fn packed_coord_round_trip() {
154        let (x, y, z) = decode_packed_coord(pack_coord(1.25, -2.5, 3.75));
155        assert!((x - 1.25).abs() < 0.002);
156        assert!((y + 2.5).abs() < 0.002);
157        assert!((z - 3.75).abs() < 0.002);
158    }
159
160    #[test]
161    fn audio_sidecar_path_format() {
162        let mut buf = [0u8; 64];
163        let n = audio_sidecar_relpath(0xabc_def01_2345_6789, &mut buf);
164        assert_eq!(n, b"spectral/audio/".len() + 16 + b".bin".len());
165        let path = std::str::from_utf8(&buf[..n]).unwrap();
166        assert!(path.starts_with("spectral/audio/"));
167        assert!(path.ends_with(".bin"));
168    }
169
170    #[test]
171    fn spectral_sheet_predicate_extracts_index() {
172        let mut q = NQuin::default();
173        q.predicate = PRED_HAS_SPECTRAL_SHEET;
174        q.object = 42;
175        assert_eq!(sigma_sheet_index_from_nquin(&q), Some(42));
176    }
177
178    #[test]
179    fn geo_vertex_bake_uses_packed_xyz() {
180        let mut q = NQuin::default();
181        q.predicate = PRED_GEO_VERTEX;
182        q.object = pack_coord(0.1, 0.2, 0.3);
183        q.metadata = 42 << 32;
184        let t = bake_quin_to_tensor(&q);
185        assert!((t.x - 0.1).abs() < 0.002);
186        assert!((t.y - 0.2).abs() < 0.002);
187        assert!((t.z - 0.3).abs() < 0.002);
188        assert!(t.is_ground_truth());
189    }
190}