1use az::Az;
2use std::{fmt, ops};
3
4type NBits = u16;
6
7pub 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 const BITS: NBits;
17
18 const ZERO: Self;
20
21 const ONE: Self;
23
24 #[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!(u32, u64 );
42
43pub trait AsBits {
45 type Bits: Bits;
47 fn to_bits(self) -> Self::Bits;
49 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
74pub 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 BiasedExponent;
85 type Exponent;
87 type Significand;
89
90 const BITS: NBits = Self::Bits::BITS as NBits;
92 const EXP_BITS: NBits;
94 const SIGNIF_BITS: NBits;
96
97 const SIGN_MASK: Self::Bits;
99 const EXP_MASK: Self::Bits;
101 const SIGNIF_MASK: Self::Bits;
103
104 const EXP_BIAS: Self::Exponent;
106
107 #[inline]
109 fn sign_bit(self) -> bool {
110 !(self.to_bits() & Self::SIGN_MASK).is_zero()
111 }
112
113 #[inline]
115 fn biased_exponent(self) -> Self::BiasedExponent {
116 ((self.to_bits() & Self::EXP_MASK) >> Self::SIGNIF_BITS).az()
117 }
118
119 #[inline]
121 fn exponent(self) -> Self::Exponent {
122 self.biased_exponent().az() - Self::EXP_BIAS
123 }
124
125 #[inline]
129 fn stored_significand(self) -> Self::Significand {
130 (self.to_bits() & Self::SIGNIF_MASK).az()
131 }
132
133 #[inline]
135 fn significand(self) -> Self::Significand {
136 self.stored_significand() + (Self::Bits::ONE << Self::SIGNIF_BITS).az()
138 }
139
140 #[inline]
144 fn fraction(self) -> Self::Significand {
145 self.stored_significand()
146 }
147
148 #[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 #[inline]
162 fn components(self) -> (bool, Self::Exponent, Self::Significand) {
163 (self.sign_bit(), self.exponent(), self.significand())
164 }
165
166 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 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}