1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
use std::fmt::Debug;
use std::ops::*;

pub trait Scalar: Copy + Debug + PartialEq + PartialOrd {}

impl<S: Copy + Debug + PartialEq + PartialOrd> Scalar for S {}

pub trait Number: Scalar + 
    Add<Output=Self> + AddAssign +
    Sub<Output=Self> + SubAssign + 
    Mul<Output=Self> + MulAssign +
    Div<Output=Self> + DivAssign
{    
    const ZERO: Self;
    const ONE: Self;
    const TWO: Self;
}

macro_rules! impl_number {
    ($ty: ty, $zero: tt, $one: tt) => {
        impl Number for $ty {
            const ZERO: Self = $zero;
            const ONE: Self = $one;
            const TWO: Self = $one + $one;
        }
    }
}

impl_number!(i8, 0, 1);
impl_number!(u8, 0, 1);
impl_number!(i16, 0, 1);
impl_number!(u16, 0, 1);
impl_number!(i32, 0, 1);
impl_number!(u32, 0, 1);
impl_number!(i64, 0, 1);
impl_number!(u64, 0, 1);
impl_number!(i128, 0, 1);
impl_number!(u128, 0, 1);
impl_number!(isize, 0, 1);
impl_number!(usize, 0, 1);
impl_number!(f32, 0.0, 1.0);
impl_number!(f64, 0.0, 1.0);

pub trait Signed: Number + Neg<Output=Self> {
    fn abs(self) -> Self;
}

macro_rules! impl_signed {
    ($ty: ty) => {
        impl Signed for $ty {
            #[inline(always)]
            fn abs(self) -> Self {
                Self::abs(self)
            } 
        }
    };
}

impl_signed!(i8);
impl_signed!(i32);
impl_signed!(i64);
impl_signed!(i128);
impl_signed!(isize);
impl_signed!(f32);
impl_signed!(f64);

pub trait Float: Signed {
    fn sqrt(self) -> Self;
    fn sin(self) -> Self;
    fn cos(self) -> Self;
    fn tan(self) -> Self;
    fn powi(self, pow: i32) -> Self;
}

macro_rules! impl_float {
    ($ty: ty) => {
        impl Float for $ty {
            #[inline(always)]
            fn sqrt(self) -> Self {
                Self::sqrt(self)
            }

            #[inline(always)]
            fn sin(self) -> Self {
                Self::sin(self)
            }

            #[inline(always)]
            fn cos(self) -> Self {
                Self::cos(self)
            }

            #[inline(always)]
            fn tan(self) -> Self {
                Self::tan(self)
            }

            #[inline(always)]
            fn powi(self, pow: i32) -> Self {
                Self::powi(self, pow)
            }
        }
    };
}

impl_float!(f32);
impl_float!(f64);