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