use either::Either;
#[cfg(feature = "derive_serdes")]
use serde;
use crate::num_traits as num;
use crate::types::{Affinity, Projectivity, Sign};
pub trait ProjectiveSpace <S, V> : VectorSpace <S> where
V : VectorSpace <S> + std::fmt::Display,
S : Field + std::fmt::Display
{
fn homography <A> (
affinity : Affinity <S, A, A, <A::Vector as Module <S>>::LinearEndo>
) -> Projectivity <S, V, V, Self, Self, Self::LinearEndo> where
A : AffineSpace <S, Vector=V>;
fn homogeneous <A> (point_or_vector : Either <A::Point, A::Vector>)
-> Self
where
A : AffineSpace <S, Vector=V>,
V : GroupAction <A::Point>;
}
pub trait EuclideanSpace <S : Real> : AffineSpace <S> where
Self::Vector : InnerProductSpace <S>
{
fn origin() -> Self::Point {
use num::Zero;
Self::Point::from_vector (Self::Vector::zero())
}
}
pub trait AffineSpace <S : Field> {
type Point : Point <Self::Vector>;
type Vector : VectorSpace <S> + GroupAction <Self::Point>;
}
impl <S, V> AffineSpace <S> for V where
S : Field,
V : VectorSpace <S> + GroupAction <V> + Point <V>
{
type Point = Self;
type Vector = Self;
}
pub trait Point <V> : Sized + std::ops::Sub <Self, Output=V> where
V : AdditiveGroup + GroupAction <Self>
{
fn to_vector (self) -> V;
fn from_vector (vector : V) -> Self;
fn origin() -> Self {
Self::from_vector (V::zero())
}
}
pub trait GroupAction <X> : Group {
fn action (self, x : X) -> X;
}
impl <G> GroupAction <G> for G where G : Group {
fn action (self, g : Self) -> Self {
Self::operation (g, self)
}
}
pub trait InnerProductSpace <S : Field> : VectorSpace <S> + Dot <S> {
fn inner_product (self, other : Self) -> S {
self.dot (other)
}
}
impl <V, S> NormedVectorSpace <S> for V where
V : InnerProductSpace <S>,
S : Field
{
fn norm_squared (self) -> S {
self.self_dot()
}
}
pub trait Dot <S : Ring> : Module <S> {
fn dot (self, other : Self) -> S;
fn self_dot (self) -> S {
self.dot (self)
}
}
pub trait NormedVectorSpace <S : Field> : VectorSpace <S> {
fn norm_squared (self) -> S;
fn norm (self) -> S where S : Sqrt {
self.norm_squared().sqrt()
}
fn normalize (self) -> Self where S : Sqrt {
self / self.norm()
}
fn unit_sigvec (self) -> Self where S : SignedExt + Sqrt {
let v = self.sigvec();
if v.is_zero() {
v
} else {
v.normalize()
}
}
}
impl <V, S> MetricSpace <S> for V where
V : NormedVectorSpace <S>,
S : Field
{
fn distance_squared (self, other : Self) -> S {
(self - other).norm_squared()
}
}
pub trait MetricSpace <S> : Sized {
fn distance_squared (self, other : Self) -> S;
fn distance (self, other : Self) -> S where S : Sqrt {
self.distance_squared (other).sqrt()
}
}
pub trait VectorSpace <S : Field> :
Module <S> + std::ops::Div <S, Output=Self> + Copy
{
fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S;
fn sigvec (self) -> Self where S : SignedExt {
self.map (|x| x.signum_or_zero())
}
}
pub trait Module <S : Ring> :
AdditiveGroup + std::ops::Mul <S, Output=Self> + Copy
{
type LinearEndo : LinearMap <S, Self, Self> + MultiplicativeMonoid;
}
pub trait LinearMap <S, V, W> : std::ops::Mul <V, Output=W> + Copy where
S : Ring,
V : Module <S>,
W : Module <S>
{
fn determinant (self) -> S;
fn transpose (self) -> Self;
}
pub trait Real : Field + SignedExt + Exp + Sqrt + Trig + MinMax {
fn pi() -> Self;
fn frac_pi_3() -> Self;
fn sqrt_3() -> Self;
fn frac_1_sqrt_3() -> Self;
fn floor (self) -> Self;
fn ceil (self) -> Self;
fn trunc (self) -> Self;
fn fract (self) -> Self;
}
pub trait Field : Ring + MultiplicativeGroup + Powi + Powf {
fn half() -> Self {
Self::one() / Self::two()
}
fn two() -> Self {
Self::one() + Self::one()
}
fn three() -> Self {
Self::one() + Self::one() + Self::one()
}
fn four() -> Self {
Self::two() * Self::two()
}
fn five() -> Self {
Self::two() + Self::three()
}
fn six() -> Self {
Self::two() * Self::three()
}
fn seven() -> Self {
Self::three() + Self::four()
}
fn eight() -> Self {
Self::two() * Self::two() * Self::two()
}
fn nine() -> Self {
Self::three() * Self::three()
}
fn ten() -> Self {
Self::two() * Self::five()
}
}
pub trait MultiplicativeGroup : MultiplicativeMonoid +
std::ops::Div <Self, Output=Self> + std::ops::DivAssign +
num::Inv <Output=Self>
{ }
pub trait Integer : Ring + num::PrimInt + num::Signed { }
pub trait Ring : Copy + PartialOrd + MinMax + AdditiveGroup +
std::ops::Mul <Self, Output=Self> + std::ops::MulAssign + num::Signed +
num::MulAdd <Self, Self, Output=Self> + num::MulAddAssign <Self, Self>
{
fn squared (self) -> Self {
self * self
}
fn cubed (self) -> Self {
self * self * self
}
}
pub trait AdditiveGroup : AdditiveMonoid +
std::ops::Sub <Self, Output=Self> + std::ops::SubAssign +
std::ops::Neg <Output=Self>
{ }
pub trait Group : PartialEq + std::ops::Neg <Output=Self> {
fn identity() -> Self;
fn operation (a : Self, b : Self) -> Self;
}
pub trait MultiplicativeMonoid : Sized + PartialEq +
std::ops::Mul <Self, Output=Self> + std::ops::MulAssign + num::One
{ }
pub trait AdditiveMonoid : Sized + PartialEq +
std::ops::Add <Self, Output=Self> + std::ops::AddAssign + num::Zero
{ }
pub trait Angle <S : Real> : Clone + Copy + PartialEq + PartialOrd + Sized +
AdditiveGroup + std::ops::Div <Self, Output=S> +
std::ops::Mul <S, Output=Self> + std::ops::Div <S, Output=Self> +
std::ops::Rem <Self, Output=Self>
{
fn full_turn() -> Self;
fn half_turn() -> Self {
Self::full_turn() / S::two()
}
fn wrap_signed (self) -> Self {
let out = (self + Self::half_turn()).wrap_unsigned() - Self::half_turn();
if out == -Self::half_turn() {
Self::half_turn()
} else {
out
}
}
fn wrap_unsigned (self) -> Self {
if self >= Self::full_turn() {
self % Self::full_turn()
} else if self < Self::zero() {
self + Self::full_turn() *
((self / Self::full_turn()).trunc().abs() + S::one())
} else {
self
}
}
}
pub trait Pow {
fn pow (self, exp : u32) -> Self;
}
pub trait Powi {
fn powi (self, n : i32) -> Self;
}
pub trait Powf {
fn powf (self, n : Self) -> Self;
}
pub trait Exp {
fn exp (self) -> Self;
}
pub trait Sqrt {
fn sqrt (self) -> Self;
}
pub trait Trig : Sized {
fn sin (self) -> Self;
fn sin_cos (self) -> (Self, Self);
fn cos (self) -> Self;
fn tan (self) -> Self;
fn asin (self) -> Self;
fn acos (self) -> Self;
fn atan (self) -> Self;
fn atan2 (self, other : Self) -> Self;
}
pub trait MinMax {
fn min (self, other : Self) -> Self;
fn max (self, other : Self) -> Self;
fn clamp (self, min : Self, max : Self) -> Self;
}
pub trait SignedExt : num::Signed {
#[inline]
fn sign (self) -> Sign {
if self.is_zero() {
Sign::Zero
} else if self.is_positive() {
Sign::Positive
} else {
debug_assert!(self.is_negative());
Sign::Negative
}
}
#[inline]
fn signum_or_zero (self) -> Self where Self : num::Zero {
if self.is_zero() {
Self::zero()
} else {
self.signum()
}
}
}
#[cfg(not(feature = "derive_serdes"))]
pub trait MaybeSerDes { }
#[cfg(feature = "derive_serdes")]
pub trait MaybeSerDes : serde::Serialize + serde::de::DeserializeOwned { }
impl <
#[cfg(not(feature = "derive_serdes"))]
T,
#[cfg(feature = "derive_serdes")]
T : serde::Serialize + serde::de::DeserializeOwned
> MaybeSerDes for T { }
macro impl_integer ($type:ty) {
impl Integer for $type { }
impl Ring for $type { }
impl AdditiveGroup for $type { }
impl AdditiveMonoid for $type { }
impl SignedExt for $type { }
impl MinMax for $type {
fn min (self, other : Self) -> Self {
Ord::min (self, other)
}
fn max (self, other : Self) -> Self {
Ord::max (self, other)
}
fn clamp (self, min : Self, max : Self) -> Self {
Ord::clamp (self, min, max)
}
}
impl Pow for $type {
fn pow (self, exp : u32) -> Self {
self.pow (exp)
}
}
}
impl_integer!(i8);
impl_integer!(i16);
impl_integer!(i32);
impl_integer!(i64);
macro impl_real_float ($type:ident) {
impl VectorSpace <Self> for $type {
fn map <F> (self, mut f : F) -> Self where F : FnMut (Self) -> Self {
f (self)
}
}
impl Module <Self> for $type {
type LinearEndo = Self;
}
impl LinearMap <Self, Self, Self> for $type {
fn determinant (self) -> Self {
self
}
fn transpose (self) -> Self {
self
}
}
impl Real for $type {
fn pi() -> Self {
std::$type::consts::PI
}
fn frac_pi_3() -> Self {
std::$type::consts::FRAC_PI_3
}
#[allow(clippy::excessive_precision)]
fn sqrt_3() -> Self {
1.732050807568877293527446341505872366942805253810380628055f64 as $type
}
#[allow(clippy::excessive_precision)]
fn frac_1_sqrt_3() -> Self {
(1.0f64 / 1.732050807568877293527446341505872366942805253810380628055f64) as $type
}
fn floor (self) -> Self {
self.floor()
}
fn ceil (self) -> Self {
self.ceil()
}
fn trunc (self) -> Self {
self.trunc()
}
fn fract (self) -> Self {
self.fract()
}
}
impl Field for $type { }
impl MultiplicativeGroup for $type { }
impl MultiplicativeMonoid for $type { }
impl Ring for $type { }
impl AdditiveGroup for $type { }
impl AdditiveMonoid for $type { }
impl SignedExt for $type { }
impl MinMax for $type {
fn min (self, other : Self) -> Self {
self.min (other)
}
fn max (self, other : Self) -> Self {
self.max (other)
}
fn clamp (self, min : Self, max : Self) -> Self {
self.clamp (min, max)
}
}
impl Powi for $type {
fn powi (self, n : i32) -> Self {
self.powi (n as i32)
}
}
impl Powf for $type {
fn powf (self, n : Self) -> Self {
self.powf (n)
}
}
impl Exp for $type {
fn exp (self) -> Self {
self.exp()
}
}
impl Sqrt for $type {
fn sqrt (self) -> Self {
self.sqrt()
}
}
impl Trig for $type {
fn sin (self) -> Self {
self.sin()
}
fn sin_cos (self) -> (Self, Self) {
self.sin_cos()
}
fn cos (self) -> Self {
self.cos()
}
fn tan (self) -> Self {
self.tan()
}
fn asin (self) -> Self {
self.asin()
}
fn acos (self) -> Self {
self.acos()
}
fn atan (self) -> Self {
self.atan()
}
fn atan2 (self, other : Self) -> Self {
self.atan2 (other)
}
}
}
impl_real_float!(f32);
impl_real_float!(f64);