Skip to main content

qualia_core_db/solvers/geometric_algebra/
mod.rs

1//! Geometric Algebra Module
2//!
3//! High-performance geometric algebra operations for QualiaDB
4//! Consolidates P2/P3 extensions into unified framework
5
6use crate::q_hash;
7
8pub mod simd_kernel;
9
10// Re-export main types for convenience
11pub 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
16/// Geometric Algebra constants and utilities
17pub mod constants {
18    /// Epsilon for floating point comparisons
19    pub const GA_EPSILON: f32 = 1e-6;
20
21    /// Maximum dimension supported
22    pub const MAX_DIMENSION: usize = 4;
23
24    /// Number of components for 3D GA
25    pub const GA3D_COMPONENTS: usize = 8;
26
27    /// Number of components for 4D GA
28    pub const GA4D_COMPONENTS: usize = 16;
29}
30
31/// Geometric Algebra utilities
32pub mod utils {
33    use super::*;
34
35    /// Convert degrees to radians
36    pub fn deg_to_rad(degrees: f32) -> f32 {
37        degrees * std::f32::consts::PI / 180.0
38    }
39
40    /// Convert radians to degrees
41    pub fn rad_to_deg(radians: f32) -> f32 {
42        radians * 180.0 / std::f32::consts::PI
43    }
44
45    /// Normalize vector
46    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    /// Cross product of two vectors
56    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    /// Dot product of two vectors
65    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    /// Angle between two vectors
70    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
83/// Geometric Algebra operations for QualiaDB integration
84pub mod qualia_integration {
85    use super::*;
86    use crate::NQuin;
87
88    /// Convert multivector to NQuin representation
89    pub fn multivector_to_quin(mv: &Multivector, context: u64) -> NQuin {
90        // Pack multivector coefficients into NQuin
91        // This is a simplified packing - full implementation would handle all grades
92
93        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        // Combine hashes for multivector representation
108        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    /// Extract multivector from NQuin
121    pub fn quin_to_multivector(quin: &NQuin) -> Option<Multivector> {
122        // This is a simplified extraction - full implementation would
123        // reconstruct the multivector from the stored hash
124        if quin.predicate == q_hash("q42:multivector") {
125            Some(Multivector::scalar(0.0)) // Placeholder
126        } else {
127            None
128        }
129    }
130
131    /// Create geometric operation Quin
132    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
149/// Performance benchmarks for geometric algebra operations
150pub mod benchmarks {
151    use super::*;
152    use std::time::Instant;
153
154    /// Benchmark geometric product performance
155    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    /// Benchmark rotor application performance
172    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    /// Run comprehensive benchmarks
189    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 kernel = get_simd_kernel();
259
260        // Test rotor composition
261        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        // Verify the result is a unit vector
269        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        // Test translator composition
273        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}