     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

    // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
    // file at the top-level directory of this distribution and at
    // http://rust-lang.org/COPYRIGHT.
    //
    // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
    // option. This file may not be copied, modified, or distributed
    // except according to those terms.

    //! Utility functions for bignums that don't make too much sense to turn into methods.

    // FIXME This module's name is a bit unfortunate, since other modules also import `core::num`.

    use cmp::Ordering::{self, Less, Equal, Greater};

    pub use num::bignum::Big32x40 as Big;

    /// Test whether truncating all bits less significant than `ones_place` introduces
    /// a relative error less, equal, or greater than 0.5 ULP.
    pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering {
        if ones_place == 0 {
            return Less;
        }
        let half_bit = ones_place - 1;
        if f.get_bit(half_bit) == 0 {
            // < 0.5 ULP
            return Less;
        }
        // If all remaining bits are zero, it's = 0.5 ULP, otherwise > 0.5
        // If there are no more bits (half_bit == 0), the below also correctly returns Equal.
        for i in 0..half_bit {
            if f.get_bit(i) == 1 {
                return Greater;
            }
        }
        Equal
    }

    /// Convert an ASCII string containing only decimal digits to a `u64`.
    ///
    /// Does not perform checks for overflow or invalid characters, so if the caller is not careful,
    /// the result is bogus and can panic (though it won't be `unsafe`). Additionally, empty strings
    /// are treated as zero. This function exists because
    ///
    /// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and
    /// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is
    ///    more complicated than this entire function.
    pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 where T : IntoIterator<Item=&'a u8> {
        let mut result = 0;
        for &c in bytes {
            result = result * 10 + (c - b'0') as u64;
        }
        result
    }

    /// Convert a string of ASCII digits into a bignum.
    ///
    /// Like `from_str_unchecked`, this function relies on the parser to weed out non-digits.
    pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big {
        let mut f = Big::from_small(0);
        for &c in integral.iter().chain(fractional) {
            let n = (c - b'0') as u32;
            f.mul_small(10);
            f.add_small(n);
        }
        f
    }

    /// Unwraps a bignum into a 64 bit integer. Panics if the number is too large.
    pub fn to_u64(x: &Big) -> u64 {
        assert!(x.bit_length() < 64);
        let d = x.digits();
        if d.len() < 2 {
            d[0] as u64
        } else {
            (d[1] as u64) << 32 | d[0] as u64
        }
    }

    /// Extract a range of bits.

    /// Index 0 is the least significant bit and the range is half-open as usual.
    /// Panics if asked to extract more bits than fit into the return type.
    pub fn get_bits(x: &Big, start: usize, end: usize) -> u64 {
        assert!(end - start <= 64);
        let mut result: u64 = 0;
        for i in (start..end).rev() {
            result = result << 1 | x.get_bit(i) as u64;
        }
        result
    }

# Help

## Keyboard Shortcuts

?
  Show this help dialog
S
  Focus the search field
⇤
  Move up in search results
⇥
  Move down in search results
⏎
  Go to active search result
+
  Collapse/expand all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)