1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use core::mem::transmute;
use super::float_info::FloatInfo;
pub trait FractExp {
type Output;
/// Returns normalized fraction and exponent of a number.
/// ```
/// // floating point numbers
/// use traiter::numbers::FractExp;
/// assert_eq!(FractExp::fract_exp(-1.5_f32), (-0.75_f32, 1));
/// assert_eq!(FractExp::fract_exp(0.0_f32), (0.0_f32, 0));
/// assert_eq!(FractExp::fract_exp(1.5_f32), (0.75_f32, 1));
/// ```
fn fract_exp(self) -> Self::Output;
}
macro_rules! float_fract_exp_impl {
($float:ty, $bits:ty) => {
impl FractExp for $float {
type Output = (Self, i32);
#[inline]
fn fract_exp(self) -> Self::Output {
const EXPONENT_MASK: $bits =
(1 << <$float>::EXPONENT_BITS_COUNT) - 1;
let bits = self.to_bits();
let exponent_bits = ((bits
>> <$float>::SIGNIFICAND_BITS_COUNT)
& EXPONENT_MASK) as i32;
if exponent_bits == 0 {
if self == (0.0 as $float) {
(self, 0)
} else {
const EXPONENT_BASE: $bits = (1
<< (<$float>::EXPONENT_BITS_COUNT - 1usize))
- 1;
const EXPONENT_DECREMENT: i32 = 64i32;
const SCALE: $float = unsafe {
transmute::<$bits, $float>(
(((EXPONENT_BASE as i32) + EXPONENT_DECREMENT)
as $bits)
<< <$float>::SIGNIFICAND_BITS_COUNT,
)
};
let (fraction, exponent) = (self * SCALE).fract_exp();
(fraction, exponent - EXPONENT_DECREMENT)
}
} else if exponent_bits == (EXPONENT_MASK as i32) {
(self, 0)
} else {
const SIGNIFICANT_MASK: $bits =
(1 << <$float>::SIGNIFICAND_BITS_COUNT) - 1;
const EXPONENT_NULL_MASK: $bits = (1
<< (<$float>::TOTAL_BITS_COUNT - 1usize))
| SIGNIFICANT_MASK;
const EXPONENT_DECREMENT: i32 = <$float>::MAX_EXP - 2i32;
(
Self::from_bits(
bits & EXPONENT_NULL_MASK
| ((EXPONENT_DECREMENT as $bits)
<< <$float>::SIGNIFICAND_BITS_COUNT),
),
exponent_bits - EXPONENT_DECREMENT,
)
}
}
}
};
}
float_fract_exp_impl!(f32, u32);
float_fract_exp_impl!(f64, u64);