use std::default::Default;
use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Not};
use std::str::{self, FromStr};
use std::fmt;
use std::cmp::Ordering::{self, Less, Greater, Equal};
use std::{i64, u64};
use std::ascii::AsciiExt;
#[cfg(feature = "serde")]
use serde;
#[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, DoubleBigDigit};
use biguint;
use biguint::to_str_radix_reversed;
use biguint::BigUint;
use UsizePromotion;
use IsizePromotion;
#[cfg(test)]
#[path = "tests/bigint.rs"]
mod bigint_tests;
#[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;
    
    #[inline]
    fn neg(self) -> Sign {
        match self {
            Minus => Plus,
            NoSign => NoSign,
            Plus => Minus,
        }
    }
}
impl Mul<Sign> 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<S>(&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<D>(deserializer: &mut D) -> Result<Self, D::Error>
        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")),
        }
    }
}
#[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<Ordering> {
        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, ParseBigIntError> {
        BigInt::from_str_radix(s, 10)
    }
}
impl Num for BigInt {
    type FromStrRadixErr = ParseBigIntError;
    
    #[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 = try!(BigUint::from_str_radix(s, radix));
        Ok(BigInt::from_biguint(sign, bu))
    }
}
impl Shl<usize> for BigInt {
    type Output = BigInt;
    #[inline]
    fn shl(self, rhs: usize) -> BigInt {
        (&self) << rhs
    }
}
impl<'a> Shl<usize> for &'a BigInt {
    type Output = BigInt;
    #[inline]
    fn shl(self, rhs: usize) -> BigInt {
        BigInt::from_biguint(self.sign, &self.data << rhs)
    }
}
impl Shr<usize> for BigInt {
    type Output = BigInt;
    #[inline]
    fn shr(self, rhs: usize) -> BigInt {
        BigInt::from_biguint(self.sign, self.data >> rhs)
    }
}
impl<'a> Shr<usize> 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
    }
}
#[inline]
fn i32_abs_as_u32(a: i32) -> u32 {
    if a == i32::min_value() {
        a as u32
    } else {
        a.abs() as u32
    }
}
#[inline]
fn i64_abs_as_u64(a: i64) -> u64 {
    if a == i64::min_value() {
        a as u64
    } else {
        a.abs() as u64
    }
}
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,
            
            (Plus, Plus) | (Minus, Minus) =>
                BigInt::from_biguint($a.sign, $a_data + $b_data),
            
            (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<BigInt> 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<BigInt> for BigInt {
    type Output = BigInt;
    #[inline]
    fn add(self, other: BigInt) -> BigInt {
        bigint_add!(self, self, self.data, other, other, other.data)
    }
}
promote_all_scalars!(impl Add for BigInt, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<BigDigit> for BigInt, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<DoubleBigDigit> for BigInt, add);
impl Add<BigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn add(self, other: BigDigit) -> BigInt {
        match self.sign {
            NoSign => From::from(other),
            Plus => BigInt::from_biguint(Plus, self.data + other),
            Minus =>
                match self.data.cmp(&From::from(other)) {
                    Equal => Zero::zero(),
                    Less => BigInt::from_biguint(Plus, other - self.data),
                    Greater => BigInt::from_biguint(Minus, self.data - other),
                }
        }
    }
}
impl Add<DoubleBigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn add(self, other: DoubleBigDigit) -> BigInt {
        match self.sign {
            NoSign => From::from(other),
            Plus => BigInt::from_biguint(Plus, self.data + other),
            Minus =>
                match self.data.cmp(&From::from(other)) {
                    Equal => Zero::zero(),
                    Less => BigInt::from_biguint(Plus, other - self.data),
                    Greater => BigInt::from_biguint(Minus, self.data - other),
                }
        }
    }
}
forward_all_scalar_binop_to_val_val_commutative!(impl Add<i32> for BigInt, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<i64> for BigInt, add);
impl Add<i32> for BigInt {
    type Output = BigInt;
    #[inline]
    fn add(self, other: i32) -> BigInt {
        if other >= 0 {
            self + other as u32
        } else {
            self - i32_abs_as_u32(other)
        }
    }
}
impl Add<i64> for BigInt {
    type Output = BigInt;
    #[inline]
    fn add(self, other: i64) -> BigInt {
        if other >= 0 {
            self + other as u64
        } else {
            self - i64_abs_as_u64(other)
        }
    }
}
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,
            
            (Plus, Minus) | (Minus, Plus) =>
                BigInt::from_biguint($a.sign, $a_data + $b_data),
            
            (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<BigInt> 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<BigInt> for BigInt {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: BigInt) -> BigInt {
        bigint_sub!(self, self, self.data, other, other, other.data)
    }
}
promote_all_scalars!(impl Sub for BigInt, sub);
forward_all_scalar_binop_to_val_val!(impl Sub<BigDigit> for BigInt, sub);
forward_all_scalar_binop_to_val_val!(impl Sub<DoubleBigDigit> for BigInt, sub);
impl Sub<BigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: BigDigit) -> BigInt {
        match self.sign {
            NoSign => BigInt::from_biguint(Minus, From::from(other)),
            Minus => BigInt::from_biguint(Minus, self.data + other),
            Plus =>
                match self.data.cmp(&From::from(other)) {
                    Equal => Zero::zero(),
                    Greater => BigInt::from_biguint(Plus, self.data - other),
                    Less => BigInt::from_biguint(Minus, other - self.data),
                }
        }
    }
}
impl Sub<BigInt> for BigDigit {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: BigInt) -> BigInt {
        -(other - self)
    }
}
impl Sub<DoubleBigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: DoubleBigDigit) -> BigInt {
        match self.sign {
            NoSign => BigInt::from_biguint(Minus, From::from(other)),
            Minus => BigInt::from_biguint(Minus, self.data + other),
            Plus =>
                match self.data.cmp(&From::from(other)) {
                    Equal => Zero::zero(),
                    Greater => BigInt::from_biguint(Plus, self.data - other),
                    Less => BigInt::from_biguint(Minus, other - self.data),
                }
        }
    }
}
impl Sub<BigInt> for DoubleBigDigit {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: BigInt) -> BigInt {
        -(other - self)
    }
}
forward_all_scalar_binop_to_val_val!(impl Sub<i32> for BigInt, sub);
forward_all_scalar_binop_to_val_val!(impl Sub<i64> for BigInt, sub);
impl Sub<i32> for BigInt {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: i32) -> BigInt {
        if other >= 0 {
            self - other as u32
        } else {
            self + i32_abs_as_u32(other)
        }
    }
}
impl Sub<BigInt> for i32 {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: BigInt) -> BigInt {
        if self >= 0 {
            self as u32 - other
        } else {
            -other - i32_abs_as_u32(self)
        }
    }
}
impl Sub<i64> for BigInt {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: i64) -> BigInt {
        if other >= 0 {
            self - other as u64
        } else {
            self + i64_abs_as_u64(other)
        }
    }
}
impl Sub<BigInt> for i64 {
    type Output = BigInt;
    #[inline]
    fn sub(self, other: BigInt) -> BigInt {
        if self >= 0 {
            self as u64 - other
        } else {
            -other - i64_abs_as_u64(self)
        }
    }
}
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)
    }
}
promote_all_scalars!(impl Mul for BigInt, mul);
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<BigDigit> for BigInt, mul);
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<DoubleBigDigit> for BigInt, mul);
impl Mul<BigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn mul(self, other: BigDigit) -> BigInt {
        BigInt::from_biguint(self.sign, self.data * other)
    }
}
impl Mul<DoubleBigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn mul(self, other: DoubleBigDigit) -> BigInt {
        BigInt::from_biguint(self.sign, self.data * other)
    }
}
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i32> for BigInt, mul);
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i64> for BigInt, mul);
impl Mul<i32> for BigInt {
    type Output = BigInt;
    #[inline]
    fn mul(self, other: i32) -> BigInt {
        if other >= 0 {
            self * other as u32
        } else {
            -(self * i32_abs_as_u32(other))
        }
    }
}
impl Mul<i64> for BigInt {
    type Output = BigInt;
    #[inline]
    fn mul(self, other: i64) -> BigInt {
        if other >= 0 {
            self * other as u64
        } else {
            -(self * i64_abs_as_u64(other))
        }
    }
}
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
    }
}
promote_all_scalars!(impl Div for BigInt, div);
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigInt, div);
forward_all_scalar_binop_to_val_val!(impl Div<DoubleBigDigit> for BigInt, div);
impl Div<BigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn div(self, other: BigDigit) -> BigInt {
        BigInt::from_biguint(self.sign, self.data / other)
    }
}
impl Div<BigInt> for BigDigit {
    type Output = BigInt;
    #[inline]
    fn div(self, other: BigInt) -> BigInt {
        BigInt::from_biguint(other.sign, self / other.data)
    }
}
impl Div<DoubleBigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn div(self, other: DoubleBigDigit) -> BigInt {
        BigInt::from_biguint(self.sign, self.data / other)
    }
}
impl Div<BigInt> for DoubleBigDigit {
    type Output = BigInt;
    #[inline]
    fn div(self, other: BigInt) -> BigInt {
        BigInt::from_biguint(other.sign, self / other.data)
    }
}
forward_all_scalar_binop_to_val_val!(impl Div<i32> for BigInt, div);
forward_all_scalar_binop_to_val_val!(impl Div<i64> for BigInt, div);
impl Div<i32> for BigInt {
    type Output = BigInt;
    #[inline]
    fn div(self, other: i32) -> BigInt {
        if other >= 0 {
            self / other as u32
        } else {
            -(self / i32_abs_as_u32(other))
        }
    }
}
impl Div<BigInt> for i32 {
    type Output = BigInt;
    #[inline]
    fn div(self, other: BigInt) -> BigInt {
        if self >= 0 {
            self as u32 / other
        } else {
            -(i32_abs_as_u32(self) / other)
        }
    }
}
impl Div<i64> for BigInt {
    type Output = BigInt;
    #[inline]
    fn div(self, other: i64) -> BigInt {
        if other >= 0 {
            self / other as u64
        } else {
            -(self / i64_abs_as_u64(other))
        }
    }
}
impl Div<BigInt> for i64 {
    type Output = BigInt;
    #[inline]
    fn div(self, other: BigInt) -> BigInt {
        if self >= 0 {
            self as u64 / other
        } else {
            -(i64_abs_as_u64(self) / other)
        }
    }
}
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
    }
}
promote_all_scalars!(impl Rem for BigInt, rem);
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigInt, rem);
forward_all_scalar_binop_to_val_val!(impl Rem<DoubleBigDigit> for BigInt, rem);
impl Rem<BigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: BigDigit) -> BigInt {
        BigInt::from_biguint(self.sign, self.data % other)
    }
}
impl Rem<BigInt> for BigDigit {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: BigInt) -> BigInt {
        BigInt::from_biguint(Plus, self % other.data)
    }
}
impl Rem<DoubleBigDigit> for BigInt {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: DoubleBigDigit) -> BigInt {
        BigInt::from_biguint(self.sign, self.data % other)
    }
}
impl Rem<BigInt> for DoubleBigDigit {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: BigInt) -> BigInt {
        BigInt::from_biguint(Plus, self % other.data)
    }
}
forward_all_scalar_binop_to_val_val!(impl Rem<i32> for BigInt, rem);
forward_all_scalar_binop_to_val_val!(impl Rem<i64> for BigInt, rem);
impl Rem<i32> for BigInt {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: i32) -> BigInt {
        if other >= 0 {
            self % other as u32
        } else {
            self % i32_abs_as_u32(other)
        }
    }
}
impl Rem<BigInt> for i32 {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: BigInt) -> BigInt {
        if self >= 0 {
            self as u32 % other
        } else {
            -(i32_abs_as_u32(self) % other)
        }
    }
}
impl Rem<i64> for BigInt {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: i64) -> BigInt {
        if other >= 0 {
            self % other as u64
        } else {
            self % i64_abs_as_u64(other)
        }
    }
}
impl Rem<BigInt> for i64 {
    type Output = BigInt;
    #[inline]
    fn rem(self, other: BigInt) -> BigInt {
        if self >= 0 {
            self as u64 % other
        } else {
            -(i64_abs_as_u64(self) % other)
        }
    }
}
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<BigInt> {
        return Some(self.add(v));
    }
}
impl CheckedSub for BigInt {
    #[inline]
    fn checked_sub(&self, v: &BigInt) -> Option<BigInt> {
        return Some(self.sub(v));
    }
}
impl CheckedMul for BigInt {
    #[inline]
    fn checked_mul(&self, v: &BigInt) -> Option<BigInt> {
        return Some(self.mul(v));
    }
}
impl CheckedDiv for BigInt {
    #[inline]
    fn checked_div(&self, v: &BigInt) -> Option<BigInt> {
        if v.is_zero() {
            return None;
        }
        return Some(self.div(v));
    }
}
impl Integer for BigInt {
    #[inline]
    fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
        
        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) {
        
        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),
        }
    }
    
    
    
    #[inline]
    fn gcd(&self, other: &BigInt) -> BigInt {
        BigInt::from_biguint(Plus, self.data.gcd(&other.data))
    }
    
    #[inline]
    fn lcm(&self, other: &BigInt) -> BigInt {
        BigInt::from_biguint(Plus, self.data.lcm(&other.data))
    }
    
    #[inline]
    fn divides(&self, other: &BigInt) -> bool {
        return self.is_multiple_of(other);
    }
    
    #[inline]
    fn is_multiple_of(&self, other: &BigInt) -> bool {
        self.data.is_multiple_of(&other.data)
    }
    
    #[inline]
    fn is_even(&self) -> bool {
        self.data.is_even()
    }
    
    #[inline]
    fn is_odd(&self) -> bool {
        self.data.is_odd()
    }
}
impl ToPrimitive for BigInt {
    #[inline]
    fn to_i64(&self) -> Option<i64> {
        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<u64> {
        match self.sign {
            Plus => self.data.to_u64(),
            NoSign => Some(0),
            Minus => None,
        }
    }
    #[inline]
    fn to_f32(&self) -> Option<f32> {
        self.data.to_f32().map(|n| {
            if self.sign == Minus {
                -n
            } else {
                n
            }
        })
    }
    #[inline]
    fn to_f64(&self) -> Option<f64> {
        self.data.to_f64().map(|n| {
            if self.sign == Minus {
                -n
            } else {
                n
            }
        })
    }
}
impl FromPrimitive for BigInt {
    #[inline]
    fn from_i64(n: i64) -> Option<BigInt> {
        Some(BigInt::from(n))
    }
    #[inline]
    fn from_u64(n: u64) -> Option<BigInt> {
        Some(BigInt::from(n))
    }
    #[inline]
    fn from_f64(n: f64) -> Option<BigInt> {
        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<i64> 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<u64> 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<BigUint> 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<S>(&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<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: serde::Deserializer
    {
        let (sign, data) = try!(serde::Deserialize::deserialize(deserializer));
        Ok(BigInt {
            sign: sign,
            data: data,
        })
    }
}
pub trait ToBigInt {
    
    fn to_bigint(&self) -> Option<BigInt>;
}
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 biguint::ToBigUint for BigInt {
    #[inline]
    fn to_biguint(&self) -> Option<BigUint> {
        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<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!(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 {
    
    fn gen_biguint(&mut self, bit_size: usize) -> BigUint;
    
    fn gen_bigint(&mut self, bit_size: usize) -> BigInt;
    
    
    fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
    
    
    
    fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
    
    
    
    fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
}
#[cfg(any(feature = "rand", test))]
impl<R: Rng> 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 {
        
        let biguint = self.gen_biguint(bit_size);
        
        let sign = if biguint.is_zero() {
            
            
            
            
            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 {
    
    
    
    #[inline]
    pub fn new(sign: Sign, digits: Vec<BigDigit>) -> BigInt {
        BigInt::from_biguint(sign, BigUint::new(digits))
    }
    
    
    
    #[inline]
    pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt {
        if sign == NoSign {
            data.assign_from_slice(&[]);
        } else if data.is_zero() {
            sign = NoSign;
        }
        BigInt {
            sign: sign,
            data: data,
        }
    }
    
    #[inline]
    pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
        BigInt::from_biguint(sign, BigUint::from_slice(slice))
    }
    
    #[inline]
    pub fn assign_from_slice(&mut self, sign: Sign, slice: &[BigDigit]) {
        if sign == NoSign {
            self.data.assign_from_slice(&[]);
            self.sign = NoSign;
        } else {
            self.data.assign_from_slice(slice);
            self.sign = match self.data.is_zero() {
                true => NoSign,
                false => sign,
            }
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> BigInt {
        BigInt::from_biguint(sign, BigUint::from_bytes_be(bytes))
    }
    
    
    
    #[inline]
    pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> BigInt {
        BigInt::from_biguint(sign, BigUint::from_bytes_le(bytes))
    }
    
    
    
    
    #[inline]
    pub 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 {
            
            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 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 {
            
            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 fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigInt> {
        str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok())
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option<BigInt> {
        BigUint::from_radix_be(buf, radix).map(|u| BigInt::from_biguint(sign, u))
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option<BigInt> {
        BigUint::from_radix_le(buf, radix).map(|u| BigInt::from_biguint(sign, u))
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_bytes_be(&self) -> (Sign, Vec<u8>) {
        (self.sign, self.data.to_bytes_be())
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
        (self.sign, self.data.to_bytes_le())
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_signed_bytes_be(&self) -> Vec<u8> {
        let mut bytes = self.data.to_bytes_be();
        let first_byte = bytes.first().map(|v| *v).unwrap_or(0);
        if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero)) {
            
            bytes.insert(0, 0);
        }
        if self.sign == Sign::Minus {
            twos_complement_be(&mut bytes);
        }
        bytes
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_signed_bytes_le(&self) -> Vec<u8> {
        let mut bytes = self.data.to_bytes_le();
        let last_byte = bytes.last().map(|v| *v).unwrap_or(0);
        if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero)) {
            
            bytes.push(0);
        }
        if self.sign == Sign::Minus {
            twos_complement_le(&mut bytes);
        }
        bytes
    }
    
    
    
    
    
    
    
    
    
    
    
    #[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) }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_radix_be(&self, radix: u32) -> (Sign, Vec<u8>) {
        (self.sign, self.data.to_radix_be(radix))
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn to_radix_le(&self, radix: u32) -> (Sign, Vec<u8>) {
        (self.sign, self.data.to_radix_le(radix))
    }
    
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn sign(&self) -> Sign {
        self.sign
    }
    
    
    #[inline]
    pub fn bits(&self) -> usize {
        self.data.bits()
    }
    
    #[inline]
    pub fn to_biguint(&self) -> Option<BigUint> {
        match self.sign {
            Plus => Some(self.data.clone()),
            NoSign => Some(Zero::zero()),
            Minus => None,
        }
    }
    #[inline]
    pub fn checked_add(&self, v: &BigInt) -> Option<BigInt> {
        return Some(self.add(v));
    }
    #[inline]
    pub fn checked_sub(&self, v: &BigInt) -> Option<BigInt> {
        return Some(self.sub(v));
    }
    #[inline]
    pub fn checked_mul(&self, v: &BigInt) -> Option<BigInt> {
        return Some(self.mul(v));
    }
    #[inline]
    pub fn checked_div(&self, v: &BigInt) -> Option<BigInt> {
        if v.is_zero() {
            return None;
        }
        return Some(self.div(v));
    }
}
#[inline]
fn twos_complement_le(digits: &mut [u8]) {
    twos_complement(digits)
}
#[inline]
fn twos_complement_be(digits: &mut [u8]) {
    twos_complement(digits.iter_mut().rev())
}
#[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.not();
        if carry {
            *d = d.wrapping_add(1);
            carry = d.is_zero();
        }
    }
}