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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use core::{f32, f64};
use core::num::Wrapping;


#[allow(non_snake_case)]
pub trait NumConst {
    fn E() -> Self;
    fn FRAC_1_PI() -> Self;
    fn FRAC_1_SQRT_2() -> Self;
    fn FRAC_2_PI() -> Self;
    fn FRAC_2_SQRT_PI() -> Self;
    fn FRAC_PI_2() -> Self;
    fn FRAC_PI_3() -> Self;
    fn FRAC_PI_4() -> Self;
    fn FRAC_PI_6() -> Self;
    fn FRAC_PI_8() -> Self;
    fn LN_10() -> Self;
    fn LN_2() -> Self;
    fn LOG10_E() -> Self;
    fn LOG2_E() -> Self;
    fn PI() -> Self;
    fn SQRT_2() -> Self;
}

macro_rules! trait_const_fixed {
    ($f:ident, $t:ident) => (
        impl NumConst for $t {
            #[inline(always)]
            fn E() -> Self { $f::consts::E as $t }
            #[inline(always)]
            fn FRAC_1_PI() -> Self { $f::consts::FRAC_1_PI as $t  }
            #[inline(always)]
            fn FRAC_1_SQRT_2() -> Self { $f::consts::FRAC_1_SQRT_2 as $t  }
            #[inline(always)]
            fn FRAC_2_PI() -> Self { $f::consts::FRAC_2_PI as $t  }
            #[inline(always)]
            fn FRAC_2_SQRT_PI() -> Self { $f::consts::FRAC_2_SQRT_PI as $t  }
            #[inline(always)]
            fn FRAC_PI_2() -> Self { $f::consts::FRAC_PI_2 as $t  }
            #[inline(always)]
            fn FRAC_PI_3() -> Self { $f::consts::FRAC_PI_3 as $t  }
            #[inline(always)]
            fn FRAC_PI_4() -> Self { $f::consts::FRAC_PI_4 as $t  }
            #[inline(always)]
            fn FRAC_PI_6() -> Self { $f::consts::FRAC_PI_6 as $t  }
            #[inline(always)]
            fn FRAC_PI_8() -> Self { $f::consts::FRAC_PI_8 as $t  }
            #[inline(always)]
            fn LN_10() -> Self { $f::consts::LN_10 as $t  }
            #[inline(always)]
            fn LN_2() -> Self { $f::consts::LN_2 as $t  }
            #[inline(always)]
            fn LOG10_E() -> Self { $f::consts::LOG10_E as $t  }
            #[inline(always)]
            fn LOG2_E() -> Self { $f::consts::LOG2_E as $t  }
            #[inline(always)]
            fn PI() -> Self { $f::consts::PI as $t  }
            #[inline(always)]
            fn SQRT_2() -> Self { $f::consts::SQRT_2 as $t  }
        }
    );
}

macro_rules! trait_const_float {
    ($t:ident) => (
        impl NumConst for $t {
            #[inline(always)]
            fn E() -> Self { $t::consts::E }
            #[inline(always)]
            fn FRAC_1_PI() -> Self { $t::consts::FRAC_1_PI }
            #[inline(always)]
            fn FRAC_1_SQRT_2() -> Self { $t::consts::FRAC_1_SQRT_2 }
            #[inline(always)]
            fn FRAC_2_PI() -> Self { $t::consts::FRAC_2_PI }
            #[inline(always)]
            fn FRAC_2_SQRT_PI() -> Self { $t::consts::FRAC_2_SQRT_PI }
            #[inline(always)]
            fn FRAC_PI_2() -> Self { $t::consts::FRAC_PI_2 }
            #[inline(always)]
            fn FRAC_PI_3() -> Self { $t::consts::FRAC_PI_3 }
            #[inline(always)]
            fn FRAC_PI_4() -> Self { $t::consts::FRAC_PI_4 }
            #[inline(always)]
            fn FRAC_PI_6() -> Self { $t::consts::FRAC_PI_6 }
            #[inline(always)]
            fn FRAC_PI_8() -> Self { $t::consts::FRAC_PI_8 }
            #[inline(always)]
            fn LN_10() -> Self { $t::consts::LN_10 }
            #[inline(always)]
            fn LN_2() -> Self { $t::consts::LN_2 }
            #[inline(always)]
            fn LOG10_E() -> Self { $t::consts::LOG10_E }
            #[inline(always)]
            fn LOG2_E() -> Self { $t::consts::LOG2_E }
            #[inline(always)]
            fn PI() -> Self { $t::consts::PI }
            #[inline(always)]
            fn SQRT_2() -> Self { $t::consts::SQRT_2 }
        }
    );
}

