Skip to content

Commit 583f779

Browse files
committed
feat(deep_causality_multivector): separated MLX code into dedicted files for better maintainabiliy.
Signed-off-by: Marvin Hansen <marvin.hansen@gmail.com>
1 parent 05d7a59 commit 583f779

17 files changed

Lines changed: 980 additions & 620 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4+
*/
5+
6+
//! CPU-only implementations for Tier 3 algebra operations.
7+
//! This module is compiled when the MLX feature is disabled.
8+
9+
use crate::{CausalMultiVector, CausalMultiVectorError};
10+
use deep_causality_num::{Field, RealField};
11+
use std::ops::{AddAssign, Neg, SubAssign};
12+
13+
// Internal implementation methods
14+
impl<T> CausalMultiVector<T> {
15+
/// Computes the squared magnitude (squared norm) of the multivector.
16+
///
17+
/// $$ ||A||^2 = \langle A \tilde{A} \rangle_0 $$
18+
pub(in crate::types::multivector) fn squared_magnitude_impl(&self) -> T
19+
where
20+
T: Field + Copy + Clone + AddAssign + SubAssign + Neg<Output = T>,
21+
{
22+
let reverse = self.reversion_impl();
23+
let product = self.geometric_product_impl(&reverse);
24+
product.data[0] // Scalar part
25+
}
26+
27+
/// Computes the inverse of the multivector $A^{-1}$ (CPU-only).
28+
pub(in crate::types::multivector) fn inverse_impl(&self) -> Result<Self, CausalMultiVectorError>
29+
where
30+
T: Field
31+
+ Copy
32+
+ Clone
33+
+ Neg<Output = T>
34+
+ core::ops::Div<Output = T>
35+
+ PartialEq
36+
+ AddAssign
37+
+ SubAssign,
38+
{
39+
let sq_mag = self.squared_magnitude_impl();
40+
if sq_mag == T::zero() {
41+
return Err(CausalMultiVectorError::zero_magnitude());
42+
}
43+
44+
let reverse = self.reversion_impl();
45+
Ok(reverse / sq_mag)
46+
}
47+
48+
/// Computes the dual of the multivector $A^*$ (CPU-only).
49+
pub(in crate::types::multivector) fn dual_impl(&self) -> Result<Self, CausalMultiVectorError>
50+
where
51+
T: Field
52+
+ Copy
53+
+ Clone
54+
+ Neg<Output = T>
55+
+ core::ops::Div<Output = T>
56+
+ PartialEq
57+
+ AddAssign
58+
+ SubAssign,
59+
{
60+
let pseudo = Self::pseudoscalar(self.metric);
61+
let pseudo_inv = pseudo.inverse_impl()?;
62+
Ok(self.geometric_product_impl(&pseudo_inv))
63+
}
64+
}
65+
66+
// Public API methods - Tier 3 operations (CPU version)
67+
impl<T> CausalMultiVector<T>
68+
where
69+
T: RealField + Copy,
70+
{
71+
/// Normalizes the multivector to unit magnitude.
72+
pub fn normalize(&self) -> Self {
73+
let mag_sq = self.squared_magnitude_impl();
74+
if mag_sq <= T::epsilon() {
75+
return self.clone();
76+
}
77+
let scale_factor = T::one() / mag_sq.sqrt();
78+
self.scale(scale_factor)
79+
}
80+
}
81+
82+
impl<T> CausalMultiVector<T>
83+
where
84+
T: Field + Copy + RealField,
85+
{
86+
/// Computes the Lie Commutator: $[A, B] = AB - BA$.
87+
/// Valid for all associative algebras.
88+
pub fn commutator(&self, rhs: &Self) -> Self {
89+
self.commutator_lie_impl(rhs)
90+
}
91+
92+
/// Computes the Multiplicative Inverse.
93+
/// $A^{-1} = \tilde{A} / |A|^2$ (For Versors).
94+
/// Requires Division (Field).
95+
pub fn inverse(&self) -> Result<Self, CausalMultiVectorError> {
96+
let mag_sq = self.squared_magnitude_impl();
97+
98+
if mag_sq.abs() <= T::epsilon() {
99+
return Err(CausalMultiVectorError::zero_magnitude());
100+
}
101+
102+
let conjugate = self.reversion_impl();
103+
let scale = T::one() / mag_sq;
104+
105+
Ok(conjugate.scale(scale))
106+
}
107+
108+
/// The Geometric Product for Commutative Coefficients.
109+
/// This is the standard CPU implementation.
110+
pub fn geometric_product(&self, rhs: &Self) -> Self {
111+
self.geometric_product_impl(rhs)
112+
}
113+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4+
*/
5+
6+
//! MLX-accelerated implementations for Tier 3 algebra operations.
7+
//! This module is compiled only when the MLX feature is enabled.
8+
9+
use crate::{CausalMultiVector, CausalMultiVectorError};
10+
use deep_causality_num::{Field, RealField};
11+
use std::ops::{AddAssign, Neg, SubAssign};
12+
13+
impl<T> CausalMultiVector<T> {
14+
/// Computes the squared magnitude (squared norm) of the multivector.
15+
///
16+
/// $$ ||A||^2 = \langle A \tilde{A} \rangle_0 $$
17+
///
18+
/// MLX-optimized version.
19+
pub(in crate::types::multivector) fn squared_magnitude_impl(&self) -> T
20+
where
21+
T: Field
22+
+ Copy
23+
+ Clone
24+
+ AddAssign
25+
+ SubAssign
26+
+ Neg<Output = T>
27+
+ Default
28+
+ PartialOrd
29+
+ Send
30+
+ Sync
31+
+ 'static,
32+
{
33+
let reverse = self.reversion_impl();
34+
let product = self.geometric_product_impl(&reverse);
35+
product.data[0] // Scalar part
36+
}
37+
38+
/// Computes the inverse of the multivector $A^{-1}$.
39+
///
40+
/// $$ A^{-1} = \frac{\tilde{A}}{A \tilde{A}} $$
41+
///
42+
/// Only valid if $A \tilde{A}$ is a non-zero scalar (Versor).
43+
pub(in crate::types::multivector) fn inverse_impl(&self) -> Result<Self, CausalMultiVectorError>
44+
where
45+
T: Field
46+
+ Copy
47+
+ Clone
48+
+ Neg<Output = T>
49+
+ core::ops::Div<Output = T>
50+
+ PartialEq
51+
+ AddAssign
52+
+ SubAssign
53+
+ Default
54+
+ PartialOrd
55+
+ Send
56+
+ Sync
57+
+ 'static,
58+
{
59+
let sq_mag = self.squared_magnitude_impl();
60+
if sq_mag == T::zero() {
61+
return Err(CausalMultiVectorError::zero_magnitude());
62+
}
63+
64+
let reverse = self.reversion_impl();
65+
let scale = T::one() / sq_mag;
66+
// Manual scaling to avoid Module<T> trait bound issue
67+
let scaled_data = reverse.data.iter().map(|v| *v * scale).collect();
68+
Ok(Self {
69+
data: scaled_data,
70+
metric: reverse.metric,
71+
})
72+
}
73+
74+
/// Computes the dual of the multivector $A^*$.
75+
///
76+
/// $$ A^* = A I^{-1} $$
77+
/// where $I$ is the pseudoscalar.
78+
pub(in crate::types::multivector) fn dual_impl(&self) -> Result<Self, CausalMultiVectorError>
79+
where
80+
T: Field
81+
+ Copy
82+
+ Clone
83+
+ Neg<Output = T>
84+
+ core::ops::Div<Output = T>
85+
+ PartialEq
86+
+ AddAssign
87+
+ SubAssign
88+
+ Default
89+
+ PartialOrd
90+
+ Send
91+
+ Sync
92+
+ 'static,
93+
{
94+
let pseudo = Self::pseudoscalar(self.metric);
95+
let pseudo_inv = pseudo.inverse_impl()?;
96+
Ok(self.geometric_product_impl(&pseudo_inv))
97+
}
98+
}
99+
100+
// Public API methods implementation (Normalize, Commutator, etc for MLX)
101+
impl<T> CausalMultiVector<T>
102+
where
103+
T: RealField + Copy,
104+
{
105+
/// Normalizes the multivector to unit magnitude.
106+
pub fn normalize(&self) -> Self
107+
where
108+
T: Default + PartialOrd + Send + Sync + 'static,
109+
{
110+
let mag_sq = self.squared_magnitude_impl();
111+
if mag_sq <= T::epsilon() {
112+
return self.clone();
113+
}
114+
let scale_factor = T::one() / mag_sq.sqrt();
115+
self.scale(scale_factor)
116+
}
117+
}
118+
119+
impl<T> CausalMultiVector<T>
120+
where
121+
T: Field + Copy + RealField,
122+
{
123+
/// Computes the Lie Commutator: $[A, B] = AB - BA$.
124+
/// Valid for all associative algebras.
125+
pub fn commutator(&self, rhs: &Self) -> Self
126+
where
127+
T: Default + PartialOrd + Send + Sync + 'static,
128+
{
129+
self.commutator_lie_impl(rhs)
130+
}
131+
132+
/// Computes the Multiplicative Inverse (Public Wrapper).
133+
/// $A^{-1} = \tilde{A} / |A|^2$ (For Versors).
134+
/// Requires Division (Field).
135+
pub fn inverse(&self) -> Result<Self, CausalMultiVectorError>
136+
where
137+
T: Default + PartialOrd + Send + Sync + 'static,
138+
{
139+
self.inverse_impl()
140+
}
141+
142+
/// The Geometric Product for Commutative Coefficients.
143+
///
144+
/// With `mlx` feature on macOS aarch64: Automatically accelerates N≥6 algebras via GPU.
145+
pub fn geometric_product(&self, rhs: &Self) -> Self
146+
where
147+
T: Default + PartialOrd + Send + Sync + 'static,
148+
{
149+
self.geometric_product_impl(rhs)
150+
}
151+
}

0 commit comments

Comments
 (0)