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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use core::hash::Hash;
use core::ops::{
    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign, Rem, RemAssign,
    BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign,
    Shl, ShlAssign, Shr, ShrAssign,
    Neg, Not,
};

pub trait Float
    : Copy + Default + Sized
    + Add + AddAssign + Div + DivAssign + Mul + MulAssign
    + Rem + RemAssign + Sub + SubAssign
{
    const WIDTH: usize;
}

pub trait Integer
    : Copy + Default + Eq + Hash + Ord + Sized
    + Not<Output=Self>
    + Add<Self, Output=Self> + AddAssign<Self>
    + Div<Self, Output=Self> + DivAssign<Self>
    + Mul<Self, Output=Self> + MulAssign<Self>
    + Sub<Self, Output=Self> + SubAssign<Self>
    + Rem<Self, Output=Self> + RemAssign<Self>
    + BitAnd<Self, Output=Self> + BitAndAssign<Self>
    + BitOr<Self, Output=Self> + BitOrAssign<Self>
    + BitXor<Self, Output=Self> + BitXorAssign<Self>
    + Shl<Self, Output=Self> + ShlAssign<Self>
    + Shr<Self, Output=Self> + ShrAssign<Self>
{
    const MIN: Self;
    const MAX: Self;
    const ZERO: Self;
    const ONE: Self;
    const WIDTH: usize;
}

pub trait Signed : Neg {}

pub trait Unsigned {}

pub trait AddSign : Integer + Unsigned {
    type Signed : DropSign<Unsigned=Self>;
    fn add_sign(self) -> <Self as AddSign>::Signed;
}

pub trait DropSign : Integer + Signed {
    type Unsigned : AddSign<Signed=Self>;
    fn drop_sign(self) -> <Self as DropSign>::Unsigned;
}

pub trait ArithmeticShr : Integer + Signed {}

pub trait LogicalShr : Integer + Unsigned {}

impl<T: Integer + Signed> ArithmeticShr for T {}

impl<T: Integer + Unsigned> LogicalShr for T {}

impl Signed for f32 {}
impl Signed for f64 {}

impl Signed for i8 {}
impl Signed for i16 {}
impl Signed for i32 {}
impl Signed for i64 {}
impl Signed for i128 {}
impl Signed for isize {}

impl Unsigned for u8 {}
impl Unsigned for u16 {}
impl Unsigned for u32 {}
impl Unsigned for u64 {}
impl Unsigned for u128 {}
impl Unsigned for usize {}

macro_rules! impl_float {
    ($type:ty = $size:expr) => {
        impl Float for $type {
            const WIDTH: usize = $size;
        }
    }
}

macro_rules! impl_integer {
    ($type:ty = $size:expr) => {
        impl Integer for $type {
            const MAX: $type = <$type>::MAX;
            const MIN: $type = <$type>::MIN;
            const ZERO: $type = 0;
            const ONE: $type = 1;
            const WIDTH: usize = $size;
        }
    }
}

macro_rules! impl_add_sign {
    ($type:ty = $signed:ty) => {
        impl AddSign for $type {
            type Signed = $signed;
            fn add_sign(self) -> $signed {
                self as $signed
            }
        }
    }
}
macro_rules! impl_drop_sign {
    ($type:ty = $unsigned:ty) => {
        impl DropSign for $type {
            type Unsigned = $unsigned;
            fn drop_sign(self) -> $unsigned {
                self as $unsigned
            }
        }
    }
}

impl_float!(f32 = 32);
impl_float!(f64 = 64);
impl_integer!(i8 = 8);
impl_integer!(i16 = 16);
impl_integer!(i32 = 32);
impl_integer!(i64 = 64);
impl_integer!(i128 = 128);
 #[cfg(target_pointer_width="32")]
impl_integer!(isize = 32);
 #[cfg(target_pointer_width="64")]
impl_integer!(isize = 64);

impl_integer!(u8 = 8);
impl_integer!(u16 = 16);
impl_integer!(u32 = 32);
impl_integer!(u64 = 32);
impl_integer!(u128 = 128);
#[cfg(target_pointer_width="32")]
impl_integer!(usize = 32);
#[cfg(target_pointer_width="64")]
impl_integer!(usize = 64);

impl_add_sign!(u8 = i8);
impl_add_sign!(u16 = i16);
impl_add_sign!(u32 = i32);
impl_add_sign!(u64 = i64);
impl_add_sign!(u128 = i128);
impl_add_sign!(usize = isize);

impl_drop_sign!(i8 = u8);
impl_drop_sign!(i16 = u16);
impl_drop_sign!(i32 = u32);
impl_drop_sign!(i64 = u64);
impl_drop_sign!(i128 = u128);
impl_drop_sign!(isize = usize);