trait_const_fixed!(f64, usize);
trait_const_fixed!(f32, u8);
trait_const_fixed!(f32, u16);
trait_const_fixed!(f64, u32);
trait_const_fixed!(f64, u64);
trait_const_fixed!(f64, u128);

trait_const_fixed!(f64, isize);
trait_const_fixed!(f32, i8);
trait_const_fixed!(f32, i16);
trait_const_fixed!(f64, i32);
trait_const_fixed!(f64, i64);
trait_const_fixed!(f64, i128);

trait_const_float!(f32);
trait_const_float!(f64);


impl<T> NumConst for Wrapping<T>
    where T: NumConst,
{
    #[inline(always)]
    fn E() -> Self { Wrapping(NumConst::E()) }
    #[inline(always)]
    fn FRAC_1_PI() -> Self { Wrapping(NumConst::FRAC_1_PI()) }
    #[inline(always)]
    fn FRAC_1_SQRT_2() -> Self { Wrapping(NumConst::FRAC_1_SQRT_2()) }
    #[inline(always)]
    fn FRAC_2_PI() -> Self { Wrapping(NumConst::FRAC_2_PI()) }
    #[inline(always)]
    fn FRAC_2_SQRT_PI() -> Self { Wrapping(NumConst::FRAC_2_SQRT_PI()) }
    #[inline(always)]
    fn FRAC_PI_2() -> Self { Wrapping(NumConst::FRAC_PI_2()) }
    #[inline(always)]
    fn FRAC_PI_3() -> Self { Wrapping(NumConst::FRAC_PI_3()) }
    #[inline(always)]
    fn FRAC_PI_4() -> Self { Wrapping(NumConst::FRAC_PI_4()) }
    #[inline(always)]
    fn FRAC_PI_6() -> Self { Wrapping(NumConst::FRAC_PI_6()) }
    #[inline(always)]
    fn FRAC_PI_8() -> Self { Wrapping(NumConst::FRAC_PI_8()) }
    #[inline(always)]
    fn LN_10() -> Self { Wrapping(NumConst::LN_10()) }
    #[inline(always)]
    fn LN_2() -> Self { Wrapping(NumConst::LN_2()) }
    #[inline(always)]
    fn LOG10_E() -> Self { Wrapping(NumConst::LOG10_E()) }
    #[inline(always)]
    fn LOG2_E() -> Self { Wrapping(NumConst::LOG2_E()) }
    #[inline(always)]
    fn PI() -> Self { Wrapping(NumConst::PI()) }
    #[inline(always)]
    fn SQRT_2() -> Self { Wrapping(NumConst::SQRT_2()) }
}


#[cfg(test)]
mod test {
    use core::{f32, f64};
    use super::NumConst;


    fn pi<T: NumConst>() -> T {
        T::PI()
    }

    #[test]
    fn test_pi() {
        assert_eq!(pi::<usize>(), 3);
        assert_eq!(pi::<isize>(), 3);
        assert_eq!(pi::<f32>(), f32::consts::PI);
        assert_eq!(pi::<f64>(), f64::consts::PI);
    }
}