#![allow(renamed_and_removed_lints, clippy::unknown_clippy_lints)]
use core::{cmp::Ordering, fmt};
use crate::error::ArithmeticError;
#[cfg(feature = "bigint")]
mod bigint;
mod generic;
mod modular;
pub use self::{
generic::{
Checked, CheckedArithmetic, CheckedArithmeticKind, NegateOnlyZero, StdArithmetic,
Unchecked, WrappingArithmetic,
},
modular::{DoubleWidth, ModularArithmetic},
};
pub trait Arithmetic<T> {
fn add(&self, x: T, y: T) -> Result<T, ArithmeticError>;
fn sub(&self, x: T, y: T) -> Result<T, ArithmeticError>;
fn mul(&self, x: T, y: T) -> Result<T, ArithmeticError>;
fn div(&self, x: T, y: T) -> Result<T, ArithmeticError>;
fn pow(&self, x: T, y: T) -> Result<T, ArithmeticError>;
fn neg(&self, x: T) -> Result<T, ArithmeticError>;
fn eq(&self, x: &T, y: &T) -> bool;
}
pub trait OrdArithmetic<T>: Arithmetic<T> {
fn partial_cmp(&self, x: &T, y: &T) -> Option<Ordering>;
}
impl<T> fmt::Debug for dyn OrdArithmetic<T> + '_ {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.debug_tuple("OrdArithmetic").finish()
}
}
pub struct FullArithmetic<T, A> {
base: A,
comparison: fn(&T, &T) -> Option<Ordering>,
}
impl<T, A: Clone> Clone for FullArithmetic<T, A> {
fn clone(&self) -> Self {
Self {
base: self.base.clone(),
comparison: self.comparison,
}
}
}
impl<T, A: Copy> Copy for FullArithmetic<T, A> {}
impl<T, A: fmt::Debug> fmt::Debug for FullArithmetic<T, A> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("FullArithmetic")
.field("base", &self.base)
.finish()
}
}
impl<T, A> Arithmetic<T> for FullArithmetic<T, A>
where
A: Arithmetic<T>,
{
#[inline]
fn add(&self, x: T, y: T) -> Result<T, ArithmeticError> {
self.base.add(x, y)
}
#[inline]
fn sub(&self, x: T, y: T) -> Result<T, ArithmeticError> {
self.base.sub(x, y)
}
#[inline]
fn mul(&self, x: T, y: T) -> Result<T, ArithmeticError> {
self.base.mul(x, y)
}
#[inline]
fn div(&self, x: T, y: T) -> Result<T, ArithmeticError> {
self.base.div(x, y)
}
#[inline]
fn pow(&self, x: T, y: T) -> Result<T, ArithmeticError> {
self.base.pow(x, y)
}
#[inline]
fn neg(&self, x: T) -> Result<T, ArithmeticError> {
self.base.neg(x)
}
#[inline]
fn eq(&self, x: &T, y: &T) -> bool {
self.base.eq(x, y)
}
}
impl<T, A> OrdArithmetic<T> for FullArithmetic<T, A>
where
A: Arithmetic<T>,
{
fn partial_cmp(&self, x: &T, y: &T) -> Option<Ordering> {
(self.comparison)(x, y)
}
}
pub trait ArithmeticExt<T>: Arithmetic<T> + Sized {
fn without_comparisons(self) -> FullArithmetic<T, Self> {
FullArithmetic {
base: self,
comparison: |_, _| None,
}
}
fn with_natural_comparison(self) -> FullArithmetic<T, Self>
where
T: PartialOrd,
{
FullArithmetic {
base: self,
comparison: |x, y| x.partial_cmp(y),
}
}
fn with_comparison(
self,
comparison: fn(&T, &T) -> Option<Ordering>,
) -> FullArithmetic<T, Self> {
FullArithmetic {
base: self,
comparison,
}
}
}
impl<T, A> ArithmeticExt<T> for A where A: Arithmetic<T> {}