use std::fmt::Display;
use num_traits::Float;
use crate::{defs::vector::Vector, traits::OuterProduct};
use crate::defs::bivector::Bivector;
use crate::defs::trivector::Trivector;
use crate::traits::GeometricProduct;
use super::{multivector::Multivector};
#[derive(Clone, Debug)]
pub enum KVector<N: Float> {
Scalar(N),
Vector(Vector<N>),
Bivector(Bivector<N>),
Trivector(Trivector<N>),
}
impl<N: Float+Display> Display for KVector<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
KVector::Scalar(s) => write!(f, "{}", *s),
KVector::Vector(v) => write!(f, "{}", v),
KVector::Bivector(bv) => write!(f, "{}", bv),
KVector::Trivector(tv) => write!(f, "{}", tv),
}
}
}
impl<N: Float> KVector<N> {
pub fn to_scalar(&self) -> Result<N, &'static str> {
if let KVector::Scalar(s) = *self {
return Result::Ok(s);
}
return Err("Illegal scalar cast!");
}
pub fn to_vector(&self) -> Result<Vector<N>, &'static str> {
if let KVector::Vector(v) = self {
return Result::Ok(v.clone());
}
return Err("Illegal vector cast!");
}
pub fn to_bivector(&self) -> Result<Bivector<N>, &'static str> {
if let KVector::Bivector(b) = self {
return Result::Ok(b.clone());
}
return Err("Illegal bivector cast!");
}
pub fn to_trivector(&self) -> Result<Trivector<N>, &'static str> {
if let KVector::Trivector(t) = self {
return Result::Ok(t.clone());
}
return Err("Illegal trivector cast!");
}
}
impl<N: Float> KVector<N> {
fn geo_scalar(self_scalar: &N, other: &Self) -> Multivector<N> {
match other {
KVector::Scalar(other_scalar) => {
Multivector::from_scalar((*self_scalar) * (*other_scalar))
},
KVector::Vector(other_vec) => {
Multivector::from_vector(other_vec * (*self_scalar))
},
KVector::Bivector(other_bivec) => {
Multivector::from_bivector(other_bivec * (*self_scalar))
},
KVector::Trivector(other_trivec) => {
Multivector::from_trivector(other_trivec * (*self_scalar))
}
}
}
fn geo_vector(self_vec: &Vector<N>, other: &Self) -> Multivector<N> {
match other {
KVector::Scalar(other_scalar) => {
Multivector::from_vector(self_vec * (*other_scalar))
},
KVector::Vector(other_vec) => {
self_vec.geo(other_vec)
},
KVector::Bivector(other_bivec) => {
self_vec.geo(other_bivec)
},
KVector::Trivector(other_trivec) => {
self_vec.geo(other_trivec)
}
}
}
fn geo_bivector(self_bivec: &Bivector<N>, other: &Self) -> Multivector<N> {
match other {
KVector::Scalar(other_scalar) => {
Multivector::from_bivector(self_bivec * (*other_scalar))
},
KVector::Vector(other_vec) => {
self_bivec.geo(other_vec)
},
KVector::Bivector(other_bivec) => {
self_bivec.geo(other_bivec)
},
KVector::Trivector(other_trivec) => {
self_bivec.geo(other_trivec)
}
}
}
fn geo_trivector(self_trivec: &Trivector<N>, other: &Self) -> Multivector<N> {
match other {
KVector::Scalar(other_scalar) => {
Multivector::from_trivector(self_trivec * (*other_scalar))
},
KVector::Vector(other_vec) => {
self_trivec.geo(other_vec)
},
KVector::Bivector(other_bivec) => {
self_trivec.geo(other_bivec)
},
KVector::Trivector(other_trivec) => {
self_trivec.geo(other_trivec)
}
}
}
}
impl<N: Float> GeometricProduct<KVector<N>, N> for KVector<N> {
fn geo(&self, other: &Self) -> Multivector<N> {
match self {
KVector::Scalar (s) => KVector::geo_scalar(s, other),
KVector::Vector (vec) => KVector::geo_vector(vec, other),
KVector::Bivector (bivec) => KVector::geo_bivector(bivec, other),
KVector::Trivector (e012) => KVector::geo_trivector(e012, other)
}
}
}
impl<N: Float> KVector<N> {
fn wedge_vec(self_vec: &Vector<N>, other: &KVector<N>) -> KVector<N> {
match other {
KVector::Scalar(other_scalar) => {
KVector::Vector(self_vec * (*other_scalar))
},
KVector::Vector(other_vec) => {
self_vec.wedge(other_vec).to_k_vector()
},
KVector::Bivector(other_bivec) => {
self_vec.wedge(other_bivec).to_k_vector()
},
KVector::Trivector(_other_trivec) => {
return KVector::Scalar(N::zero())
}
}
}
fn wedge_bivec(self_bivec: &Bivector<N>, other: &KVector<N>) -> KVector<N> {
match other {
KVector::Scalar(other_scalar) => {
KVector::Bivector(self_bivec * (*other_scalar))
},
KVector::Vector(other_vec) => {
self_bivec.wedge(other_vec).to_k_vector()
},
_ => KVector::Scalar(N::zero())
}
}
fn wedge_trivec(self_trivec: &Trivector<N>, other: &KVector<N>) -> KVector<N> {
match other {
KVector::Scalar(other_scalar) => {
KVector::Trivector(self_trivec * (*other_scalar))
},
_ => KVector::Scalar(N::zero())
}
}
}
impl<N: Float> OuterProduct<KVector<N>, N> for KVector<N> {
type Output = KVector<N>;
fn wedge(&self, other: &KVector<N>) -> Self::Output {
match self {
KVector::Scalar(self_scalar) => {
match other {
KVector::Scalar(other_scalar) => {
KVector::Scalar((*self_scalar) * (*other_scalar))
}
KVector::Vector(other_vec) => {
KVector::Vector(other_vec * *self_scalar) },
KVector::Bivector(other_bivec) => {
KVector::Bivector(other_bivec * *self_scalar)
},
KVector::Trivector(other_trivec) => {
KVector::Trivector(other_trivec * *self_scalar)
}
}
},
KVector::Vector(self_vec) => KVector::wedge_vec(self_vec, other),
KVector::Bivector(self_bivec) => KVector::wedge_bivec(self_bivec, other),
KVector::Trivector(self_trivec) => KVector::wedge_trivec(self_trivec, other)
}
}
}