use crate::*;
use std::ops::{Div, DivAssign, Mul, MulAssign};
use derive_more::{Add, AddAssign, Neg, Sub, SubAssign};
use inner_space::{DotProduct, VectorSpace};
use scalars::{Exp, Real, Zero};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Add, AddAssign, Sub, SubAssign, Neg)]
pub struct Bivector<T> {
pub xy: T,
}
impl<T> Bivector<T> {
pub fn new(xy: T) -> Self {
Self { xy }
}
}
impl<T: Real> Exp for Bivector<T> {
type Output = Rotor<T>;
fn exp(self) -> Rotor<T> {
let [xy, scalar] = self.xy.sin_cos();
Rotor { scalar, xy }
}
fn exp2(self) -> Rotor<T> {
self.exp()
}
}
impl<T: Zero> Bivector<T> {
pub fn xy(xy: T) -> Self {
Self { xy }
}
}
impl<T: Zero> Zero for Bivector<T> {
fn zero() -> Self {
Self { xy: T::zero() }
}
fn is_zero(&self) -> bool {
self.xy.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,
}
}
}
impl<T> MulAssign<T> for Bivector<T>
where
T: MulAssign + Copy,
{
fn mul_assign(&mut self, other: T) {
self.xy *= 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,
}
}
}
impl<T> DivAssign<T> for Bivector<T>
where
T: DivAssign + Copy,
{
fn div_assign(&mut self, other: T) {
self.xy /= 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
}
fn scalar(&self, other: &Self) -> T {
self.xy * other.xy
}
}
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,
xy: self.xy * other.scalar,
}
}
}
impl<T: std::fmt::Display> std::fmt::Display for Bivector<T> {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "({})", self.xy)
}
}
impl<T: std::str::FromStr> std::str::FromStr for Bivector<T> {
type Err = String;
fn from_str(source: &str) -> Result<Self, Self::Err> {
let trimmed = source
.strip_prefix('(')
.and_then(|s| s.strip_suffix(')'))
.ok_or_else(|| format!("expected format (xy), got {source}"))?;
let xy = trimmed
.trim()
.parse::<T>()
.map_err(|_| "failed to parse xy component".to_string())?;
Ok(Self { xy })
}
}