use std::{fmt::Display, ops::Mul};
use num_traits::Float;
use crate::traits::{GeometricProduct, OuterProduct, GradeProjection, RegressiveProduct, Normalize, MagnitudeSqr, Dagger};
use super::{multivector::Multivector, trivector::Trivector, vector::Vector, k_vector::KVector};
#[derive(Clone, Debug)]
pub struct Bivector<N>
where N: Float {
pub e01: N,
pub e20: N, pub e12: N,
}
impl<N: Float> Bivector<N> {
pub fn zero() -> Self {
Bivector {
e01: N::zero(),
e20: N::zero(),
e12: N::zero()
}
}
pub fn new(e01: N, e20: N, e12: N) -> Self {
Bivector { e01, e20, e12 }
}
}
impl<N: Float> Bivector<N> {
pub fn to_multivector(&self) -> Multivector<N> {
Multivector {
trivector: Trivector::zero(),
bivector: self.clone(),
vector: Vector::zero(),
scalar: N::zero()
}
}
pub fn to_k_vector(&self) -> KVector<N> {
KVector::Bivector(self.clone())
}
}
impl<N: Float+Display> Display for Bivector<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{{ {}e₀₁, {}e₂₀, {}e₁₂ }}", self.e01, self.e20, self.e12)
}
}
impl<N: Float> GeometricProduct<Multivector<N>, N> for Bivector<N> {
fn geo(&self, other: &Multivector<N>) -> Multivector<N> {
self.to_multivector()
.geo(&other)
}
}
impl<N: Float> GeometricProduct<Bivector<N>, N> for Bivector<N> {
fn geo(&self, other: &Bivector<N>) -> Multivector<N> {
self.to_multivector()
.geo(&other.to_multivector())
}
}
impl<N: Float> GeometricProduct<Vector<N>, N> for Bivector<N> {
fn geo(&self, other: &Vector<N>) -> Multivector<N> {
self.to_multivector()
.geo(&other.to_multivector())
}
}
impl<N: Float> GeometricProduct<Trivector<N>, N> for Bivector<N> {
fn geo(&self, other: &Trivector<N>) -> Multivector<N> {
self.to_multivector()
.geo(&other.to_multivector())
}
}
impl<N> Mul<N> for Bivector<N>
where N: Float {
type Output = Self;
fn mul(self, rhs: N) -> Self::Output {
Bivector {
e01: self.e01 * rhs,
e20: self.e20 * rhs,
e12: self.e12 * rhs,
}
}
}
impl<N> Mul<N> for &Bivector<N>
where N: Float {
type Output = Bivector<N>;
fn mul(self, rhs: N) -> Self::Output {
Bivector {
e01: self.e01 * rhs,
e20: self.e20 * rhs,
e12: self.e12 * rhs,
}
}
}
impl<N: Float> OuterProduct<Bivector<N>, N> for Bivector<N> {
type Output = N;
fn wedge(&self, _other: &Bivector<N>) -> Self::Output {
N::zero()
}
}
impl<N: Float> OuterProduct<Vector<N>, N> for Bivector<N> {
type Output = Trivector<N>;
fn wedge(&self, other: &Vector<N>) -> Self::Output {
let product = self.geo(other);
product.grade_proj(3)
.to_trivector()
.unwrap()
}
}
impl<N: Float> RegressiveProduct<Bivector<N>, N> for Bivector<N> {
type Output = Vector<N>;
fn regressive(&self, other: &Bivector<N>) -> Self::Output {
Vector {
e0:
self.e01 * other.e20
- self.e20 * other.e01,
e1:
- self.e01 * other.e12
+ self.e12 * other.e01,
e2:
self.e20 * other.e12
- self.e12 * other.e20
}
}
}
impl<N: Float> MagnitudeSqr<N> for Bivector<N> {
fn magnitude_sqr(&self) -> N {
let self_mv = self.to_multivector();
self_mv.reverse().geo(&self_mv)
.scalar
}
}
impl<N: Float> Normalize for Bivector<N> {
fn normalized(&self) -> Self {
let inv_magnitude = N::from(1.0).unwrap()/self.magnitude_sqr().sqrt();
Bivector {
e01: self.e01 * inv_magnitude,
e20: self.e20 * inv_magnitude,
e12: self.e12 * inv_magnitude
}
}
}