pub mod epga1d; pub mod ppga1d; pub mod hpga1d; pub mod epga2d; pub mod ppga2d; pub mod hpga2d; pub mod epga3d; pub mod ppga3d; pub mod hpga3d; pub mod simd; pub mod polynomial; impl Zero for f32 { fn zero() -> Self { 0.0 } } impl One for f32 { fn one() -> Self { 1.0 } } impl Automorphism for f32 { type Output = f32; fn automorphism(self) -> f32 { self } } impl Reversal for f32 { type Output = f32; fn reversal(self) -> f32 { self } } impl Conjugation for f32 { type Output = f32; fn conjugation(self) -> f32 { self } } impl GeometricProduct for f32 { type Output = f32; fn geometric_product(self, other: f32) -> f32 { self * other } } impl OuterProduct for f32 { type Output = f32; fn outer_product(self, other: f32) -> f32 { self * other } } impl InnerProduct for f32 { type Output = f32; fn inner_product(self, other: f32) -> f32 { self * other } } impl LeftContraction for f32 { type Output = f32; fn left_contraction(self, other: f32) -> f32 { self * other } } impl RightContraction for f32 { type Output = f32; fn right_contraction(self, other: f32) -> f32 { self * other } } impl ScalarProduct for f32 { type Output = f32; fn scalar_product(self, other: f32) -> f32 { self * other } } impl SquaredMagnitude for f32 { type Output = f32; fn squared_magnitude(self) -> f32 { self.scalar_product(self.reversal()) } } impl Magnitude for f32 { type Output = f32; fn magnitude(self) -> f32 { self.abs() } } impl Scale for f32 { type Output = f32; fn scale(self, other: f32) -> f32 { self.geometric_product(other) } } impl Signum for f32 { type Output = f32; fn signum(self) -> f32 { f32::signum(self) } } impl Inverse for f32 { type Output = f32; fn inverse(self) -> f32 { 1.0 / self } } impl GeometricQuotient for f32 { type Output = f32; fn geometric_quotient(self, other: f32) -> f32 { self.geometric_product(other.inverse()) } } impl Transformation for f32 { type Output = f32; fn transformation(self, other: f32) -> f32 { self.geometric_product(other) .geometric_product(self.reversal()) } } impl epga1d::ComplexNumber { pub fn real(self) -> f32 { self[0] } pub fn imaginary(self) -> f32 { self[1] } pub fn from_polar(magnitude: f32, argument: f32) -> Self { Self::new(magnitude * argument.cos(), magnitude * argument.sin()) } pub fn arg(self) -> f32 { self.imaginary().atan2(self.real()) } } impl Exp for epga1d::ComplexNumber { type Output = Self; fn exp(self) -> Self { Self::from_polar(self[0].exp(), self[1]) } } impl Ln for epga1d::ComplexNumber { type Output = Self; fn ln(self) -> Self { Self::new(self.magnitude().ln(), self.arg()) } } impl Powf for epga1d::ComplexNumber { type Output = Self; fn powf(self, exponent: f32) -> Self { Self::from_polar(self.magnitude().powf(exponent), self.arg() * exponent) } } impl Exp for ppga2d::IdealPoint { type Output = ppga2d::Translator; fn exp(self) -> ppga2d::Translator { ppga2d::Translator::new(1.0, self[0], self[1]) } } impl Ln for ppga2d::Translator { type Output = ppga2d::IdealPoint; fn ln(self) -> ppga2d::IdealPoint { let result: ppga2d::IdealPoint = self.into(); result.scale(1.0 / self[0]) } } impl Powf for ppga2d::Translator { type Output = Self; fn powf(self, exponent: f32) -> Self { self.ln().scale(exponent).exp() } } impl Exp for ppga2d::Point { type Output = ppga2d::Motor; fn exp(self) -> ppga2d::Motor { let det = self[0] * self[0]; if det <= 0.0 { return ppga2d::Motor::new(1.0, 0.0, self[1], self[2]); } let a = det.sqrt(); let c = a.cos(); let s = a.sin() / a; let g0 = simd::Simd32x3::from(s) * self.group0(); ppga2d::Motor::new(c, g0[0], g0[1], g0[2]) } } impl Ln for ppga2d::Motor { type Output = ppga2d::Point; fn ln(self) -> ppga2d::Point { let det = 1.0 - self[0] * self[0]; if det <= 0.0 { return ppga2d::Point::new(0.0, self[2], self[3]); } let a = 1.0 / det; let b = self[0].acos() * a.sqrt(); let g0 = simd::Simd32x4::from(b) * self.group0(); ppga2d::Point::new(g0[1], g0[2], g0[3]) } } impl Powf for ppga2d::Motor { type Output = Self; fn powf(self, exponent: f32) -> Self { self.ln().scale(exponent).exp() } } impl Exp for ppga3d::IdealPoint { type Output = ppga3d::Translator; fn exp(self) -> ppga3d::Translator { ppga3d::Translator::new(1.0, self[0], self[1], self[2]) } } impl Ln for ppga3d::Translator { type Output = ppga3d::IdealPoint; fn ln(self) -> ppga3d::IdealPoint { let result: ppga3d::IdealPoint = self.into(); result.scale(1.0 / self[0]) } } impl Powf for ppga3d::Translator { type Output = Self; fn powf(self, exponent: f32) -> Self { self.ln().scale(exponent).exp() } } impl Exp for ppga3d::Line { type Output = ppga3d::Motor; fn exp(self) -> ppga3d::Motor { let det = self[3] * self[3] + self[4] * self[4] + self[5] * self[5]; if det <= 0.0 { return ppga3d::Motor::new(1.0, 0.0, 0.0, 0.0, 0.0, self[0], self[1], self[2]); } let a = det.sqrt(); let c = a.cos(); let s = a.sin() / a; let m = self[0] * self[3] + self[1] * self[4] + self[2] * self[5]; let t = m / det * (c - s); let g0 = simd::Simd32x3::from(s) * self.group1(); let g1 = simd::Simd32x3::from(s) * self.group0() + simd::Simd32x3::from(t) * self.group1(); ppga3d::Motor::new(c, g0[0], g0[1], g0[2], s * m, g1[0], g1[1], g1[2]) } } impl Ln for ppga3d::Motor { type Output = ppga3d::Line; fn ln(self) -> ppga3d::Line { let det = 1.0 - self[0] * self[0]; if det <= 0.0 { return ppga3d::Line::new(self[5], self[6], self[7], 0.0, 0.0, 0.0); } let a = 1.0 / det; let b = self[0].acos() * a.sqrt(); let c = a * self[4] * (1.0 - self[0] * b); let g0 = simd::Simd32x4::from(b) * self.group1() + simd::Simd32x4::from(c) * self.group0(); let g1 = simd::Simd32x4::from(b) * self.group0(); ppga3d::Line::new(g0[1], g0[2], g0[3], g1[1], g1[2], g1[3]) } } impl Powf for ppga3d::Motor { type Output = Self; fn powf(self, exponent: f32) -> Self { self.ln().scale(exponent).exp() } } /// All elements set to `0.0` pub trait Zero { fn zero() -> Self; } /// All elements set to `0.0`, except for the scalar, which is set to `1.0` pub trait One { fn one() -> Self; } /// Element order reversed pub trait Dual { type Output; fn dual(self) -> Self::Output; } /// Negates elements with `grade % 2 == 1` /// /// Also called main involution pub trait Automorphism { type Output; fn automorphism(self) -> Self::Output; } /// Negates elements with `grade % 4 >= 2` /// /// Also called transpose pub trait Reversal { type Output; fn reversal(self) -> Self::Output; } /// Negates elements with `(grade + 3) % 4 < 2` pub trait Conjugation { type Output; fn conjugation(self) -> Self::Output; } /// General multi vector multiplication pub trait GeometricProduct { type Output; fn geometric_product(self, other: T) -> Self::Output; } /// General multi vector division pub trait GeometricQuotient { type Output; fn geometric_quotient(self, other: T) -> Self::Output; } /// Dual of the geometric product grade filtered by `t == r + s` /// /// Also called join pub trait RegressiveProduct { type Output; fn regressive_product(self, other: T) -> Self::Output; } /// Geometric product grade filtered by `t == r + s` /// /// Also called meet or exterior product pub trait OuterProduct { type Output; fn outer_product(self, other: T) -> Self::Output; } /// Geometric product grade filtered by `t == (r - s).abs()` /// /// Also called fat dot product pub trait InnerProduct { type Output; fn inner_product(self, other: T) -> Self::Output; } /// Geometric product grade filtered by `t == s - r` pub trait LeftContraction { type Output; fn left_contraction(self, other: T) -> Self::Output; } /// Geometric product grade filtered by `t == r - s` pub trait RightContraction { type Output; fn right_contraction(self, other: T) -> Self::Output; } /// Geometric product grade filtered by `t == 0` pub trait ScalarProduct { type Output; fn scalar_product(self, other: T) -> Self::Output; } /// `self * other * self.reversion()` /// /// Also called sandwich product pub trait Transformation { type Output; fn transformation(self, other: T) -> Self::Output; } /// Geometric product with a scalar pub trait Scale { type Output; fn scale(self, other: f32) -> Self::Output; } /// Square of the magnitude pub trait SquaredMagnitude { type Output; fn squared_magnitude(self) -> Self::Output; } /// Length as scalar /// /// Also called amplitude, absolute value or norm pub trait Magnitude { type Output; fn magnitude(self) -> Self::Output; } /// Direction without magnitude (set to scalar `-1.0` or `1.0`) /// /// Also called sign or normalize pub trait Signum { type Output; fn signum(self) -> Self::Output; } /// Raises a number to the scalar power of `-1.0` pub trait Inverse { type Output; fn inverse(self) -> Self::Output; } /// The natural logarithm pub trait Ln { type Output; fn ln(self) -> Self::Output; } /// The exponential function pub trait Exp { type Output; fn exp(self) -> Self::Output; } /// Raises a number to an integer scalar power pub trait Powi { type Output; fn powi(self, exponent: isize) -> Self::Output; } /// Raises a number to an floating point scalar power pub trait Powf { type Output; fn powf(self, exponent: f32) -> Self::Output; }