Skip to main content

microfloat/
num_traits_impl.rs

1use core::num::FpCategory;
2
3use crate::{
4    f4e2m1fn, f6e2m3fn, f6e3m2fn, f8e3m4, f8e4m3, f8e4m3b11fnuz, f8e4m3fn, f8e4m3fnuz, f8e5m2,
5    f8e5m2fnuz, f8e8m0fnu,
6};
7use num_traits::{
8    Bounded, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Zero, float::FloatCore,
9};
10
11macro_rules! impl_common_num_traits {
12    ($($type:ty),* $(,)?) => {
13        $(
14            impl ToPrimitive for $type {
15                fn to_i64(&self) -> Option<i64> {
16                    <$type>::to_f32(*self).to_i64()
17                }
18
19                fn to_u64(&self) -> Option<u64> {
20                    <$type>::to_f32(*self).to_u64()
21                }
22
23                fn to_f32(&self) -> Option<f32> {
24                    Some(<$type>::to_f32(*self))
25                }
26
27                fn to_f64(&self) -> Option<f64> {
28                    Some(<$type>::to_f64(*self))
29                }
30            }
31
32            impl FromPrimitive for $type {
33                fn from_i64(n: i64) -> Option<Self> {
34                    n.to_f32().map(Self::from_f32)
35                }
36
37                fn from_u64(n: u64) -> Option<Self> {
38                    n.to_f32().map(Self::from_f32)
39                }
40
41                fn from_f32(n: f32) -> Option<Self> {
42                    Some(Self::from_f32(n))
43                }
44
45                fn from_f64(n: f64) -> Option<Self> {
46                    Some(Self::from_f64(n))
47                }
48            }
49
50            impl NumCast for $type {
51                fn from<T: ToPrimitive>(n: T) -> Option<Self> {
52                    n.to_f32().map(Self::from_f32)
53                }
54            }
55
56            impl Bounded for $type {
57                fn min_value() -> Self {
58                    Self::MIN
59                }
60
61                fn max_value() -> Self {
62                    Self::MAX
63                }
64            }
65        )*
66    };
67}
68
69macro_rules! impl_zero_one_num_signed {
70    ($($type:ty),* $(,)?) => {
71        $(
72            impl Zero for $type {
73                fn zero() -> Self {
74                    Self::ZERO
75                }
76
77                fn is_zero(&self) -> bool {
78                    self.classify() == FpCategory::Zero
79                }
80            }
81
82            impl One for $type {
83                fn one() -> Self {
84                    Self::ONE
85                }
86            }
87
88            impl Num for $type {
89                type FromStrRadixErr = <f32 as Num>::FromStrRadixErr;
90
91                fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
92                    f32::from_str_radix(str, radix).map(Self::from_f32)
93                }
94            }
95
96            impl Signed for $type {
97                fn abs(&self) -> Self {
98                    <$type>::abs(*self)
99                }
100
101                fn abs_sub(&self, other: &Self) -> Self {
102                    if *self <= *other {
103                        Self::ZERO
104                    } else {
105                        *self - *other
106                    }
107                }
108
109                fn signum(&self) -> Self {
110                    <$type>::signum(*self)
111                }
112
113                fn is_positive(&self) -> bool {
114                    self.is_sign_positive() && !self.is_zero()
115                }
116
117                fn is_negative(&self) -> bool {
118                    self.is_sign_negative() && !self.is_zero()
119                }
120            }
121
122            impl FloatCore for $type {
123                fn infinity() -> Self {
124                    Self::INFINITY
125                }
126
127                fn neg_infinity() -> Self {
128                    Self::NEG_INFINITY
129                }
130
131                fn nan() -> Self {
132                    Self::NAN
133                }
134
135                fn neg_zero() -> Self {
136                    Self::NEG_ZERO
137                }
138
139                fn min_value() -> Self {
140                    Self::MIN
141                }
142
143                fn min_positive_value() -> Self {
144                    Self::MIN_POSITIVE
145                }
146
147                fn epsilon() -> Self {
148                    Self::EPSILON
149                }
150
151                fn max_value() -> Self {
152                    Self::MAX
153                }
154
155                fn is_nan(self) -> bool {
156                    <$type>::is_nan(self)
157                }
158
159                fn is_infinite(self) -> bool {
160                    <$type>::is_infinite(self)
161                }
162
163                fn is_finite(self) -> bool {
164                    <$type>::is_finite(self)
165                }
166
167                fn is_normal(self) -> bool {
168                    <$type>::is_normal(self)
169                }
170
171                fn classify(self) -> FpCategory {
172                    <$type>::classify(self)
173                }
174
175                fn to_degrees(self) -> Self {
176                    Self::from_f32(<$type>::to_f32(self).to_degrees())
177                }
178
179                fn to_radians(self) -> Self {
180                    Self::from_f32(<$type>::to_f32(self).to_radians())
181                }
182
183                fn integer_decode(self) -> (u64, i16, i8) {
184                    <f32 as FloatCore>::integer_decode(<$type>::to_f32(self))
185                }
186            }
187        )*
188    };
189}
190
191impl_common_num_traits!(
192    f8e3m4,
193    f8e4m3,
194    f8e4m3b11fnuz,
195    f8e4m3fn,
196    f8e4m3fnuz,
197    f8e5m2,
198    f8e5m2fnuz,
199    f8e8m0fnu,
200    f4e2m1fn,
201    f6e2m3fn,
202    f6e3m2fn,
203);
204
205impl_zero_one_num_signed!(
206    f8e3m4,
207    f8e4m3,
208    f8e4m3b11fnuz,
209    f8e4m3fn,
210    f8e4m3fnuz,
211    f8e5m2,
212    f8e5m2fnuz,
213    f4e2m1fn,
214    f6e2m3fn,
215    f6e3m2fn,
216);