decompose_float/
ieee754.rs1use crate::{Decompose, DecomposeResult};
2
3macro_rules! ieee754 {
4 ($fty: ty, $ity: ty, $exponent_width: literal, $mantissa_width: literal) => {
5 impl Decompose for $fty {
6 fn decompose(&self) -> DecomposeResult {
7 let uint = self.to_bits();
8 let is_neg = uint >= (1 << ($exponent_width + $mantissa_width));
9 let mut exp = ((uint >> $mantissa_width) & ((1 << $exponent_width) - 1)) as i32 - ((1 << ($exponent_width - 1)) - 1);
10 let mut mantissa = uint & ((1 << $mantissa_width) - 1);
11
12 if exp == -((1 << ($exponent_width - 1)) - 1) {
13 exp += 1;
14
15 if mantissa == 0 {
16 if is_neg {
17 return DecomposeResult::NegZero;
18 }
19
20 else {
21 return DecomposeResult::Zero;
22 }
23 }
24
25 let to_shift = $mantissa_width - mantissa.ilog2();
26 mantissa <<= to_shift;
27 exp -= to_shift as i32;
28 mantissa -= 1 << $mantissa_width;
29 }
30
31 else if exp == 1 << ($exponent_width - 1) {
32 if mantissa == 0 {
33 if is_neg {
34 return DecomposeResult::NegInfinity;
35 }
36
37 else {
38 return DecomposeResult::Infinity;
39 }
40 }
41
42 else {
43 return DecomposeResult::NotANumber;
44 }
45 }
46
47 let mut mantissa = mantissa as u128;
48 mantissa <<= (127 - $mantissa_width);
49 mantissa |= 1 << 127;
50 DecomposeResult::Normal { is_neg, exp, mantissa }
51 }
52 }
53
54 impl From<DecomposeResult> for $fty {
59 fn from(r: DecomposeResult) -> $fty {
60 match r {
61 DecomposeResult::Normal { is_neg, exp, mantissa } => if 1 << ($exponent_width - 1) <= exp && is_neg {
62 <$fty>::NEG_INFINITY
63 } else if 1 << ($exponent_width - 1) <= exp {
64 <$fty>::INFINITY
65 } else if exp <= -((1 << ($exponent_width - 1)) + $mantissa_width - 1) && is_neg {
66 -0.0
67 } else if exp <= -((1 << ($exponent_width - 1)) + $mantissa_width - 1) {
68 0.0
69 } else if -((1 << ($exponent_width - 1)) + $mantissa_width - 2) <= exp && exp <= -((1 << ($exponent_width - 1)) - 1) {
70 let is_neg = (is_neg as $ity) << ($exponent_width + $mantissa_width);
71 let mut mantissa = (mantissa >> (127 - $mantissa_width)) as $ity;
72 let to_shift = -(((1 << ($exponent_width - 1)) - 1) - 1) - exp;
73 mantissa >>= to_shift;
74 <$fty>::from_bits(is_neg | mantissa)
75 } else {
76 let is_neg = (is_neg as $ity) << ($exponent_width + $mantissa_width);
77 let exp = ((exp + ((1 << ($exponent_width - 1)) - 1)) as $ity) << $mantissa_width;
78 let mantissa = ((mantissa >> (127 - $mantissa_width)) & ((1 << $mantissa_width) - 1)) as $ity;
79 <$fty>::from_bits(is_neg | exp | mantissa)
80 },
81 DecomposeResult::Zero => 0.0,
82 DecomposeResult::NegZero => -0.0,
83 DecomposeResult::Infinity => <$fty>::INFINITY,
84 DecomposeResult::NegInfinity => <$fty>::NEG_INFINITY,
85 DecomposeResult::NotANumber => <$fty>::NAN,
86 }
87 }
88 }
89 };
90}
91
92#[cfg(feature = "f16")]
93ieee754!(f16, u16, 5, 10);
94
95ieee754!(f32, u32, 8, 23);
96ieee754!(f64, u64, 11, 52);
97
98#[cfg(feature = "f128")]
99ieee754!(f128, u128, 15, 112);