1
1
use super :: super :: { CastFrom , CastInto , Float , IntTy , MinInt } ;
2
2
3
+ /// Scale the exponent.
4
+ ///
5
+ /// From N3220:
6
+ ///
7
+ /// > The scalbn and scalbln functions compute `x * b^n`, where `b = FLT_RADIX` if the return type
8
+ /// > of the function is a standard floating type, or `b = 10` if the return type of the function
9
+ /// > is a decimal floating type. A range error occurs for some finite x, depending on n.
10
+ /// >
11
+ /// > [...]
12
+ /// >
13
+ /// > * `scalbn(±0, n)` returns `±0`.
14
+ /// > * `scalbn(x, 0)` returns `x`.
15
+ /// > * `scalbn(±∞, n)` returns `±∞`.
16
+ /// >
17
+ /// > If the calculation does not overflow or underflow, the returned value is exact and
18
+ /// > independent of the current rounding direction mode.
3
19
pub fn scalbn < F : Float > ( mut x : F , mut n : i32 ) -> F
4
20
where
5
21
u32 : CastInto < F :: Int > ,
6
22
F :: Int : CastFrom < i32 > ,
7
23
F :: Int : CastFrom < u32 > ,
8
24
{
25
+ if n == 0 || x == F :: ZERO || x. is_nan ( ) || x. is_infinite ( ) {
26
+ return x;
27
+ }
28
+
9
29
// Bits including the implicit bit
10
30
let sig_total_bits = F :: SIG_BITS + 1 ;
11
31
12
32
// Maximum and minimum values when biased
13
33
let exp_max: i32 = F :: EXP_BIAS as i32 ;
14
34
let exp_min = -( exp_max - 1 ) ;
35
+ let exp_min_with_subnorm = -( ( F :: EXP_BIAS + F :: SIG_BITS + 1 ) as i32 ) ;
36
+
37
+ // let x_exp = x.exp();
38
+ // let x_sig = x.frac();
39
+
40
+ if n > exp_max {
41
+ return F :: INFINITY * x. signum ( ) ;
42
+ }
43
+
44
+ if n < exp_min_with_subnorm {
45
+ return F :: ZERO * x. signum ( ) ;
46
+ }
15
47
16
48
// 2 ^ Emax, where Emax is the maximum biased exponent value (1023 for f64)
17
49
let f_exp_max = F :: from_bits ( F :: Int :: cast_from ( F :: EXP_BIAS << 1 ) << F :: SIG_BITS ) ;
@@ -20,14 +52,20 @@ where
20
52
// 2 ^ sig_total_bits, representation of what can be accounted for with subnormals
21
53
let f_exp_subnorm = F :: from_bits ( ( F :: EXP_BIAS + sig_total_bits) . cast ( ) << F :: SIG_BITS ) ;
22
54
55
+ // std::println!("{exp_max} {exp_min} {n}");
56
+ // std::dbg!(x, exp_max, exp_min, n);
57
+
23
58
if n > exp_max {
24
59
x *= f_exp_max;
25
60
n -= exp_max;
61
+ // std::dbg!(11, x, n);
26
62
if n > exp_max {
27
63
x *= f_exp_max;
28
64
n -= exp_max;
65
+ // std::dbg!(12, x, n);
29
66
if n > exp_max {
30
67
n = exp_max;
68
+ // std::dbg!(13, x, n);
31
69
}
32
70
}
33
71
} else if n < exp_min {
@@ -36,14 +74,31 @@ where
36
74
37
75
x *= mul;
38
76
n += add;
77
+ // std::dbg!(21, x, n);
39
78
if n < exp_min {
40
79
x *= mul;
41
80
n += add;
81
+ // std::dbg!(22, x, n);
42
82
if n < exp_min {
43
83
n = exp_min;
84
+ // std::dbg!(23, x, n);
44
85
}
45
86
}
46
87
}
47
88
48
89
x * F :: from_bits ( F :: Int :: cast_from ( F :: EXP_BIAS as i32 + n) << F :: SIG_BITS )
49
90
}
91
+
92
+ // DELETE
93
+
94
+ extern crate std;
95
+
96
+ #[ test]
97
+ fn testme ( ) {
98
+ assert_eq ! ( scalbn:: <f16>( f16:: from_bits( 0x6ecb ) , -1336428830 ) , f16:: ZERO ) ;
99
+ }
100
+
101
+ #[ test]
102
+ fn testme2 ( ) {
103
+ // assert_eq!(scalbn(-f64::INFINITY, -2147033648), f64::ZERO);
104
+ }
0 commit comments