use std::default::Default; use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub}; use std::str::{self, FromStr}; use std::fmt; use std::cmp::Ordering::{self, Less, Greater, Equal}; use std::{f32, f64}; use std::{u8, i64, u64}; use std::ascii::AsciiExt; #[cfg(feature = "serde")] use serde; // Some of the tests of non-RNG-based functionality are randomized using the // RNG-based functionality, so the RNG-based functionality needs to be enabled // for tests. #[cfg(any(feature = "rand", test))] use rand::Rng; use integer::Integer; use traits::{ToPrimitive, FromPrimitive, Num, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, Signed, Zero, One}; use self::Sign::{Minus, NoSign, Plus}; use super::ParseBigIntError; use super::big_digit; use super::big_digit::BigDigit; use biguint; use biguint::to_str_radix_reversed; use biguint::BigUint; #[cfg(test)] #[path = "tests/bigint.rs"] mod bigint_tests; /// A Sign is a `BigInt`'s composing element. #[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub enum Sign { Minus, NoSign, Plus, } impl Neg for Sign { type Output = Sign; /// Negate Sign value. #[inline] fn neg(self) -> Sign { match self { Minus => Plus, NoSign => NoSign, Plus => Minus, } } } impl Mul for Sign { type Output = Sign; #[inline] fn mul(self, other: Sign) -> Sign { match (self, other) { (NoSign, _) | (_, NoSign) => NoSign, (Plus, Plus) | (Minus, Minus) => Plus, (Plus, Minus) | (Minus, Plus) => Minus, } } } #[cfg(feature = "serde")] impl serde::Serialize for Sign { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer { match *self { Sign::Minus => (-1i8).serialize(serializer), Sign::NoSign => 0i8.serialize(serializer), Sign::Plus => 1i8.serialize(serializer), } } } #[cfg(feature = "serde")] impl serde::Deserialize for Sign { fn deserialize(deserializer: &mut D) -> Result where D: serde::Deserializer { use serde::de::Error; let sign: i8 = try!(serde::Deserialize::deserialize(deserializer)); match sign { -1 => Ok(Sign::Minus), 0 => Ok(Sign::NoSign), 1 => Ok(Sign::Plus), _ => Err(D::Error::invalid_value("sign must be -1, 0, or 1")), } } } /// A big signed integer type. #[derive(Clone, Debug, Hash)] #[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] pub struct BigInt { sign: Sign, data: BigUint, } impl PartialEq for BigInt { #[inline] fn eq(&self, other: &BigInt) -> bool { self.cmp(other) == Equal } } impl Eq for BigInt {} impl PartialOrd for BigInt { #[inline] fn partial_cmp(&self, other: &BigInt) -> Option { Some(self.cmp(other)) } } impl Ord for BigInt { #[inline] fn cmp(&self, other: &BigInt) -> Ordering { let scmp = self.sign.cmp(&other.sign); if scmp != Equal { return scmp; } match self.sign { NoSign => Equal, Plus => self.data.cmp(&other.data), Minus => other.data.cmp(&self.data), } } } impl Default for BigInt { #[inline] fn default() -> BigInt { Zero::zero() } } impl fmt::Display for BigInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "", &self.data.to_str_radix(10)) } } impl fmt::Binary for BigInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "0b", &self.data.to_str_radix(2)) } } impl fmt::Octal for BigInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "0o", &self.data.to_str_radix(8)) } } impl fmt::LowerHex for BigInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "0x", &self.data.to_str_radix(16)) } } impl fmt::UpperHex for BigInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad_integral(!self.is_negative(), "0x", &self.data.to_str_radix(16).to_ascii_uppercase()) } } impl FromStr for BigInt { type Err = ParseBigIntError; #[inline] fn from_str(s: &str) -> Result { BigInt::from_str_radix(s, 10) } } impl Num for BigInt { type FromStrRadixErr = ParseBigIntError; /// Creates and initializes a BigInt. #[inline] fn from_str_radix(mut s: &str, radix: u32) -> Result { let sign = if s.starts_with('-') { let tail = &s[1..]; if !tail.starts_with('+') { s = tail } Minus } else { Plus }; let bu = try!(BigUint::from_str_radix(s, radix)); Ok(BigInt::from_biguint(sign, bu)) } } impl Shl for BigInt { type Output = BigInt; #[inline] fn shl(self, rhs: usize) -> BigInt { (&self) << rhs } } impl<'a> Shl for &'a BigInt { type Output = BigInt; #[inline] fn shl(self, rhs: usize) -> BigInt { BigInt::from_biguint(self.sign, &self.data << rhs) } } impl Shr for BigInt { type Output = BigInt; #[inline] fn shr(self, rhs: usize) -> BigInt { BigInt::from_biguint(self.sign, self.data >> rhs) } } impl<'a> Shr for &'a BigInt { type Output = BigInt; #[inline] fn shr(self, rhs: usize) -> BigInt { BigInt::from_biguint(self.sign, &self.data >> rhs) } } impl Zero for BigInt { #[inline] fn zero() -> BigInt { BigInt::from_biguint(NoSign, Zero::zero()) } #[inline] fn is_zero(&self) -> bool { self.sign == NoSign } } impl One for BigInt { #[inline] fn one() -> BigInt { BigInt::from_biguint(Plus, One::one()) } } impl Signed for BigInt { #[inline] fn abs(&self) -> BigInt { match self.sign { Plus | NoSign => self.clone(), Minus => BigInt::from_biguint(Plus, self.data.clone()), } } #[inline] fn abs_sub(&self, other: &BigInt) -> BigInt { if *self <= *other { Zero::zero() } else { self - other } } #[inline] fn signum(&self) -> BigInt { match self.sign { Plus => BigInt::from_biguint(Plus, One::one()), Minus => BigInt::from_biguint(Minus, One::one()), NoSign => Zero::zero(), } } #[inline] fn is_positive(&self) -> bool { self.sign == Plus } #[inline] fn is_negative(&self) -> bool { self.sign == Minus } } // We want to forward to BigUint::add, but it's not clear how that will go until // we compare both sign and magnitude. So we duplicate this body for every // val/ref combination, deferring that decision to BigUint's own forwarding. macro_rules! bigint_add { ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { match ($a.sign, $b.sign) { (_, NoSign) => $a_owned, (NoSign, _) => $b_owned, // same sign => keep the sign with the sum of magnitudes (Plus, Plus) | (Minus, Minus) => BigInt::from_biguint($a.sign, $a_data + $b_data), // opposite signs => keep the sign of the larger with the difference of magnitudes (Plus, Minus) | (Minus, Plus) => match $a.data.cmp(&$b.data) { Less => BigInt::from_biguint($b.sign, $b_data - $a_data), Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), Equal => Zero::zero(), }, } }; } impl<'a, 'b> Add<&'b BigInt> for &'a BigInt { type Output = BigInt; #[inline] fn add(self, other: &BigInt) -> BigInt { bigint_add!(self, self.clone(), &self.data, other, other.clone(), &other.data) } } impl<'a> Add for &'a BigInt { type Output = BigInt; #[inline] fn add(self, other: BigInt) -> BigInt { bigint_add!(self, self.clone(), &self.data, other, other, other.data) } } impl<'a> Add<&'a BigInt> for BigInt { type Output = BigInt; #[inline] fn add(self, other: &BigInt) -> BigInt { bigint_add!(self, self, self.data, other, other.clone(), &other.data) } } impl Add for BigInt { type Output = BigInt; #[inline] fn add(self, other: BigInt) -> BigInt { bigint_add!(self, self, self.data, other, other, other.data) } } // We want to forward to BigUint::sub, but it's not clear how that will go until // we compare both sign and magnitude. So we duplicate this body for every // val/ref combination, deferring that decision to BigUint's own forwarding. macro_rules! bigint_sub { ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { match ($a.sign, $b.sign) { (_, NoSign) => $a_owned, (NoSign, _) => -$b_owned, // opposite signs => keep the sign of the left with the sum of magnitudes (Plus, Minus) | (Minus, Plus) => BigInt::from_biguint($a.sign, $a_data + $b_data), // same sign => keep or toggle the sign of the left with the difference of magnitudes (Plus, Plus) | (Minus, Minus) => match $a.data.cmp(&$b.data) { Less => BigInt::from_biguint(-$a.sign, $b_data - $a_data), Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), Equal => Zero::zero(), }, } }; } impl<'a, 'b> Sub<&'b BigInt> for &'a BigInt { type Output = BigInt; #[inline] fn sub(self, other: &BigInt) -> BigInt { bigint_sub!(self, self.clone(), &self.data, other, other.clone(), &other.data) } } impl<'a> Sub for &'a BigInt { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { bigint_sub!(self, self.clone(), &self.data, other, other, other.data) } } impl<'a> Sub<&'a BigInt> for BigInt { type Output = BigInt; #[inline] fn sub(self, other: &BigInt) -> BigInt { bigint_sub!(self, self, self.data, other, other.clone(), &other.data) } } impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { bigint_sub!(self, self, self.data, other, other, other.data) } } forward_all_binop_to_ref_ref!(impl Mul for BigInt, mul); impl<'a, 'b> Mul<&'b BigInt> for &'a BigInt { type Output = BigInt; #[inline] fn mul(self, other: &BigInt) -> BigInt { BigInt::from_biguint(self.sign * other.sign, &self.data * &other.data) } } forward_all_binop_to_ref_ref!(impl Div for BigInt, div); impl<'a, 'b> Div<&'b BigInt> for &'a BigInt { type Output = BigInt; #[inline] fn div(self, other: &BigInt) -> BigInt { let (q, _) = self.div_rem(other); q } } forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem); impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt { type Output = BigInt; #[inline] fn rem(self, other: &BigInt) -> BigInt { let (_, r) = self.div_rem(other); r } } impl Neg for BigInt { type Output = BigInt; #[inline] fn neg(mut self) -> BigInt { self.sign = -self.sign; self } } impl<'a> Neg for &'a BigInt { type Output = BigInt; #[inline] fn neg(self) -> BigInt { -self.clone() } } impl CheckedAdd for BigInt { #[inline] fn checked_add(&self, v: &BigInt) -> Option { return Some(self.add(v)); } } impl CheckedSub for BigInt { #[inline] fn checked_sub(&self, v: &BigInt) -> Option { return Some(self.sub(v)); } } impl CheckedMul for BigInt { #[inline] fn checked_mul(&self, v: &BigInt) -> Option { return Some(self.mul(v)); } } impl CheckedDiv for BigInt { #[inline] fn checked_div(&self, v: &BigInt) -> Option { if v.is_zero() { return None; } return Some(self.div(v)); } } impl Integer for BigInt { #[inline] fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { // r.sign == self.sign let (d_ui, r_ui) = self.data.div_mod_floor(&other.data); let d = BigInt::from_biguint(self.sign, d_ui); let r = BigInt::from_biguint(self.sign, r_ui); if other.is_negative() { (-d, r) } else { (d, r) } } #[inline] fn div_floor(&self, other: &BigInt) -> BigInt { let (d, _) = self.div_mod_floor(other); d } #[inline] fn mod_floor(&self, other: &BigInt) -> BigInt { let (_, m) = self.div_mod_floor(other); m } fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { // m.sign == other.sign let (d_ui, m_ui) = self.data.div_rem(&other.data); let d = BigInt::from_biguint(Plus, d_ui); let m = BigInt::from_biguint(Plus, m_ui); let one: BigInt = One::one(); match (self.sign, other.sign) { (_, NoSign) => panic!(), (Plus, Plus) | (NoSign, Plus) => (d, m), (Plus, Minus) | (NoSign, Minus) => { if m.is_zero() { (-d, Zero::zero()) } else { (-d - one, m + other) } } (Minus, Plus) => { if m.is_zero() { (-d, Zero::zero()) } else { (-d - one, other - m) } } (Minus, Minus) => (d, -m), } } /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. /// /// The result is always positive. #[inline] fn gcd(&self, other: &BigInt) -> BigInt { BigInt::from_biguint(Plus, self.data.gcd(&other.data)) } /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn lcm(&self, other: &BigInt) -> BigInt { BigInt::from_biguint(Plus, self.data.lcm(&other.data)) } /// Deprecated, use `is_multiple_of` instead. #[inline] fn divides(&self, other: &BigInt) -> bool { return self.is_multiple_of(other); } /// Returns `true` if the number is a multiple of `other`. #[inline] fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) } /// Returns `true` if the number is divisible by `2`. #[inline] fn is_even(&self) -> bool { self.data.is_even() } /// Returns `true` if the number is not divisible by `2`. #[inline] fn is_odd(&self) -> bool { self.data.is_odd() } } impl ToPrimitive for BigInt { #[inline] fn to_i64(&self) -> Option { match self.sign { Plus => self.data.to_i64(), NoSign => Some(0), Minus => { self.data.to_u64().and_then(|n| { let m: u64 = 1 << 63; if n < m { Some(-(n as i64)) } else if n == m { Some(i64::MIN) } else { None } }) } } } #[inline] fn to_u64(&self) -> Option { match self.sign { Plus => self.data.to_u64(), NoSign => Some(0), Minus => None, } } #[inline] fn to_f32(&self) -> Option { self.data.to_f32().map(|n| { if self.sign == Minus { -n } else { n } }) } #[inline] fn to_f64(&self) -> Option { self.data.to_f64().map(|n| { if self.sign == Minus { -n } else { n } }) } } impl FromPrimitive for BigInt { #[inline] fn from_i64(n: i64) -> Option { Some(BigInt::from(n)) } #[inline] fn from_u64(n: u64) -> Option { Some(BigInt::from(n)) } #[inline] fn from_f64(n: f64) -> Option { if n >= 0.0 { BigUint::from_f64(n).map(|x| BigInt::from_biguint(Plus, x)) } else { BigUint::from_f64(-n).map(|x| BigInt::from_biguint(Minus, x)) } } } impl From for BigInt { #[inline] fn from(n: i64) -> Self { if n >= 0 { BigInt::from(n as u64) } else { let u = u64::MAX - (n as u64) + 1; BigInt { sign: Minus, data: BigUint::from(u), } } } } macro_rules! impl_bigint_from_int { ($T:ty) => { impl From<$T> for BigInt { #[inline] fn from(n: $T) -> Self { BigInt::from(n as i64) } } } } impl_bigint_from_int!(i8); impl_bigint_from_int!(i16); impl_bigint_from_int!(i32); impl_bigint_from_int!(isize); impl From for BigInt { #[inline] fn from(n: u64) -> Self { if n > 0 { BigInt { sign: Plus, data: BigUint::from(n), } } else { BigInt::zero() } } } macro_rules! impl_bigint_from_uint { ($T:ty) => { impl From<$T> for BigInt { #[inline] fn from(n: $T) -> Self { BigInt::from(n as u64) } } } } impl_bigint_from_uint!(u8); impl_bigint_from_uint!(u16); impl_bigint_from_uint!(u32); impl_bigint_from_uint!(usize); impl From for BigInt { #[inline] fn from(n: BigUint) -> Self { if n.is_zero() { BigInt::zero() } else { BigInt { sign: Plus, data: n, } } } } #[cfg(feature = "serde")] impl serde::Serialize for BigInt { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer { (self.sign, &self.data).serialize(serializer) } } #[cfg(feature = "serde")] impl serde::Deserialize for BigInt { fn deserialize(deserializer: &mut D) -> Result where D: serde::Deserializer { let (sign, data) = try!(serde::Deserialize::deserialize(deserializer)); Ok(BigInt { sign: sign, data: data, }) } } /// A generic trait for converting a value to a `BigInt`. pub trait ToBigInt { /// Converts the value of `self` to a `BigInt`. fn to_bigint(&self) -> Option; } impl ToBigInt for BigInt { #[inline] fn to_bigint(&self) -> Option { Some(self.clone()) } } impl ToBigInt for BigUint { #[inline] fn to_bigint(&self) -> Option { if self.is_zero() { Some(Zero::zero()) } else { Some(BigInt { sign: Plus, data: self.clone(), }) } } } impl biguint::ToBigUint for BigInt { #[inline] fn to_biguint(&self) -> Option { match self.sign() { Plus => Some(self.data.clone()), NoSign => Some(Zero::zero()), Minus => None, } } } macro_rules! impl_to_bigint { ($T:ty, $from_ty:path) => { impl ToBigInt for $T { #[inline] fn to_bigint(&self) -> Option { $from_ty(*self) } } } } impl_to_bigint!(isize, FromPrimitive::from_isize); impl_to_bigint!(i8, FromPrimitive::from_i8); impl_to_bigint!(i16, FromPrimitive::from_i16); impl_to_bigint!(i32, FromPrimitive::from_i32); impl_to_bigint!(i64, FromPrimitive::from_i64); impl_to_bigint!(usize, FromPrimitive::from_usize); impl_to_bigint!(u8, FromPrimitive::from_u8); impl_to_bigint!(u16, FromPrimitive::from_u16); impl_to_bigint!(u32, FromPrimitive::from_u32); impl_to_bigint!(u64, FromPrimitive::from_u64); impl_to_bigint!(f32, FromPrimitive::from_f32); impl_to_bigint!(f64, FromPrimitive::from_f64); pub trait RandBigInt { /// Generate a random `BigUint` of the given bit size. fn gen_biguint(&mut self, bit_size: usize) -> BigUint; /// Generate a random BigInt of the given bit size. fn gen_bigint(&mut self, bit_size: usize) -> BigInt; /// Generate a random `BigUint` less than the given bound. Fails /// when the bound is zero. fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint; /// Generate a random `BigUint` within the given range. The lower /// bound is inclusive; the upper bound is exclusive. Fails when /// the upper bound is not greater than the lower bound. fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint; /// Generate a random `BigInt` within the given range. The lower /// bound is inclusive; the upper bound is exclusive. Fails when /// the upper bound is not greater than the lower bound. fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt; } #[cfg(any(feature = "rand", test))] impl RandBigInt for R { fn gen_biguint(&mut self, bit_size: usize) -> BigUint { let (digits, rem) = bit_size.div_rem(&big_digit::BITS); let mut data = Vec::with_capacity(digits + 1); for _ in 0..digits { data.push(self.gen()); } if rem > 0 { let final_digit: BigDigit = self.gen(); data.push(final_digit >> (big_digit::BITS - rem)); } BigUint::new(data) } fn gen_bigint(&mut self, bit_size: usize) -> BigInt { // Generate a random BigUint... let biguint = self.gen_biguint(bit_size); // ...and then randomly assign it a Sign... let sign = if biguint.is_zero() { // ...except that if the BigUint is zero, we need to try // again with probability 0.5. This is because otherwise, // the probability of generating a zero BigInt would be // double that of any other number. if self.gen() { return self.gen_bigint(bit_size); } else { NoSign } } else if self.gen() { Plus } else { Minus }; BigInt::from_biguint(sign, biguint) } fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint { assert!(!bound.is_zero()); let bits = bound.bits(); loop { let n = self.gen_biguint(bits); if n < *bound { return n; } } } fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint { assert!(*lbound < *ubound); return lbound + self.gen_biguint_below(&(ubound - lbound)); } fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt { assert!(*lbound < *ubound); let delta = (ubound - lbound).to_biguint().unwrap(); return lbound + self.gen_biguint_below(&delta).to_bigint().unwrap(); } } impl BigInt { /// Creates and initializes a BigInt. /// /// The digits are in little-endian base 2^32. #[inline] pub fn new(sign: Sign, digits: Vec) -> BigInt { BigInt::from_biguint(sign, BigUint::new(digits)) } /// Creates and initializes a `BigInt`. /// /// The digits are in little-endian base 2^32. #[inline] pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt { if sign == NoSign || data.is_zero() { return BigInt { sign: NoSign, data: Zero::zero(), }; } BigInt { sign: sign, data: data, } } /// Creates and initializes a `BigInt`. #[inline] pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_slice(slice)) } /// Creates and initializes a `BigInt`. /// /// The bytes are in big-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::{BigInt, Sign}; /// /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"A"), /// BigInt::parse_bytes(b"65", 10).unwrap()); /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AA"), /// BigInt::parse_bytes(b"16705", 10).unwrap()); /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AB"), /// BigInt::parse_bytes(b"16706", 10).unwrap()); /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"Hello world!"), /// BigInt::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); /// ``` #[inline] pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_bytes_be(bytes)) } /// Creates and initializes a `BigInt`. /// /// The bytes are in little-endian byte order. #[inline] pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_bytes_le(bytes)) } /// Returns the sign and the byte representation of the `BigInt` in little-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::{ToBigInt, Sign}; /// /// let i = -1125.to_bigint().unwrap(); /// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4])); /// ``` #[inline] pub fn to_bytes_le(&self) -> (Sign, Vec) { (self.sign, self.data.to_bytes_le()) } /// Returns the sign and the byte representation of the `BigInt` in big-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::{ToBigInt, Sign}; /// /// let i = -1125.to_bigint().unwrap(); /// assert_eq!(i.to_bytes_be(), (Sign::Minus, vec![4, 101])); /// ``` #[inline] pub fn to_bytes_be(&self) -> (Sign, Vec) { (self.sign, self.data.to_bytes_be()) } /// Returns the integer formatted as a string in the given radix. /// `radix` must be in the range `[2, 36]`. /// /// # Examples /// /// ``` /// use num_bigint::BigInt; /// /// let i = BigInt::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.data, radix); if self.is_negative() { v.push(b'-'); } v.reverse(); unsafe { String::from_utf8_unchecked(v) } } /// Returns the sign of the `BigInt` as a `Sign`. /// /// # Examples /// /// ``` /// use num_bigint::{ToBigInt, Sign}; /// /// assert_eq!(ToBigInt::to_bigint(&1234).unwrap().sign(), Sign::Plus); /// assert_eq!(ToBigInt::to_bigint(&-4321).unwrap().sign(), Sign::Minus); /// assert_eq!(ToBigInt::to_bigint(&0).unwrap().sign(), Sign::NoSign); /// ``` #[inline] pub fn sign(&self) -> Sign { self.sign } /// Creates and initializes a `BigInt`. /// /// # Examples /// /// ``` /// use num_bigint::{BigInt, ToBigInt}; /// /// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234)); /// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD)); /// assert_eq!(BigInt::parse_bytes(b"G", 16), None); /// ``` #[inline] pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok()) } /// Determines the fewest bits necessary to express the `BigInt`, /// not including the sign. #[inline] pub fn bits(&self) -> usize { self.data.bits() } /// Converts this `BigInt` into a `BigUint`, if it's not negative. #[inline] pub fn to_biguint(&self) -> Option { match self.sign { Plus => Some(self.data.clone()), NoSign => Some(Zero::zero()), Minus => None, } } #[inline] pub fn checked_add(&self, v: &BigInt) -> Option { return Some(self.add(v)); } #[inline] pub fn checked_sub(&self, v: &BigInt) -> Option { return Some(self.sub(v)); } #[inline] pub fn checked_mul(&self, v: &BigInt) -> Option { return Some(self.mul(v)); } #[inline] pub fn checked_div(&self, v: &BigInt) -> Option { if v.is_zero() { return None; } return Some(self.div(v)); } }