use crate::algebra::*;
pub use core::cmp::{PartialOrd, Ord};
pub trait AddOrdered: PartialOrd {}
pub trait MulOrdered: PartialOrd {}
pub trait Signed: PartialOrd + Zero {
fn positive(&self) -> bool;
fn negative(&self) -> bool;
fn non_negative(&self) -> bool;
fn non_positive(&self) -> bool;
}
impl<G: PartialOrd + Zero> Signed for G {
#[inline] default fn positive(&self) -> bool { self > &Self::zero() }
#[inline] default fn negative(&self) -> bool { self < &Self::zero() }
#[inline] default fn non_negative(&self) -> bool { self >= &Self::zero() }
#[inline] default fn non_positive(&self) -> bool { self <= &Self::zero() }
}
pub trait Sign: Signed {
fn signum(self) -> Self;
fn abs(self) -> Self;
}
pub trait ArchimedeanProperty: AddOrdered + AddAssociative {}
pub trait ArchimedeanDiv: Sized + ArchimedeanProperty {
fn embed_nat<N:Natural>(n:N) -> Self;
fn div_arch(self, rhs: Self) -> Self;
fn rem_arch(self, rhs: Self) -> Self;
fn div_alg_arch(self, rhs: Self) -> (Self, Self);
}
pub trait OrdMagma = AddMagma + AddOrdered;
pub trait OrdSemigroup = OrdMagma + AddSemigroup;
pub trait OrdLoop = OrdMagma + AddLoop;
pub trait OrdMonoid = OrdSemigroup + AddMonoid + Signed;
pub trait OrdGroup = OrdMonoid + AddGroup;
pub trait OrdAbelianGroup = OrdGroup + AddAbelianGroup;
pub trait OrdSemiring = Semiring + OrdMonoid + MulOrdered;
pub trait OrdUnitalSemiring = OrdSemiring + UnitalSemiring;
pub trait OrdCommutativeSemiring = OrdUnitalSemiring + CommutativeSemiring;
pub trait OrdDivisionSemiring = OrdUnitalSemiring + DivisionSemiring;
pub trait OrdRing = Ring + OrdAbelianGroup + MulOrdered;
pub trait OrdUnitalRing = OrdRing + UnitalRing + Sign;
pub trait OrdCommutativeRing = OrdUnitalRing + CommutativeRing;
pub trait OrdDivisionRing = OrdCommutativeRing + DivisionRing;
pub trait OrdField = OrdUnitalRing + Field;
pub trait ArchSemigroup = OrdSemigroup + ArchimedeanProperty;
pub trait ArchMonoid = ArchSemigroup + OrdMonoid;
pub trait ArchGroup = ArchMonoid + OrdGroup;
pub trait ArchAbelianGroup = ArchMonoid + OrdAbelianGroup;
pub trait ArchSemiring = ArchMonoid + OrdSemiring;
pub trait ArchUnitalSemiring = ArchSemiring + OrdUnitalSemiring + ArchimedeanDiv;
pub trait ArchCommutativeSemiring = ArchUnitalSemiring + OrdCommutativeSemiring;
pub trait ArchDivisionSemiring = ArchCommutativeSemiring + OrdDivisionSemiring;
pub trait ArchRing = ArchAbelianGroup + OrdRing;
pub trait ArchUnitalRing = ArchRing + OrdUnitalRing + ArchimedeanDiv;
pub trait ArchCommutativeRing = ArchUnitalRing + OrdCommutativeRing;
pub trait ArchDivisionRing = ArchCommutativeRing + OrdDivisionRing;
pub trait ArchField = ArchUnitalRing + OrdField;
macro_rules! impl_ordered_int {
($($t:ident)*) => {$(
impl AddOrdered for $t {}
impl MulOrdered for $t {}
impl ArchimedeanProperty for $t {}
impl Sign for $t {
#[inline] fn signum(self) -> Self { $t::signum(self) }
#[inline] fn abs(self) -> Self { $t::abs(self) }
}
impl ArchimedeanDiv for $t {
#[inline] fn embed_nat<N:Natural>(n:N) -> Self { (1).mul_n(n) }
#[inline] fn div_arch(self, rhs:Self) -> Self {self.div_euclid(rhs)}
#[inline] fn rem_arch(self, rhs:Self) -> Self {self.rem_euclid(rhs)}
#[inline] fn div_alg_arch(self, rhs:Self) -> (Self, Self) {(self.div_arch(rhs), self.rem_arch(rhs))}
}
)*}
}
macro_rules! impl_ordered_uint {
($($t:ty)*) => {$(
impl AddOrdered for $t {}
impl MulOrdered for $t {}
impl ArchimedeanProperty for $t {}
impl Sign for $t {
#[inline] fn signum(self) -> Self { if self==0 {0} else {1} }
#[inline] fn abs(self) -> Self { self }
}
impl ArchimedeanDiv for $t {
#[inline] fn embed_nat<N:Natural>(n:N) -> Self { (1).mul_n(n) }
#[inline] fn div_arch(self, rhs:Self) -> Self {self / rhs}
#[inline] fn rem_arch(self, rhs:Self) -> Self {self % rhs}
#[inline] fn div_alg_arch(self, rhs:Self) -> (Self, Self) {(self / rhs, self % rhs)}
}
)*}
}
macro_rules! impl_ordered_float {
($($t:ident)*) => {$(
impl AddOrdered for $t {}
impl MulOrdered for $t {}
impl ArchimedeanProperty for $t {}
impl Sign for $t {
#[inline] fn signum(self) -> Self {
#[cfg(feature = "std")] {$t::signum(self)}
#[cfg(not(feature = "std"))] {if self<0.0 {-1.0} else if self>0.0 {1.0} else {0.0}}
}
#[inline] fn abs(self) -> Self {
#[cfg(feature = "std")] {$t::abs(self)}
#[cfg(not(feature = "std"))] {if self<0.0 {-self} else {self}}
}
}
impl ArchimedeanDiv for $t {
#[inline] fn embed_nat<N:Natural>(n:N) -> Self { (1.0).mul_n(n) }
#[inline] fn rem_arch(self, rhs:Self) -> Self {
let rem = self % rhs;
if rem < 0.0 { rem + rhs.abs() } else { rem }
}
#[inline] fn div_arch(self, rhs:Self) -> Self { self.div_alg_arch(rhs).0 }
#[inline] fn div_alg_arch(self, rhs:Self) -> (Self, Self) {
let rem = self.rem_arch(rhs);
((self - rem) / rhs, rem)
}
}
)*}
}
mod impls {
use super::{ AddOrdered, MulOrdered, ArchimedeanProperty, Sign, ArchimedeanDiv, Natural, MulN };
impl_ordered_int!(i8 i16 i32 i64 i128 isize);
impl_ordered_uint!(u8 u16 u32 u64 u128 usize);
impl_ordered_float!(f32 f64);
}