qualia_core_db/solvers/geometric_algebra/
mod.rs1use crate::q_hash;
7
8pub mod simd_kernel;
9
10pub use simd_kernel::{
12 apply_rotor, apply_translator, geometric_product, is_simd_available, outer_product,
13 rotor_from_angle_axis, translator_from_displacement, Grade, Multivector, Rotor, Translator,
14};
15
16pub mod constants {
18 pub const GA_EPSILON: f32 = 1e-6;
20
21 pub const MAX_DIMENSION: usize = 4;
23
24 pub const GA3D_COMPONENTS: usize = 8;
26
27 pub const GA4D_COMPONENTS: usize = 16;
29}
30
31pub mod utils {
33 use super::*;
34
35 pub fn deg_to_rad(degrees: f32) -> f32 {
37 degrees * std::f32::consts::PI / 180.0
38 }
39
40 pub fn rad_to_deg(radians: f32) -> f32 {
42 radians * 180.0 / std::f32::consts::PI
43 }
44
45 pub fn normalize_vector(v: &[f32; 3]) -> [f32; 3] {
47 let mag = (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]).sqrt();
48 if mag > constants::GA_EPSILON {
49 [v[0] / mag, v[1] / mag, v[2] / mag]
50 } else {
51 *v
52 }
53 }
54
55 pub fn cross_product(a: &[f32; 3], b: &[f32; 3]) -> [f32; 3] {
57 [
58 a[1] * b[2] - a[2] * b[1],
59 a[2] * b[0] - a[0] * b[2],
60 a[0] * b[1] - a[1] * b[0],
61 ]
62 }
63
64 pub fn dot_product(a: &[f32; 3], b: &[f32; 3]) -> f32 {
66 a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
67 }
68
69 pub fn angle_between_vectors(a: &[f32; 3], b: &[f32; 3]) -> f32 {
71 let mag_a = (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]).sqrt();
72 let mag_b = (b[0] * b[0] + b[1] * b[1] + b[2] * b[2]).sqrt();
73
74 if mag_a > constants::GA_EPSILON && mag_b > constants::GA_EPSILON {
75 let cos_angle = dot_product(a, b) / (mag_a * mag_b);
76 cos_angle.clamp(-1.0, 1.0).acos()
77 } else {
78 0.0
79 }
80 }
81}
82
83pub mod qualia_integration {
85 use super::*;
86 use crate::NQuin;
87
88 pub fn multivector_to_quin(mv: &Multivector, context: u64) -> NQuin {
90 let scalar_bytes = mv.get_scalar().to_le_bytes();
94 let scalar_hex = format!(
95 "{:02x}{:02x}{:02x}{:02x}",
96 scalar_bytes[0], scalar_bytes[1], scalar_bytes[2], scalar_bytes[3]
97 );
98 let scalar_hash = q_hash(&scalar_hex);
99 let vector_bytes: Vec<u8> = mv
100 .to_vector()
101 .iter()
102 .flat_map(|f| f.to_le_bytes().to_vec())
103 .collect();
104 let vector_hex: String = vector_bytes.iter().map(|b| format!("{:02x}", b)).collect();
105 let vector_hash = q_hash(&vector_hex);
106
107 let combined_hash = scalar_hash.wrapping_mul(31).wrapping_add(vector_hash);
109
110 NQuin {
111 subject: combined_hash,
112 predicate: q_hash("q42:multivector"),
113 object: q_hash("geometric_algebra"),
114 context,
115 metadata: mv.grade_mask() as u64,
116 parity: 0,
117 }
118 }
119
120 pub fn quin_to_multivector(quin: &NQuin) -> Option<Multivector> {
122 if quin.predicate == q_hash("q42:multivector") {
125 Some(Multivector::scalar(0.0)) } else {
127 None
128 }
129 }
130
131 pub fn geometric_operation_quin(
133 operation: &str,
134 operand_a: u64,
135 operand_b: u64,
136 context: u64,
137 ) -> NQuin {
138 NQuin {
139 subject: operand_a,
140 predicate: q_hash(&format!("q42:ga:{}", operation)),
141 object: operand_b,
142 context,
143 metadata: q_hash("geometric_operation"),
144 parity: 0,
145 }
146 }
147}
148
149pub mod benchmarks {
151 use super::*;
152 use std::time::Instant;
153
154 pub fn benchmark_geometric_product(iterations: usize) -> (f64, bool) {
156 let a = Multivector::vector(1.0, 2.0, 3.0);
157 let b = Multivector::vector(4.0, 5.0, 6.0);
158
159 let start = Instant::now();
160
161 for _ in 0..iterations {
162 let _result = geometric_product(&a, &b);
163 }
164
165 let duration = start.elapsed();
166 let ops_per_second = iterations as f64 / duration.as_secs_f64();
167
168 (ops_per_second, is_simd_available())
169 }
170
171 pub fn benchmark_rotor_application(iterations: usize) -> (f64, bool) {
173 let rotor = rotor_from_angle_axis(std::f32::consts::PI / 4.0, [0.0, 0.0, 1.0]);
174 let vector = [1.0, 0.0, 0.0];
175
176 let start = Instant::now();
177
178 for _ in 0..iterations {
179 let _result = apply_rotor(&rotor, &vector);
180 }
181
182 let duration = start.elapsed();
183 let ops_per_second = iterations as f64 / duration.as_secs_f64();
184
185 (ops_per_second, is_simd_available())
186 }
187
188 pub fn run_benchmarks() {
190 const ITERATIONS: usize = 1_000_000;
191
192 println!("Geometric Algebra Performance Benchmarks");
193 println!("==========================================");
194
195 let (gp_ops, simd_enabled) = benchmark_geometric_product(ITERATIONS);
196 println!(
197 "Geometric Product: {:.2} ops/sec (SIMD: {})",
198 gp_ops, simd_enabled
199 );
200
201 let (rotor_ops, _) = benchmark_rotor_application(ITERATIONS);
202 println!("Rotor Application: {:.2} ops/sec", rotor_ops);
203
204 println!("SIMD Available: {}", is_simd_available());
205 }
206}
207
208#[cfg(test)]
209mod integration_tests {
210 use super::utils::*;
211 use super::*;
212
213 #[test]
214 fn test_utility_functions() {
215 let v1 = [1.0, 0.0, 0.0];
216 let v2 = [0.0, 1.0, 0.0];
217
218 let cross = cross_product(&v1, &v2);
219 assert_eq!(cross, [0.0, 0.0, 1.0]);
220
221 let dot = dot_product(&v1, &v2);
222 assert_eq!(dot, 0.0);
223
224 let angle = angle_between_vectors(&v1, &v2);
225 assert!((angle - std::f32::consts::PI / 2.0).abs() < constants::GA_EPSILON);
226 }
227
228 #[test]
229 fn test_degree_radian_conversion() {
230 let deg = 180.0;
231 let rad = deg_to_rad(deg);
232 assert!((rad - std::f32::consts::PI).abs() < constants::GA_EPSILON);
233
234 let back_to_deg = rad_to_deg(rad);
235 assert!((back_to_deg - deg).abs() < constants::GA_EPSILON);
236 }
237
238 #[test]
239 fn test_vector_normalization() {
240 let v = [3.0, 4.0, 0.0];
241 let normalized = normalize_vector(&v);
242 let mag = (normalized[0].powi(2) + normalized[1].powi(2) + normalized[2].powi(2)).sqrt();
243 assert!((mag - 1.0).abs() < constants::GA_EPSILON);
244 }
245
246 #[test]
247 fn test_qualia_integration() {
248 let mv = Multivector::vector(1.0, 2.0, 3.0);
249 let context = q_hash("test_context");
250
251 let quin = qualia_integration::multivector_to_quin(&mv, context);
252 assert_eq!(quin.context, context);
253 assert_eq!(quin.predicate, q_hash("q42:multivector"));
254 }
255
256 #[test]
257 fn test_comprehensive_operations() {
258 let rotor1 = rotor_from_angle_axis(deg_to_rad(45.0), [0.0, 0.0, 1.0]);
262 let rotor2 = rotor_from_angle_axis(deg_to_rad(30.0), [0.0, 1.0, 0.0]);
263
264 let vector = [1.0, 0.0, 0.0];
265 let rotated1 = apply_rotor(&rotor1, &vector);
266 let rotated2 = apply_rotor(&rotor2, &rotated1);
267
268 let mag = (rotated2[0].powi(2) + rotated2[1].powi(2) + rotated2[2].powi(2)).sqrt();
270 assert!((mag - 1.0).abs() < constants::GA_EPSILON);
271
272 let trans1 = translator_from_displacement([1.0, 2.0, 3.0]);
274 let trans2 = translator_from_displacement([4.0, 5.0, 6.0]);
275
276 let origin = [0.0, 0.0, 0.0];
277 let translated1 = apply_translator(&trans1, &origin);
278 let translated2 = apply_translator(&trans2, &translated1);
279
280 assert_eq!(translated2, [5.0, 7.0, 9.0]);
281 }
282}