use std::cmp::PartialOrd;
use std::fmt::Debug;
use std::iter::Sum;
use std::marker::Sized;
use std::num::{Saturating, Wrapping};
use std::ops::Add;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Neg;
use std::ops::Sub;
pub trait NumericByValue<Rhs = Self, Output = Self>:
Add<Rhs, Output = Output>
+ Sub<Rhs, Output = Output>
+ Mul<Rhs, Output = Output>
+ Div<Rhs, Output = Output>
+ Neg<Output = Output>
+ Sized
{
}
impl<T, Rhs, Output> NumericByValue<Rhs, Output> for T where
T: Div<Rhs, Output = Output>
+ Add<Rhs, Output = Output>
+ Sub<Rhs, Output = Output>
+ Mul<Rhs, Output = Output>
+ Neg<Output = Output>
+ Sized
{
}
pub trait NumericRef<T>:
NumericByValue<T, T>
+ for<'a> NumericByValue<&'a T, T> {}
impl<RefT, T> NumericRef<T> for RefT where
RefT: NumericByValue<T, T> + for<'a> NumericByValue<&'a T, T>
{
}
pub trait Numeric:
NumericByValue
+ for<'a> NumericByValue<&'a Self>
+ Clone
+ ZeroOne
+ FromUsize
+ Sum
+ PartialOrd
+ Debug {}
impl<T> Numeric for T where
T: NumericByValue
+ for<'a> NumericByValue<&'a T>
+ Clone
+ ZeroOne
+ FromUsize
+ Sum
+ PartialOrd
+ Debug
{
}
pub trait ZeroOne: Sized {
fn zero() -> Self;
fn one() -> Self;
}
impl<T: ZeroOne> ZeroOne for Wrapping<T> {
#[inline]
fn zero() -> Wrapping<T> {
Wrapping(T::zero())
}
#[inline]
fn one() -> Wrapping<T> {
Wrapping(T::one())
}
}
impl<T: ZeroOne> ZeroOne for Saturating<T> {
#[inline]
fn zero() -> Saturating<T> {
Saturating(T::zero())
}
#[inline]
fn one() -> Saturating<T> {
Saturating(T::one())
}
}
macro_rules! zero_one_integral {
($T:ty) => {
impl ZeroOne for $T {
#[inline]
fn zero() -> $T {
0
}
#[inline]
fn one() -> $T {
1
}
}
};
}
macro_rules! zero_one_float {
($T:ty) => {
impl ZeroOne for $T {
#[inline]
fn zero() -> $T {
0.0
}
#[inline]
fn one() -> $T {
1.0
}
}
};
}
zero_one_integral!(u8);
zero_one_integral!(i8);
zero_one_integral!(u16);
zero_one_integral!(i16);
zero_one_integral!(u32);
zero_one_integral!(i32);
zero_one_integral!(u64);
zero_one_integral!(i64);
zero_one_integral!(u128);
zero_one_integral!(i128);
zero_one_float!(f32);
zero_one_float!(f64);
zero_one_integral!(usize);
zero_one_integral!(isize);
pub trait FromUsize: Sized {
fn from_usize(n: usize) -> Option<Self>;
}
impl<T: FromUsize> FromUsize for Wrapping<T> {
fn from_usize(n: usize) -> Option<Wrapping<T>> {
Some(Wrapping(T::from_usize(n)?))
}
}
impl<T: FromUsize> FromUsize for Saturating<T> {
fn from_usize(n: usize) -> Option<Saturating<T>> {
Some(Saturating(T::from_usize(n)?))
}
}
macro_rules! from_usize_integral {
($T:ty) => {
impl FromUsize for $T {
#[inline]
fn from_usize(n: usize) -> Option<$T> {
if n <= (<$T>::MAX as usize) {
Some(n as $T)
} else {
None
}
}
}
};
}
macro_rules! from_usize_float {
($T:ty) => {
impl FromUsize for $T {
#[inline]
fn from_usize(n: usize) -> Option<$T> {
Some(n as $T)
}
}
};
}
from_usize_integral!(u8);
from_usize_integral!(i8);
from_usize_integral!(u16);
from_usize_integral!(i16);
from_usize_integral!(u32);
from_usize_integral!(i32);
from_usize_integral!(u64);
from_usize_integral!(i64);
from_usize_integral!(u128);
from_usize_integral!(i128);
from_usize_float!(f32);
from_usize_float!(f64);
from_usize_integral!(usize);
from_usize_integral!(isize);
pub mod extra {
use crate::numeric::{Numeric, NumericByValue};
pub trait Sqrt {
type Output;
fn sqrt(self) -> Self::Output;
}
macro_rules! sqrt_float {
($T:ty) => {
impl Sqrt for $T {
type Output = $T;
#[inline]
fn sqrt(self) -> Self::Output {
self.sqrt()
}
}
impl Sqrt for &$T {
type Output = $T;
#[inline]
fn sqrt(self) -> Self::Output {
self.clone().sqrt()
}
}
};
}
sqrt_float!(f32);
sqrt_float!(f64);
pub trait Exp {
type Output;
fn exp(self) -> Self::Output;
}
macro_rules! exp_float {
($T:ty) => {
impl Exp for $T {
type Output = $T;
#[inline]
fn exp(self) -> Self::Output {
self.exp()
}
}
impl Exp for &$T {
type Output = $T;
#[inline]
fn exp(self) -> Self::Output {
self.clone().exp()
}
}
};
}
exp_float!(f32);
exp_float!(f64);
pub trait Pow<Rhs = Self> {
type Output;
fn pow(self, rhs: Rhs) -> Self::Output;
}
macro_rules! pow_float {
($T:ty) => {
impl Pow<$T> for $T {
type Output = $T;
#[inline]
fn pow(self, rhs: Self) -> Self::Output {
self.powf(rhs)
}
}
impl<'a> Pow<&'a $T> for $T {
type Output = $T;
#[inline]
fn pow(self, rhs: &Self) -> Self::Output {
self.powf(rhs.clone())
}
}
impl<'a> Pow<$T> for &'a $T {
type Output = $T;
#[inline]
fn pow(self, rhs: $T) -> Self::Output {
self.powf(rhs)
}
}
impl<'a, 'b> Pow<&'b $T> for &'a $T {
type Output = $T;
#[inline]
fn pow(self, rhs: &$T) -> Self::Output {
self.powf(rhs.clone())
}
}
};
}
pow_float!(f32);
pow_float!(f64);
pub trait Pi {
fn pi() -> Self;
}
impl Pi for f32 {
fn pi() -> f32 {
std::f32::consts::PI
}
}
impl Pi for f64 {
fn pi() -> f64 {
std::f64::consts::PI
}
}
pub trait Ln {
type Output;
fn ln(self) -> Self::Output;
}
macro_rules! ln_float {
($T:ty) => {
impl Ln for $T {
type Output = $T;
#[inline]
fn ln(self) -> Self::Output {
self.ln()
}
}
impl Ln for &$T {
type Output = $T;
#[inline]
fn ln(self) -> Self::Output {
self.clone().ln()
}
}
};
}
ln_float!(f32);
ln_float!(f64);
pub trait Sin {
type Output;
fn sin(self) -> Self::Output;
}
macro_rules! sin_float {
($T:ty) => {
impl Sin for $T {
type Output = $T;
#[inline]
fn sin(self) -> Self::Output {
self.sin()
}
}
impl Sin for &$T {
type Output = $T;
#[inline]
fn sin(self) -> Self::Output {
self.clone().sin()
}
}
};
}
sin_float!(f32);
sin_float!(f64);
pub trait Cos {
type Output;
fn cos(self) -> Self::Output;
}
macro_rules! cos_float {
($T:ty) => {
impl Cos for $T {
type Output = $T;
#[inline]
fn cos(self) -> Self::Output {
self.cos()
}
}
impl Cos for &$T {
type Output = $T;
#[inline]
fn cos(self) -> Self::Output {
self.clone().cos()
}
}
};
}
cos_float!(f32);
cos_float!(f64);
pub trait RealByValue<Rhs = Self, Output = Self>:
Sqrt<Output = Output>
+ Exp<Output = Output>
+ Pow<Rhs, Output = Output>
+ Ln<Output = Output>
+ Sin<Output = Output>
+ Cos<Output = Output>
+ Sized
+ NumericByValue<Rhs, Output>
{
}
impl<T, Rhs, Output> RealByValue<Rhs, Output> for T where
T: Sqrt<Output = Output>
+ Exp<Output = Output>
+ Pow<Rhs, Output = Output>
+ Ln<Output = Output>
+ Sin<Output = Output>
+ Cos<Output = Output>
+ Sized
+ NumericByValue<Rhs, Output>
{
}
pub trait RealRef<T>:
RealByValue<T, T>
+ for<'a> RealByValue<&'a T, T> {}
impl<RefT, T> RealRef<T> for RefT where RefT: RealByValue<T, T> + for<'a> RealByValue<&'a T, T> {}
pub trait Real:
RealByValue
+ for<'a> RealByValue<&'a Self>
+ Pi
+ Numeric {}
impl<T> Real for T where T: RealByValue + for<'a> RealByValue<&'a T> + Pi + Numeric {}
}