use crate::error::IError;
use crate::error::IResult;
pub trait Equal {
fn equal(&self, rhs: &Self) -> bool;
}
pub trait Zero
where
Self: Default,
{
fn zero() -> Self {
Self::default()
}
fn is_zero(&self) -> bool;
}
pub trait One {
fn one() -> Self;
fn is_one(&self) -> bool;
}
pub trait Number: Equal + Zero + One
where
Self: std::clone::Clone
+ std::default::Default
+ std::fmt::Debug
+ std::fmt::Display
+ std::iter::Sum
+ std::ops::Add<Output = Self>
+ std::ops::Sub<Output = Self>
+ std::ops::Mul<Output = Self>
+ std::ops::Neg<Output = Self>,
{
fn abs(self) -> Self;
fn conjugate(self) -> Self;
fn ndiv(self, rhs: Self) -> IResult<Self>;
}
impl Equal for i32 {
fn equal(&self, rhs: &Self) -> bool {
self == rhs
}
}
impl Zero for i32 {
fn is_zero(&self) -> bool {
self == &0i32
}
}
impl One for i32 {
fn one() -> Self {
1i32
}
fn is_one(&self) -> bool {
self == &1i32
}
}
impl Number for i32 {
fn abs(self) -> Self {
i32::abs(self)
}
fn conjugate(self) -> Self {
self
}
fn ndiv(self, rhs: Self) -> IResult<Self> {
if rhs.is_zero() {
Err(IError::DividedByZero)
} else {
Ok(self / rhs)
}
}
}
impl Equal for f32 {
fn equal(&self, rhs: &Self) -> bool {
(self - rhs).is_zero()
}
}
impl Zero for f32 {
fn is_zero(&self) -> bool {
self.abs() < f32::EPSILON.sqrt()
}
}
impl One for f32 {
fn one() -> Self {
1.0f32
}
fn is_one(&self) -> bool {
(self - Self::one()).is_zero()
}
}
impl Number for f32 {
fn abs(self) -> Self {
f32::abs(self)
}
fn conjugate(self) -> Self {
self
}
fn ndiv(self, rhs: Self) -> IResult<Self> {
if rhs.is_zero() {
Err(IError::DividedByZero)
} else {
Ok(self / rhs)
}
}
}
pub trait Integeral
where
Self: Number + std::cmp::PartialOrd + std::ops::Rem<Output = Self>,
{
fn gcd(&self, rhs: &Self) -> Self {
if rhs.clone().equal(&Self::zero()) {
self.clone().abs()
} else {
rhs.gcd(&(self.clone().rem(rhs.clone())))
}
}
fn lcm(&self, rhs: &Self) -> Self {
match (self.clone() * rhs.clone()).abs().ndiv(self.gcd(rhs)) {
Ok(division) => division,
Err(_) => -Self::one(),
}
}
}
impl Integeral for i32 {}
pub trait Fractional
where
Self: Number,
{
fn nsqrt(self) -> IResult<Self>;
fn from_usize(size: usize) -> Self;
}
impl Fractional for f32 {
fn nsqrt(self) -> IResult<Self> {
Ok(self.sqrt())
}
fn from_usize(size: usize) -> Self {
size as f32
}
}