float_traits/
traits.rs

1use core;
2use core::ops::Neg;
3use core::cmp::PartialOrd;
4use core::clone::Clone;
5use num_traits::{Num, Bounded};
6use num_integer::Integer;
7
8pub trait Abs {
9    type Output: Num;
10    fn abs(&self) -> Self::Output;
11    fn sign(&self) -> Self::Output;
12}
13
14macro_rules! impl_abs {
15    ($($num:ty)*) => ($(
16        impl Abs for $num {
17            type Output = $num;
18            #[inline]
19            fn abs(&self) -> $num {
20                self.clone().abs()
21            }
22            fn sign(&self) -> $num {
23                self.signum()
24            }
25        }
26        impl<'a> Abs for &'a $num {
27            type Output = $num;
28            #[inline]
29            fn abs(&self) -> $num {
30                self.clone().abs()
31            }
32            fn sign(&self) -> $num {
33                self.clone().signum()
34            }
35        }
36    )*)
37}
38
39impl_abs!(f32 f64);
40
41pub trait Sqrt {
42    type Output: Num;
43    fn sqrt(self) -> Self::Output;
44}
45
46macro_rules! impl_sqrt {
47    ($($num:ty)*) => ($(
48        impl Sqrt for $num {
49            type Output = $num;
50            #[inline]
51            fn sqrt(self) -> Self {
52                self.sqrt()
53            }
54        }
55        impl<'a> Sqrt for &'a $num {
56            type Output = $num;
57            #[inline]
58            fn sqrt(self) -> $num {
59                self.clone().sqrt()
60            }
61        }
62    )*)
63}
64
65impl_sqrt!(f32 f64);
66
67pub trait GeneralFloat: Num + PartialOrd {
68    type Exponent: Integer;
69    fn radix() -> Self;
70    fn bit_size() -> Self::Exponent;
71    fn epsilon() -> Self;
72    fn radix_powi(p: Self::Exponent) -> Self;
73}
74
75pub trait BinaryFloat: Num + PartialOrd {
76    type Expo: Integer;
77    fn bits() -> Self::Expo;
78    fn eps() -> Self;
79    fn two_powi(p: Self::Expo) -> Self;
80}
81
82impl<T: BinaryFloat> GeneralFloat for T {
83    type Exponent = T::Expo;
84    #[inline]
85    fn radix() -> T {
86        T::one() + T::one()
87    }
88    #[inline]
89    fn bit_size() -> T::Expo {
90        T::bits()
91    }
92    #[inline]
93    fn epsilon() -> T {
94        T::eps()
95    }
96    #[inline]
97    fn radix_powi(p: T::Expo) -> T {
98        T::two_powi(p)
99    }
100}
101
102pub trait BoundedFloat: Bounded + GeneralFloat {
103    fn max_exponent() -> Self::Exponent;
104    fn min_exponent() -> Self::Exponent;
105}
106
107pub trait Overflow: Num + PartialOrd {
108    fn overflow() -> Self;
109    fn neg_overflow() -> Self;
110}
111
112pub trait Infinite: Num + PartialOrd {
113    fn infinity() -> Self;
114    fn neg_infinity() -> Self;
115    fn is_infinite(&self) -> bool;
116}
117
118impl<T: Infinite> Overflow for T {
119    #[inline]
120    fn overflow() -> Self {
121        T::infinity()
122    }
123    #[inline]
124    fn neg_overflow() -> Self {
125        T::neg_infinity()
126    }
127}
128
129pub trait Underflow: Num {
130    fn min_positive() -> Self;
131    fn unit_underflow() -> Self;
132}
133
134pub trait IEEE754Float
135    : Abs<Output=Self> + Sqrt<Output = Self> + Neg<Output = Self> +
136    BinaryFloat + BoundedFloat + Infinite + Underflow
137    {
138    fn nan() -> Self;
139}
140
141macro_rules! impl_fxx {
142    ($fxx:ident, $expo:ty, [$emin:expr,$emax:expr], $bits:expr) => (
143        impl BinaryFloat for $fxx {
144            type Expo = $expo;
145            #[inline]
146            fn bits() -> Self::Expo{
147                $bits
148            }
149            #[inline]
150            fn eps() -> Self{
151                core::$fxx::EPSILON
152            }
153            #[inline]
154            fn two_powi(p: Self::Expo) -> Self{
155                $fxx::radix().powi(p)
156            }
157        }
158        impl BoundedFloat for $fxx {
159            #[inline]
160            fn max_exponent() -> Self::Exponent{
161                $emax
162            }
163            #[inline]
164            fn min_exponent() -> Self::Exponent{
165                $emin
166            }
167        }
168        impl Infinite for $fxx {
169            #[inline]
170            fn infinity() -> Self{
171                core::$fxx::INFINITY
172            }
173            #[inline]
174            fn neg_infinity() -> Self{
175                core::$fxx::NEG_INFINITY
176            }
177            #[inline]
178            fn is_infinite(&self) -> bool{
179                $fxx::is_infinite(*self)
180            }
181        }
182        impl Underflow for $fxx {
183            #[inline]
184            fn min_positive() -> Self{
185                core::$fxx::MIN_POSITIVE
186            }
187            #[inline]
188            fn unit_underflow() -> Self{
189                core::$fxx::MIN_POSITIVE * core::$fxx::EPSILON
190            }
191        }
192        impl IEEE754Float for $fxx {
193            #[inline]
194            fn nan() -> Self {
195                core::$fxx::NAN
196            }
197        }
198    )
199}
200
201impl_fxx!(f32, i32, [-126, 127], 24);
202impl_fxx!(f64, i32, [-1022, 1023], 53);
203
204mod tests {
205    #[test]
206    fn f64abs() {
207        use super::{Abs,IEEE754Float};
208        assert!((-1.0).abs() == <f64 as Abs>::abs(&-1.0f64));
209        assert!(f64::nan().is_nan());
210    }
211}