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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use crate::lib::convert::From;
use crate::lib::mem;
use crate::util::*;
use super::float::ExtendedFloat;
use super::mantissa::Mantissa;
perftools_inline!{
pub(crate) fn from_int<T, M>(t: T)
-> ExtendedFloat<M>
where T: Integer,
M: Mantissa
{
debug_assert!(mem::size_of::<T>() <= mem::size_of::<M>(), "Possible truncation in ExtendedFloat::from_int.");
ExtendedFloat {
mant: as_cast(t),
exp: 0,
}
}}
perftools_inline!{
pub(crate) fn from_float<T, M>(t: T)
-> ExtendedFloat<M>
where T: Float,
M: Mantissa
{
ExtendedFloat {
mant: as_cast(t.mantissa()),
exp: t.exponent(),
}
}}
perftools_inline!{
pub(crate) fn into_float<T, M>(fp: ExtendedFloat<M>)
-> T
where T: Float,
M: Mantissa
{
if fp.mant.is_zero() || fp.exp < T::DENORMAL_EXPONENT {
T::ZERO
} else if fp.exp >= T::MAX_EXPONENT {
T::from_bits(T::INFINITY_BITS)
} else {
let exp: M;
if (fp.exp == T::DENORMAL_EXPONENT) && (fp.mant & as_cast::<M, _>(T::HIDDEN_BIT_MASK)).is_zero() {
exp = M::ZERO;
} else {
exp = as_cast::<M, _>(fp.exp + T::EXPONENT_BIAS);
}
let exp = exp << T::MANTISSA_SIZE;
let mant = fp.mant & as_cast::<M, _>(T::MANTISSA_MASK);
T::from_bits(as_cast(mant | exp))
}
}}
impl<F: Float> From<F> for ExtendedFloat<F::Unsigned> where F::Unsigned: Mantissa {
perftools_inline!{
fn from(f: F) -> Self {
from_float(f)
}}
}
impl<M: Mantissa> From<(M, i32)> for ExtendedFloat<M> {
perftools_inline!{
fn from(t: (M, i32)) -> Self {
ExtendedFloat { mant: t.0, exp: t.1 }
}}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn convert_float_test() {
let f: f32 = 1e-45;
let fp: ExtendedFloat<u32> = f.into();
assert_eq!(fp, ExtendedFloat { mant: 1u32, exp: -149 });
}
#[test]
fn convert_tuple_test() {
let t = (1u64, 0i32);
let fp: ExtendedFloat<u64> = t.into();
assert_eq!(fp, ExtendedFloat { mant: 1u64, exp: 0 });
}
}