qualia_core_db/tensor/
bake_pipeline.rs1use crate::{q_hash, NQuin};
6
7use super::Tensor10D;
8
9pub const PRED_GEO_VERTEX: u64 = q_hash("geo:hasVertex");
10pub const PRED_HAS_SPECTRAL_SHEET: u64 = q_hash("q42:hasSpectralSheet");
12
13pub 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#[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#[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#[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#[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#[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
131pub 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}