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,
               AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign,
               MulAssign, RemAssign, ShlAssign, ShrAssign, SubAssign};
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;
#[path = "monty.rs"]
mod monty;
pub use self::algorithms::big_digit;
pub use self::big_digit::{BigDigit, DoubleBigDigit, ZERO_BIG_DIGIT};
use self::algorithms::{mac_with_carry, mul3, scalar_mul, 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 self::monty::monty_modpow;
use UsizePromotion;
use ParseBigIntError;
#[cfg(test)]
#[path = "tests/biguint.rs"]
mod biguint_tests;
#[derive(Clone, Debug, Hash)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
pub struct BigUint {
    data: Vec<BigDigit>,
}
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<Ordering> {
        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, ParseBigIntError> {
        BigUint::from_str_radix(s, 10)
    }
}
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)
}
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; 
    
    
    for &c in v {
        d |= (c as BigDigit) << dbits;
        dbits += bits;
        if dbits >= big_digit::BITS {
            data.push(d);
            dbits -= big_digit::BITS;
            
            
            d = (c as BigDigit) >> (bits - dbits);
        }
    }
    if dbits > 0 {
        debug_assert!(dbits < big_digit::BITS);
        data.push(d as BigDigit);
    }
    BigUint::new(data)
}
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));
    
    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;
    
    fn from_str_radix(s: &str, radix: u32) -> Result<BigUint, ParseBigIntError> {
        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() {
            
            let e = u64::from_str_radix(s, radix).unwrap_err();
            return Err(e.into());
        }
        if s.starts_with('_') {
            
            
            let e = u64::from_str_radix(s, radix).unwrap_err();
            return Err(e.into());
        }
        
        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,
                b'_' => continue,
                _ => u8::MAX,
            };
            if d < radix as u8 {
                v.push(d);
            } else {
                
                
                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() {
            
            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);
forward_val_assign!(impl BitAndAssign for BigUint, bitand_assign);
impl<'a> BitAnd<&'a BigUint> for BigUint {
    type Output = BigUint;
    #[inline]
    fn bitand(mut self, other: &BigUint) -> BigUint {
        self &= other;
        self
    }
}
impl<'a> BitAndAssign<&'a BigUint> for BigUint {
    #[inline]
    fn bitand_assign(&mut self, other: &BigUint) {
        for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) {
            *ai &= bi;
        }
        self.data.truncate(other.data.len());
        self.normalize();
    }
}
forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor);
forward_val_assign!(impl BitOrAssign for BigUint, bitor_assign);
impl<'a> BitOr<&'a BigUint> for BigUint {
    type Output = BigUint;
    fn bitor(mut self, other: &BigUint) -> BigUint {
        self |= other;
        self
    }
}
impl<'a> BitOrAssign<&'a BigUint> for BigUint {
    #[inline]
    fn bitor_assign(&mut self, other: &BigUint) {
        for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) {
            *ai |= bi;
        }
        if other.data.len() > self.data.len() {
            let extra = &other.data[self.data.len()..];
            self.data.extend(extra.iter().cloned());
        }
    }
}
forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor);
forward_val_assign!(impl BitXorAssign for BigUint, bitxor_assign);
impl<'a> BitXor<&'a BigUint> for BigUint {
    type Output = BigUint;
    fn bitxor(mut self, other: &BigUint) -> BigUint {
        self ^= other;
        self
    }
}
impl<'a> BitXorAssign<&'a BigUint> for BigUint {
    #[inline]
    fn bitxor_assign(&mut self, other: &BigUint) {
        for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) {
            *ai ^= bi;
        }
        if other.data.len() > self.data.len() {
            let extra = &other.data[self.data.len()..];
            self.data.extend(extra.iter().cloned());
        }
        self.normalize();
    }
}
impl Shl<usize> for BigUint {
    type Output = BigUint;
    #[inline]
    fn shl(self, rhs: usize) -> BigUint {
        biguint_shl(Cow::Owned(self), rhs)
    }
}
impl<'a> Shl<usize> for &'a BigUint {
    type Output = BigUint;
    #[inline]
    fn shl(self, rhs: usize) -> BigUint {
        biguint_shl(Cow::Borrowed(self), rhs)
    }
}
impl ShlAssign<usize> for BigUint {
    #[inline]
    fn shl_assign(&mut self, rhs: usize) {
        *self = biguint_shl(Cow::Borrowed(&*self), rhs);
    }
}
impl Shr<usize> for BigUint {
    type Output = BigUint;
    #[inline]
    fn shr(self, rhs: usize) -> BigUint {
        biguint_shr(Cow::Owned(self), rhs)
    }
}
impl<'a> Shr<usize> for &'a BigUint {
    type Output = BigUint;
    #[inline]
    fn shr(self, rhs: usize) -> BigUint {
        biguint_shr(Cow::Borrowed(self), rhs)
    }
}
impl ShrAssign<usize> for BigUint {
    #[inline]
    fn shr_assign(&mut self, rhs: usize) {
        *self = 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);
forward_val_assign!(impl AddAssign for BigUint, add_assign);
impl<'a> Add<&'a BigUint> for BigUint {
    type Output = BigUint;
    fn add(mut self, other: &BigUint) -> BigUint {
        self += other;
        self
    }
}
impl<'a> AddAssign<&'a BigUint> for BigUint {
    #[inline]
    fn add_assign(&mut self, other: &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);
        }
    }
}
promote_unsigned_scalars!(impl Add for BigUint, add);
promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<BigDigit> for BigUint, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<DoubleBigDigit> for BigUint, add);
impl Add<BigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn add(mut self, other: BigDigit) -> BigUint {
        self += other;
        self
    }
}
impl AddAssign<BigDigit> for BigUint {
    #[inline]
    fn add_assign(&mut self, other: BigDigit) {
        if other != 0 {
            if self.data.len() == 0 {
                self.data.push(0);
            }
            let carry = __add2(&mut self.data, &[other]);
            if carry != 0 {
                self.data.push(carry);
            }
        }
    }
}
impl Add<DoubleBigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn add(mut self, other: DoubleBigDigit) -> BigUint {
        self += other;
        self
    }
}
impl AddAssign<DoubleBigDigit> for BigUint {
    #[inline]
    fn add_assign(&mut self, other: DoubleBigDigit) {
        let (hi, lo) = big_digit::from_doublebigdigit(other);
        if hi == 0 {
            *self += lo;
        } else {
            while self.data.len() < 2 {
                self.data.push(0);
            }
            let carry = __add2(&mut self.data, &[lo, hi]);
            if carry != 0 {
                self.data.push(carry);
            }
        }
    }
}
forward_val_val_binop!(impl Sub for BigUint, sub);
forward_ref_ref_binop!(impl Sub for BigUint, sub);
forward_val_assign!(impl SubAssign for BigUint, sub_assign);
impl<'a> Sub<&'a BigUint> for BigUint {
    type Output = BigUint;
    fn sub(mut self, other: &BigUint) -> BigUint {
        self -= other;
        self
    }
}
impl<'a> SubAssign<&'a BigUint> for BigUint {
    fn sub_assign(&mut self, other: &'a BigUint) {
        sub2(&mut self.data[..], &other.data[..]);
        self.normalize();
    }
}
impl<'a> Sub<BigUint> 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.normalized()
    }
}
promote_unsigned_scalars!(impl Sub for BigUint, sub);
promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
forward_all_scalar_binop_to_val_val!(impl Sub<BigDigit> for BigUint, sub);
forward_all_scalar_binop_to_val_val!(impl Sub<DoubleBigDigit> for BigUint, sub);
impl Sub<BigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn sub(mut self, other: BigDigit) -> BigUint {
        self -= other;
        self
    }
}
impl SubAssign<BigDigit> for BigUint {
    fn sub_assign(&mut self, other: BigDigit) {
        sub2(&mut self.data[..], &[other]);
        self.normalize();
    }
}
impl Sub<BigUint> for BigDigit {
    type Output = BigUint;
    #[inline]
    fn sub(self, mut other: BigUint) -> BigUint {
        if other.data.len() == 0 {
            other.data.push(0);
        }
        sub2rev(&[self], &mut other.data[..]);
        other.normalized()
    }
}
impl Sub<DoubleBigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn sub(mut self, other: DoubleBigDigit) -> BigUint {
        self -= other;
        self
    }
}
impl SubAssign<DoubleBigDigit> for BigUint {
    fn sub_assign(&mut self, other: DoubleBigDigit) {
        let (hi, lo) = big_digit::from_doublebigdigit(other);
        sub2(&mut self.data[..], &[lo, hi]);
        self.normalize();
    }
}
impl Sub<BigUint> for DoubleBigDigit {
    type Output = BigUint;
    #[inline]
    fn sub(self, mut other: BigUint) -> BigUint {
        while other.data.len() < 2 {
            other.data.push(0);
        }
        let (hi, lo) = big_digit::from_doublebigdigit(self);
        sub2rev(&[lo, hi], &mut other.data[..]);
        other.normalized()
    }
}
forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul);
forward_val_assign!(impl MulAssign for BigUint, mul_assign);
impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint {
    type Output = BigUint;
    #[inline]
    fn mul(self, other: &BigUint) -> BigUint {
        mul3(&self.data[..], &other.data[..])
    }
}
impl<'a> MulAssign<&'a BigUint> for BigUint {
    #[inline]
    fn mul_assign(&mut self, other: &'a BigUint) {
        *self = &*self * other
    }
}
promote_unsigned_scalars!(impl Mul for BigUint, mul);
promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign);
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<BigDigit> for BigUint, mul);
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<DoubleBigDigit> for BigUint, mul);
impl Mul<BigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn mul(mut self, other: BigDigit) -> BigUint {
        self *= other;
        self
    }
}
impl MulAssign<BigDigit> for BigUint {
    #[inline]
    fn mul_assign(&mut self, other: BigDigit) {
        if other == 0 {
            self.data.clear();
        } else {
            let carry = scalar_mul(&mut self.data[..], other);
            if carry != 0 {
                self.data.push(carry);
            }
        }
    }
}
impl Mul<DoubleBigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn mul(mut self, other: DoubleBigDigit) -> BigUint {
        self *= other;
        self
    }
}
impl MulAssign<DoubleBigDigit> for BigUint {
    #[inline]
    fn mul_assign(&mut self, other: DoubleBigDigit) {
        if other == 0 {
            self.data.clear();
        } else if other <= BigDigit::max_value() as DoubleBigDigit {
            *self *= other as BigDigit
        } else {
            let (hi, lo) = big_digit::from_doublebigdigit(other);
            *self = mul3(&self.data[..], &[lo, hi])
        }
    }
}
forward_all_binop_to_ref_ref!(impl Div for BigUint, div);
forward_val_assign!(impl DivAssign for BigUint, div_assign);
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);
        q
    }
}
impl<'a> DivAssign<&'a BigUint> for BigUint {
    #[inline]
    fn div_assign(&mut self, other: &'a BigUint) {
        *self = &*self / other;
    }
}
promote_unsigned_scalars!(impl Div for BigUint, div);
promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigUint, div);
forward_all_scalar_binop_to_val_val!(impl Div<DoubleBigDigit> for BigUint, div);
impl Div<BigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn div(self, other: BigDigit) -> BigUint {
        let (q, _) = div_rem_digit(self, other);
        q
    }
}
impl DivAssign<BigDigit> for BigUint {
    #[inline]
    fn div_assign(&mut self, other: BigDigit) {
        *self = &*self / other;
    }
}
impl Div<BigUint> for BigDigit {
    type Output = BigUint;
    #[inline]
    fn div(self, other: BigUint) -> BigUint {
        match other.data.len() {
            0 => panic!(),
            1 => From::from(self / other.data[0]),
            _ => Zero::zero(),
        }
    }
}
impl Div<DoubleBigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn div(self, other: DoubleBigDigit) -> BigUint {
        let (q, _) = self.div_rem(&From::from(other));
        q
    }
}
impl DivAssign<DoubleBigDigit> for BigUint {
    #[inline]
    fn div_assign(&mut self, other: DoubleBigDigit) {
        *self = &*self / other;
    }
}
impl Div<BigUint> for DoubleBigDigit {
    type Output = BigUint;
    #[inline]
    fn div(self, other: BigUint) -> BigUint {
        match other.data.len() {
            0 => panic!(),
            1 => From::from(self / other.data[0] as u64),
            2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])),
            _ => Zero::zero(),
        }
    }
}
forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem);
forward_val_assign!(impl RemAssign for BigUint, rem_assign);
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);
        r
    }
}
impl<'a> RemAssign<&'a BigUint> for BigUint {
    #[inline]
    fn rem_assign(&mut self, other: &BigUint) {
        *self = &*self % other;
    }
}
promote_unsigned_scalars!(impl Rem for BigUint, rem);
promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigUint, rem);
forward_all_scalar_binop_to_val_val!(impl Rem<DoubleBigDigit> for BigUint, rem);
impl Rem<BigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn rem(self, other: BigDigit) -> BigUint {
        let (_, r) = div_rem_digit(self, other);
        From::from(r)
    }
}
impl RemAssign<BigDigit> for BigUint {
    #[inline]
    fn rem_assign(&mut self, other: BigDigit) {
        *self = &*self % other;
    }
}
impl Rem<BigUint> for BigDigit {
    type Output = BigUint;
    #[inline]
    fn rem(mut self, other: BigUint) -> BigUint {
        self %= other;
        From::from(self)
    }
}
macro_rules! impl_rem_assign_scalar {
    ($scalar:ty, $to_scalar:ident) => {
        forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign);
        impl<'a> RemAssign<&'a BigUint> for $scalar {
            #[inline]
            fn rem_assign(&mut self, other: &BigUint) {
                *self = match other.$to_scalar() {
                    None => *self,
                    Some(0) => panic!(),
                    Some(v) => *self % v
                };
            }
        }
    }
}
impl_rem_assign_scalar!(usize, to_usize);
impl_rem_assign_scalar!(u64, to_u64);
impl_rem_assign_scalar!(u32, to_u32);
impl_rem_assign_scalar!(u16, to_u16);
impl_rem_assign_scalar!(u8, to_u8);
impl_rem_assign_scalar!(isize, to_isize);
impl_rem_assign_scalar!(i64, to_i64);
impl_rem_assign_scalar!(i32, to_i32);
impl_rem_assign_scalar!(i16, to_i16);
impl_rem_assign_scalar!(i8, to_i8);
impl Rem<DoubleBigDigit> for BigUint {
    type Output = BigUint;
    #[inline]
    fn rem(self, other: DoubleBigDigit) -> BigUint {
        let (_, r) = self.div_rem(&From::from(other));
        r
    }
}
impl RemAssign<DoubleBigDigit> for BigUint {
    #[inline]
    fn rem_assign(&mut self, other: DoubleBigDigit) {
        *self = &*self % other;
    }
}
impl Rem<BigUint> for DoubleBigDigit {
    type Output = BigUint;
    #[inline]
    fn rem(mut self, other: BigUint) -> BigUint {
        self %= other;
        From::from(self)
    }
}
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<BigUint> {
        return Some(self.add(v));
    }
}
impl CheckedSub for BigUint {
    #[inline]
    fn checked_sub(&self, v: &BigUint) -> Option<BigUint> {
        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<BigUint> {
        return Some(self.mul(v));
    }
}
impl CheckedDiv for BigUint {
    #[inline]
    fn checked_div(&self, v: &BigUint) -> Option<BigUint> {
        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)
    }
    
    
    
