use crate::algebra::*;
use crate::analysis::*;
pub trait Metric<X, R:Real> {
fn distance(&self, x1:X, x2:X) -> R;
}
pub trait Seminorm<K:UnitalRing, X:RingModule<K>, R:Real> {
#[inline] fn norm(&self, x:X) -> R;
#[inline] fn normalize(&self, x:X) -> X where K:From<R> {x.clone() * K::from(self.norm(x).inv())}
}
pub trait Norm<K:UnitalRing, X:RingModule<K>, R:Real>: Seminorm<K,X,R> {}
pub trait InnerProduct<K:ComplexRing, M:RingModule<K>>: HermitianForm<K,M> + Norm<K,M,K::Real>{}
pub trait NormedMetric<K,X,R> = Norm<K,X,R> + Metric<X,R> where K:UnitalRing, X:RingModule<K>, R:Real;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct InnerProductMetric;
impl<R:Real, V:InnerProductSpace<R>> Metric<V,R> for InnerProductMetric {
#[inline(always)] fn distance(&self, x1:V, x2:V) -> R {x1.dist_euclid(x2)}
}
impl<K:ComplexRing, V:InnerProductSpace<K>> Seminorm<K,V,K::Real> for InnerProductMetric {
#[inline(always)] fn norm(&self, x:V) -> K::Real {x.norm()}
}
impl<K:ComplexRing, V:InnerProductSpace<K>> Norm<K,V,K::Real> for InnerProductMetric {}
impl<K:ComplexRing, V:InnerProductSpace<K>> SesquilinearForm<K,V> for InnerProductMetric {
#[inline] fn product_of(&self, v1:V, v2:V) -> K {v1.inner_product(v2)}
#[inline] fn sigma(&self, x:K) -> K {x.conj()}
#[inline] fn sigma_inv(&self, x:K) -> K {x.conj()}
}
impl<K:ComplexRing, V:InnerProductSpace<K>> ReflexiveForm<K,V> for InnerProductMetric {}
impl<K:ComplexRing, V:InnerProductSpace<K>> SymSesquilinearForm<K,V> for InnerProductMetric {}
impl<K:Real, V:InnerProductSpace<K>> BilinearForm<K,V> for InnerProductMetric {}
impl<K:ComplexRing, V:InnerProductSpace<K>> ComplexSesquilinearForm<K,V> for InnerProductMetric {}
impl<K:ComplexRing, V:InnerProductSpace<K>> InnerProduct<K,V> for InnerProductMetric {}
pub trait InnerProductSpace<F: ComplexRing>: RingModule<F> {
fn inner_product(self, rhs:Self) -> F;
#[inline] fn norm_sqrd(self) -> F::Real {self.clone().inner_product(self).as_real()}
#[inline] fn norm(self) -> F::Real {self.norm_sqrd().sqrt()}
#[inline] fn dist_euclid(self, rhs: Self) -> F::Real {(self - rhs).norm()}
#[inline] fn normalized(self) -> Self where F:From<<F as ComplexSubset>::Real> {
self.clone() * F::from(self.norm().inv())
}
#[inline] fn orthogonal(self, rhs:Self) -> bool {self.inner_product(rhs).is_zero()}
#[inline] fn reject(self, rhs: Self) -> Self where F:ComplexField { rhs.clone() - self.project(rhs) }
#[inline] fn project(self, rhs: Self) -> Self where F:ComplexField {
let l = self.clone().inner_product(self.clone()).inv() * self.clone().inner_product(rhs);
self * l
}
#[inline] fn angle(self, rhs: Self) -> F where F:Trig+From<<F as ComplexSubset>::Real> {
let l1 = self.clone().norm();
let l2 = rhs.clone().norm();
(self.inner_product(rhs) * (l1*l2).inv().into()).acos()
}
}
#[cfg(feature = "std")]
macro_rules! impl_metric {
(@int $($f:ident)*) => {$(
impl InnerProductSpace<$f> for $f {
#[inline(always)] fn inner_product(self, rhs:Self) -> $f {self * rhs}
#[inline(always)] fn norm(self) -> <$f as ComplexSubset>::Real {$f::as_real(self.abs())}
#[inline(always)] fn orthogonal(self, rhs:Self) -> bool {self==0 || rhs==0}
}
)*};
(@float $($f:ident)*) => {$(
impl InnerProductSpace<$f> for $f {
#[inline(always)] fn inner_product(self, rhs:Self) -> $f {self * rhs}
#[inline(always)] fn norm(self) -> $f {self.abs()}
#[inline(always)] fn normalized(self) -> $f {self.signum()}
#[inline(always)] fn orthogonal(self, rhs:Self) -> bool {self==0.0 || rhs==0.0}
#[inline(always)] fn reject(self, rhs: Self) -> Self { if self==0.0 {rhs} else {0.0} }
#[inline(always)] fn project(self, rhs: Self) -> Self { if self==0.0 {0.0} else {rhs} }
#[inline(always)]
fn angle(self, rhs: Self) -> $f {
if (self==0.0) ^ (rhs==0.0) {
::core::$f::consts::FRAC_PI_2
} else if (self<0.0) ^ (rhs<0.0) {
::core::$f::consts::PI
} else {
0.0
}
}
}
)*}
}
#[cfg(feature = "std")]
mod impls {
use super::{ ComplexSubset, InnerProductSpace };
impl_metric!(@float f32 f64);
impl_metric!(@int i32 i64);
}