|  | use super::Sign::{self, Minus, NoSign, Plus}; | 
|  | use super::{BigInt, ToBigInt}; | 
|  |  | 
|  | use crate::std_alloc::Vec; | 
|  | #[cfg(has_try_from)] | 
|  | use crate::TryFromBigIntError; | 
|  | use crate::{BigUint, ParseBigIntError, ToBigUint}; | 
|  |  | 
|  | use core::cmp::Ordering::{Equal, Greater, Less}; | 
|  | #[cfg(has_try_from)] | 
|  | use core::convert::TryFrom; | 
|  | use core::str::{self, FromStr}; | 
|  | use num_traits::{FromPrimitive, Num, One, ToPrimitive, Zero}; | 
|  |  | 
|  | impl FromStr for BigInt { | 
|  | type Err = ParseBigIntError; | 
|  |  | 
|  | #[inline] | 
|  | fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> { | 
|  | 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<BigInt, ParseBigIntError> { | 
|  | let sign = if s.starts_with('-') { | 
|  | let tail = &s[1..]; | 
|  | if !tail.starts_with('+') { | 
|  | s = tail | 
|  | } | 
|  | Minus | 
|  | } else { | 
|  | Plus | 
|  | }; | 
|  | let bu = BigUint::from_str_radix(s, radix)?; | 
|  | Ok(BigInt::from_biguint(sign, bu)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ToPrimitive for BigInt { | 
|  | #[inline] | 
|  | fn to_i64(&self) -> Option<i64> { | 
|  | match self.sign { | 
|  | Plus => self.data.to_i64(), | 
|  | NoSign => Some(0), | 
|  | Minus => { | 
|  | let n = self.data.to_u64()?; | 
|  | let m: u64 = 1 << 63; | 
|  | match n.cmp(&m) { | 
|  | Less => Some(-(n as i64)), | 
|  | Equal => Some(core::i64::MIN), | 
|  | Greater => None, | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn to_i128(&self) -> Option<i128> { | 
|  | match self.sign { | 
|  | Plus => self.data.to_i128(), | 
|  | NoSign => Some(0), | 
|  | Minus => { | 
|  | let n = self.data.to_u128()?; | 
|  | let m: u128 = 1 << 127; | 
|  | match n.cmp(&m) { | 
|  | Less => Some(-(n as i128)), | 
|  | Equal => Some(core::i128::MIN), | 
|  | Greater => None, | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn to_u64(&self) -> Option<u64> { | 
|  | match self.sign { | 
|  | Plus => self.data.to_u64(), | 
|  | NoSign => Some(0), | 
|  | Minus => None, | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn to_u128(&self) -> Option<u128> { | 
|  | match self.sign { | 
|  | Plus => self.data.to_u128(), | 
|  | NoSign => Some(0), | 
|  | Minus => None, | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn to_f32(&self) -> Option<f32> { | 
|  | let n = self.data.to_f32()?; | 
|  | Some(if self.sign == Minus { -n } else { n }) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn to_f64(&self) -> Option<f64> { | 
|  | let n = self.data.to_f64()?; | 
|  | Some(if self.sign == Minus { -n } else { n }) | 
|  | } | 
|  | } | 
|  |  | 
|  | macro_rules! impl_try_from_bigint { | 
|  | ($T:ty, $to_ty:path) => { | 
|  | #[cfg(has_try_from)] | 
|  | impl TryFrom<&BigInt> for $T { | 
|  | type Error = TryFromBigIntError<()>; | 
|  |  | 
|  | #[inline] | 
|  | fn try_from(value: &BigInt) -> Result<$T, TryFromBigIntError<()>> { | 
|  | $to_ty(value).ok_or(TryFromBigIntError::new(())) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(has_try_from)] | 
|  | impl TryFrom<BigInt> for $T { | 
|  | type Error = TryFromBigIntError<BigInt>; | 
|  |  | 
|  | #[inline] | 
|  | fn try_from(value: BigInt) -> Result<$T, TryFromBigIntError<BigInt>> { | 
|  | <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value)) | 
|  | } | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | impl_try_from_bigint!(u8, ToPrimitive::to_u8); | 
|  | impl_try_from_bigint!(u16, ToPrimitive::to_u16); | 
|  | impl_try_from_bigint!(u32, ToPrimitive::to_u32); | 
|  | impl_try_from_bigint!(u64, ToPrimitive::to_u64); | 
|  | impl_try_from_bigint!(usize, ToPrimitive::to_usize); | 
|  | impl_try_from_bigint!(u128, ToPrimitive::to_u128); | 
|  |  | 
|  | impl_try_from_bigint!(i8, ToPrimitive::to_i8); | 
|  | impl_try_from_bigint!(i16, ToPrimitive::to_i16); | 
|  | impl_try_from_bigint!(i32, ToPrimitive::to_i32); | 
|  | impl_try_from_bigint!(i64, ToPrimitive::to_i64); | 
|  | impl_try_from_bigint!(isize, ToPrimitive::to_isize); | 
|  | impl_try_from_bigint!(i128, ToPrimitive::to_i128); | 
|  |  | 
|  | impl FromPrimitive for BigInt { | 
|  | #[inline] | 
|  | fn from_i64(n: i64) -> Option<BigInt> { | 
|  | Some(BigInt::from(n)) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn from_i128(n: i128) -> Option<BigInt> { | 
|  | Some(BigInt::from(n)) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn from_u64(n: u64) -> Option<BigInt> { | 
|  | Some(BigInt::from(n)) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn from_u128(n: u128) -> Option<BigInt> { | 
|  | Some(BigInt::from(n)) | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn from_f64(n: f64) -> Option<BigInt> { | 
|  | if n >= 0.0 { | 
|  | BigUint::from_f64(n).map(BigInt::from) | 
|  | } else { | 
|  | let x = BigUint::from_f64(-n)?; | 
|  | Some(-BigInt::from(x)) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<i64> for BigInt { | 
|  | #[inline] | 
|  | fn from(n: i64) -> Self { | 
|  | if n >= 0 { | 
|  | BigInt::from(n as u64) | 
|  | } else { | 
|  | let u = core::u64::MAX - (n as u64) + 1; | 
|  | BigInt { | 
|  | sign: Minus, | 
|  | data: BigUint::from(u), | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<i128> for BigInt { | 
|  | #[inline] | 
|  | fn from(n: i128) -> Self { | 
|  | if n >= 0 { | 
|  | BigInt::from(n as u128) | 
|  | } else { | 
|  | let u = core::u128::MAX - (n as u128) + 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<u64> for BigInt { | 
|  | #[inline] | 
|  | fn from(n: u64) -> Self { | 
|  | if n > 0 { | 
|  | BigInt { | 
|  | sign: Plus, | 
|  | data: BigUint::from(n), | 
|  | } | 
|  | } else { | 
|  | BigInt::zero() | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<u128> for BigInt { | 
|  | #[inline] | 
|  | fn from(n: u128) -> 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<BigUint> for BigInt { | 
|  | #[inline] | 
|  | fn from(n: BigUint) -> Self { | 
|  | if n.is_zero() { | 
|  | BigInt::zero() | 
|  | } else { | 
|  | BigInt { | 
|  | sign: Plus, | 
|  | data: n, | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ToBigInt for BigInt { | 
|  | #[inline] | 
|  | fn to_bigint(&self) -> Option<BigInt> { | 
|  | Some(self.clone()) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ToBigInt for BigUint { | 
|  | #[inline] | 
|  | fn to_bigint(&self) -> Option<BigInt> { | 
|  | if self.is_zero() { | 
|  | Some(Zero::zero()) | 
|  | } else { | 
|  | Some(BigInt { | 
|  | sign: Plus, | 
|  | data: self.clone(), | 
|  | }) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ToBigUint for BigInt { | 
|  | #[inline] | 
|  | fn to_biguint(&self) -> Option<BigUint> { | 
|  | match self.sign() { | 
|  | Plus => Some(self.data.clone()), | 
|  | NoSign => Some(Zero::zero()), | 
|  | Minus => None, | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(has_try_from)] | 
|  | impl TryFrom<&BigInt> for BigUint { | 
|  | type Error = TryFromBigIntError<()>; | 
|  |  | 
|  | #[inline] | 
|  | fn try_from(value: &BigInt) -> Result<BigUint, TryFromBigIntError<()>> { | 
|  | value | 
|  | .to_biguint() | 
|  | .ok_or_else(|| TryFromBigIntError::new(())) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[cfg(has_try_from)] | 
|  | impl TryFrom<BigInt> for BigUint { | 
|  | type Error = TryFromBigIntError<BigInt>; | 
|  |  | 
|  | #[inline] | 
|  | fn try_from(value: BigInt) -> Result<BigUint, TryFromBigIntError<BigInt>> { | 
|  | if value.sign() == Sign::Minus { | 
|  | Err(TryFromBigIntError::new(value)) | 
|  | } else { | 
|  | Ok(value.data) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | macro_rules! impl_to_bigint { | 
|  | ($T:ty, $from_ty:path) => { | 
|  | impl ToBigInt for $T { | 
|  | #[inline] | 
|  | fn to_bigint(&self) -> Option<BigInt> { | 
|  | $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!(i128, FromPrimitive::from_i128); | 
|  |  | 
|  | 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!(u128, FromPrimitive::from_u128); | 
|  |  | 
|  | impl_to_bigint!(f32, FromPrimitive::from_f32); | 
|  | impl_to_bigint!(f64, FromPrimitive::from_f64); | 
|  |  | 
|  | impl From<bool> for BigInt { | 
|  | fn from(x: bool) -> Self { | 
|  | if x { | 
|  | One::one() | 
|  | } else { | 
|  | Zero::zero() | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub(super) fn from_signed_bytes_be(digits: &[u8]) -> BigInt { | 
|  | let sign = match digits.first() { | 
|  | Some(v) if *v > 0x7f => Sign::Minus, | 
|  | Some(_) => Sign::Plus, | 
|  | None => return BigInt::zero(), | 
|  | }; | 
|  |  | 
|  | if sign == Sign::Minus { | 
|  | // two's-complement the content to retrieve the magnitude | 
|  | let mut digits = Vec::from(digits); | 
|  | twos_complement_be(&mut digits); | 
|  | BigInt::from_biguint(sign, BigUint::from_bytes_be(&digits)) | 
|  | } else { | 
|  | BigInt::from_biguint(sign, BigUint::from_bytes_be(digits)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub(super) fn from_signed_bytes_le(digits: &[u8]) -> BigInt { | 
|  | let sign = match digits.last() { | 
|  | Some(v) if *v > 0x7f => Sign::Minus, | 
|  | Some(_) => Sign::Plus, | 
|  | None => return BigInt::zero(), | 
|  | }; | 
|  |  | 
|  | if sign == Sign::Minus { | 
|  | // two's-complement the content to retrieve the magnitude | 
|  | let mut digits = Vec::from(digits); | 
|  | twos_complement_le(&mut digits); | 
|  | BigInt::from_biguint(sign, BigUint::from_bytes_le(&digits)) | 
|  | } else { | 
|  | BigInt::from_biguint(sign, BigUint::from_bytes_le(digits)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub(super) fn to_signed_bytes_be(x: &BigInt) -> Vec<u8> { | 
|  | let mut bytes = x.data.to_bytes_be(); | 
|  | let first_byte = bytes.first().cloned().unwrap_or(0); | 
|  | if first_byte > 0x7f | 
|  | && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && x.sign == Sign::Minus) | 
|  | { | 
|  | // msb used by magnitude, extend by 1 byte | 
|  | bytes.insert(0, 0); | 
|  | } | 
|  | if x.sign == Sign::Minus { | 
|  | twos_complement_be(&mut bytes); | 
|  | } | 
|  | bytes | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub(super) fn to_signed_bytes_le(x: &BigInt) -> Vec<u8> { | 
|  | let mut bytes = x.data.to_bytes_le(); | 
|  | let last_byte = bytes.last().cloned().unwrap_or(0); | 
|  | if last_byte > 0x7f | 
|  | && !(last_byte == 0x80 | 
|  | && bytes.iter().rev().skip(1).all(Zero::is_zero) | 
|  | && x.sign == Sign::Minus) | 
|  | { | 
|  | // msb used by magnitude, extend by 1 byte | 
|  | bytes.push(0); | 
|  | } | 
|  | if x.sign == Sign::Minus { | 
|  | twos_complement_le(&mut bytes); | 
|  | } | 
|  | bytes | 
|  | } | 
|  |  | 
|  | /// Perform in-place two's complement of the given binary representation, | 
|  | /// in little-endian byte order. | 
|  | #[inline] | 
|  | fn twos_complement_le(digits: &mut [u8]) { | 
|  | twos_complement(digits) | 
|  | } | 
|  |  | 
|  | /// Perform in-place two's complement of the given binary representation | 
|  | /// in big-endian byte order. | 
|  | #[inline] | 
|  | fn twos_complement_be(digits: &mut [u8]) { | 
|  | twos_complement(digits.iter_mut().rev()) | 
|  | } | 
|  |  | 
|  | /// Perform in-place two's complement of the given digit iterator | 
|  | /// starting from the least significant byte. | 
|  | #[inline] | 
|  | fn twos_complement<'a, I>(digits: I) | 
|  | where | 
|  | I: IntoIterator<Item = &'a mut u8>, | 
|  | { | 
|  | let mut carry = true; | 
|  | for d in digits { | 
|  | *d = !*d; | 
|  | if carry { | 
|  | *d = d.wrapping_add(1); | 
|  | carry = d.is_zero(); | 
|  | } | 
|  | } | 
|  | } |