]> git.lizzy.rs Git - rust.git/blob - src/libcore/tests/num/dec2flt/rawfp.rs
merge with master to pick up pulldown switch
[rust.git] / src / libcore / tests / num / dec2flt / rawfp.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::f64;
12 use std::mem;
13 use core::num::diy_float::Fp;
14 use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal};
15
16 fn integer_decode(f: f64) -> (u64, i16, i8) {
17     let bits: u64 = unsafe { mem::transmute(f) };
18     let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
19     let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
20     let mantissa = if exponent == 0 {
21         (bits & 0xfffffffffffff) << 1
22     } else {
23         (bits & 0xfffffffffffff) | 0x10000000000000
24     };
25     // Exponent bias + mantissa shift
26     exponent -= 1023 + 52;
27     (mantissa, exponent, sign)
28 }
29
30 #[test]
31 fn fp_to_float_half_to_even() {
32     fn is_normalized(sig: u64) -> bool {
33         // intentionally written without {min,max}_sig() as a sanity check
34         sig >> 52 == 1 && sig >> 53 == 0
35     }
36
37     fn conv(sig: u64) -> u64 {
38         // The significands are perfectly in range, so the exponent should not matter
39         let (m1, e1, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 0 }));
40         assert_eq!(e1, 0 + 64 - 53);
41         let (m2, e2, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: 55 }));
42         assert_eq!(e2, 55 + 64 - 53);
43         assert_eq!(m2, m1);
44         let (m3, e3, _) = integer_decode(fp_to_float::<f64>(Fp { f: sig, e: -78 }));
45         assert_eq!(e3, -78 + 64 - 53);
46         assert_eq!(m3, m2);
47         m3
48     }
49
50     let odd = 0x1F_EDCB_A012_345F;
51     let even = odd - 1;
52     assert!(is_normalized(odd));
53     assert!(is_normalized(even));
54     assert_eq!(conv(odd << 11), odd);
55     assert_eq!(conv(even << 11), even);
56     assert_eq!(conv(odd << 11 | 1 << 10), odd + 1);
57     assert_eq!(conv(even << 11 | 1 << 10), even);
58     assert_eq!(conv(even << 11 | 1 << 10 | 1), even + 1);
59     assert_eq!(conv(odd << 11 | 1 << 9), odd);
60     assert_eq!(conv(even << 11 | 1 << 9), even);
61     assert_eq!(conv(odd << 11 | 0x7FF), odd + 1);
62     assert_eq!(conv(even << 11 | 0x7FF), even + 1);
63     assert_eq!(conv(odd << 11 | 0x3FF), odd);
64     assert_eq!(conv(even << 11 | 0x3FF), even);
65 }
66
67 #[test]
68 fn integers_to_f64() {
69     assert_eq!(fp_to_float::<f64>(Fp { f: 1, e: 0 }), 1.0);
70     assert_eq!(fp_to_float::<f64>(Fp { f: 42, e: 7 }), (42 << 7) as f64);
71     assert_eq!(fp_to_float::<f64>(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64);
72     assert_eq!(fp_to_float::<f64>(Fp { f: 4, e: -3 }), 0.5);
73 }
74
75 const SOME_FLOATS: [f64; 9] =
76     [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997,
77      9843579834.35892, 12456.0e-150, 54389573.0e-150];
78
79
80 #[test]
81 fn human_f64_roundtrip() {
82     for &x in &SOME_FLOATS {
83         let (f, e, _) = integer_decode(x);
84         let fp = Fp { f: f, e: e};
85         assert_eq!(fp_to_float::<f64>(fp), x);
86     }
87 }
88
89 #[test]
90 fn rounding_overflow() {
91     let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 };
92     let rounded = round_normal::<f64>(x);
93     let adjusted_k = x.e + 64 - 53;
94     assert_eq!(rounded.sig, 1 << 52);
95     assert_eq!(rounded.k, adjusted_k + 1);
96 }
97
98 #[test]
99 fn prev_float_monotonic() {
100     let mut x = 1.0;
101     for _ in 0..100 {
102         let x1 = prev_float(x);
103         assert!(x1 < x);
104         assert!(x - x1 < 1e-15);
105         x = x1;
106     }
107 }
108
109 const MIN_SUBNORMAL: f64 = 5e-324;
110
111 #[test]
112 fn next_float_zero() {
113     let tiny = next_float(0.0);
114     assert_eq!(tiny, MIN_SUBNORMAL);
115     assert!(tiny != 0.0);
116 }
117
118 #[test]
119 fn next_float_subnormal() {
120     let second = next_float(MIN_SUBNORMAL);
121     // For subnormals, MIN_SUBNORMAL is the ULP
122     assert!(second != MIN_SUBNORMAL);
123     assert!(second > 0.0);
124     assert_eq!(second - MIN_SUBNORMAL, MIN_SUBNORMAL);
125 }
126
127 #[test]
128 fn next_float_inf() {
129     assert_eq!(next_float(f64::MAX), f64::INFINITY);
130     assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
131 }
132
133 #[test]
134 fn next_prev_identity() {
135     for &x in &SOME_FLOATS {
136         assert_eq!(prev_float(next_float(x)), x);
137         assert_eq!(prev_float(prev_float(next_float(next_float(x)))), x);
138         assert_eq!(next_float(prev_float(x)), x);
139         assert_eq!(next_float(next_float(prev_float(prev_float(x)))), x);
140     }
141 }
142
143 #[test]
144 fn next_float_monotonic() {
145     let mut x = 0.49999999999999;
146     assert!(x < 0.5);
147     for _ in 0..200 {
148         let x1 = next_float(x);
149         assert!(x1 > x);
150         assert!(x1 - x < 1e-15, "next_float_monotonic: delta = {:?}", x1 - x);
151         x = x1;
152     }
153     assert!(x > 0.5);
154 }