use crate::algebra::lattice::Lattice;
use crate::algebra::ring::{DivisionRing, EuclideanDomain};
use crate::operators::exp::Exponentiation;
use crate::operators::trig::TrigOps;
use crate::operators::{Additive, ClosedOps, Multiplicative, Operator};
use crate::properties::archimedean::ArchimedeanDiv;
use crate::properties::helpers::identity::{One, Zero};
pub trait Field<A: Operator = Additive, M: Operator = Multiplicative>: DivisionRing<A, M> {}
pub trait PartiallyOrderedField<A: Operator = Additive, M: Operator = Multiplicative>:
Field<A, M> + Lattice
{
}
pub trait RealField:
Field + TrigOps + EuclideanDomain + ArchimedeanDiv + Lattice + Exponentiation
{
}
pub trait ComplexField:
Field + TrigOps + EuclideanDomain + ArchimedeanDiv + Lattice + Exponentiation
{
type RealField: RealField;
fn from_real(re: Self::RealField) -> Self;
fn from_imaginary(im: Self::RealField) -> Self;
fn real(&self) -> Self::RealField;
fn imaginary(&self) -> Self::RealField;
fn modulus(&self) -> Self::RealField;
fn modulus_squared(&self) -> Self::RealField;
fn argument(&self) -> Self::RealField;
fn scale(&self, scalar: Self::RealField) -> Self;
fn unscale(&self, scalar: Self::RealField) -> Self;
fn to_polar(&self) -> (Self::RealField, Self::RealField) {
(self.modulus(), self.argument())
}
fn to_exponential(&self) -> (Self::RealField, Self);
fn signum(&self) -> Self {
self.to_exponential().1
}
}
impl<T, A: Operator, M: Operator> Field<A, M> for T where T: DivisionRing<A, M> + ClosedOps {}
impl<T, A: Operator, M: Operator> PartiallyOrderedField<A, M> for T where T: Field<A, M> + Lattice {}
impl<T> RealField for T where
T: Field + TrigOps + Exponentiation + EuclideanDomain + ArchimedeanDiv + Lattice
{
}
macro_rules! impl_complex {
($($set:ty)*) => {
$(
impl ComplexField for $set {
type RealField = $set;
#[inline]
fn from_real(re: Self::RealField) -> Self {
re
}
#[inline]
fn from_imaginary(_: Self::RealField) -> Self {
Self::zero()
}
#[inline]
fn real(&self) -> Self::RealField {
*self
}
#[inline]
fn imaginary(&self) -> Self::RealField {
Self::zero()
}
#[inline]
fn modulus(&self) -> Self::RealField {
self.abs()
}
#[inline]
fn modulus_squared(&self) -> Self::RealField {
self * self
}
#[inline]
fn argument(&self) -> Self::RealField {
if *self >= Self::zero() {
Self::zero()
} else {
Self::PI
}
}
#[inline]
fn scale(&self, scalar: Self::RealField) -> Self {
self * scalar
}
#[inline]
fn unscale(&self, scalar: Self::RealField) -> Self {
self / scalar
}
#[inline]
fn to_exponential(&self) -> (Self::RealField, Self) {
let m = self.modulus();
if !m.is_zero() {
(m, self.unscale(m))
} else {
(Self::RealField::zero(), Self::one())
}
}
}
)*
}
}
impl_complex!(f32 f64);