use crate::*;
use std::{
fmt::{self, Display, Formatter},
ops::{Div, DivAssign, Mul, MulAssign},
str::FromStr,
};
use derive_more::{Add, AddAssign, Neg, Sub, SubAssign};
use inner_space::{DotProduct, InnerSpace, VectorSpace};
use scalars::{Exp, Real, Zero};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Add, AddAssign, Sub, SubAssign, Neg)]
pub struct Bivector<T> {
pub xy: T,
pub xz: T,
pub yz: T,
}
impl<T> Bivector<T> {
pub fn new(xy: T, xz: T, yz: T) -> Self {
Self { xy, xz, yz }
}
}
impl<T: Real> Exp for Bivector<T> {
type Output = Rotor<T>;
fn exp(self) -> Rotor<T> {
let magnitude = self.magnitude();
let [sin, cos] = magnitude.sin_cos();
let scale = if magnitude.is_zero() {
T::zero()
} else {
sin / magnitude
};
Rotor {
scalar: cos,
xy: self.xy * scale,
xz: self.xz * scale,
yz: self.yz * scale,
}
}
fn exp2(self) -> Rotor<T> {
self.exp()
}
}
impl<T: Zero> Bivector<T> {
pub fn xy(xy: T) -> Self {
Self {
xy,
xz: T::zero(),
yz: T::zero(),
}
}
pub fn xz(xz: T) -> Self {
Self {
xy: T::zero(),
xz,
yz: T::zero(),
}
}
pub fn yz(yz: T) -> Self {
Self {
xy: T::zero(),
xz: T::zero(),
yz,
}
}
}
impl<T: Zero> Zero for Bivector<T> {
fn zero() -> Self {
Self {
xy: T::zero(),
xz: T::zero(),
yz: T::zero(),
}
}
fn is_zero(&self) -> bool {
self.xy.is_zero() && self.xz.is_zero() && self.yz.is_zero()
}
}
impl<T> Mul<T> for Bivector<T>
where
T: Mul<Output = T> + Copy,
{
type Output = Self;
fn mul(self, other: T) -> Self {
Self {
xy: self.xy * other,
xz: self.xz * other,
yz: self.yz * other,
}
}
}
impl<T> MulAssign<T> for Bivector<T>
where
T: MulAssign + Copy,
{
fn mul_assign(&mut self, other: T) {
self.xy *= other;
self.xz *= other;
self.yz *= other;
}
}
impl<T> Div<T> for Bivector<T>
where
T: Div<Output = T> + Copy,
{
type Output = Self;
fn div(self, other: T) -> Self {
Self {
xy: self.xy / other,
xz: self.xz / other,
yz: self.yz / other,
}
}
}
impl<T> DivAssign<T> for Bivector<T>
where
T: DivAssign + Copy,
{
fn div_assign(&mut self, other: T) {
self.xy /= other;
self.xz /= other;
self.yz /= other;
}
}
impl<T: Real> VectorSpace for Bivector<T> {
type Scalar = T;
}
impl<T: Real> DotProduct for Bivector<T> {
type Output = Self::Scalar;
fn dot(&self, other: &Self) -> T {
-self.xy * other.xy - self.xz * other.xz - self.yz * other.yz
}
fn scalar(&self, other: &Self) -> T {
self.xy * other.xy + self.xz * other.xz + self.yz * other.yz
}
}
impl<T: Real> DotProduct<Vector<T>> for Bivector<T> {
type Output = Vector<T>;
#[inline]
fn dot(&self, other: &Vector<T>) -> Vector<T> {
other.dot(self)
}
}
impl<T: Real> DotProduct<Rotor<T>> for Bivector<T> {
type Output = Rotor<T>;
fn dot(&self, other: &Rotor<T>) -> Rotor<T> {
Rotor {
scalar: -self.xy * other.xy - self.xz * other.xz - self.yz * other.yz,
xy: self.xy * other.scalar + self.yz * other.xz - self.xz * other.yz,
xz: self.xz * other.scalar - self.yz * other.xy + self.xy * other.yz,
yz: self.yz * other.scalar + self.xz * other.xy - self.xy * other.xz,
}
}
}
impl<T: Display> Display for Bivector<T> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
write!(formatter, "({}, {}, {})", self.xy, self.xz, self.yz)
}
}
impl<T: FromStr> FromStr for Bivector<T> {
type Err = ParseBivectorError;
fn from_str(source: &str) -> Result<Self, Self::Err> {
let trimmed = source.trim();
let inner = trimmed
.strip_prefix('(')
.and_then(|s| s.strip_suffix(')'))
.ok_or(ParseBivectorError)?;
let parts: Vec<&str> = inner.split(',').collect();
if parts.len() != 3 {
return Err(ParseBivectorError);
}
let xy = parts[0].trim().parse().map_err(|_| ParseBivectorError)?;
let xz = parts[1].trim().parse().map_err(|_| ParseBivectorError)?;
let yz = parts[2].trim().parse().map_err(|_| ParseBivectorError)?;
Ok(Self { xy, xz, yz })
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseBivectorError;
impl Display for ParseBivectorError {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
write!(formatter, "invalid bivector format")
}
}
impl std::error::Error for ParseBivectorError {}