use num::complex::Complex;
use num::rational::Ratio;
use num::{Integer, Num, One, Zero};
use std::num::Wrapping;
use std::ops::{Add, Mul};
use crate::gradienttype::GradientType;
pub trait InstZero: Sized + Add<Self, Output = Self> {
fn zero(&self) -> Self;
fn is_zero(&self) -> bool;
fn set_zero(&mut self) {
*self = self.zero();
}
}
pub trait InstOne: Sized + Mul<Self, Output = Self> {
fn one(&self) -> Self;
fn set_one(&mut self) {
*self = self.one();
}
fn is_one(&self) -> bool
where
Self: PartialEq,
{
*self == self.one()
}
}
pub trait GradientIdentity: Sized
where
Self: GradientType<Self>
{
fn grad_identity(&self) -> <Self as GradientType<Self>>::GradientType;
}
macro_rules! impl_zero {
($($t:ty),*) => ($(
impl InstZero for $t {
fn zero(&self) -> $t {
<$t as Zero>::zero()
}
fn is_zero(&self) -> bool {
<$t as Zero>::is_zero(self)
}
}
)*)
}
impl_zero!(u32, i128, i16, u128, f64, usize, i32, i8, f32, i64, u16, isize, u8, u64);
impl_zero!(num::BigInt, num::BigUint);
impl<T> InstZero for Wrapping<T>
where
T: Zero,
Wrapping<T>: Add<Wrapping<T>, Output = Wrapping<T>>,
{
fn zero(&self) -> Wrapping<T> {
<Wrapping<T> as Zero>::zero()
}
fn is_zero(&self) -> bool {
<Wrapping<T> as Zero>::is_zero(self)
}
}
impl<T> InstZero for Ratio<T>
where
T: Clone + Integer,
{
fn zero(&self) -> Ratio<T> {
<Ratio<T> as Zero>::zero()
}
fn is_zero(&self) -> bool {
<Ratio<T> as Zero>::is_zero(self)
}
}
impl<T> InstZero for Complex<T>
where
T: Clone + Num,
{
fn zero(&self) -> Complex<T> {
<Complex<T> as Zero>::zero()
}
fn is_zero(&self) -> bool {
<Complex<T> as Zero>::is_zero(self)
}
}
macro_rules! impl_one {
($($t:ty),*) => ($(
impl InstOne for $t {
fn one(&self) -> $t {
<$t as One>::one()
}
}
)*)
}
impl_one!(i64, u128, f32, u16, u32, i16, f64, isize, i32, u8, u64, usize, i128, i8);
impl_one!(num::BigInt, num::BigUint);
impl<T> InstOne for Wrapping<T>
where
T: One,
Wrapping<T>: Mul<Wrapping<T>, Output = Wrapping<T>>,
{
fn one(&self) -> Wrapping<T> {
<Wrapping<T> as One>::one()
}
}
impl<T> InstOne for Ratio<T>
where
T: Clone + Integer,
{
fn one(&self) -> Ratio<T> {
<Ratio<T> as One>::one()
}
}
impl<T> InstOne for Complex<T>
where
T: Clone + Num,
{
fn one(&self) -> Complex<T> {
<Complex<T> as One>::one()
}
}
macro_rules! impl_grad_identity {
($($t:ty),*) => ($(
impl<G> GradientIdentity for $t
where
Self: GradientType<Self, GradientType = G>,
G: One,
{
fn grad_identity(&self) -> G
{
G::one()
}
}
)*)
}
impl_grad_identity!(i64, u128, f32, u16, u32, i16, f64, isize, i32, u8, u64, usize, i128, i8);
impl_grad_identity!(num::BigInt, num::BigUint);
impl<T, G> GradientIdentity for Wrapping<T>
where
Self: GradientType<Self, GradientType = G>,
G: One,
{
fn grad_identity(&self) -> G {
G::one()
}
}
impl<T, G> GradientIdentity for Ratio<T>
where
Self: GradientType<Self, GradientType = G>,
T: Clone + Integer,
G: One,
{
fn grad_identity(&self) -> G {
G::one()
}
}
impl<T, G> GradientIdentity for Complex<T>
where
Self: GradientType<Self, GradientType = G>,
T: Clone + Num,
G: One,
{
fn grad_identity(&self) -> G {
G::one()
}
}