]> git.lizzy.rs Git - rust.git/blob - src/libcore/num/dec2flt/num.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / libcore / num / dec2flt / num.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 //! Utility functions for bignums that don't make too much sense to turn into methods.
12
13 // FIXME This module's name is a bit unfortunate, since other modules also import `core::num`.
14
15 use cmp::Ordering::{self, Less, Equal, Greater};
16
17 pub use num::bignum::Big32x40 as Big;
18
19 /// Test whether truncating all bits less significant than `ones_place` introduces
20 /// a relative error less, equal, or greater than 0.5 ULP.
21 pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering {
22     if ones_place == 0 {
23         return Less;
24     }
25     let half_bit = ones_place - 1;
26     if f.get_bit(half_bit) == 0 {
27         // < 0.5 ULP
28         return Less;
29     }
30     // If all remaining bits are zero, it's = 0.5 ULP, otherwise > 0.5
31     // If there are no more bits (half_bit == 0), the below also correctly returns Equal.
32     for i in 0..half_bit {
33         if f.get_bit(i) == 1 {
34             return Greater;
35         }
36     }
37     Equal
38 }
39
40 /// Convert an ASCII string containing only decimal digits to a `u64`.
41 ///
42 /// Does not perform checks for overflow or invalid characters, so if the caller is not careful,
43 /// the result is bogus and can panic (though it won't be `unsafe`). Additionally, empty strings
44 /// are treated as zero. This function exists because
45 ///
46 /// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and
47 /// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is
48 ///    more complicated than this entire function.
49 pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 where T : IntoIterator<Item=&'a u8> {
50     let mut result = 0;
51     for &c in bytes {
52         result = result * 10 + (c - b'0') as u64;
53     }
54     result
55 }
56
57 /// Convert a string of ASCII digits into a bignum.
58 ///
59 /// Like `from_str_unchecked`, this function relies on the parser to weed out non-digits.
60 pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big {
61     let mut f = Big::from_small(0);
62     for &c in integral.iter().chain(fractional) {
63         let n = (c - b'0') as u32;
64         f.mul_small(10);
65         f.add_small(n);
66     }
67     f
68 }
69
70 /// Unwraps a bignum into a 64 bit integer. Panics if the number is too large.
71 pub fn to_u64(x: &Big) -> u64 {
72     assert!(x.bit_length() < 64);
73     let d = x.digits();
74     if d.len() < 2 {
75         d[0] as u64
76     } else {
77         (d[1] as u64) << 32 | d[0] as u64
78     }
79 }
80
81
82 /// Extract a range of bits.
83
84 /// Index 0 is the least significant bit and the range is half-open as usual.
85 /// Panics if asked to extract more bits than fit into the return type.
86 pub fn get_bits(x: &Big, start: usize, end: usize) -> u64 {
87     assert!(end - start <= 64);
88     let mut result: u64 = 0;
89     for i in (start..end).rev() {
90         result = result << 1 | x.get_bit(i) as u64;
91     }
92     result
93 }