float_dbg/
lib.rs

1use az::Az;
2use std::{fmt, ops};
3
4/// Type to represent the number of bits.
5type NBits = u16;
6
7/// Types suitable for bit representations.
8pub trait Bits: Copy + Eq + PartialEq
9where
10    Self: fmt::Binary,
11    Self: ops::Shl<NBits, Output = Self>,
12    Self: ops::Shr<NBits, Output = Self>,
13    Self: ops::BitAnd<Output = Self>,
14{
15    /// The number of bits.
16    const BITS: NBits;
17
18    /// The value `0`.
19    const ZERO: Self;
20
21    /// The value `1`.
22    const ONE: Self;
23
24    /// Test if the value is zero.
25    #[inline]
26    fn is_zero(self) -> bool {
27        self == Self::ZERO
28    }
29}
30
31macro_rules! impl_Bits {
32    ($($T:ty),*) => {$(
33        impl Bits for $T {
34            const BITS: NBits = <$T>::BITS as NBits;
35            const ZERO: Self = 0;
36            const ONE:Self=1;
37        }
38    )*};
39}
40
41impl_Bits!(/*u8, u16,*/ u32, u64 /*, u128*/);
42
43/// Conversions to and from bit representations.
44pub trait AsBits {
45    /// Type for the bit representation of `Self`.
46    type Bits: Bits;
47    /// Convert to the underlying bit representation.
48    fn to_bits(self) -> Self::Bits;
49    /// Convert from the underlying bit representation.
50    fn from_bits(b: Self::Bits) -> Self;
51}
52
53macro_rules! impl_AsBits {
54    ($F:ty, $Bits:ty) => {
55        impl AsBits for $F {
56            type Bits = $Bits;
57
58            #[inline]
59            fn to_bits(self) -> Self::Bits {
60                self.to_bits()
61            }
62
63            #[inline]
64            fn from_bits(b: Self::Bits) -> Self {
65                Self::from_bits(b)
66            }
67        }
68    };
69}
70
71impl_AsBits!(f32, u32);
72impl_AsBits!(f64, u64);
73
74/// Types that represent a floating point number.
75pub trait Float: Copy + PartialEq + PartialOrd + AsBits
76where
77    Self::Bits: az::Cast<Self::BiasedExponent>,
78    Self::BiasedExponent: az::Cast<Self::Exponent>,
79    Self::Bits: az::Cast<Self::Significand>,
80    Self::Exponent: ops::Sub<Output = Self::Exponent>,
81    Self::Significand: ops::Add<Output = Self::Significand>,
82{
83    /// Type for the the biased exponent.
84    type BiasedExponent;
85    /// Type for the true (unbiased) signed exponent.
86    type Exponent;
87    /// Type for the significand, both with and without implicit bit.
88    type Significand;
89
90    /// The number of bits (defaults to [`<Self as AsBits>::Bits::BITS`](Bits::BITS)).
91    const BITS: NBits = Self::Bits::BITS as NBits;
92    /// The number of bits of the exponent.
93    const EXP_BITS: NBits;
94    /// The number of bits of the stored significand (not counting the implicit bit).
95    const SIGNIF_BITS: NBits;
96
97    /// The mask for the sign bit.
98    const SIGN_MASK: Self::Bits;
99    /// The mask for the biased exponent bits.
100    const EXP_MASK: Self::Bits;
101    /// The mask for the stored significand bits (no implicit bit).
102    const SIGNIF_MASK: Self::Bits;
103
104    /// The exponent bias.
105    const EXP_BIAS: Self::Exponent;
106
107    /// True if the sign bit is set, false otherwise.
108    #[inline]
109    fn sign_bit(self) -> bool {
110        !(self.to_bits() & Self::SIGN_MASK).is_zero()
111    }
112
113    /// The biased exponent, as it is stored in the bit representation.
114    #[inline]
115    fn biased_exponent(self) -> Self::BiasedExponent {
116        ((self.to_bits() & Self::EXP_MASK) >> Self::SIGNIF_BITS).az()
117    }
118
119    /// The true (unbiased) signed exponent.
120    #[inline]
121    fn exponent(self) -> Self::Exponent {
122        self.biased_exponent().az() - Self::EXP_BIAS
123    }
124
125    /// The significand without the implicit bit, as it is stored in the bit representation.
126    ///
127    /// Synonym of [`Float::fraction`].
128    #[inline]
129    fn stored_significand(self) -> Self::Significand {
130        (self.to_bits() & Self::SIGNIF_MASK).az()
131    }
132
133    /// The true significand, with the implicit bit added.
134    #[inline]
135    fn significand(self) -> Self::Significand {
136        // Fixme
137        self.stored_significand() + (Self::Bits::ONE << Self::SIGNIF_BITS).az()
138    }
139
140    /// The significand without the implicit bit, as it is stored in the bit representation.
141    ///
142    /// Synonym of [`Float::stored_significand`].
143    #[inline]
144    fn fraction(self) -> Self::Significand {
145        self.stored_significand()
146    }
147
148    /// The triple of stored components:
149    /// sign bit, biased exponent, significand without implicit bit.
150    #[inline]
151    fn raw_components(self) -> (bool, Self::BiasedExponent, Self::Significand) {
152        (
153            self.sign_bit(),
154            self.biased_exponent(),
155            self.stored_significand(),
156        )
157    }
158
159    /// The triple of true components:
160    /// sign bit, exponent, significand with implicit bit.
161    #[inline]
162    fn components(self) -> (bool, Self::Exponent, Self::Significand) {
163        (self.sign_bit(), self.exponent(), self.significand())
164    }
165
166    /// Nicely prints the components of a floating point number.
167    ///
168    /// ```
169    /// # use float_dbg::Float;
170    /// 0.032_f32.explain();
171    /// ```
172    ///
173    /// ```text
174    /// value = 0.032
175    /// bits: 00111101000000110001001001101111
176    ///       ±^^^^^^^^_______________________
177    /// sign: +
178    /// exponent = 122 - 127 = -5
179    /// significand = 2^23 + 201327 = 8589935
180    /// ```
181    fn explain(self)
182    where
183        Self: fmt::Debug,
184        Self::BiasedExponent: fmt::Debug,
185        Self::Exponent: fmt::Debug,
186        Self::Significand: fmt::Debug,
187    {
188        println!("value = {:?}", self);
189        println!(
190            "bits: {:0width$b}",
191            self.to_bits(),
192            width = Self::Bits::BITS as usize
193        );
194        println!(
195            "      ±{:^<e$}{:_<f$}",
196            "",
197            "",
198            e = Self::EXP_BITS as usize,
199            f = Self::SIGNIF_BITS as usize
200        );
201        println!("sign: {}", if self.sign_bit() { "-" } else { "+" });
202        println!(
203            "exponent = {:?} - {:?} = {:?}",
204            self.biased_exponent(),
205            Self::EXP_BIAS,
206            self.exponent()
207        );
208        println!(
209            "significand = 2^{:?} + {:?} = {:?}",
210            Self::SIGNIF_BITS,
211            self.stored_significand(),
212            self.significand()
213        );
214    }
215}
216
217macro_rules! impl_Float {
218    ($F:ty, $BiasedExponent:ty, $Exponent:ty, $Significand:ty; $exp_bits:expr, $signif_bits:expr) => {
219        impl Float for $F {
220            type BiasedExponent = $BiasedExponent;
221            type Exponent = $Exponent;
222            type Significand = $Significand;
223
224            const EXP_BITS: NBits = $exp_bits;
225            const SIGNIF_BITS: NBits = $signif_bits;
226
227            // The following could be default values defined in the trait Float
228            // if `<<` and `-` were constant functions on `Self::Bits`.
229
230            const SIGN_MASK: Self::Bits = 1 << (Self::EXP_BITS + Self::SIGNIF_BITS);
231            const EXP_MASK: Self::Bits = (1 << Self::EXP_BITS) - 1 << Self::SIGNIF_BITS;
232            const SIGNIF_MASK: Self::Bits = (1 << Self::SIGNIF_BITS) - 1;
233
234            const EXP_BIAS: Self::Exponent = ((1 << Self::EXP_BITS - 1) - 1);
235        }
236    };
237}
238
239impl_Float!(f32, u8, i16, u32; 8, 23);
240impl_Float!(f64, u16, i16, u64; 11, 52);
241
242#[cfg(test)]
243mod tests {
244    use super::*;
245
246    #[test]
247    fn f32_components() {
248        let x = 0.032_f32;
249        assert_eq!(x.components(), (false, -5, 8589935));
250    }
251
252    #[test]
253    fn f64_components() {
254        let x = 0.032_f64;
255        assert_eq!(x.components(), (false, -5, 4611686018427388));
256    }
257}