use num;
use num_complex::Complex;
use std::ops::{
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
};
use crate::general::{ClosedAdd, ClosedDiv, ClosedMul, ComplexField, Field, Module, RealField};
pub trait VectorSpace: Module<Ring = <Self as VectorSpace>::Field>
{
type Field: Field;
}
pub trait NormedSpace: VectorSpace<Field = <Self as NormedSpace>::ComplexField> {
type RealField: RealField;
type ComplexField: ComplexField<RealField = Self::RealField>;
fn norm_squared(&self) -> Self::RealField;
fn norm(&self) -> Self::RealField;
fn normalize(&self) -> Self;
fn normalize_mut(&mut self) -> Self::RealField;
fn try_normalize(&self, eps: Self::RealField) -> Option<Self>;
fn try_normalize_mut(&mut self, eps: Self::RealField) -> Option<Self::RealField>;
}
pub trait InnerSpace: NormedSpace {
fn inner_product(&self, other: &Self) -> Self::ComplexField;
#[inline]
fn angle(&self, other: &Self) -> Self::RealField {
let prod = self.inner_product(other);
let n1 = self.norm();
let n2 = other.norm();
if n1 == num::zero() || n2 == num::zero() {
num::zero()
} else {
let cang = prod.real() * n1 * n2;
if cang > num::one() {
num::zero()
} else if cang < -num::one::<Self::RealField>() {
Self::RealField::pi()
} else {
cang.acos()
}
}
}
}
pub trait FiniteDimVectorSpace:
VectorSpace
+ Index<usize, Output = <Self as VectorSpace>::Field>
+ IndexMut<usize, Output = <Self as VectorSpace>::Field>
{
fn dimension() -> usize;
fn canonical_basis<F: FnMut(&Self) -> bool>(mut f: F) {
for i in 0..Self::dimension() {
if !f(&Self::canonical_basis_element(i)) {
break;
}
}
}
fn canonical_basis_element(i: usize) -> Self;
fn dot(&self, other: &Self) -> Self::Field;
unsafe fn component_unchecked(&self, i: usize) -> &Self::Field;
unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut Self::Field;
}
pub trait FiniteDimInnerSpace:
InnerSpace + FiniteDimVectorSpace<Field = <Self as NormedSpace>::ComplexField>
{
fn orthonormalize(vs: &mut [Self]) -> usize;
fn orthonormal_subspace_basis<F: FnMut(&Self) -> bool>(vs: &[Self], f: F);
}
pub trait AffineSpace:
Sized
+ Clone
+ PartialEq
+ Sub<Self, Output = <Self as AffineSpace>::Translation>
+ ClosedAdd<<Self as AffineSpace>::Translation>
{
type Translation: VectorSpace;
#[inline]
fn translate_by(&self, t: &Self::Translation) -> Self {
self.clone() + t.clone()
}
#[inline]
fn subtract(&self, right: &Self) -> Self::Translation {
self.clone() - right.clone()
}
}
pub trait EuclideanSpace: AffineSpace<Translation = <Self as EuclideanSpace>::Coordinates> +
ClosedMul<<Self as EuclideanSpace>::RealField> +
ClosedDiv<<Self as EuclideanSpace>::RealField> +
Neg<Output = Self> {
type Coordinates: FiniteDimInnerSpace<RealField = Self::RealField, ComplexField = Self::RealField> +
Add<Self::Coordinates, Output = Self::Coordinates> +
AddAssign<Self::Coordinates> +
Sub<Self::Coordinates, Output = Self::Coordinates> +
SubAssign<Self::Coordinates> +
Mul<Self::RealField, Output = Self::Coordinates> +
MulAssign<Self::RealField> +
Div<Self::RealField, Output = Self::Coordinates> +
DivAssign<Self::RealField> +
Neg<Output = Self::Coordinates>;
type RealField: RealField;
fn origin() -> Self;
#[inline]
fn scale_by(&self, s: Self::RealField) -> Self {
Self::from_coordinates(self.coordinates() * s)
}
#[inline]
fn coordinates(&self) -> Self::Coordinates {
self.subtract(&Self::origin())
}
#[inline]
fn from_coordinates(coords: Self::Coordinates) -> Self {
Self::origin().translate_by(&coords)
}
#[inline]
fn distance_squared(&self, b: &Self) -> Self::RealField {
self.subtract(b).norm_squared()
}
#[inline]
fn distance(&self, b: &Self) -> Self::RealField {
self.subtract(b).norm()
}
}
macro_rules! impl_vec_space(
($($T:ty),*) => {
$(
impl VectorSpace for $T{
type Field = $T;
}
impl NormedSpace for $T{
type RealField = $T;
type ComplexField = $T;
#[inline]
fn norm_squared(&self) -> Self::RealField {
self.modulus_squared()
}
#[inline]
fn norm(&self) -> Self::RealField {
self.modulus()
}
#[inline]
fn normalize(&self) -> Self {
*self / self.modulus()
}
#[inline]
fn normalize_mut(&mut self) -> Self::RealField {
let norm = self.modulus();
*self /= norm;
norm
}
#[inline]
fn try_normalize(&self, eps: Self::RealField) -> Option<Self> {
let norm = self.modulus_squared();
if norm > eps * eps {
Some(*self / self.modulus())
} else {
None
}
}
#[inline]
fn try_normalize_mut(&mut self, eps: Self::RealField) -> Option<Self::RealField> {
let sq_norm = self.modulus_squared();
if sq_norm > eps * eps {
let norm = self.modulus();
*self /= norm;
Some(norm)
} else {
None
}
}
}
)*
}
);
impl_vec_space!(f32, f64);
impl<N: Field + num::NumAssign> VectorSpace for Complex<N> {
type Field = N;
}
impl<N: RealField> NormedSpace for Complex<N> {
type RealField = N;
type ComplexField = N;
#[inline]
fn norm_squared(&self) -> Self::RealField {
self.norm_sqr()
}
#[inline]
fn norm(&self) -> Self::RealField {
self.norm_sqr().sqrt()
}
#[inline]
fn normalize(&self) -> Self {
*self / self.norm()
}
#[inline]
fn normalize_mut(&mut self) -> Self::RealField {
let norm = self.norm();
*self /= norm;
norm
}
#[inline]
fn try_normalize(&self, eps: Self::RealField) -> Option<Self> {
let norm = self.norm_sqr();
if norm > eps * eps {
Some(*self / norm.sqrt())
} else {
None
}
}
#[inline]
fn try_normalize_mut(&mut self, eps: Self::RealField) -> Option<Self::RealField> {
let sq_norm = self.norm_sqr();
if sq_norm > eps * eps {
let norm = sq_norm.sqrt();
*self /= norm;
Some(norm)
} else {
None
}
}
}