#![allow(clippy::suspicious_arithmetic_impl)]
use crate::std_alloc::{String, Vec};
use core::cmp::Ordering::{self, Equal};
use core::default::Default;
use core::fmt;
use core::hash;
use core::ops::{Neg, Not};
use core::str;
use core::{i128, u128};
use core::{i64, u64};
use num_integer::{Integer, Roots};
use num_traits::{Num, One, Pow, Signed, Zero};
use self::Sign::{Minus, NoSign, Plus};
use crate::big_digit::BigDigit;
use crate::biguint::to_str_radix_reversed;
use crate::biguint::{BigUint, IntDigits, U32Digits, U64Digits};
mod addition;
mod division;
mod multiplication;
mod subtraction;
mod bits;
mod convert;
mod power;
mod shift;
#[cfg(any(feature = "quickcheck", feature = "arbitrary"))]
mod arbitrary;
#[cfg(feature = "serde")]
mod serde;
#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)]
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,
}
}
}
#[derive(Debug)]
pub struct BigInt {
sign: Sign,
data: BigUint,
}
impl Clone for BigInt {
#[inline]
fn clone(&self) -> Self {
BigInt {
sign: self.sign,
data: self.data.clone(),
}
}
#[inline]
fn clone_from(&mut self, other: &Self) {
self.sign = other.sign;
self.data.clone_from(&other.data);
}
}
impl hash::Hash for BigInt {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
debug_assert!((self.sign != NoSign) ^ self.data.is_zero());
self.sign.hash(state);
if self.sign != NoSign {
self.data.hash(state);
}
}
}
impl PartialEq for BigInt {
#[inline]
fn eq(&self, other: &BigInt) -> bool {
debug_assert!((self.sign != NoSign) ^ self.data.is_zero());
debug_assert!((other.sign != NoSign) ^ other.data.is_zero());
self.sign == other.sign && (self.sign == NoSign || self.data == other.data)
}
}
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 {
debug_assert!((self.sign != NoSign) ^ self.data.is_zero());
debug_assert!((other.sign != NoSign) ^ other.data.is_zero());
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 {
let mut s = self.data.to_str_radix(16);
s.make_ascii_uppercase();
f.pad_integral(!self.is_negative(), "0x", &s)
}
}
impl Not for BigInt {
type Output = BigInt;
fn not(mut self) -> BigInt {
match self.sign {
NoSign | Plus => {
self.data += 1u32;
self.sign = Minus;
}
Minus => {
self.data -= 1u32;
self.sign = if self.data.is_zero() { NoSign } else { Plus };
}
}
self
}
}
impl<'a> Not for &'a BigInt {
type Output = BigInt;
fn not(self) -> BigInt {
match self.sign {
NoSign => -BigInt::one(),
Plus => -BigInt::from(&self.data + 1u32),
Minus => BigInt::from(&self.data - 1u32),
}
}
}
impl Zero for BigInt {
#[inline]
fn zero() -> BigInt {
BigInt {
sign: NoSign,
data: BigUint::zero(),
}
}
#[inline]
fn set_zero(&mut self) {
self.data.set_zero();
self.sign = NoSign;
}
#[inline]
fn is_zero(&self) -> bool {
self.sign == NoSign
}
}
impl One for BigInt {
#[inline]
fn one() -> BigInt {
BigInt {
sign: Plus,
data: BigUint::one(),
}
}
#[inline]
fn set_one(&mut self) {
self.data.set_one();
self.sign = Plus;
}
#[inline]
fn is_one(&self) -> bool {
self.sign == Plus && self.data.is_one()
}
}
impl Signed for BigInt {
#[inline]
fn abs(&self) -> BigInt {
match self.sign {
Plus | NoSign => self.clone(),
Minus => BigInt::from(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::one(),
Minus => -BigInt::one(),
NoSign => BigInt::zero(),
}
}
#[inline]
fn is_positive(&self) -> bool {
self.sign == Plus
}
#[inline]
fn is_negative(&self) -> bool {
self.sign == Minus
}
}
trait UnsignedAbs {
type Unsigned;
fn uabs(self) -> Self::Unsigned;
fn checked_uabs(self) -> CheckedUnsignedAbs<Self::Unsigned>;
}
enum CheckedUnsignedAbs<T> {
Positive(T),
Negative(T),
}
use self::CheckedUnsignedAbs::{Negative, Positive};
macro_rules! impl_unsigned_abs {
($Signed:ty, $Unsigned:ty) => {
impl UnsignedAbs for $Signed {
type Unsigned = $Unsigned;
#[inline]
fn uabs(self) -> $Unsigned {
self.wrapping_abs() as $Unsigned
}
#[inline]
fn checked_uabs(self) -> CheckedUnsignedAbs<Self::Unsigned> {
if self >= 0 {
Positive(self as $Unsigned)
} else {
Negative(self.wrapping_neg() as $Unsigned)
}
}
}
};
}
impl_unsigned_abs!(i8, u8);
impl_unsigned_abs!(i16, u16);
impl_unsigned_abs!(i32, u32);
impl_unsigned_abs!(i64, u64);
impl_unsigned_abs!(i128, u128);
impl_unsigned_abs!(isize, usize);
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 Integer for BigInt {
#[inline]
fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
let (d_ui, r_ui) = self.data.div_rem(&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_ui, m) = self.data.div_mod_floor(&other.data);
let d = BigInt::from(d_ui);
match (self.sign, other.sign) {
(Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => d,
(Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => {
if m.is_zero() {
-d
} else {
-d - 1u32
}
}
(_, NoSign) => unreachable!(),
}
}
#[inline]
fn mod_floor(&self, other: &BigInt) -> BigInt {
let m_ui = self.data.mod_floor(&other.data);
let m = BigInt::from_biguint(other.sign, m_ui);
match (self.sign, other.sign) {
(Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => m,
(Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => {
if m.is_zero() {
m
} else {
other - m
}
}
(_, NoSign) => unreachable!(),
}
}
fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
let (d_ui, m_ui) = self.data.div_mod_floor(&other.data);
let d = BigInt::from(d_ui);
let m = BigInt::from_biguint(other.sign, m_ui);
match (self.sign, other.sign) {
(Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => (d, m),
(Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => {
if m.is_zero() {
(-d, m)
} else {
(-d - 1u32, other - m)
}
}
(_, NoSign) => unreachable!(),
}
}
#[inline]
fn div_ceil(&self, other: &Self) -> Self {
let (d_ui, m) = self.data.div_mod_floor(&other.data);
let d = BigInt::from(d_ui);
match (self.sign, other.sign) {
(Plus, Minus) | (NoSign, Minus) | (Minus, Plus) => -d,
(Plus, Plus) | (NoSign, Plus) | (Minus, Minus) => {
if m.is_zero() {
d
} else {
d + 1u32
}
}
(_, NoSign) => unreachable!(),
}
}
#[inline]
fn gcd(&self, other: &BigInt) -> BigInt {
BigInt::from(self.data.gcd(&other.data))
}
#[inline]
fn lcm(&self, other: &BigInt) -> BigInt {
BigInt::from(self.data.lcm(&other.data))
}
#[inline]
fn gcd_lcm(&self, other: &BigInt) -> (BigInt, BigInt) {
let (gcd, lcm) = self.data.gcd_lcm(&other.data);
(BigInt::from(gcd), BigInt::from(lcm))
}
#[inline]
fn extended_gcd_lcm(&self, other: &BigInt) -> (num_integer::ExtendedGcd<BigInt>, BigInt) {
let egcd = self.extended_gcd(other);
let lcm = if egcd.gcd.is_zero() {
BigInt::zero()
} else {
BigInt::from(&self.data / &egcd.gcd.data * &other.data)
};
(egcd, lcm)
}
#[inline]
fn divides(&self, other: &BigInt) -> bool {
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()
}
#[inline]
fn next_multiple_of(&self, other: &Self) -> Self {
let m = self.mod_floor(other);
if m.is_zero() {
self.clone()
} else {
self + (other - m)
}
}
#[inline]
fn prev_multiple_of(&self, other: &Self) -> Self {
self - self.mod_floor(other)
}
}
impl Roots for BigInt {
fn nth_root(&self, n: u32) -> Self {
assert!(
!(self.is_negative() && n.is_even()),
"root of degree {} is imaginary",
n
);
BigInt::from_biguint(self.sign, self.data.nth_root(n))
}
fn sqrt(&self) -> Self {
assert!(!self.is_negative(), "square root is imaginary");
BigInt::from_biguint(self.sign, self.data.sqrt())
}
fn cbrt(&self) -> Self {
BigInt::from_biguint(self.sign, self.data.cbrt())
}
}
impl IntDigits for BigInt {
#[inline]
fn digits(&self) -> &[BigDigit] {
self.data.digits()
}
#[inline]
fn digits_mut(&mut self) -> &mut Vec<BigDigit> {
self.data.digits_mut()
}
#[inline]
fn normalize(&mut self) {
self.data.normalize();
if self.data.is_zero() {
self.sign = NoSign;
}
}
#[inline]
fn capacity(&self) -> usize {
self.data.capacity()
}
#[inline]
fn len(&self) -> usize {
self.data.len()
}
}
pub trait ToBigInt {
fn to_bigint(&self) -> Option<BigInt>;
}
impl BigInt {
#[inline]
pub fn new(sign: Sign, digits: Vec<u32>) -> 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, data }
}
#[inline]
pub fn from_slice(sign: Sign, slice: &[u32]) -> BigInt {
BigInt::from_biguint(sign, BigUint::from_slice(slice))
}
#[inline]
pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) {
if sign == NoSign {
self.set_zero();
} else {
self.data.assign_from_slice(slice);
self.sign = if self.data.is_zero() { NoSign } else { 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 {
convert::from_signed_bytes_be(digits)
}
#[inline]
pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt {
convert::from_signed_bytes_le(digits)
}
#[inline]
pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<BigInt> {
let s = str::from_utf8(buf).ok()?;
BigInt::from_str_radix(s, radix).ok()
}
pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option<BigInt> {
let u = BigUint::from_radix_be(buf, radix)?;
Some(BigInt::from_biguint(sign, u))
}
pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option<BigInt> {
let u = BigUint::from_radix_le(buf, radix)?;
Some(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_u32_digits(&self) -> (Sign, Vec<u32>) {
(self.sign, self.data.to_u32_digits())
}
#[inline]
pub fn to_u64_digits(&self) -> (Sign, Vec<u64>) {
(self.sign, self.data.to_u64_digits())
}
#[inline]
pub fn iter_u32_digits(&self) -> U32Digits<'_> {
self.data.iter_u32_digits()
}
#[inline]
pub fn iter_u64_digits(&self) -> U64Digits<'_> {
self.data.iter_u64_digits()
}
#[inline]
pub fn to_signed_bytes_be(&self) -> Vec<u8> {
convert::to_signed_bytes_be(self)
}
#[inline]
pub fn to_signed_bytes_le(&self) -> Vec<u8> {
convert::to_signed_bytes_le(self)
}
#[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 magnitude(&self) -> &BigUint {
&self.data
}
#[inline]
pub fn into_parts(self) -> (Sign, BigUint) {
(self.sign, self.data)
}
#[inline]
pub fn bits(&self) -> u64 {
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> {
Some(self + v)
}
#[inline]
pub fn checked_sub(&self, v: &BigInt) -> Option<BigInt> {
Some(self - v)
}
#[inline]
pub fn checked_mul(&self, v: &BigInt) -> Option<BigInt> {
Some(self * v)
}
#[inline]
pub fn checked_div(&self, v: &BigInt) -> Option<BigInt> {
if v.is_zero() {
return None;
}
Some(self / v)
}
pub fn pow(&self, exponent: u32) -> Self {
Pow::pow(self, exponent)
}
pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
power::modpow(self, exponent, modulus)
}
pub fn sqrt(&self) -> Self {
Roots::sqrt(self)
}
pub fn cbrt(&self) -> Self {
Roots::cbrt(self)
}
pub fn nth_root(&self, n: u32) -> Self {
Roots::nth_root(self, n)
}
pub fn trailing_zeros(&self) -> Option<u64> {
self.data.trailing_zeros()
}
pub fn bit(&self, bit: u64) -> bool {
if self.is_negative() {
if bit >= u64::from(crate::big_digit::BITS) * self.len() as u64 {
true
} else {
let trailing_zeros = self.data.trailing_zeros().unwrap();
match Ord::cmp(&bit, &trailing_zeros) {
Ordering::Less => false,
Ordering::Equal => true,
Ordering::Greater => !self.data.bit(bit),
}
}
} else {
self.data.bit(bit)
}
}
pub fn set_bit(&mut self, bit: u64, value: bool) {
match self.sign {
Sign::Plus => self.data.set_bit(bit, value),
Sign::Minus => bits::set_negative_bit(self, bit, value),
Sign::NoSign => {
if value {
self.data.set_bit(bit, true);
self.sign = Sign::Plus;
} else {
}
}
}
self.normalize();
}
}
#[test]
fn test_from_biguint() {
fn check(inp_s: Sign, inp_n: usize, ans_s: Sign, ans_n: usize) {
let inp = BigInt::from_biguint(inp_s, BigUint::from(inp_n));
let ans = BigInt {
sign: ans_s,
data: BigUint::from(ans_n),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test]
fn test_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let inp = BigInt::from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: BigUint::from(ans_n),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}
#[test]
fn test_assign_from_slice() {
fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) {
let mut inp = BigInt::from_slice(Minus, &[2627_u32, 0_u32, 9182_u32, 42_u32]);
inp.assign_from_slice(inp_s, &[inp_n]);
let ans = BigInt {
sign: ans_s,
data: BigUint::from(ans_n),
};
assert_eq!(inp, ans);
}
check(Plus, 1, Plus, 1);
check(Plus, 0, NoSign, 0);
check(Minus, 1, Minus, 1);
check(NoSign, 1, NoSign, 0);
}