use crate::op::Operator;
use super::real::Real;
use super::{DivisionRing, Field, Group, Magma, VectorSpace};
pub trait NormedSpace<Oa: Operator, Om: Operator>: VectorSpace<Oa, Om>
where
Self::Scalar: Field<Oa, Om>,
{
type RealField: Real;
fn norm_squared(&self) -> Self::RealField;
fn norm(&self) -> Self::RealField {
self.norm_squared().sqrt()
}
fn scale_real(&self, r: Self::RealField) -> Self
where
Self: Sized;
fn normalize(&self) -> Self
where
Self: Sized,
{
self.scale_real(self.norm().inv())
}
fn try_normalize(&self, eps: Self::RealField) -> Option<Self>
where
Self: Sized,
{
let n = self.norm();
if n > eps { Some(self.scale_real(n.inv())) } else { None }
}
}
pub trait InnerSpace<Oa: Operator, Om: Operator>: NormedSpace<Oa, Om>
where
Self::Scalar: Field<Oa, Om>,
{
fn inner_product(&self, other: &Self) -> Self::RealField;
fn angle(&self, other: &Self) -> Self::RealField
where
Self: Sized,
{
let cos = self.inner_product(other) / (self.norm() * other.norm());
cos.acos()
}
}
pub trait FiniteDimVectorSpace<Oa: Operator, Om: Operator>: VectorSpace<Oa, Om>
where
Self::Scalar: Field<Oa, Om>,
{
fn dimension() -> usize;
fn canonical_basis_element(i: usize) -> Self;
fn canonical_basis<F: FnMut(&Self) -> bool>(mut f: F)
where
Self: Sized,
{
for i in 0..Self::dimension() {
if f(&Self::canonical_basis_element(i)) {
break;
}
}
}
fn dot(&self, other: &Self) -> Self::Scalar;
}
pub trait FiniteDimInnerSpace<Oa: Operator, Om: Operator>:
FiniteDimVectorSpace<Oa, Om> + InnerSpace<Oa, Om>
where
Self::Scalar: Field<Oa, Om>,
{
fn orthonormalize(vs: &mut [Self]) -> usize
where
Self: Copy,
{
let zero = Self::RealField::default();
let mut k = 0;
for i in 0..vs.len() {
let mut v = vs[i];
for u in vs[..k].iter() {
let proj = v.inner_product(u);
let term = u.scale_real(proj);
v = <Self as Magma<Oa>>::combine(&v, &<Self as Group<Oa>>::inverse(&term));
}
let n = v.norm();
if n > zero {
vs[k] = v.scale_real(n.inv());
k += 1;
}
}
k
}
}