unsigned_float/
convert.rs1use core::fmt;
2
3#[cfg(feature = "f128")]
4use crate::Uf64;
5use crate::{Uf8, Uf8E5M3, Uf16, Uf16E6M10, Uf32};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum ConversionError {
10 Negative,
12 Nan,
14 Infinite,
16 Overflow,
18 Underflow,
20}
21
22impl fmt::Display for ConversionError {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self {
25 Self::Negative => f.write_str("value is negative"),
26 Self::Nan => f.write_str("value is NaN"),
27 Self::Infinite => f.write_str("value is infinite"),
28 Self::Overflow => f.write_str("value is too large"),
29 Self::Underflow => f.write_str("positive value is too small"),
30 }
31 }
32}
33
34pub(crate) fn check_finite_non_negative(value: f64) -> Result<(), ConversionError> {
35 if value.is_nan() {
36 Err(ConversionError::Nan)
37 } else if value.is_infinite() {
38 Err(ConversionError::Infinite)
39 } else if value < 0.0 {
40 Err(ConversionError::Negative)
41 } else {
42 Ok(())
43 }
44}
45
46pub(crate) fn check_encoded(
47 value: f64,
48 is_zero: bool,
49 is_infinite: bool,
50) -> Result<(), ConversionError> {
51 if is_infinite {
52 Err(ConversionError::Overflow)
53 } else if value != 0.0 && is_zero {
54 Err(ConversionError::Underflow)
55 } else {
56 Ok(())
57 }
58}
59
60macro_rules! impl_try_from_float {
61 ($float:ty, $($uf:ty),* $(,)?) => {
62 $(
63 impl TryFrom<$float> for $uf {
64 type Error = ConversionError;
65
66 fn try_from(value: $float) -> Result<Self, Self::Error> {
67 Self::try_from_f64(value as f64)
68 }
69 }
70 )*
71 };
72}
73
74macro_rules! impl_try_from_unsigned_int {
75 ($($int:ty),* $(,)?) => {
76 $(
77 impl TryFrom<$int> for Uf8 {
78 type Error = ConversionError;
79
80 fn try_from(value: $int) -> Result<Self, Self::Error> {
81 Self::try_from_f64(value as f64)
82 }
83 }
84
85 impl TryFrom<$int> for Uf16 {
86 type Error = ConversionError;
87
88 fn try_from(value: $int) -> Result<Self, Self::Error> {
89 Self::try_from_f64(value as f64)
90 }
91 }
92
93 impl TryFrom<$int> for Uf8E5M3 {
94 type Error = ConversionError;
95
96 fn try_from(value: $int) -> Result<Self, Self::Error> {
97 Self::try_from_f64(value as f64)
98 }
99 }
100
101 impl TryFrom<$int> for Uf16E6M10 {
102 type Error = ConversionError;
103
104 fn try_from(value: $int) -> Result<Self, Self::Error> {
105 Self::try_from_f64(value as f64)
106 }
107 }
108
109 impl TryFrom<$int> for Uf32 {
110 type Error = ConversionError;
111
112 fn try_from(value: $int) -> Result<Self, Self::Error> {
113 Self::try_from_f64(value as f64)
114 }
115 }
116 )*
117 };
118}
119
120macro_rules! impl_try_from_signed_int {
121 ($($int:ty),* $(,)?) => {
122 $(
123 impl TryFrom<$int> for Uf8 {
124 type Error = ConversionError;
125
126 fn try_from(value: $int) -> Result<Self, Self::Error> {
127 if value < 0 {
128 Err(ConversionError::Negative)
129 } else {
130 Self::try_from_f64(value as f64)
131 }
132 }
133 }
134
135 impl TryFrom<$int> for Uf16 {
136 type Error = ConversionError;
137
138 fn try_from(value: $int) -> Result<Self, Self::Error> {
139 if value < 0 {
140 Err(ConversionError::Negative)
141 } else {
142 Self::try_from_f64(value as f64)
143 }
144 }
145 }
146
147 impl TryFrom<$int> for Uf8E5M3 {
148 type Error = ConversionError;
149
150 fn try_from(value: $int) -> Result<Self, Self::Error> {
151 if value < 0 {
152 Err(ConversionError::Negative)
153 } else {
154 Self::try_from_f64(value as f64)
155 }
156 }
157 }
158
159 impl TryFrom<$int> for Uf16E6M10 {
160 type Error = ConversionError;
161
162 fn try_from(value: $int) -> Result<Self, Self::Error> {
163 if value < 0 {
164 Err(ConversionError::Negative)
165 } else {
166 Self::try_from_f64(value as f64)
167 }
168 }
169 }
170
171 impl TryFrom<$int> for Uf32 {
172 type Error = ConversionError;
173
174 fn try_from(value: $int) -> Result<Self, Self::Error> {
175 if value < 0 {
176 Err(ConversionError::Negative)
177 } else {
178 Self::try_from_f64(value as f64)
179 }
180 }
181 }
182 )*
183 };
184}
185
186impl_try_from_float!(f64, Uf8, Uf8E5M3, Uf16, Uf16E6M10, Uf32);
187
188impl_try_from_unsigned_int!(u8, u16, u32, u64, u128, usize);
189impl_try_from_signed_int!(i8, i16, i32, i64, i128, isize);
190
191#[cfg(feature = "f128")]
192macro_rules! impl_try_from_unsigned_int_uf64 {
193 ($($int:ty),* $(,)?) => {
194 $(
195 impl TryFrom<$int> for Uf64 {
196 type Error = ConversionError;
197
198 fn try_from(value: $int) -> Result<Self, Self::Error> {
199 Self::try_from_f128(value as f128)
200 }
201 }
202 )*
203 };
204}
205
206#[cfg(feature = "f128")]
207macro_rules! impl_try_from_signed_int_uf64 {
208 ($($int:ty),* $(,)?) => {
209 $(
210 impl TryFrom<$int> for Uf64 {
211 type Error = ConversionError;
212
213 fn try_from(value: $int) -> Result<Self, Self::Error> {
214 if value < 0 {
215 Err(ConversionError::Negative)
216 } else {
217 Self::try_from_f128(value as f128)
218 }
219 }
220 }
221 )*
222 };
223}
224
225#[cfg(feature = "f128")]
226impl_try_from_unsigned_int_uf64!(u8, u16, u32, u64, u128, usize);
227
228#[cfg(feature = "f128")]
229impl_try_from_signed_int_uf64!(i8, i16, i32, i64, i128, isize);