#![doc = " Trait implementations for hyperbolic."]
#![doc = ""]
#![doc = " This file is auto-generated by clifford-codegen."]
#![doc = " Do not edit manually."]
use super::types::{HypUnit, Hyperbolic, Scalar};
#[allow(unused_imports)]
use crate::ops::{
Antidot, Antireverse, Antisandwich, Antiwedge, BulkContract, BulkExpand, Dot,
InverseAntisandwich, InverseSandwich, Involute, LeftContract, Reverse, RightComplement,
RightContract, Sandwich, ScalarProduct, Transform, Versor, VersorInverse, Wedge,
WeightContract, WeightDual, WeightExpand,
};
use crate::scalar::Float;
#[allow(unused_imports)]
use crate::wrappers::Unit;
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::ops::{Add, Mul, Neg, Sub};
impl<T: Float> Add for HypUnit<T> {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self::new_unchecked(self.j() + rhs.j())
}
}
impl<T: Float> Sub for HypUnit<T> {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self::new_unchecked(self.j() - rhs.j())
}
}
impl<T: Float> Neg for HypUnit<T> {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self::new_unchecked(-self.j())
}
}
impl<T: Float> Mul<T> for HypUnit<T> {
type Output = Self;
#[inline]
fn mul(self, scalar: T) -> Self {
self.scale(scalar)
}
}
impl Mul<HypUnit<f32>> for f32 {
type Output = HypUnit<f32>;
#[inline]
fn mul(self, v: HypUnit<f32>) -> HypUnit<f32> {
v.scale(self)
}
}
impl Mul<HypUnit<f64>> for f64 {
type Output = HypUnit<f64>;
#[inline]
fn mul(self, v: HypUnit<f64>) -> HypUnit<f64> {
v.scale(self)
}
}
impl<T: Float> Mul<HypUnit<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn mul(self, rhs: HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.j())
}
}
impl<T: Float> Mul<Hyperbolic<T>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn mul(self, rhs: Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(rhs.hyp() * self.j(), rhs.real() * self.j())
}
}
impl<T: Float> Mul<Scalar<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn mul(self, rhs: Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.j())
}
}
impl<T: Float> Add for Hyperbolic<T> {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self::new_unchecked(self.real() + rhs.real(), self.hyp() + rhs.hyp())
}
}
impl<T: Float> Sub for Hyperbolic<T> {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self::new_unchecked(self.real() - rhs.real(), self.hyp() - rhs.hyp())
}
}
impl<T: Float> Neg for Hyperbolic<T> {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self::new_unchecked(-self.real(), -self.hyp())
}
}
impl<T: Float> Mul<T> for Hyperbolic<T> {
type Output = Self;
#[inline]
fn mul(self, scalar: T) -> Self {
self.scale(scalar)
}
}
impl Mul<Hyperbolic<f32>> for f32 {
type Output = Hyperbolic<f32>;
#[inline]
fn mul(self, v: Hyperbolic<f32>) -> Hyperbolic<f32> {
v.scale(self)
}
}
impl Mul<Hyperbolic<f64>> for f64 {
type Output = Hyperbolic<f64>;
#[inline]
fn mul(self, v: Hyperbolic<f64>) -> Hyperbolic<f64> {
v.scale(self)
}
}
impl<T: Float> Mul<HypUnit<T>> for Hyperbolic<T> {
type Output = Hyperbolic<T>;
#[inline]
fn mul(self, rhs: HypUnit<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(rhs.j() * self.hyp(), rhs.j() * self.real())
}
}
impl<T: Float> Mul<Hyperbolic<T>> for Hyperbolic<T> {
type Output = Hyperbolic<T>;
#[inline]
fn mul(self, rhs: Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
rhs.hyp() * self.hyp() + rhs.real() * self.real(),
rhs.hyp() * self.real() + rhs.real() * self.hyp(),
)
}
}
impl<T: Float> Mul<Scalar<T>> for Hyperbolic<T> {
type Output = Hyperbolic<T>;
#[inline]
fn mul(self, rhs: Scalar<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(rhs.s() * self.real(), rhs.s() * self.hyp())
}
}
impl<T: Float> Add for Scalar<T> {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self::new_unchecked(self.s() + rhs.s())
}
}
impl<T: Float> Sub for Scalar<T> {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self::new_unchecked(self.s() - rhs.s())
}
}
impl<T: Float> Neg for Scalar<T> {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self::new_unchecked(-self.s())
}
}
impl<T: Float> Mul<T> for Scalar<T> {
type Output = Self;
#[inline]
fn mul(self, scalar: T) -> Self {
self.scale(scalar)
}
}
impl Mul<Scalar<f32>> for f32 {
type Output = Scalar<f32>;
#[inline]
fn mul(self, v: Scalar<f32>) -> Scalar<f32> {
v.scale(self)
}
}
impl Mul<Scalar<f64>> for f64 {
type Output = Scalar<f64>;
#[inline]
fn mul(self, v: Scalar<f64>) -> Scalar<f64> {
v.scale(self)
}
}
impl<T: Float> Mul<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn mul(self, rhs: HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.s())
}
}
impl<T: Float> Mul<Hyperbolic<T>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn mul(self, rhs: Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(rhs.real() * self.s(), rhs.hyp() * self.s())
}
}
impl<T: Float> Mul<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn mul(self, rhs: Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.s())
}
}
#[doc = "Wedge (exterior/outer) product of [`HypUnit`] and [`Scalar`].\n\nThe wedge product `a ^ b` computes the outer product, which represents\nthe oriented subspace spanned by both operands. The result grade is the\nsum of the input grades (or zero if they share common factors)."]
impl<T: Float> Wedge<Scalar<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Scalar<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Unit<Scalar<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.as_inner().j())
}
}
#[doc = "Wedge (exterior/outer) product of [`Scalar`] and [`HypUnit`].\n\nThe wedge product `a ^ b` computes the outer product, which represents\nthe oriented subspace spanned by both operands. The result grade is the\nsum of the input grades (or zero if they share common factors)."]
impl<T: Float> Wedge<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<HypUnit<T>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Unit<HypUnit<T>>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn wedge(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.as_inner().s())
}
}
#[doc = "Wedge (exterior/outer) product of [`Scalar`] and [`Scalar`].\n\nThe wedge product `a ^ b` computes the outer product, which represents\nthe oriented subspace spanned by both operands. The result grade is the\nsum of the input grades (or zero if they share common factors)."]
impl<T: Float> Wedge<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn wedge(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn wedge(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn wedge(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Wedge<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn wedge(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.as_inner().s())
}
}
#[doc = "Antiwedge (regressive/meet) product of [`HypUnit`] and [`HypUnit`].\n\nThe antiwedge product `a v b` computes the meet of two subspaces,\nreturning the largest subspace contained in both. In projective geometry,\nthis finds intersections (e.g., where two planes meet to form a line)."]
impl<T: Float> Antiwedge<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn antiwedge(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn antiwedge(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn antiwedge(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn antiwedge(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.as_inner().j())
}
}
#[doc = "Antiwedge (regressive/meet) product of [`HypUnit`] and [`Scalar`].\n\nThe antiwedge product `a v b` computes the meet of two subspaces,\nreturning the largest subspace contained in both. In projective geometry,\nthis finds intersections (e.g., where two planes meet to form a line)."]
impl<T: Float> Antiwedge<Scalar<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<Scalar<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<Unit<Scalar<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.as_inner().j())
}
}
#[doc = "Antiwedge (regressive/meet) product of [`Scalar`] and [`HypUnit`].\n\nThe antiwedge product `a v b` computes the meet of two subspaces,\nreturning the largest subspace contained in both. In projective geometry,\nthis finds intersections (e.g., where two planes meet to form a line)."]
impl<T: Float> Antiwedge<HypUnit<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<HypUnit<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<Unit<HypUnit<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antiwedge<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn antiwedge(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.as_inner().s())
}
}
#[doc = "Left contraction of [`HypUnit`] into [`HypUnit`].\n\nThe left contraction `a _| b` projects `a` onto `b`, returning the\ncomponent of `b` orthogonal to `a`. The result grade is grade(b) - grade(a)\n(or zero if grade(a) > grade(b))."]
impl<T: Float> LeftContract<HypUnit<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.as_inner().j())
}
}
#[doc = "Left contraction of [`Scalar`] into [`HypUnit`].\n\nThe left contraction `a _| b` projects `a` onto `b`, returning the\ncomponent of `b` orthogonal to `a`. The result grade is grade(b) - grade(a)\n(or zero if grade(a) > grade(b))."]
impl<T: Float> LeftContract<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn left_contract(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<HypUnit<T>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn left_contract(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<Unit<HypUnit<T>>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn left_contract(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn left_contract(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.as_inner().s())
}
}
#[doc = "Left contraction of [`Scalar`] into [`Scalar`].\n\nThe left contraction `a _| b` projects `a` onto `b`, returning the\ncomponent of `b` orthogonal to `a`. The result grade is grade(b) - grade(a)\n(or zero if grade(a) > grade(b))."]
impl<T: Float> LeftContract<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> LeftContract<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn left_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.as_inner().s())
}
}
#[doc = "Right contraction of [`HypUnit`] by [`HypUnit`].\n\nThe right contraction `a |_ b` projects `b` onto `a`, returning the\ncomponent of `a` orthogonal to `b`. The result grade is grade(a) - grade(b)\n(or zero if grade(b) > grade(a))."]
impl<T: Float> RightContract<HypUnit<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.as_inner().j())
}
}
#[doc = "Right contraction of [`HypUnit`] by [`Scalar`].\n\nThe right contraction `a |_ b` projects `b` onto `a`, returning the\ncomponent of `a` orthogonal to `b`. The result grade is grade(a) - grade(b)\n(or zero if grade(b) > grade(a))."]
impl<T: Float> RightContract<Scalar<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn right_contract(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Scalar<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn right_contract(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Unit<Scalar<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn right_contract(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn right_contract(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.as_inner().j())
}
}
#[doc = "Right contraction of [`Scalar`] by [`Scalar`].\n\nThe right contraction `a |_ b` projects `b` onto `a`, returning the\ncomponent of `a` orthogonal to `b`. The result grade is grade(a) - grade(b)\n(or zero if grade(b) > grade(a))."]
impl<T: Float> RightContract<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> RightContract<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn right_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.as_inner().s())
}
}
#[doc = "Sandwich product: [`HypUnit`] x [`HypUnit`] x rev([`HypUnit`]).\n\nThe sandwich product `v x a x rev(v)` applies the transformation\nrepresented by the versor `v` to the operand `a`. For rotors, this\nperforms rotation; for motors, it performs rigid body transformation."]
#[allow(unused_variables)]
impl<T: Float> Sandwich<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(self.j() * operand.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(-(operand.j()))
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.as_inner().j() * self.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(-(operand.as_inner().j()))
}
}
#[doc = "Sandwich product: [`HypUnit`] x [`Hyperbolic`] x rev([`HypUnit`]).\n\nThe sandwich product `v x a x rev(v)` applies the transformation\nrepresented by the versor `v` to the operand `a`. For rotors, this\nperforms rotation; for motors, it performs rigid body transformation."]
#[allow(unused_variables)]
impl<T: Float> Sandwich<Hyperbolic<T>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
self.j() * operand.real() * self.j(),
self.j() * operand.hyp() * self.j(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Hyperbolic<T>> for Unit<HypUnit<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(-(operand.real()), -(operand.hyp()))
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Hyperbolic<T>>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
operand.as_inner().real() * self.j() * self.j(),
operand.as_inner().hyp() * self.j() * self.j(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Hyperbolic<T>>> for Unit<HypUnit<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(-(operand.as_inner().real()), -(operand.as_inner().hyp()))
}
}
#[doc = "Sandwich product: [`HypUnit`] x [`Scalar`] x rev([`HypUnit`]).\n\nThe sandwich product `v x a x rev(v)` applies the transformation\nrepresented by the versor `v` to the operand `a`. For rotors, this\nperforms rotation; for motors, it performs rigid body transformation."]
#[allow(unused_variables)]
impl<T: Float> Sandwich<Scalar<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(self.j() * operand.s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Scalar<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(-(operand.s()))
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Scalar<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(operand.as_inner().s() * self.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(-(operand.as_inner().s()))
}
}
#[doc = "Sandwich product: [`Scalar`] x [`HypUnit`] x rev([`Scalar`]).\n\nThe sandwich product `v x a x rev(v)` applies the transformation\nrepresented by the versor `v` to the operand `a`. For rotors, this\nperforms rotation; for motors, it performs rigid body transformation."]
#[allow(unused_variables)]
impl<T: Float> Sandwich<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(self.s() * operand.j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<HypUnit<T>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<HypUnit<T>>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.as_inner().j() * self.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn sandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.as_inner().j())
}
}
#[doc = "Sandwich product: [`Scalar`] x [`Hyperbolic`] x rev([`Scalar`]).\n\nThe sandwich product `v x a x rev(v)` applies the transformation\nrepresented by the versor `v` to the operand `a`. For rotors, this\nperforms rotation; for motors, it performs rigid body transformation."]
#[allow(unused_variables)]
impl<T: Float> Sandwich<Hyperbolic<T>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
self.s() * operand.real() * self.s(),
self.s() * operand.hyp() * self.s(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Hyperbolic<T>> for Unit<Scalar<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(operand.real(), operand.hyp())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Hyperbolic<T>>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
operand.as_inner().real() * self.s() * self.s(),
operand.as_inner().hyp() * self.s() * self.s(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Hyperbolic<T>>> for Unit<Scalar<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(operand.as_inner().real(), operand.as_inner().hyp())
}
}
#[doc = "Sandwich product: [`Scalar`] x [`Scalar`] x rev([`Scalar`]).\n\nThe sandwich product `v x a x rev(v)` applies the transformation\nrepresented by the versor `v` to the operand `a`. For rotors, this\nperforms rotation; for motors, it performs rigid body transformation."]
#[allow(unused_variables)]
impl<T: Float> Sandwich<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(self.s() * operand.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(operand.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(operand.as_inner().s() * self.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Sandwich<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn sandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(operand.as_inner().s())
}
}
#[doc = "Antisandwich product: [`HypUnit`] x [`HypUnit`] x antirev([`HypUnit`]).\n\nThe antisandwich product `v x a x antirev(v)` is the dual of the\nsandwich product, used in Projective GA for transforming dual objects\n(planes, ideal points). Motors use antisandwich for plane transforms."]
#[allow(unused_variables)]
impl<T: Float> Antisandwich<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(self.j() * operand.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(-(operand.j()))
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.as_inner().j() * self.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(-(operand.as_inner().j()))
}
}
#[doc = "Antisandwich product: [`HypUnit`] x [`Hyperbolic`] x antirev([`HypUnit`]).\n\nThe antisandwich product `v x a x antirev(v)` is the dual of the\nsandwich product, used in Projective GA for transforming dual objects\n(planes, ideal points). Motors use antisandwich for plane transforms."]
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Hyperbolic<T>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
self.j() * operand.real() * self.j(),
self.j() * operand.hyp() * self.j(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Hyperbolic<T>> for Unit<HypUnit<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(-(operand.real()), -(operand.hyp()))
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Hyperbolic<T>>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
operand.as_inner().real() * self.j() * self.j(),
operand.as_inner().hyp() * self.j() * self.j(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Hyperbolic<T>>> for Unit<HypUnit<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(-(operand.as_inner().real()), -(operand.as_inner().hyp()))
}
}
#[doc = "Antisandwich product: [`HypUnit`] x [`Scalar`] x antirev([`HypUnit`]).\n\nThe antisandwich product `v x a x antirev(v)` is the dual of the\nsandwich product, used in Projective GA for transforming dual objects\n(planes, ideal points). Motors use antisandwich for plane transforms."]
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Scalar<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(self.j() * operand.s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Scalar<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(-(operand.s()))
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Scalar<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(operand.as_inner().s() * self.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(-(operand.as_inner().s()))
}
}
#[doc = "Antisandwich product: [`Scalar`] x [`HypUnit`] x antirev([`Scalar`]).\n\nThe antisandwich product `v x a x antirev(v)` is the dual of the\nsandwich product, used in Projective GA for transforming dual objects\n(planes, ideal points). Motors use antisandwich for plane transforms."]
#[allow(unused_variables)]
impl<T: Float> Antisandwich<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(self.s() * operand.j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<HypUnit<T>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.j())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<HypUnit<T>>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.as_inner().j() * self.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(operand.as_inner().j())
}
}
#[doc = "Antisandwich product: [`Scalar`] x [`Hyperbolic`] x antirev([`Scalar`]).\n\nThe antisandwich product `v x a x antirev(v)` is the dual of the\nsandwich product, used in Projective GA for transforming dual objects\n(planes, ideal points). Motors use antisandwich for plane transforms."]
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Hyperbolic<T>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
self.s() * operand.real() * self.s(),
self.s() * operand.hyp() * self.s(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Hyperbolic<T>> for Unit<Scalar<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(operand.real(), operand.hyp())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Hyperbolic<T>>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(
operand.as_inner().real() * self.s() * self.s(),
operand.as_inner().hyp() * self.s() * self.s(),
)
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Hyperbolic<T>>> for Unit<Scalar<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(operand.as_inner().real(), operand.as_inner().hyp())
}
}
#[doc = "Antisandwich product: [`Scalar`] x [`Scalar`] x antirev([`Scalar`]).\n\nThe antisandwich product `v x a x antirev(v)` is the dual of the\nsandwich product, used in Projective GA for transforming dual objects\n(planes, ideal points). Motors use antisandwich for plane transforms."]
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(self.s() * operand.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(operand.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(operand.as_inner().s() * self.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> Antisandwich<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn antisandwich(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(operand.as_inner().s())
}
}
#[doc = "Transform a [`HypUnit`] using this [`HypUnit`].\n\nApplies the geometric transformation represented by this versor.\nFor rotors, this performs rotation. For motors, this performs rigid\nbody transformation (rotation + translation). Internally uses the\nsandwich product."]
impl<T: Float> Transform<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &HypUnit<T>) -> HypUnit<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &HypUnit<T>) -> HypUnit<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
self.sandwich(operand)
}
}
#[doc = "Transform a [`Hyperbolic`] using this [`HypUnit`].\n\nApplies the geometric transformation represented by this versor.\nFor rotors, this performs rotation. For motors, this performs rigid\nbody transformation (rotation + translation). Internally uses the\nsandwich product."]
impl<T: Float> Transform<Hyperbolic<T>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Hyperbolic<T>> for Unit<HypUnit<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Hyperbolic<T>>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Hyperbolic<T>>> for Unit<HypUnit<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
#[doc = "Transform a [`Scalar`] using this [`HypUnit`].\n\nApplies the geometric transformation represented by this versor.\nFor rotors, this performs rotation. For motors, this performs rigid\nbody transformation (rotation + translation). Internally uses the\nsandwich product."]
impl<T: Float> Transform<Scalar<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Scalar<T>) -> Scalar<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Scalar<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Scalar<T>) -> Scalar<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Scalar<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
self.sandwich(operand)
}
}
#[doc = "Transform a [`HypUnit`] using this [`Scalar`].\n\nApplies the geometric transformation represented by this versor.\nFor rotors, this performs rotation. For motors, this performs rigid\nbody transformation (rotation + translation). Internally uses the\nsandwich product."]
impl<T: Float> Transform<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &HypUnit<T>) -> HypUnit<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<HypUnit<T>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &HypUnit<T>) -> HypUnit<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<HypUnit<T>>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn transform(&self, operand: &Unit<HypUnit<T>>) -> HypUnit<T> {
self.sandwich(operand)
}
}
#[doc = "Transform a [`Hyperbolic`] using this [`Scalar`].\n\nApplies the geometric transformation represented by this versor.\nFor rotors, this performs rotation. For motors, this performs rigid\nbody transformation (rotation + translation). Internally uses the\nsandwich product."]
impl<T: Float> Transform<Hyperbolic<T>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Hyperbolic<T>> for Unit<Scalar<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Hyperbolic<T>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Hyperbolic<T>>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Hyperbolic<T>>> for Unit<Scalar<T>> {
type Output = Hyperbolic<T>;
#[inline]
fn transform(&self, operand: &Unit<Hyperbolic<T>>) -> Hyperbolic<T> {
self.sandwich(operand)
}
}
#[doc = "Transform a [`Scalar`] using this [`Scalar`].\n\nApplies the geometric transformation represented by this versor.\nFor rotors, this performs rotation. For motors, this performs rigid\nbody transformation (rotation + translation). Internally uses the\nsandwich product."]
impl<T: Float> Transform<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Scalar<T>) -> Scalar<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Scalar<T>) -> Scalar<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
self.sandwich(operand)
}
}
impl<T: Float> Transform<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn transform(&self, operand: &Unit<Scalar<T>>) -> Scalar<T> {
self.sandwich(operand)
}
}
#[allow(unused_variables)]
impl<T: Float> InverseSandwich<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn try_inverse_sandwich(&self, operand: &HypUnit<T>) -> Option<HypUnit<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(HypUnit::new_unchecked(
(self.j() * operand.j() * self.j()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseSandwich<Hyperbolic<T>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn try_inverse_sandwich(&self, operand: &Hyperbolic<T>) -> Option<Hyperbolic<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Hyperbolic::new_unchecked(
(self.j() * operand.real() * self.j()) * inv_norm_sq,
(self.j() * operand.hyp() * self.j()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseSandwich<Scalar<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn try_inverse_sandwich(&self, operand: &Scalar<T>) -> Option<Scalar<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Scalar::new_unchecked(
(self.j() * operand.s() * self.j()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseSandwich<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn try_inverse_sandwich(&self, operand: &HypUnit<T>) -> Option<HypUnit<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(HypUnit::new_unchecked(
(self.s() * operand.j() * self.s()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseSandwich<Hyperbolic<T>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn try_inverse_sandwich(&self, operand: &Hyperbolic<T>) -> Option<Hyperbolic<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Hyperbolic::new_unchecked(
(self.s() * operand.real() * self.s()) * inv_norm_sq,
(self.s() * operand.hyp() * self.s()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseSandwich<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn try_inverse_sandwich(&self, operand: &Scalar<T>) -> Option<Scalar<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Scalar::new_unchecked(
(self.s() * operand.s() * self.s()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseAntisandwich<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn try_inverse_antisandwich(&self, operand: &HypUnit<T>) -> Option<HypUnit<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(HypUnit::new_unchecked(
(self.j() * operand.j() * self.j()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseAntisandwich<Hyperbolic<T>> for HypUnit<T> {
type Output = Hyperbolic<T>;
#[inline]
fn try_inverse_antisandwich(&self, operand: &Hyperbolic<T>) -> Option<Hyperbolic<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Hyperbolic::new_unchecked(
(self.j() * operand.real() * self.j()) * inv_norm_sq,
(self.j() * operand.hyp() * self.j()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseAntisandwich<Scalar<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn try_inverse_antisandwich(&self, operand: &Scalar<T>) -> Option<Scalar<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Scalar::new_unchecked(
(self.j() * operand.s() * self.j()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseAntisandwich<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn try_inverse_antisandwich(&self, operand: &HypUnit<T>) -> Option<HypUnit<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(HypUnit::new_unchecked(
(self.s() * operand.j() * self.s()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseAntisandwich<Hyperbolic<T>> for Scalar<T> {
type Output = Hyperbolic<T>;
#[inline]
fn try_inverse_antisandwich(&self, operand: &Hyperbolic<T>) -> Option<Hyperbolic<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Hyperbolic::new_unchecked(
(self.s() * operand.real() * self.s()) * inv_norm_sq,
(self.s() * operand.hyp() * self.s()) * inv_norm_sq,
))
}
}
#[allow(unused_variables)]
impl<T: Float> InverseAntisandwich<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn try_inverse_antisandwich(&self, operand: &Scalar<T>) -> Option<Scalar<T>> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Scalar::new_unchecked(
(self.s() * operand.s() * self.s()) * inv_norm_sq,
))
}
}
impl<T: Float> Versor<HypUnit<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn compose(&self, other: &HypUnit<T>) -> Scalar<T> {
*self * *other
}
}
impl<T: Float> Versor<Scalar<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn compose(&self, other: &Scalar<T>) -> HypUnit<T> {
*self * *other
}
}
impl<T: Float> Versor<HypUnit<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn compose(&self, other: &HypUnit<T>) -> HypUnit<T> {
*self * *other
}
}
impl<T: Float> Versor<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn compose(&self, other: &Scalar<T>) -> Scalar<T> {
*self * *other
}
}
impl<T: Float> ScalarProduct<HypUnit<T>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &HypUnit<T>) -> T {
self.j() * rhs.j()
}
}
#[allow(unused_variables)]
impl<T: Float> ScalarProduct<HypUnit<T>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &HypUnit<T>) -> T {
rhs.j() * self.as_inner().j()
}
}
#[allow(unused_variables)]
impl<T: Float> ScalarProduct<Unit<HypUnit<T>>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.j()
}
}
#[allow(unused_variables)]
impl<T: Float> ScalarProduct<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.as_inner().j()
}
}
impl<T: Float> ScalarProduct<Scalar<T>> for Scalar<T> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &Scalar<T>) -> T {
self.s() * rhs.s()
}
}
#[allow(unused_variables)]
impl<T: Float> ScalarProduct<Scalar<T>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &Scalar<T>) -> T {
rhs.s() * self.as_inner().s()
}
}
#[allow(unused_variables)]
impl<T: Float> ScalarProduct<Unit<Scalar<T>>> for Scalar<T> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.s()
}
}
#[allow(unused_variables)]
impl<T: Float> ScalarProduct<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn scalar_product(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.as_inner().s()
}
}
#[doc = "Bulk contraction of [`HypUnit`] with [`HypUnit`].\n\nThe bulk contraction extracts the Euclidean (non-degenerate) component\nof the interior product. In PGA, this isolates the finite/spatial part."]
impl<T: Float> BulkContract<HypUnit<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.as_inner().j())
}
}
#[doc = "Bulk contraction of [`HypUnit`] with [`Scalar`].\n\nThe bulk contraction extracts the Euclidean (non-degenerate) component\nof the interior product. In PGA, this isolates the finite/spatial part."]
impl<T: Float> BulkContract<Scalar<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn bulk_contract(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Scalar<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn bulk_contract(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Unit<Scalar<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn bulk_contract(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn bulk_contract(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.as_inner().j())
}
}
#[doc = "Bulk contraction of [`Scalar`] with [`Scalar`].\n\nThe bulk contraction extracts the Euclidean (non-degenerate) component\nof the interior product. In PGA, this isolates the finite/spatial part."]
impl<T: Float> BulkContract<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkContract<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn bulk_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.as_inner().s())
}
}
#[doc = "Weight contraction of [`HypUnit`] with [`HypUnit`].\n\nThe weight contraction extracts the degenerate/ideal component of the\ninterior product. In PGA, this measures the 'weight' or projective part."]
impl<T: Float> WeightContract<HypUnit<T>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.as_inner().j())
}
}
#[doc = "Weight contraction of [`HypUnit`] with [`Scalar`].\n\nThe weight contraction extracts the degenerate/ideal component of the\ninterior product. In PGA, this measures the 'weight' or projective part."]
impl<T: Float> WeightContract<Scalar<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn weight_contract(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Scalar<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn weight_contract(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Unit<Scalar<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn weight_contract(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Unit<Scalar<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn weight_contract(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.as_inner().j())
}
}
#[doc = "Weight contraction of [`Scalar`] with [`Scalar`].\n\nThe weight contraction extracts the degenerate/ideal component of the\ninterior product. In PGA, this measures the 'weight' or projective part."]
impl<T: Float> WeightContract<Scalar<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Scalar<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &Scalar<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.s() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Unit<Scalar<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightContract<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn weight_contract(&self, rhs: &Unit<Scalar<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().s() * self.as_inner().s())
}
}
#[doc = "Bulk expansion of [`HypUnit`] with [`HypUnit`].\n\nThe bulk expansion is the dual of bulk contraction, extracting the\nEuclidean component of the exterior product complement."]
impl<T: Float> BulkExpand<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.as_inner().j())
}
}
#[doc = "Bulk expansion of [`Scalar`] with [`HypUnit`].\n\nThe bulk expansion is the dual of bulk contraction, extracting the\nEuclidean component of the exterior product complement."]
impl<T: Float> BulkExpand<HypUnit<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn bulk_expand(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<HypUnit<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn bulk_expand(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<Unit<HypUnit<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn bulk_expand(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn bulk_expand(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.as_inner().s())
}
}
#[doc = "Bulk expansion of [`Scalar`] with [`Scalar`].\n\nThe bulk expansion is the dual of bulk contraction, extracting the\nEuclidean component of the exterior product complement."]
impl<T: Float> BulkExpand<Scalar<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<Scalar<T>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<Unit<Scalar<T>>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> BulkExpand<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn bulk_expand(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.as_inner().s())
}
}
#[doc = "Weight expansion of [`HypUnit`] with [`HypUnit`].\n\nThe weight expansion is the dual of weight contraction, extracting the\ndegenerate/ideal component of the exterior product complement."]
impl<T: Float> WeightExpand<HypUnit<T>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<HypUnit<T>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &HypUnit<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.j() * self.as_inner().j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<Unit<HypUnit<T>>> for HypUnit<T> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.j())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &Unit<HypUnit<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().j() * self.as_inner().j())
}
}
#[doc = "Weight expansion of [`Scalar`] with [`HypUnit`].\n\nThe weight expansion is the dual of weight contraction, extracting the\ndegenerate/ideal component of the exterior product complement."]
impl<T: Float> WeightExpand<HypUnit<T>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn weight_expand(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<HypUnit<T>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn weight_expand(&self, rhs: &HypUnit<T>) -> Scalar<T> {
Scalar::new_unchecked(rhs.j() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<Unit<HypUnit<T>>> for Scalar<T> {
type Output = Scalar<T>;
#[inline]
fn weight_expand(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<Unit<HypUnit<T>>> for Unit<Scalar<T>> {
type Output = Scalar<T>;
#[inline]
fn weight_expand(&self, rhs: &Unit<HypUnit<T>>) -> Scalar<T> {
Scalar::new_unchecked(rhs.as_inner().j() * self.as_inner().s())
}
}
#[doc = "Weight expansion of [`Scalar`] with [`Scalar`].\n\nThe weight expansion is the dual of weight contraction, extracting the\ndegenerate/ideal component of the exterior product complement."]
impl<T: Float> WeightExpand<Scalar<T>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<Scalar<T>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &Scalar<T>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.s() * self.as_inner().s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<Unit<Scalar<T>>> for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.s())
}
}
#[allow(unused_variables)]
impl<T: Float> WeightExpand<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Output = HypUnit<T>;
#[inline]
fn weight_expand(&self, rhs: &Unit<Scalar<T>>) -> HypUnit<T> {
HypUnit::new_unchecked(rhs.as_inner().s() * self.as_inner().s())
}
}
impl<T: Float> Dot<HypUnit<T>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &HypUnit<T>) -> T {
self.j() * rhs.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<HypUnit<T>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &HypUnit<T>) -> T {
rhs.j() * self.as_inner().j()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<HypUnit<T>>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.as_inner().j()
}
}
impl<T: Float> Dot<Hyperbolic<T>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Hyperbolic<T>) -> T {
self.j() * rhs.hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Hyperbolic<T>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Hyperbolic<T>) -> T {
rhs.hyp() * self.as_inner().j()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Hyperbolic<T>>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Hyperbolic<T>>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.as_inner().j()
}
}
impl<T: Float> Dot<HypUnit<T>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &HypUnit<T>) -> T {
self.hyp() * rhs.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<HypUnit<T>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &HypUnit<T>) -> T {
rhs.j() * self.as_inner().hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<HypUnit<T>>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<HypUnit<T>>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.as_inner().hyp()
}
}
impl<T: Float> Dot<Hyperbolic<T>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Hyperbolic<T>) -> T {
self.real() * rhs.real() + self.hyp() * rhs.hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Hyperbolic<T>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Hyperbolic<T>) -> T {
rhs.hyp() * self.as_inner().hyp() + rhs.real() * self.as_inner().real()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Hyperbolic<T>>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.hyp() + rhs.as_inner().real() * self.real()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Hyperbolic<T>>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.as_inner().hyp()
+ rhs.as_inner().real() * self.as_inner().real()
}
}
impl<T: Float> Dot<Scalar<T>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Scalar<T>) -> T {
self.real() * rhs.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Scalar<T>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Scalar<T>) -> T {
rhs.s() * self.as_inner().real()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Scalar<T>>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.real()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Scalar<T>>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.as_inner().real()
}
}
impl<T: Float> Dot<Hyperbolic<T>> for Scalar<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Hyperbolic<T>) -> T {
self.s() * rhs.real()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Hyperbolic<T>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Hyperbolic<T>) -> T {
rhs.real() * self.as_inner().s()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Hyperbolic<T>>> for Scalar<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().real() * self.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Hyperbolic<T>>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().real() * self.as_inner().s()
}
}
impl<T: Float> Dot<Scalar<T>> for Scalar<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Scalar<T>) -> T {
self.s() * rhs.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Scalar<T>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Scalar<T>) -> T {
rhs.s() * self.as_inner().s()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Scalar<T>>> for Scalar<T> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Dot<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn dot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.as_inner().s()
}
}
impl<T: Float> Antidot<HypUnit<T>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &HypUnit<T>) -> T {
self.j() * rhs.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<HypUnit<T>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &HypUnit<T>) -> T {
rhs.j() * self.as_inner().j()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<HypUnit<T>>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<HypUnit<T>>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.as_inner().j()
}
}
impl<T: Float> Antidot<Hyperbolic<T>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Hyperbolic<T>) -> T {
self.j() * rhs.hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Hyperbolic<T>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Hyperbolic<T>) -> T {
rhs.hyp() * self.as_inner().j()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Hyperbolic<T>>> for HypUnit<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Hyperbolic<T>>> for Unit<HypUnit<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.as_inner().j()
}
}
impl<T: Float> Antidot<HypUnit<T>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &HypUnit<T>) -> T {
self.hyp() * rhs.j()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<HypUnit<T>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &HypUnit<T>) -> T {
rhs.j() * self.as_inner().hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<HypUnit<T>>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<HypUnit<T>>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<HypUnit<T>>) -> T {
rhs.as_inner().j() * self.as_inner().hyp()
}
}
impl<T: Float> Antidot<Hyperbolic<T>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Hyperbolic<T>) -> T {
self.real() * rhs.real() + self.hyp() * rhs.hyp()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Hyperbolic<T>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Hyperbolic<T>) -> T {
rhs.hyp() * self.as_inner().hyp() + rhs.real() * self.as_inner().real()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Hyperbolic<T>>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.hyp() + rhs.as_inner().real() * self.real()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Hyperbolic<T>>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().hyp() * self.as_inner().hyp()
+ rhs.as_inner().real() * self.as_inner().real()
}
}
impl<T: Float> Antidot<Scalar<T>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Scalar<T>) -> T {
self.real() * rhs.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Scalar<T>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Scalar<T>) -> T {
rhs.s() * self.as_inner().real()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Scalar<T>>> for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.real()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Scalar<T>>> for Unit<Hyperbolic<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.as_inner().real()
}
}
impl<T: Float> Antidot<Hyperbolic<T>> for Scalar<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Hyperbolic<T>) -> T {
self.s() * rhs.real()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Hyperbolic<T>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Hyperbolic<T>) -> T {
rhs.real() * self.as_inner().s()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Hyperbolic<T>>> for Scalar<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().real() * self.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Hyperbolic<T>>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Hyperbolic<T>>) -> T {
rhs.as_inner().real() * self.as_inner().s()
}
}
impl<T: Float> Antidot<Scalar<T>> for Scalar<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Scalar<T>) -> T {
self.s() * rhs.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Scalar<T>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Scalar<T>) -> T {
rhs.s() * self.as_inner().s()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Scalar<T>>> for Scalar<T> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.s()
}
}
#[allow(unused_variables)]
impl<T: Float> Antidot<Unit<Scalar<T>>> for Unit<Scalar<T>> {
type Scalar = T;
#[inline]
fn antidot(&self, rhs: &Unit<Scalar<T>>) -> T {
rhs.as_inner().s() * self.as_inner().s()
}
}
impl<T: Float> Reverse for HypUnit<T> {
#[inline]
fn reverse(&self) -> Self {
Self::new_unchecked(self.j())
}
}
impl<T: Float> Reverse for Hyperbolic<T> {
#[inline]
fn reverse(&self) -> Self {
Self::new_unchecked(self.real(), self.hyp())
}
}
impl<T: Float> Reverse for Scalar<T> {
#[inline]
fn reverse(&self) -> Self {
Self::new_unchecked(self.s())
}
}
impl<T: Float> Antireverse for HypUnit<T> {
#[inline]
fn antireverse(&self) -> Self {
Self::new_unchecked(self.j())
}
}
impl<T: Float> Antireverse for Hyperbolic<T> {
#[inline]
fn antireverse(&self) -> Self {
Self::new_unchecked(self.real(), self.hyp())
}
}
impl<T: Float> Antireverse for Scalar<T> {
#[inline]
fn antireverse(&self) -> Self {
Self::new_unchecked(self.s())
}
}
impl<T: Float> Involute for HypUnit<T> {
#[inline]
fn involute(&self) -> Self {
Self::new_unchecked(-self.j())
}
}
impl<T: Float> Involute for Hyperbolic<T> {
#[inline]
fn involute(&self) -> Self {
Self::new_unchecked(self.real(), -self.hyp())
}
}
impl<T: Float> Involute for Scalar<T> {
#[inline]
fn involute(&self) -> Self {
Self::new_unchecked(self.s())
}
}
impl<T: Float> RightComplement for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn right_complement(&self) -> Scalar<T> {
Scalar::new_unchecked(self.j())
}
}
impl<T: Float> RightComplement for Hyperbolic<T> {
type Output = Hyperbolic<T>;
#[inline]
fn right_complement(&self) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(self.hyp(), self.real())
}
}
impl<T: Float> RightComplement for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn right_complement(&self) -> HypUnit<T> {
HypUnit::new_unchecked(self.s())
}
}
impl<T: Float> WeightDual for HypUnit<T> {
type Output = Scalar<T>;
#[inline]
fn weight_dual(&self) -> Scalar<T> {
Scalar::new_unchecked(self.j())
}
}
impl<T: Float> WeightDual for Hyperbolic<T> {
type Output = Hyperbolic<T>;
#[inline]
fn weight_dual(&self) -> Hyperbolic<T> {
Hyperbolic::new_unchecked(self.hyp(), self.real())
}
}
impl<T: Float> WeightDual for Scalar<T> {
type Output = HypUnit<T>;
#[inline]
fn weight_dual(&self) -> HypUnit<T> {
HypUnit::new_unchecked(self.s())
}
}
impl<T: Float> VersorInverse for HypUnit<T> {
fn try_inverse(&self) -> Option<Self> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Self::new_unchecked(self.j() * inv_norm_sq))
}
}
impl<T: Float> VersorInverse for Scalar<T> {
fn try_inverse(&self) -> Option<Self> {
let norm_sq = <Self as crate::norm::Normed>::norm_squared(self);
if norm_sq.abs() < T::epsilon() {
return None;
}
let inv_norm_sq = T::one() / norm_sq;
Some(Self::new_unchecked(self.s() * inv_norm_sq))
}
}
impl<T: Float> crate::norm::Normed for HypUnit<T> {
type Scalar = T;
#[inline]
fn norm_squared(&self) -> T {
-self.j() * self.j()
}
fn try_normalize(&self) -> Option<Self> {
let n = self.norm();
if n < T::epsilon() {
None
} else {
Some(self.scale(T::one() / n))
}
}
#[inline]
fn scale(&self, factor: T) -> Self {
Self::new_unchecked(self.j() * factor)
}
}
impl<T: Float> crate::norm::Normed for Hyperbolic<T> {
type Scalar = T;
#[inline]
fn norm_squared(&self) -> T {
self.real() * self.real() + -self.hyp() * self.hyp()
}
fn try_normalize(&self) -> Option<Self> {
let n = self.norm();
if n < T::epsilon() {
None
} else {
Some(self.scale(T::one() / n))
}
}
#[inline]
fn scale(&self, factor: T) -> Self {
Self::new_unchecked(self.real() * factor, self.hyp() * factor)
}
}
impl<T: Float> crate::norm::Normed for Scalar<T> {
type Scalar = T;
#[inline]
fn norm_squared(&self) -> T {
self.s() * self.s()
}
fn try_normalize(&self) -> Option<Self> {
let n = self.norm();
if n < T::epsilon() {
None
} else {
Some(self.scale(T::one() / n))
}
}
#[inline]
fn scale(&self, factor: T) -> Self {
Self::new_unchecked(self.s() * factor)
}
}
impl<T: Float + AbsDiffEq<Epsilon = T>> AbsDiffEq for HypUnit<T> {
type Epsilon = T;
fn default_epsilon() -> Self::Epsilon {
T::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
self.j().abs_diff_eq(&other.j(), epsilon)
}
}
impl<T: Float + RelativeEq<Epsilon = T>> RelativeEq for HypUnit<T> {
fn default_max_relative() -> Self::Epsilon {
T::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
self.j().relative_eq(&other.j(), epsilon, max_relative)
}
}
impl<T: Float + UlpsEq<Epsilon = T>> UlpsEq for HypUnit<T> {
fn default_max_ulps() -> u32 {
T::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
self.j().ulps_eq(&other.j(), epsilon, max_ulps)
}
}
impl<T: Float + AbsDiffEq<Epsilon = T>> AbsDiffEq for Hyperbolic<T> {
type Epsilon = T;
fn default_epsilon() -> Self::Epsilon {
T::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
self.real().abs_diff_eq(&other.real(), epsilon)
&& self.hyp().abs_diff_eq(&other.hyp(), epsilon)
}
}
impl<T: Float + RelativeEq<Epsilon = T>> RelativeEq for Hyperbolic<T> {
fn default_max_relative() -> Self::Epsilon {
T::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
self.real()
.relative_eq(&other.real(), epsilon, max_relative)
&& self.hyp().relative_eq(&other.hyp(), epsilon, max_relative)
}
}
impl<T: Float + UlpsEq<Epsilon = T>> UlpsEq for Hyperbolic<T> {
fn default_max_ulps() -> u32 {
T::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
self.real().ulps_eq(&other.real(), epsilon, max_ulps)
&& self.hyp().ulps_eq(&other.hyp(), epsilon, max_ulps)
}
}
impl<T: Float + AbsDiffEq<Epsilon = T>> AbsDiffEq for Scalar<T> {
type Epsilon = T;
fn default_epsilon() -> Self::Epsilon {
T::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
self.s().abs_diff_eq(&other.s(), epsilon)
}
}
impl<T: Float + RelativeEq<Epsilon = T>> RelativeEq for Scalar<T> {
fn default_max_relative() -> Self::Epsilon {
T::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
self.s().relative_eq(&other.s(), epsilon, max_relative)
}
}
impl<T: Float + UlpsEq<Epsilon = T>> UlpsEq for Scalar<T> {
fn default_max_ulps() -> u32 {
T::default_max_ulps()
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
self.s().ulps_eq(&other.s(), epsilon, max_ulps)
}
}
#[cfg(any(test, feature = "proptest-support"))]
#[allow(clippy::missing_docs_in_private_items)]
mod arbitrary_impls {
use super::*;
use proptest::prelude::*;
use proptest::strategy::BoxedStrategy;
use std::fmt::Debug;
impl<T: Float + Debug + 'static> Arbitrary for HypUnit<T> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
(-100.0f64..100.0)
.prop_map(|x0| HypUnit::new_unchecked(T::from_f64(x0)))
.boxed()
}
}
impl<T: Float + Debug + 'static> Arbitrary for Hyperbolic<T> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
(-100.0f64..100.0, -100.0f64..100.0)
.prop_map(|(x0, x1)| Hyperbolic::new_unchecked(T::from_f64(x0), T::from_f64(x1)))
.boxed()
}
}
impl<T: Float + Debug + 'static> Arbitrary for Scalar<T> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
(-100.0f64..100.0)
.prop_map(|x0| Scalar::new_unchecked(T::from_f64(x0)))
.boxed()
}
}
}
#[cfg(test)]
#[allow(clippy::missing_docs_in_private_items)]
mod verification_tests {
use super::*;
use crate::algebra::Multivector;
#[allow(unused_imports)]
use crate::norm::{DegenerateNormed, Normed};
use crate::signature::Cl1_0_0;
#[allow(unused_imports)]
use crate::wrappers::Unit;
use approx::relative_eq;
use proptest::prelude::*;
const REL_EPSILON: f64 = 1e-10;
proptest! {
#[test]
fn hypunit_add_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result = a + b;
let generic_result = mv_a + mv_b;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Add mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
#[test]
fn hypunit_sub_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result = a - b;
let generic_result = mv_a - mv_b;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Sub mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
#[test]
fn hypunit_neg_matches_multivector(a in any::<HypUnit<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let specialized_result = -a;
let generic_result = -mv_a;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Neg mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn hyperbolic_add_matches_multivector(a in any::<Hyperbolic<f64>>(), b in any::<Hyperbolic<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result = a + b;
let generic_result = mv_a + mv_b;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Add mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
#[test]
fn hyperbolic_sub_matches_multivector(a in any::<Hyperbolic<f64>>(), b in any::<Hyperbolic<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result = a - b;
let generic_result = mv_a - mv_b;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Sub mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
#[test]
fn hyperbolic_neg_matches_multivector(a in any::<Hyperbolic<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let specialized_result = -a;
let generic_result = -mv_a;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Neg mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn scalar_add_matches_multivector(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result = a + b;
let generic_result = mv_a + mv_b;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Add mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
#[test]
fn scalar_sub_matches_multivector(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result = a - b;
let generic_result = mv_a - mv_b;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Sub mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
#[test]
fn scalar_neg_matches_multivector(a in any::<Scalar<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let specialized_result = -a;
let generic_result = -mv_a;
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Neg mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn wedge_hypunit_scalar_hypunit_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::Wedge;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.wedge(&b);
let generic_result = mv_a.exterior(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Wedge product mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn wedge_scalar_hypunit_hypunit_matches_multivector(a in any::<Scalar<f64>>(), b in any::<HypUnit<f64>>()) {
use crate::ops::Wedge;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.wedge(&b);
let generic_result = mv_a.exterior(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Wedge product mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn wedge_scalar_scalar_scalar_matches_multivector(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::Wedge;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: Scalar<f64> = a.wedge(&b);
let generic_result = mv_a.exterior(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Wedge product mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn bulk_contraction_hypunit_hypunit_scalar_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
use crate::ops::BulkContract;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: Scalar<f64> = a.bulk_contract(&b);
let generic_result = mv_a.bulk_contraction(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Bulk contraction mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn bulk_contraction_hypunit_scalar_hypunit_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::BulkContract;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.bulk_contract(&b);
let generic_result = mv_a.bulk_contraction(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Bulk contraction mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn bulk_contraction_scalar_scalar_scalar_matches_multivector(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::BulkContract;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: Scalar<f64> = a.bulk_contract(&b);
let generic_result = mv_a.bulk_contraction(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Bulk contraction mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn weight_contraction_hypunit_hypunit_scalar_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
use crate::ops::WeightContract;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: Scalar<f64> = a.weight_contract(&b);
let generic_result = mv_a.weight_contraction(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Weight contraction mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn weight_contraction_hypunit_scalar_hypunit_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::WeightContract;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.weight_contract(&b);
let generic_result = mv_a.weight_contraction(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Weight contraction mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn weight_contraction_scalar_scalar_scalar_matches_multivector(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::WeightContract;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: Scalar<f64> = a.weight_contract(&b);
let generic_result = mv_a.weight_contraction(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Weight contraction mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn bulk_expansion_hypunit_hypunit_hypunit_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
use crate::ops::BulkExpand;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.bulk_expand(&b);
let generic_result = mv_a.bulk_expansion(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Bulk expansion mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn bulk_expansion_scalar_hypunit_scalar_matches_multivector(a in any::<Scalar<f64>>(), b in any::<HypUnit<f64>>()) {
use crate::ops::BulkExpand;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: Scalar<f64> = a.bulk_expand(&b);
let generic_result = mv_a.bulk_expansion(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Bulk expansion mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn bulk_expansion_scalar_scalar_hypunit_matches_multivector(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::BulkExpand;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.bulk_expand(&b);
let generic_result = mv_a.bulk_expansion(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Bulk expansion mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn weight_expansion_hypunit_hypunit_hypunit_matches_multivector(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
use crate::ops::WeightExpand;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.weight_expand(&b);
let generic_result = mv_a.weight_expansion(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Weight expansion mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn weight_expansion_scalar_hypunit_scalar_matches_multivector(a in any::<Scalar<f64>>(), b in any::<HypUnit<f64>>()) {
use crate::ops::WeightExpand;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: Scalar<f64> = a.weight_expand(&b);
let generic_result = mv_a.weight_expansion(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Weight expansion mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn weight_expansion_scalar_scalar_hypunit_matches_multivector(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
use crate::ops::WeightExpand;
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let specialized_result: HypUnit<f64> = a.weight_expand(&b);
let generic_result = mv_a.weight_expansion(&mv_b);
let specialized_mv: Multivector<f64, Cl1_0_0> = specialized_result.into();
prop_assert!(
relative_eq!(specialized_mv, generic_result, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"Weight expansion mismatch: specialized={:?}, generic={:?}",
specialized_mv, generic_result
);
}
}
proptest! {
#[test]
fn de_morgan_geometric_hypunit(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let lhs = (mv_a * mv_b).complement();
let rhs = mv_a.complement().antiproduct(&mv_b.complement());
prop_assert!(
relative_eq!(lhs, rhs, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"De Morgan (geometric) failed: complement(a*b)={:?}, complement(a)⋇complement(b)={:?}",
lhs, rhs
);
}
#[test]
fn de_morgan_antiproduct_hypunit(a in any::<HypUnit<f64>>(), b in any::<HypUnit<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let lhs = mv_a.antiproduct(&mv_b).complement();
let rhs = mv_a.complement() * mv_b.complement();
prop_assert!(
relative_eq!(lhs, rhs, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"De Morgan (antiproduct) failed: complement(a⋇b)={:?}, complement(a)*complement(b)={:?}",
lhs, rhs
);
}
}
proptest! {
#[test]
fn de_morgan_geometric_scalar(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let lhs = (mv_a * mv_b).complement();
let rhs = mv_a.complement().antiproduct(&mv_b.complement());
prop_assert!(
relative_eq!(lhs, rhs, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"De Morgan (geometric) failed: complement(a*b)={:?}, complement(a)⋇complement(b)={:?}",
lhs, rhs
);
}
#[test]
fn de_morgan_antiproduct_scalar(a in any::<Scalar<f64>>(), b in any::<Scalar<f64>>()) {
let mv_a: Multivector<f64, Cl1_0_0> = a.into();
let mv_b: Multivector<f64, Cl1_0_0> = b.into();
let lhs = mv_a.antiproduct(&mv_b).complement();
let rhs = mv_a.complement() * mv_b.complement();
prop_assert!(
relative_eq!(lhs, rhs, epsilon = REL_EPSILON, max_relative = REL_EPSILON),
"De Morgan (antiproduct) failed: complement(a⋇b)={:?}, complement(a)*complement(b)={:?}",
lhs, rhs
);
}
}
}