use std::borrow::Cow; use std::default::Default; use std::iter::repeat; use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub}; use std::str::{self, FromStr}; use std::fmt; use std::cmp; use std::cmp::Ordering::{self, Less, Greater, Equal}; use std::{f32, f64}; use std::{u8, u64}; use std::ascii::AsciiExt; #[cfg(feature = "serde")] use serde; use integer::Integer; use traits::{ToPrimitive, FromPrimitive, Float, Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, Zero, One}; #[path = "algorithms.rs"] mod algorithms; pub use self::algorithms::big_digit; pub use self::big_digit::{BigDigit, DoubleBigDigit, ZERO_BIG_DIGIT}; use self::algorithms::{mac_with_carry, mul3, div_rem, div_rem_digit}; use self::algorithms::{__add2, add2, sub2, sub2rev}; use self::algorithms::{biguint_shl, biguint_shr}; use self::algorithms::{cmp_slice, fls, ilog2}; use ParseBigIntError; #[cfg(test)] #[path = "tests/biguint.rs"] mod biguint_tests; /// A big unsigned integer type. /// /// A `BigUint`-typed value `BigUint { data: vec!(a, b, c) }` represents a number /// `(a + b * big_digit::BASE + c * big_digit::BASE^2)`. #[derive(Clone, Debug, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct BigUint { data: Vec, } impl PartialEq for BigUint { #[inline] fn eq(&self, other: &BigUint) -> bool { match self.cmp(other) { Equal => true, _ => false, } } } impl Eq for BigUint {} impl PartialOrd for BigUint { #[inline] fn partial_cmp(&self, other: &BigUint) -> Option { Some(self.cmp(other)) } } impl Ord for BigUint { #[inline] fn cmp(&self, other: &BigUint) -> Ordering { cmp_slice(&self.data[..], &other.data[..]) } } impl Default for BigUint { #[inline] fn default() -> BigUint { Zero::zero() } } impl fmt::Display for BigUint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "", &self.to_str_radix(10)) } } impl fmt::LowerHex for BigUint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "0x", &self.to_str_radix(16)) } } impl fmt::UpperHex for BigUint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "0x", &self.to_str_radix(16).to_ascii_uppercase()) } } impl fmt::Binary for BigUint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "0b", &self.to_str_radix(2)) } } impl fmt::Octal for BigUint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(true, "0o", &self.to_str_radix(8)) } } impl FromStr for BigUint { type Err = ParseBigIntError; #[inline] fn from_str(s: &str) -> Result { BigUint::from_str_radix(s, 10) } } // Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides // BigDigit::BITS fn from_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0); debug_assert!(v.iter().all(|&c| (c as BigDigit) < (1 << bits))); let digits_per_big_digit = big_digit::BITS / bits; let data = v.chunks(digits_per_big_digit) .map(|chunk| { chunk.iter().rev().fold(0, |acc, &c| (acc << bits) | c as BigDigit) }) .collect(); BigUint::new(data) } // Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide // BigDigit::BITS fn from_inexact_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0); debug_assert!(v.iter().all(|&c| (c as BigDigit) < (1 << bits))); let big_digits = (v.len() * bits + big_digit::BITS - 1) / big_digit::BITS; let mut data = Vec::with_capacity(big_digits); let mut d = 0; let mut dbits = 0; // number of bits we currently have in d // walk v accumululating bits in d; whenever we accumulate big_digit::BITS in d, spit out a // big_digit: for &c in v { d |= (c as BigDigit) << dbits; dbits += bits; if dbits >= big_digit::BITS { data.push(d); dbits -= big_digit::BITS; // if dbits was > big_digit::BITS, we dropped some of the bits in c (they couldn't fit // in d) - grab the bits we lost here: d = (c as BigDigit) >> (bits - dbits); } } if dbits > 0 { debug_assert!(dbits < big_digit::BITS); data.push(d as BigDigit); } BigUint::new(data) } // Read little-endian radix digits fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { debug_assert!(!v.is_empty() && !radix.is_power_of_two()); debug_assert!(v.iter().all(|&c| (c as u32) < radix)); // Estimate how big the result will be, so we can pre-allocate it. let bits = (radix as f64).log2() * v.len() as f64; let big_digits = (bits / big_digit::BITS as f64).ceil(); let mut data = Vec::with_capacity(big_digits as usize); let (base, power) = get_radix_base(radix); let radix = radix as BigDigit; let r = v.len() % power; let i = if r == 0 { power } else { r }; let (head, tail) = v.split_at(i); let first = head.iter().fold(0, |acc, &d| acc * radix + d as BigDigit); data.push(first); debug_assert!(tail.len() % power == 0); for chunk in tail.chunks(power) { if data.last() != Some(&0) { data.push(0); } let mut carry = 0; for d in data.iter_mut() { *d = mac_with_carry(0, *d, base, &mut carry); } debug_assert!(carry == 0); let n = chunk.iter().fold(0, |acc, &d| acc * radix + d as BigDigit); add2(&mut data, &[n]); } BigUint::new(data) } impl Num for BigUint { type FromStrRadixErr = ParseBigIntError; /// Creates and initializes a `BigUint`. fn from_str_radix(s: &str, radix: u32) -> Result { assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); let mut s = s; if s.starts_with('+') { let tail = &s[1..]; if !tail.starts_with('+') { s = tail } } if s.is_empty() { // create ParseIntError::Empty let e = u64::from_str_radix(s, radix).unwrap_err(); return Err(e.into()); } // First normalize all characters to plain digit values let mut v = Vec::with_capacity(s.len()); for b in s.bytes() { let d = match b { b'0'...b'9' => b - b'0', b'a'...b'z' => b - b'a' + 10, b'A'...b'Z' => b - b'A' + 10, _ => u8::MAX, }; if d < radix as u8 { v.push(d); } else { // create ParseIntError::InvalidDigit // Include the previous character for context. let i = cmp::max(v.len(), 1) - 1; let e = u64::from_str_radix(&s[i..], radix).unwrap_err(); return Err(e.into()); } } let res = if radix.is_power_of_two() { // Powers of two can use bitwise masks and shifting instead of multiplication let bits = ilog2(radix); v.reverse(); if big_digit::BITS % bits == 0 { from_bitwise_digits_le(&v, bits) } else { from_inexact_bitwise_digits_le(&v, bits) } } else { from_radix_digits_be(&v, radix) }; Ok(res) } } forward_all_binop_to_val_ref_commutative!(impl BitAnd for BigUint, bitand); impl<'a> BitAnd<&'a BigUint> for BigUint { type Output = BigUint; #[inline] fn bitand(self, other: &BigUint) -> BigUint { let mut data = self.data; for (ai, &bi) in data.iter_mut().zip(other.data.iter()) { *ai &= bi; } data.truncate(other.data.len()); BigUint::new(data) } } forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor); impl<'a> BitOr<&'a BigUint> for BigUint { type Output = BigUint; fn bitor(self, other: &BigUint) -> BigUint { let mut data = self.data; for (ai, &bi) in data.iter_mut().zip(other.data.iter()) { *ai |= bi; } if other.data.len() > data.len() { let extra = &other.data[data.len()..]; data.extend(extra.iter().cloned()); } BigUint::new(data) } } forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor); impl<'a> BitXor<&'a BigUint> for BigUint { type Output = BigUint; fn bitxor(self, other: &BigUint) -> BigUint { let mut data = self.data; for (ai, &bi) in data.iter_mut().zip(other.data.iter()) { *ai ^= bi; } if other.data.len() > data.len() { let extra = &other.data[data.len()..]; data.extend(extra.iter().cloned()); } BigUint::new(data) } } impl Shl for BigUint { type Output = BigUint; #[inline] fn shl(self, rhs: usize) -> BigUint { biguint_shl(Cow::Owned(self), rhs) } } impl<'a> Shl for &'a BigUint { type Output = BigUint; #[inline] fn shl(self, rhs: usize) -> BigUint { biguint_shl(Cow::Borrowed(self), rhs) } } impl Shr for BigUint { type Output = BigUint; #[inline] fn shr(self, rhs: usize) -> BigUint { biguint_shr(Cow::Owned(self), rhs) } } impl<'a> Shr for &'a BigUint { type Output = BigUint; #[inline] fn shr(self, rhs: usize) -> BigUint { biguint_shr(Cow::Borrowed(self), rhs) } } impl Zero for BigUint { #[inline] fn zero() -> BigUint { BigUint::new(Vec::new()) } #[inline] fn is_zero(&self) -> bool { self.data.is_empty() } } impl One for BigUint { #[inline] fn one() -> BigUint { BigUint::new(vec![1]) } } impl Unsigned for BigUint {} forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); impl<'a> Add<&'a BigUint> for BigUint { type Output = BigUint; fn add(mut self, other: &BigUint) -> BigUint { if self.data.len() < other.data.len() { let extra = other.data.len() - self.data.len(); self.data.extend(repeat(0).take(extra)); } let carry = __add2(&mut self.data[..], &other.data[..]); if carry != 0 { self.data.push(carry); } self } } forward_val_val_binop!(impl Sub for BigUint, sub); forward_ref_ref_binop!(impl Sub for BigUint, sub); impl<'a> Sub<&'a BigUint> for BigUint { type Output = BigUint; fn sub(mut self, other: &BigUint) -> BigUint { sub2(&mut self.data[..], &other.data[..]); self.normalize() } } impl<'a> Sub for &'a BigUint { type Output = BigUint; fn sub(self, mut other: BigUint) -> BigUint { if other.data.len() < self.data.len() { let extra = self.data.len() - other.data.len(); other.data.extend(repeat(0).take(extra)); } sub2rev(&self.data[..], &mut other.data[..]); other.normalize() } } forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul); impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint { type Output = BigUint; #[inline] fn mul(self, other: &BigUint) -> BigUint { mul3(&self.data[..], &other.data[..]) } } forward_all_binop_to_ref_ref!(impl Div for BigUint, div); impl<'a, 'b> Div<&'b BigUint> for &'a BigUint { type Output = BigUint; #[inline] fn div(self, other: &BigUint) -> BigUint { let (q, _) = self.div_rem(other); return q; } } forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem); impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint { type Output = BigUint; #[inline] fn rem(self, other: &BigUint) -> BigUint { let (_, r) = self.div_rem(other); return r; } } impl Neg for BigUint { type Output = BigUint; #[inline] fn neg(self) -> BigUint { panic!() } } impl<'a> Neg for &'a BigUint { type Output = BigUint; #[inline] fn neg(self) -> BigUint { panic!() } } impl CheckedAdd for BigUint { #[inline] fn checked_add(&self, v: &BigUint) -> Option { return Some(self.add(v)); } } impl CheckedSub for BigUint { #[inline] fn checked_sub(&self, v: &BigUint) -> Option { match self.cmp(v) { Less => None, Equal => Some(Zero::zero()), Greater => Some(self.sub(v)), } } } impl CheckedMul for BigUint { #[inline] fn checked_mul(&self, v: &BigUint) -> Option { return Some(self.mul(v)); } } impl CheckedDiv for BigUint { #[inline] fn checked_div(&self, v: &BigUint) -> Option { if v.is_zero() { return None; } return Some(self.div(v)); } } impl Integer for BigUint { #[inline] fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { div_rem(self, other) } #[inline] fn div_floor(&self, other: &BigUint) -> BigUint { let (d, _) = div_rem(self, other); d } #[inline] fn mod_floor(&self, other: &BigUint) -> BigUint { let (_, m) = div_rem(self, other); m } #[inline] fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) { div_rem(self, other) } /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. /// /// The result is always positive. #[inline] fn gcd(&self, other: &BigUint) -> BigUint { // Use Euclid's algorithm let mut m = (*self).clone(); let mut n = (*other).clone(); while !m.is_zero() { let temp = m; m = n % &temp; n = temp; } return n; } /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn lcm(&self, other: &BigUint) -> BigUint { ((self * other) / self.gcd(other)) } /// Deprecated, use `is_multiple_of` instead. #[inline] fn divides(&self, other: &BigUint) -> bool { self.is_multiple_of(other) } /// Returns `true` if the number is a multiple of `other`. #[inline] fn is_multiple_of(&self, other: &BigUint) -> bool { (self % other).is_zero() } /// Returns `true` if the number is divisible by `2`. #[inline] fn is_even(&self) -> bool { // Considering only the last digit. match self.data.first() { Some(x) => x.is_even(), None => true, } } /// Returns `true` if the number is not divisible by `2`. #[inline] fn is_odd(&self) -> bool { !self.is_even() } } fn high_bits_to_u64(v: &BigUint) -> u64 { match v.data.len() { 0 => 0, 1 => v.data[0] as u64, _ => { let mut bits = v.bits(); let mut ret = 0u64; let mut ret_bits = 0; for d in v.data.iter().rev() { let digit_bits = (bits - 1) % big_digit::BITS + 1; let bits_want = cmp::min(64 - ret_bits, digit_bits); if bits_want != 64 { ret <<= bits_want; } ret |= *d as u64 >> (digit_bits - bits_want); ret_bits += bits_want; bits -= bits_want; if ret_bits == 64 { break; } } ret } } } impl ToPrimitive for BigUint { #[inline] fn to_i64(&self) -> Option { self.to_u64().and_then(|n| { // If top bit of u64 is set, it's too large to convert to i64. if n >> 63 == 0 { Some(n as i64) } else { None } }) } #[inline] fn to_u64(&self) -> Option { let mut ret: u64 = 0; let mut bits = 0; for i in self.data.iter() { if bits >= 64 { return None; } ret += (*i as u64) << bits; bits += big_digit::BITS; } Some(ret) } #[inline] fn to_f32(&self) -> Option { let mantissa = high_bits_to_u64(self); let exponent = self.bits() - fls(mantissa); if exponent > f32::MAX_EXP as usize { None } else { let ret = (mantissa as f32) * 2.0f32.powi(exponent as i32); if ret.is_infinite() { None } else { Some(ret) } } } #[inline] fn to_f64(&self) -> Option { let mantissa = high_bits_to_u64(self); let exponent = self.bits() - fls(mantissa); if exponent > f64::MAX_EXP as usize { None } else { let ret = (mantissa as f64) * 2.0f64.powi(exponent as i32); if ret.is_infinite() { None } else { Some(ret) } } } } impl FromPrimitive for BigUint { #[inline] fn from_i64(n: i64) -> Option { if n >= 0 { Some(BigUint::from(n as u64)) } else { None } } #[inline] fn from_u64(n: u64) -> Option { Some(BigUint::from(n)) } #[inline] fn from_f64(mut n: f64) -> Option { // handle NAN, INFINITY, NEG_INFINITY if !n.is_finite() { return None; } // match the rounding of casting from float to int n = n.trunc(); // handle 0.x, -0.x if n.is_zero() { return Some(BigUint::zero()); } let (mantissa, exponent, sign) = Float::integer_decode(n); if sign == -1 { return None; } let mut ret = BigUint::from(mantissa); if exponent > 0 { ret = ret << exponent as usize; } else if exponent < 0 { ret = ret >> (-exponent) as usize; } Some(ret) } } impl From for BigUint { #[inline] fn from(mut n: u64) -> Self { let mut ret: BigUint = Zero::zero(); while n != 0 { ret.data.push(n as BigDigit); // don't overflow if BITS is 64: n = (n >> 1) >> (big_digit::BITS - 1); } ret } } macro_rules! impl_biguint_from_uint { ($T:ty) => { impl From<$T> for BigUint { #[inline] fn from(n: $T) -> Self { BigUint::from(n as u64) } } } } impl_biguint_from_uint!(u8); impl_biguint_from_uint!(u16); impl_biguint_from_uint!(u32); impl_biguint_from_uint!(usize); /// A generic trait for converting a value to a `BigUint`. pub trait ToBigUint { /// Converts the value of `self` to a `BigUint`. fn to_biguint(&self) -> Option; } impl ToBigUint for BigUint { #[inline] fn to_biguint(&self) -> Option { Some(self.clone()) } } macro_rules! impl_to_biguint { ($T:ty, $from_ty:path) => { impl ToBigUint for $T { #[inline] fn to_biguint(&self) -> Option { $from_ty(*self) } } } } impl_to_biguint!(isize, FromPrimitive::from_isize); impl_to_biguint!(i8, FromPrimitive::from_i8); impl_to_biguint!(i16, FromPrimitive::from_i16); impl_to_biguint!(i32, FromPrimitive::from_i32); impl_to_biguint!(i64, FromPrimitive::from_i64); impl_to_biguint!(usize, FromPrimitive::from_usize); impl_to_biguint!(u8, FromPrimitive::from_u8); impl_to_biguint!(u16, FromPrimitive::from_u16); impl_to_biguint!(u32, FromPrimitive::from_u32); impl_to_biguint!(u64, FromPrimitive::from_u64); impl_to_biguint!(f32, FromPrimitive::from_f32); impl_to_biguint!(f64, FromPrimitive::from_f64); // Extract bitwise digits that evenly divide BigDigit fn to_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0); let last_i = u.data.len() - 1; let mask: BigDigit = (1 << bits) - 1; let digits_per_big_digit = big_digit::BITS / bits; let digits = (u.bits() + bits - 1) / bits; let mut res = Vec::with_capacity(digits); for mut r in u.data[..last_i].iter().cloned() { for _ in 0..digits_per_big_digit { res.push((r & mask) as u8); r >>= bits; } } let mut r = u.data[last_i]; while r != 0 { res.push((r & mask) as u8); r >>= bits; } res } // Extract bitwise digits that don't evenly divide BigDigit fn to_inexact_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0); let mask: BigDigit = (1 << bits) - 1; let digits = (u.bits() + bits - 1) / bits; let mut res = Vec::with_capacity(digits); let mut r = 0; let mut rbits = 0; for c in &u.data { r |= *c << rbits; rbits += big_digit::BITS; while rbits >= bits { res.push((r & mask) as u8); r >>= bits; // r had more bits than it could fit - grab the bits we lost if rbits > big_digit::BITS { r = *c >> (big_digit::BITS - (rbits - bits)); } rbits -= bits; } } if rbits != 0 { res.push(r as u8); } while let Some(&0) = res.last() { res.pop(); } res } // Extract little-endian radix digits #[inline(always)] // forced inline to get const-prop for radix=10 fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { debug_assert!(!u.is_zero() && !radix.is_power_of_two()); // Estimate how big the result will be, so we can pre-allocate it. let radix_digits = ((u.bits() as f64) / (radix as f64).log2()).ceil(); let mut res = Vec::with_capacity(radix_digits as usize); let mut digits = u.clone(); let (base, power) = get_radix_base(radix); let radix = radix as BigDigit; while digits.data.len() > 1 { let (q, mut r) = div_rem_digit(digits, base); for _ in 0..power { res.push((r % radix) as u8); r /= radix; } digits = q; } let mut r = digits.data[0]; while r != 0 { res.push((r % radix) as u8); r /= radix; } res } pub fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); if u.is_zero() { return vec![b'0']; } let mut res = if radix.is_power_of_two() { // Powers of two can use bitwise masks and shifting instead of division let bits = ilog2(radix); if big_digit::BITS % bits == 0 { to_bitwise_digits_le(u, bits) } else { to_inexact_bitwise_digits_le(u, bits) } } else if radix == 10 { // 10 is so common that it's worth separating out for const-propagation. // Optimizers can often turn constant division into a faster multiplication. to_radix_digits_le(u, 10) } else { to_radix_digits_le(u, radix) }; // Now convert everything to ASCII digits. for r in &mut res { debug_assert!((*r as u32) < radix); if *r < 10 { *r += b'0'; } else { *r += b'a' - 10; } } res } impl BigUint { /// Creates and initializes a `BigUint`. /// /// The digits are in little-endian base 2^32. #[inline] pub fn new(digits: Vec) -> BigUint { BigUint { data: digits }.normalize() } /// Creates and initializes a `BigUint`. /// /// The digits are in little-endian base 2^32. #[inline] pub fn from_slice(slice: &[BigDigit]) -> BigUint { BigUint::new(slice.to_vec()) } /// Creates and initializes a `BigUint`. /// /// The bytes are in big-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// assert_eq!(BigUint::from_bytes_be(b"A"), /// BigUint::parse_bytes(b"65", 10).unwrap()); /// assert_eq!(BigUint::from_bytes_be(b"AA"), /// BigUint::parse_bytes(b"16705", 10).unwrap()); /// assert_eq!(BigUint::from_bytes_be(b"AB"), /// BigUint::parse_bytes(b"16706", 10).unwrap()); /// assert_eq!(BigUint::from_bytes_be(b"Hello world!"), /// BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); /// ``` #[inline] pub fn from_bytes_be(bytes: &[u8]) -> BigUint { if bytes.is_empty() { Zero::zero() } else { let mut v = bytes.to_vec(); v.reverse(); BigUint::from_bytes_le(&*v) } } /// Creates and initializes a `BigUint`. /// /// The bytes are in little-endian byte order. #[inline] pub fn from_bytes_le(bytes: &[u8]) -> BigUint { if bytes.is_empty() { Zero::zero() } else { from_bitwise_digits_le(bytes, 8) } } /// Returns the byte representation of the `BigUint` in little-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); /// assert_eq!(i.to_bytes_le(), vec![101, 4]); /// ``` #[inline] pub fn to_bytes_le(&self) -> Vec { if self.is_zero() { vec![0] } else { to_bitwise_digits_le(self, 8) } } /// Returns the byte representation of the `BigUint` in big-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); /// assert_eq!(i.to_bytes_be(), vec![4, 101]); /// ``` #[inline] pub fn to_bytes_be(&self) -> Vec { let mut v = self.to_bytes_le(); v.reverse(); v } /// Returns the integer formatted as a string in the given radix. /// `radix` must be in the range `[2, 36]`. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// let i = BigUint::parse_bytes(b"ff", 16).unwrap(); /// assert_eq!(i.to_str_radix(16), "ff"); /// ``` #[inline] pub fn to_str_radix(&self, radix: u32) -> String { let mut v = to_str_radix_reversed(self, radix); v.reverse(); unsafe { String::from_utf8_unchecked(v) } } /// Creates and initializes a `BigUint`. /// /// # Examples /// /// ``` /// use num_bigint::{BigUint, ToBigUint}; /// /// assert_eq!(BigUint::parse_bytes(b"1234", 10), ToBigUint::to_biguint(&1234)); /// assert_eq!(BigUint::parse_bytes(b"ABCD", 16), ToBigUint::to_biguint(&0xABCD)); /// assert_eq!(BigUint::parse_bytes(b"G", 16), None); /// ``` #[inline] pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { str::from_utf8(buf).ok().and_then(|s| BigUint::from_str_radix(s, radix).ok()) } /// Determines the fewest bits necessary to express the `BigUint`. #[inline] pub fn bits(&self) -> usize { if self.is_zero() { return 0; } let zeros = self.data.last().unwrap().leading_zeros(); return self.data.len() * big_digit::BITS - zeros as usize; } /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to /// be nonzero. #[inline] fn normalize(mut self) -> BigUint { while let Some(&0) = self.data.last() { self.data.pop(); } self } } #[cfg(feature = "serde")] impl serde::Serialize for BigUint { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer { self.data.serialize(serializer) } } #[cfg(feature = "serde")] impl serde::Deserialize for BigUint { fn deserialize(deserializer: &mut D) -> Result where D: serde::Deserializer { let data = try!(Vec::deserialize(deserializer)); Ok(BigUint { data: data }) } } /// Returns the greatest power of the radix <= big_digit::BASE #[inline] fn get_radix_base(radix: u32) -> (BigDigit, usize) { debug_assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); debug_assert!(!radix.is_power_of_two()); // To generate this table: // for radix in 2u64..37 { // let mut power = big_digit::BITS / fls(radix as u64); // let mut base = radix.pow(power as u32); // // while let Some(b) = base.checked_mul(radix) { // if b > big_digit::MAX { // break; // } // base = b; // power += 1; // } // // println!("({:10}, {:2}), // {:2}", base, power, radix); // } match big_digit::BITS { 32 => { const BASES: [(u32, usize); 37] = [(0, 0), (0, 0), (0, 0), // 2 (3486784401, 20),// 3 (0, 0), // 4 (1220703125, 13),// 5 (2176782336, 12),// 6 (1977326743, 11),// 7 (0, 0), // 8 (3486784401, 10),// 9 (1000000000, 9), // 10 (2357947691, 9), // 11 (429981696, 8), // 12 (815730721, 8), // 13 (1475789056, 8), // 14 (2562890625, 8), // 15 (0, 0), // 16 (410338673, 7), // 17 (612220032, 7), // 18 (893871739, 7), // 19 (1280000000, 7), // 20 (1801088541, 7), // 21 (2494357888, 7), // 22 (3404825447, 7), // 23 (191102976, 6), // 24 (244140625, 6), // 25 (308915776, 6), // 26 (387420489, 6), // 27 (481890304, 6), // 28 (594823321, 6), // 29 (729000000, 6), // 30 (887503681, 6), // 31 (0, 0), // 32 (1291467969, 6), // 33 (1544804416, 6), // 34 (1838265625, 6), // 35 (2176782336, 6) // 36 ]; let (base, power) = BASES[radix as usize]; (base as BigDigit, power) } 64 => { const BASES: [(u64, usize); 37] = [(0, 0), (0, 0), (9223372036854775808, 63), // 2 (12157665459056928801, 40), // 3 (4611686018427387904, 31), // 4 (7450580596923828125, 27), // 5 (4738381338321616896, 24), // 6 (3909821048582988049, 22), // 7 (9223372036854775808, 21), // 8 (12157665459056928801, 20), // 9 (10000000000000000000, 19), // 10 (5559917313492231481, 18), // 11 (2218611106740436992, 17), // 12 (8650415919381337933, 17), // 13 (2177953337809371136, 16), // 14 (6568408355712890625, 16), // 15 (1152921504606846976, 15), // 16 (2862423051509815793, 15), // 17 (6746640616477458432, 15), // 18 (15181127029874798299, 15), // 19 (1638400000000000000, 14), // 20 (3243919932521508681, 14), // 21 (6221821273427820544, 14), // 22 (11592836324538749809, 14), // 23 (876488338465357824, 13), // 24 (1490116119384765625, 13), // 25 (2481152873203736576, 13), // 26 (4052555153018976267, 13), // 27 (6502111422497947648, 13), // 28 (10260628712958602189, 13), // 29 (15943230000000000000, 13), // 30 (787662783788549761, 12), // 31 (1152921504606846976, 12), // 32 (1667889514952984961, 12), // 33 (2386420683693101056, 12), // 34 (3379220508056640625, 12), // 35 (4738381338321616896, 12), // 36 ]; let (base, power) = BASES[radix as usize]; (base as BigDigit, power) } _ => panic!("Invalid bigdigit size") } }