1use core::cmp::Ordering;
2use core::fmt;
3use core::ops::{Add, Div, Mul, Sub};
4
5use crate::{ConversionError, dispatch};
6
7macro_rules! impl_float_format {
8 ($ty:ty, $to_float:ident) => {
9 impl fmt::Display for $ty {
10 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11 fmt::Display::fmt(&self.$to_float(), f)
12 }
13 }
14
15 impl fmt::LowerExp for $ty {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 fmt::LowerExp::fmt(&self.$to_float(), f)
18 }
19 }
20
21 impl fmt::UpperExp for $ty {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 fmt::UpperExp::fmt(&self.$to_float(), f)
24 }
25 }
26 };
27}
28
29#[derive(Clone, Copy, Default, Hash, PartialEq, Eq)]
30#[repr(transparent)]
31pub struct Uf64E11M52(u64);
33
34pub type Uf64 = Uf64E11M52;
36
37impl Uf64E11M52 {
38 pub const EXPONENT_BITS: u32 = 11;
39 pub const MANTISSA_BITS: u32 = 52;
40 pub const EXPONENT_BIAS: i32 = 1023;
41 pub const EXPONENT_MASK: u64 = 0x7ff0_0000_0000_0000;
42 pub const MANTISSA_MASK: u64 = 0x000f_ffff_ffff_ffff;
43
44 pub const ZERO: Self = Self(0);
45 pub const ONE: Self = Self(0x3ff0_0000_0000_0000);
46 pub const INFINITY: Self = Self(0x7ff0_0000_0000_0000);
47 pub const NAN: Self = Self(0x7ff8_0000_0000_0000);
48 pub const MAX: Self = Self(0x7fef_ffff_ffff_ffff);
49 pub const MIN_POSITIVE: Self = Self(0x0000_0000_0000_0001);
50 pub const MIN_NORMAL: Self = Self(0x0010_0000_0000_0000);
51
52 pub const fn from_bits(bits: u64) -> Self {
53 Self(bits)
54 }
55
56 pub const fn to_bits(self) -> u64 {
57 self.0
58 }
59
60 pub fn from_f128(value: f128) -> Self {
61 Self(dispatch::f128_to_uf64(value))
62 }
63
64 pub fn to_f128(self) -> f128 {
65 dispatch::uf64_to_f128(self.0)
66 }
67
68 pub fn try_from_f128(value: f128) -> Result<Self, ConversionError> {
69 if value.is_nan() {
70 return Err(ConversionError::Nan);
71 }
72 if value.is_infinite() {
73 return Err(ConversionError::Infinite);
74 }
75 if value < 0.0_f128 {
76 return Err(ConversionError::Negative);
77 }
78
79 let encoded = Self::from_f128(value);
80 if encoded.is_infinite() {
81 Err(ConversionError::Overflow)
82 } else if value != 0.0_f128 && encoded.is_zero() {
83 Err(ConversionError::Underflow)
84 } else {
85 Ok(encoded)
86 }
87 }
88
89 pub fn from_f64(value: f64) -> Self {
90 Self::from_f128(value as f128)
91 }
92
93 pub fn to_f64(self) -> f64 {
94 self.to_f128() as f64
95 }
96
97 pub fn try_from_f64(value: f64) -> Result<Self, ConversionError> {
98 crate::convert::check_finite_non_negative(value)?;
99
100 let encoded = Self::from_f64(value);
101 crate::convert::check_encoded(value, encoded.is_zero(), encoded.is_infinite())?;
102
103 Ok(encoded)
104 }
105
106 pub fn from_f32(value: f32) -> Self {
107 Self::from_f128(value as f128)
108 }
109
110 pub fn to_f32(self) -> f32 {
111 self.to_f128() as f32
112 }
113
114 #[cfg(feature = "f16")]
115 pub fn from_f16(value: f16) -> Self {
116 Self::from_f128(value as f128)
117 }
118
119 #[cfg(feature = "f16")]
120 pub fn to_f16(self) -> f16 {
121 self.to_f128() as f16
122 }
123
124 pub const fn exponent(self) -> u64 {
125 (self.0 & Self::EXPONENT_MASK) >> Self::MANTISSA_BITS
126 }
127
128 pub const fn mantissa(self) -> u64 {
129 self.0 & Self::MANTISSA_MASK
130 }
131
132 pub const fn is_zero(self) -> bool {
133 self.0 == 0
134 }
135
136 pub const fn is_nan(self) -> bool {
137 self.exponent() == 0x7ff && self.mantissa() != 0
138 }
139
140 pub const fn is_infinite(self) -> bool {
141 self.0 == Self::INFINITY.0
142 }
143
144 pub const fn is_finite(self) -> bool {
145 self.exponent() != 0x7ff
146 }
147
148 pub const fn is_subnormal(self) -> bool {
149 self.exponent() == 0 && self.mantissa() != 0
150 }
151}
152
153impl From<f32> for Uf64E11M52 {
154 fn from(value: f32) -> Self {
155 Self::from_f32(value)
156 }
157}
158
159impl From<f64> for Uf64E11M52 {
160 fn from(value: f64) -> Self {
161 Self::from_f64(value)
162 }
163}
164
165#[cfg(feature = "f16")]
166impl From<f16> for Uf64E11M52 {
167 fn from(value: f16) -> Self {
168 Self::from_f16(value)
169 }
170}
171
172#[cfg(feature = "f16")]
173impl From<Uf64E11M52> for f16 {
174 fn from(value: Uf64E11M52) -> Self {
175 value.to_f16()
176 }
177}
178
179impl From<Uf64E11M52> for f32 {
180 fn from(value: Uf64E11M52) -> Self {
181 value.to_f32()
182 }
183}
184
185impl From<Uf64E11M52> for f64 {
186 fn from(value: Uf64E11M52) -> Self {
187 value.to_f64()
188 }
189}
190
191impl From<Uf64E11M52> for f128 {
192 fn from(value: Uf64E11M52) -> Self {
193 value.to_f128()
194 }
195}
196
197impl TryFrom<f128> for Uf64E11M52 {
198 type Error = ConversionError;
199
200 fn try_from(value: f128) -> Result<Self, Self::Error> {
201 Self::try_from_f128(value)
202 }
203}
204
205impl Ord for Uf64E11M52 {
206 fn cmp(&self, other: &Self) -> Ordering {
207 self.0.cmp(&other.0)
208 }
209}
210
211impl PartialOrd for Uf64E11M52 {
212 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
213 Some(self.cmp(other))
214 }
215}
216
217impl Add for Uf64E11M52 {
218 type Output = Self;
219
220 fn add(self, rhs: Self) -> Self::Output {
221 Self(dispatch::add_uf64(self.0, rhs.0))
222 }
223}
224
225impl Sub for Uf64E11M52 {
226 type Output = Self;
227
228 fn sub(self, rhs: Self) -> Self::Output {
229 Self(dispatch::sub_uf64(self.0, rhs.0))
230 }
231}
232
233impl Mul for Uf64E11M52 {
234 type Output = Self;
235
236 fn mul(self, rhs: Self) -> Self::Output {
237 Self(dispatch::mul_uf64(self.0, rhs.0))
238 }
239}
240
241impl Div for Uf64E11M52 {
242 type Output = Self;
243
244 fn div(self, rhs: Self) -> Self::Output {
245 Self(dispatch::div_uf64(self.0, rhs.0))
246 }
247}
248
249impl fmt::Debug for Uf64E11M52 {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 f.debug_tuple("Uf64E11M52").field(&self.to_f64()).finish()
252 }
253}
254
255impl_float_format!(Uf64E11M52, to_f64);