    #[inline]
    fn gcd(&self, other: &BigUint) -> BigUint {
        
        let mut m = (*self).clone();
        let mut n = (*other).clone();
        while !m.is_zero() {
            let temp = m;
            m = n % &temp;
            n = temp;
        }
        return n;
    }
    
    #[inline]
    fn lcm(&self, other: &BigUint) -> BigUint {
        ((self * other) / self.gcd(other))
    }
    
    #[inline]
    fn divides(&self, other: &BigUint) -> bool {
        self.is_multiple_of(other)
    }
    
    #[inline]
    fn is_multiple_of(&self, other: &BigUint) -> bool {
        (self % other).is_zero()
    }
    
    #[inline]
    fn is_even(&self) -> bool {
        
        match self.data.first() {
            Some(x) => x.is_even(),
            None => true,
        }
    }
    
    #[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<i64> {
        self.to_u64().and_then(|n| {
            
            if n >> 63 == 0 {
                Some(n as i64)
            } else {
                None
            }
        })
    }
    #[inline]
    fn to_u64(&self) -> Option<u64> {
        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<f32> {
        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<f64> {
        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<BigUint> {
        if n >= 0 {
            Some(BigUint::from(n as u64))
        } else {
            None
        }
    }
    #[inline]
    fn from_u64(n: u64) -> Option<BigUint> {
        Some(BigUint::from(n))
    }
    #[inline]
    fn from_f64(mut n: f64) -> Option<BigUint> {
        
        if !n.is_finite() {
            return None;
        }
        
        n = n.trunc();
        
        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<u64> for BigUint {
    #[inline]
    fn from(mut n: u64) -> Self {
        let mut ret: BigUint = Zero::zero();
        while n != 0 {
            ret.data.push(n as BigDigit);
            
            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);
pub trait ToBigUint {
    
    fn to_biguint(&self) -> Option<BigUint>;
}
impl ToBigUint for BigUint {
    #[inline]
    fn to_biguint(&self) -> Option<BigUint> {
        Some(self.clone())
    }
}
macro_rules! impl_to_biguint {
    ($T:ty, $from_ty:path) => {
        impl ToBigUint for $T {
            #[inline]
            fn to_biguint(&self) -> Option<BigUint> {
                $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);
fn to_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec<u8> {
    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
}
fn to_inexact_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec<u8> {
    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;
            
            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
}
#[inline(always)] 
fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec<u8> {
    debug_assert!(!u.is_zero() && !radix.is_power_of_two());
    
    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_radix_le(u: &BigUint, radix: u32) -> Vec<u8> {
    if u.is_zero() {
        vec![0]
    } else if radix.is_power_of_two() {
        
        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 {
        
        
        to_radix_digits_le(u, 10)
    } else {
        to_radix_digits_le(u, radix)
    }
}
pub fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec<u8> {
    assert!(2 <= radix && radix <= 36, "The radix must be within 2...36");
    if u.is_zero() {
        return vec![b'0'];
    }
    let mut res = to_radix_le(u, radix);
    
    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 {
    
    
    
    #[inline]
    pub fn new(digits: Vec<BigDigit>) -> BigUint {
        BigUint { data: digits }.normalized()
    }
    
    
    
    #[inline]
    pub fn from_slice(slice: &[BigDigit]) -> BigUint {
        BigUint::new(slice.to_vec())
    }
    
    
    
    #[inline]
    pub fn assign_from_slice(&mut self, slice: &[BigDigit]) {
        self.data.resize(slice.len(), 0);
        self.data.clone_from_slice(slice);
        self.normalize();
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[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)
        }
    }
    
    
    
    #[inline]
    pub fn from_bytes_le(bytes: &[u8]) -> BigUint {
        if bytes.is_empty() {
            Zero::zero()
        } else {
            from_bitwise_digits_le(bytes, 8)
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigUint> {
        str::from_utf8(buf).ok().and_then(|s| BigUint::from_str_radix(s, radix).ok())
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    pub fn from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint> {
        assert!(2 <= radix && radix <= 256, "The radix must be within 2...256");
        if radix != 256 && buf.iter().any(|&b| b >= radix as u8) {
            return None;
        }
        let res = if radix.is_power_of_two() {
            
            let bits = ilog2(radix);
            let mut v = Vec::from(buf);
            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(buf, radix)
        };
        Some(res)
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    pub fn from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint> {
        assert!(2 <= radix && radix <= 256, "The radix must be within 2...256");
        if radix != 256 && buf.iter().any(|&b| b >= radix as u8) {
            return None;
        }
        let res = if radix.is_power_of_two() {
            
            let bits = ilog2(radix);
            if big_digit::BITS % bits == 0 {
                from_bitwise_digits_le(buf, bits)
            } else {
                from_inexact_bitwise_digits_le(buf, bits)
            }
        } else {
            let mut v = Vec::from(buf);
            v.reverse();
            from_radix_digits_be(&v, radix)
        };
        Some(res)
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_bytes_be(&self) -> Vec<u8> {
        let mut v = self.to_bytes_le();
        v.reverse();
        v
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_bytes_le(&self) -> Vec<u8> {
        if self.is_zero() {
            vec![0]
        } else {
            to_bitwise_digits_le(self, 8)
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    #[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) }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_radix_be(&self, radix: u32) -> Vec<u8> {
        let mut v = to_radix_le(self, radix);
        v.reverse();
        v
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_radix_le(&self, radix: u32) -> Vec<u8> {
        to_radix_le(self, radix)
    }
    
    #[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;
    }
    
    
    #[inline]
    fn normalize(&mut self) {
        while let Some(&0) = self.data.last() {
            self.data.pop();
        }
    }
    
    #[inline]
    fn normalized(mut self) -> BigUint {
        self.normalize();
        self
    }
    
    pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
        assert!(!modulus.is_zero(), "divide by zero!");
        
        if modulus.is_odd() {
            return monty_modpow(self, exponent, modulus);
        }
        
        let one = BigUint::one();
        if exponent.is_zero() { return one; }
        let mut base = self % modulus;
        let mut exp = exponent.clone();
        while exp.is_even() {
            base = &base * &base % modulus;
            exp >>= 1;
        }
        if exp == one { return base }
        let mut acc = base.clone();
        while exp > one {
            exp >>= 1;
            base = &base * &base % modulus;
            if exp.is_odd() {
                acc = acc * &base % modulus;
            }
        }
        acc
    }
}
#[cfg(feature = "serde")]
impl serde::Serialize for BigUint {
    fn serialize<S>(&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<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: serde::Deserializer
    {
        let data = try!(Vec::deserialize(deserializer));
        Ok(BigUint { data: data })
    }
}
#[inline]
fn get_radix_base(radix: u32) -> (BigDigit, usize) {
    debug_assert!(2 <= radix && radix <= 256, "The radix must be within 2...256");
    debug_assert!(!radix.is_power_of_two());
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    match big_digit::BITS {
        32  => {
            const BASES: [(u32, usize); 257] = [
                (         0,  0),
                (         0,  0),
                (         0,  0), 
                (3486784401, 20), 
                (         0,  0), 
                (1220703125, 13), 
                (2176782336, 12), 
                (1977326743, 11), 
                (         0,  0), 
                (3486784401, 10), 
                (1000000000,  9), 
                (2357947691,  9), 
                ( 429981696,  8), 
                ( 815730721,  8), 
                (1475789056,  8), 
                (2562890625,  8), 
                (         0,  0), 
                ( 410338673,  7), 
                ( 612220032,  7), 
                ( 893871739,  7), 
                (1280000000,  7), 
                (1801088541,  7), 
                (2494357888,  7), 
                (3404825447,  7), 
                ( 191102976,  6), 
                ( 244140625,  6), 
                ( 308915776,  6), 
                ( 387420489,  6), 
                ( 481890304,  6), 
                ( 594823321,  6), 
                ( 729000000,  6), 
                ( 887503681,  6), 
                (         0,  0), 
                (1291467969,  6), 
                (1544804416,  6), 
                (1838265625,  6), 
                (2176782336,  6), 
                (2565726409,  6), 
                (3010936384,  6), 
                (3518743761,  6), 
                (4096000000,  6), 
                ( 115856201,  5), 
                ( 130691232,  5), 
                ( 147008443,  5), 
                ( 164916224,  5), 
                ( 184528125,  5), 
                ( 205962976,  5), 
                ( 229345007,  5), 
                ( 254803968,  5), 
                ( 282475249,  5), 
                ( 312500000,  5), 
                ( 345025251,  5), 
                ( 380204032,  5), 
                ( 418195493,  5), 
                ( 459165024,  5), 
                ( 503284375,  5), 
                ( 550731776,  5), 
                ( 601692057,  5), 
                ( 656356768,  5), 
                ( 714924299,  5), 
                ( 777600000,  5), 
                ( 844596301,  5), 
                ( 916132832,  5), 
                ( 992436543,  5), 
                (         0,  0), 
                (1160290625,  5), 
                (1252332576,  5), 
                (1350125107,  5), 
                (1453933568,  5), 
                (1564031349,  5), 
                (1680700000,  5), 
                (1804229351,  5), 
                (1934917632,  5), 
                (2073071593,  5), 
                (2219006624,  5), 
                (2373046875,  5), 
                (2535525376,  5), 
                (2706784157,  5), 
                (2887174368,  5), 
                (3077056399,  5), 
                (3276800000,  5), 
                (3486784401,  5), 
                (3707398432,  5), 
                (3939040643,  5), 
                (4182119424,  5), 
                (  52200625,  4), 
                (  54700816,  4), 
                (  57289761,  4), 
                (  59969536,  4), 
                (  62742241,  4), 
                (  65610000,  4), 
                (  68574961,  4), 
                (  71639296,  4), 
                (  74805201,  4), 
                (  78074896,  4), 
                (  81450625,  4), 
                (  84934656,  4), 
                (  88529281,  4), 
                (  92236816,  4), 
                (  96059601,  4), 
                ( 100000000,  4), 
                ( 104060401,  4), 
                ( 108243216,  4), 
                ( 112550881,  4), 
                ( 116985856,  4), 
                ( 121550625,  4), 
                ( 126247696,  4), 
                ( 131079601,  4), 
                ( 136048896,  4), 
                ( 141158161,  4), 
                ( 146410000,  4), 
                ( 151807041,  4), 
                ( 157351936,  4), 
                ( 163047361,  4), 
                ( 168896016,  4), 
                ( 174900625,  4), 
                ( 181063936,  4), 
                ( 187388721,  4), 
                ( 193877776,  4), 
                ( 200533921,  4), 
                ( 207360000,  4), 
                ( 214358881,  4), 
                ( 221533456,  4), 
                ( 228886641,  4), 
                ( 236421376,  4), 
                ( 244140625,  4), 
                ( 252047376,  4), 
                ( 260144641,  4), 
                (         0,  0), 
                ( 276922881,  4), 
                ( 285610000,  4), 
                ( 294499921,  4), 
                ( 303595776,  4), 
                ( 312900721,  4), 
                ( 322417936,  4), 
                ( 332150625,  4), 
                ( 342102016,  4), 
                ( 352275361,  4), 
                ( 362673936,  4), 
                ( 373301041,  4), 
                ( 384160000,  4), 
                ( 395254161,  4), 
                ( 406586896,  4), 
                ( 418161601,  4), 
                ( 429981696,  4), 
                ( 442050625,  4), 
                ( 454371856,  4), 
                ( 466948881,  4), 
                ( 479785216,  4), 
                ( 492884401,  4), 
                ( 506250000,  4), 
                ( 519885601,  4), 
                ( 533794816,  4), 
                ( 547981281,  4), 
                ( 562448656,  4), 
                ( 577200625,  4), 
                ( 592240896,  4), 
                ( 607573201,  4), 
                ( 623201296,  4), 
                ( 639128961,  4), 
                ( 655360000,  4), 
                ( 671898241,  4), 
                ( 688747536,  4), 
                ( 705911761,  4), 
                ( 723394816,  4), 
                ( 741200625,  4), 
                ( 759333136,  4), 
                ( 777796321,  4), 
                ( 796594176,  4), 
                ( 815730721,  4), 
                ( 835210000,  4), 
                ( 855036081,  4), 
                ( 875213056,  4), 
                ( 895745041,  4), 
                ( 916636176,  4), 
                ( 937890625,  4), 
                ( 959512576,  4), 
                ( 981506241,  4), 
                (1003875856,  4), 
                (1026625681,  4), 
                (1049760000,  4), 
                (1073283121,  4), 
                (1097199376,  4), 
                (1121513121,  4), 
                (1146228736,  4), 
                (1171350625,  4), 
                (1196883216,  4), 
                (1222830961,  4), 
                (1249198336,  4), 
                (1275989841,  4), 
                (1303210000,  4), 
                (1330863361,  4), 
                (1358954496,  4), 
                (1387488001,  4), 
                (1416468496,  4), 
                (1445900625,  4), 
                (1475789056,  4), 
                (1506138481,  4), 
                (1536953616,  4), 
                (1568239201,  4), 
                (1600000000,  4), 
                (1632240801,  4), 
                (1664966416,  4), 
                (1698181681,  4), 
                (1731891456,  4), 
                (1766100625,  4), 
                (1800814096,  4), 
                (1836036801,  4), 
                (1871773696,  4), 
                (1908029761,  4), 
                (1944810000,  4), 
                (1982119441,  4), 
                (2019963136,  4), 
                (2058346161,  4), 
                (2097273616,  4), 
                (2136750625,  4), 
                (2176782336,  4), 
                (2217373921,  4), 
                (2258530576,  4), 
                (2300257521,  4), 
                (2342560000,  4), 
                (2385443281,  4), 
                (2428912656,  4), 
                (2472973441,  4), 
                (2517630976,  4), 
                (2562890625,  4), 
                (2608757776,  4), 
                (2655237841,  4), 
                (2702336256,  4), 
                (2750058481,  4), 
                (2798410000,  4), 
                (2847396321,  4), 
                (2897022976,  4), 
                (2947295521,  4), 
                (2998219536,  4), 
                (3049800625,  4), 
                (3102044416,  4), 
                (3154956561,  4), 
                (3208542736,  4), 
                (3262808641,  4), 
                (3317760000,  4), 
                (3373402561,  4), 
                (3429742096,  4), 
                (3486784401,  4), 
                (3544535296,  4), 
                (3603000625,  4), 
                (3662186256,  4), 
                (3722098081,  4), 
                (3782742016,  4), 
                (3844124001,  4), 
                (3906250000,  4), 
                (3969126001,  4), 
                (4032758016,  4), 
                (4097152081,  4), 
                (4162314256,  4), 
                (4228250625,  4), 
                (         0,  0), 
            ];
            let (base, power) = BASES[radix as usize];
            (base as BigDigit, power)
        }
        64  => {
            const BASES: [(u64, usize); 257] = [
                (                   0,  0),
                (                   0,  0),
                ( 9223372036854775808, 63), 
                (12157665459056928801, 40), 
                ( 4611686018427387904, 31), 
                ( 7450580596923828125, 27), 
                ( 4738381338321616896, 24), 
                ( 3909821048582988049, 22), 
                ( 9223372036854775808, 21), 
                (12157665459056928801, 20), 
                (10000000000000000000, 19), 
                ( 5559917313492231481, 18), 
                ( 2218611106740436992, 17), 
                ( 8650415919381337933, 17), 
                ( 2177953337809371136, 16), 
                ( 6568408355712890625, 16), 
                ( 1152921504606846976, 15), 
                ( 2862423051509815793, 15), 
                ( 6746640616477458432, 15), 
                (15181127029874798299, 15), 
                ( 1638400000000000000, 14), 
                ( 3243919932521508681, 14), 
                ( 6221821273427820544, 14), 
                (11592836324538749809, 14), 
                (  876488338465357824, 13), 
                ( 1490116119384765625, 13), 
                ( 2481152873203736576, 13), 
                ( 4052555153018976267, 13), 
                ( 6502111422497947648, 13), 
                (10260628712958602189, 13), 
                (15943230000000000000, 13), 
                (  787662783788549761, 12), 
                ( 1152921504606846976, 12), 
                ( 1667889514952984961, 12), 
                ( 2386420683693101056, 12), 
                ( 3379220508056640625, 12), 
                ( 4738381338321616896, 12), 
                ( 6582952005840035281, 12), 
                ( 9065737908494995456, 12), 
                (12381557655576425121, 12), 
                (16777216000000000000, 12), 
                (  550329031716248441, 11), 
                (  717368321110468608, 11), 
                (  929293739471222707, 11), 
                ( 1196683881290399744, 11), 
                ( 1532278301220703125, 11), 
                ( 1951354384207722496, 11), 
                ( 2472159215084012303, 11), 
                ( 3116402981210161152, 11), 
                ( 3909821048582988049, 11), 
                ( 4882812500000000000, 11), 
                ( 6071163615208263051, 11), 
                ( 7516865509350965248, 11), 
                ( 9269035929372191597, 11), 
                (11384956040305711104, 11), 
                (13931233916552734375, 11), 
                (16985107389382393856, 11), 
                (  362033331456891249, 10), 
                (  430804206899405824, 10), 
                (  511116753300641401, 10), 
                (  604661760000000000, 10), 
                (  713342911662882601, 10), 
                (  839299365868340224, 10), 
                (  984930291881790849, 10), 
                ( 1152921504606846976, 10), 
                ( 1346274334462890625, 10), 
                ( 1568336880910795776, 10), 
                ( 1822837804551761449, 10), 
                ( 2113922820157210624, 10), 
                ( 2446194060654759801, 10), 
                ( 2824752490000000000, 10), 
                ( 3255243551009881201, 10), 
                ( 3743906242624487424, 10), 
                ( 4297625829703557649, 10), 
                ( 4923990397355877376, 10), 
                ( 5631351470947265625, 10), 
                ( 6428888932339941376, 10), 
                ( 7326680472586200649, 10), 
                ( 8335775831236199424, 10), 
                ( 9468276082626847201, 10), 
                (10737418240000000000, 10), 
                (12157665459056928801, 10), 
                (13744803133596058624, 10), 
                (15516041187205853449, 10), 
                (17490122876598091776, 10), 
                (  231616946283203125,  9), 
                (  257327417311663616,  9), 
                (  285544154243029527,  9), 
                (  316478381828866048,  9), 
                (  350356403707485209,  9), 
                (  387420489000000000,  9), 
                (  427929800129788411,  9), 
                (  472161363286556672,  9), 
                (  520411082988487293,  9), 
                (  572994802228616704,  9), 
                (  630249409724609375,  9), 
                (  692533995824480256,  9), 
                (  760231058654565217,  9), 
                (  833747762130149888,  9), 
                (  913517247483640899,  9), 
                ( 1000000000000000000,  9), 
                ( 1093685272684360901,  9), 
                ( 1195092568622310912,  9), 
                ( 1304773183829244583,  9), 
                ( 1423311812421484544,  9), 
                ( 1551328215978515625,  9), 
                ( 1689478959002692096,  9), 
                ( 1838459212420154507,  9), 
                ( 1999004627104432128,  9), 
                ( 2171893279442309389,  9), 
                ( 2357947691000000000,  9), 
                ( 2558036924386500591,  9), 
                ( 2773078757450186752,  9), 
                ( 3004041937984268273,  9), 
                ( 3251948521156637184,  9), 
                ( 3517876291919921875,  9), 
                ( 3802961274698203136,  9), 
                ( 4108400332687853397,  9), 
                ( 4435453859151328768,  9), 
                ( 4785448563124474679,  9), 
                ( 5159780352000000000,  9), 
                ( 5559917313492231481,  9), 
                ( 5987402799531080192,  9), 
                ( 6443858614676334363,  9), 
                ( 6930988311686938624,  9), 
                ( 7450580596923828125,  9), 
                ( 8004512848309157376,  9), 
                ( 8594754748609397887,  9), 
                ( 9223372036854775808,  9), 
                ( 9892530380752880769,  9), 
                (10604499373000000000,  9), 
                (11361656654439817571,  9), 
                (12166492167065567232,  9), 
                (13021612539908538853,  9), 
                (13929745610903012864,  9), 
                (14893745087865234375,  9), 
                (15916595351771938816,  9), 
                (17001416405572203977,  9), 
                (18151468971815029248,  9), 
                (  139353667211683681,  8), 
                (  147578905600000000,  8), 
                (  156225851787813921,  8), 
                (  165312903998914816,  8), 
                (  174859124550883201,  8), 
                (  184884258895036416,  8), 
                (  195408755062890625,  8), 
                (  206453783524884736,  8), 
                (  218041257467152161,  8), 
                (  230193853492166656,  8), 
                (  242935032749128801,  8), 
                (  256289062500000000,  8), 
                (  270281038127131201,  8), 
                (  284936905588473856,  8), 
                (  300283484326400961,  8), 
                (  316348490636206336,  8), 
                (  333160561500390625,  8), 
                (  350749278894882816,  8), 
                (  369145194573386401,  8), 
                (  388379855336079616,  8), 
                (  408485828788939521,  8), 
                (  429496729600000000,  8), 
                (  451447246258894081,  8), 
                (  474373168346071296,  8), 
                (  498311414318121121,  8), 
                (  523300059815673856,  8), 
                (  549378366500390625,  8), 
                (  576586811427594496,  8), 
                (  604967116961135041,  8), 
                (  634562281237118976,  8), 
                (  665416609183179841,  8), 
                (  697575744100000000,  8), 
                (  731086699811838561,  8), 
                (  765997893392859136,  8), 
                (  802359178476091681,  8), 
                (  840221879151902976,  8), 
                (  879638824462890625,  8), 
                (  920664383502155776,  8), 
                (  963354501121950081,  8), 
                ( 1007766734259732736,  8), 
                ( 1053960288888713761,  8), 
                ( 1101996057600000000,  8), 
                ( 1151936657823500641,  8), 
                ( 1203846470694789376,  8), 
                ( 1257791680575160641,  8), 
                ( 1313840315232157696,  8), 
                ( 1372062286687890625,  8), 
                ( 1432529432742502656,  8), 
                ( 1495315559180183521,  8), 
                ( 1560496482665168896,  8), 
                ( 1628150074335205281,  8), 
                ( 1698356304100000000,  8), 
                ( 1771197285652216321,  8), 
                ( 1846757322198614016,  8), 
                ( 1925122952918976001,  8), 
                ( 2006383000160502016,  8), 
                ( 2090628617375390625,  8), 
                ( 2177953337809371136,  8), 
                ( 2268453123948987361,  8), 
                ( 2362226417735475456,  8), 
                ( 2459374191553118401,  8), 
                ( 2560000000000000000,  8), 
                ( 2664210032449121601,  8), 
                ( 2772113166407885056,  8), 
                ( 2883821021683985761,  8), 
                ( 2999448015365799936,  8), 
                ( 3119111417625390625,  8), 
                ( 3242931408352297216,  8), 
                ( 3371031134626313601,  8), 
                ( 3503536769037500416,  8), 
                ( 3640577568861717121,  8), 
                ( 3782285936100000000,  8), 
                ( 3928797478390152481,  8), 
                ( 4080251070798954496,  8), 
                ( 4236788918503437921,  8), 
                ( 4398556620369715456,  8), 
                ( 4565703233437890625,  8), 
                ( 4738381338321616896,  8), 
                ( 4916747105530914241,  8), 
                ( 5100960362726891776,  8), 
                ( 5291184662917065441,  8), 
                ( 5487587353600000000,  8), 
                ( 5690339646868044961,  8), 
                ( 5899616690476974336,  8), 
                ( 6115597639891380481,  8), 
                ( 6338465731314712576,  8), 
                ( 6568408355712890625,  8), 
                ( 6805617133840466176,  8), 
                ( 7050287992278341281,  8), 
                ( 7302621240492097536,  8), 
                ( 7562821648920027361,  8), 
                ( 7831098528100000000,  8), 
                ( 8107665808844335041,  8), 
                ( 8392742123471896576,  8), 
                ( 8686550888106661441,  8), 
                ( 8989320386052055296,  8), 
                ( 9301283852250390625,  8), 
                ( 9622679558836781056,  8), 
                ( 9953750901796946721,  8), 
                (10294746488738365696,  8), 
                (10645920227784266881,  8), 
                (11007531417600000000,  8), 
                (11379844838561358721,  8), 
                (11763130845074473216,  8), 
                (12157665459056928801,  8), 
                (12563730464589807616,  8), 
                (12981613503750390625,  8), 
                (13411608173635297536,  8), 
                (13854014124583882561,  8), 
                (14309137159611744256,  8), 
                (14777289335064248001,  8), 
                (15258789062500000000,  8), 
                (15753961211814252001,  8), 
                (16263137215612256256,  8), 
                (16786655174842630561,  8), 
                (17324859965700833536,  8), 
                (17878103347812890625,  8), 
                (   72057594037927936,  7), 
            ];
            let (base, power) = BASES[radix as usize];
            (base as BigDigit, power)
        }
        _   => panic!("Invalid bigdigit size")
    }
}