microfloat/
num_traits_impl.rs1use 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);