use alloc::string::String; use alloc::vec::Vec; use core::cmp; use core::cmp::Ordering; use core::default::Default; use core::fmt; use core::hash; use core::mem; use core::str;
use num_integer::{Integer, Roots}; use num_traits::{ConstZero, Num, One, Pow, ToPrimitive, Unsigned, Zero};
mod addition; mod division; mod multiplication; mod subtraction;
mod arbitrary; mod bits; mod convert; mod iter; mod monty; mod power; mod serde; mod shift;
#[inline] fn div_ceil(&self, other: &BigUint) -> BigUint { let (d, m) = division::div_rem_ref(self, other); if m.is_zero() {
d
} else {
d + 1u32
}
}
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. /// /// The result is always positive. #[inline] fn gcd(&self, other: &Self) -> Self { #[inline] fn twos(x: &BigUint) -> u64 {
x.trailing_zeros().unwrap_or(0)
}
// Stein's algorithm ifself.is_zero() { return other.clone();
} if other.is_zero() { returnself.clone();
} letmut m = self.clone(); letmut n = other.clone();
// find common factors of 2 let shift = cmp::min(twos(&n), twos(&m));
// divide m and n by 2 until odd // m inside loop
n >>= twos(&n);
while !m.is_zero() {
m >>= twos(&m); if n > m {
mem::swap(&mut n, &mut m)
}
m -= &n;
}
n << shift
}
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] fn lcm(&self, other: &BigUint) -> BigUint { ifself.is_zero() && other.is_zero() { Self::ZERO
} else { self / self.gcd(other) * other
}
}
/// Calculates the Greatest Common Divisor (GCD) and /// Lowest Common Multiple (LCM) together. #[inline] fn gcd_lcm(&self, other: &Self) -> (Self, Self) { let gcd = self.gcd(other); let lcm = if gcd.is_zero() { Self::ZERO
} else { self / &gcd * other
};
(gcd, lcm)
}
/// Returns `true` if the number is a multiple of `other`. #[inline] fn is_multiple_of(&self, other: &BigUint) -> bool { if other.is_zero() { returnself.is_zero();
}
(self % other).is_zero()
}
/// Returns `true` if the number is divisible by `2`. #[inline] fn is_even(&self) -> bool { // Considering only the last digit. matchself.data.first() {
Some(x) => x.is_even(),
None => true,
}
}
/// Returns `true` if the number is not divisible by `2`. #[inline] fn is_odd(&self) -> bool {
!self.is_even()
}
/// Rounds up to nearest multiple of argument. #[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)
}
} /// Rounds down to nearest multiple of argument. #[inline] fn prev_multiple_of(&self, other: &Self) -> Self { self - self.mod_floor(other)
}
// If the value increased, then the initial guess must have been low. // Repeat until we reverse course. while x < xn { // Sometimes an increase will go way too far, especially with large // powers, and then take a long time to walk back. We know an upper // bound based on bit size, so saturate on that.
x = if xn.bits() > max_bits {
BigUint::one() << max_bits
} else {
xn
};
xn = f(&x);
}
// Now keep repeating while the estimate is decreasing. while x > xn {
x = xn;
xn = f(&x);
}
x
}
impl Roots for BigUint { // nth_root, sqrt and cbrt use Newton's method to compute // principal root of a given degree for a given integer.
// Reference: // Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.14 fn nth_root(&self, n: u32) -> Self {
assert!(n > 0, "root degree n must be at least 1");
match n { // Optimize for small n 1 => returnself.clone(), 2 => returnself.sqrt(), 3 => returnself.cbrt(),
_ => (),
}
// The root of non-zero values less than 2ⁿ can only be 1. let bits = self.bits(); let n64 = u64::from(n); if bits <= n64 { return BigUint::one();
}
// If we fit in `u64`, compute the root that way. iflet Some(x) = self.to_u64() { return x.nth_root(n).into();
}
let max_bits = bits / n64 + 1;
#[cfg(feature = "std")] let guess = matchself.to_f64() {
Some(f) if f.is_finite() => { use num_traits::FromPrimitive;
// We fit in `f64` (lossy), so get a better initial guess from that.
BigUint::from_f64((f.ln() / f64::from(n)).exp()).unwrap()
}
_ => { // Try to guess by scaling down such that it does fit in `f64`. // With some (x * 2ⁿᵏ), its nth root ≈ (ⁿ√x * 2ᵏ) let extra_bits = bits - (f64::MAX_EXP as u64 - 1); let root_scale = Integer::div_ceil(&extra_bits, &n64); let scale = root_scale * n64; if scale < bits && bits - scale > n64 {
(self >> scale).nth_root(n) << root_scale
} else {
BigUint::one() << max_bits
}
}
};
#[cfg(not(feature = "std"))] let guess = BigUint::one() << max_bits;
let n_min_1 = n - 1;
fixpoint(guess, max_bits, move |s| { let q = self / s.pow(n_min_1); let t = n_min_1 * s + q;
t / n
})
}
// If we fit in `u64`, compute the root that way. iflet Some(x) = self.to_u64() { return x.sqrt().into();
}
let bits = self.bits(); let max_bits = bits / 2 + 1;
#[cfg(feature = "std")] let guess = matchself.to_f64() {
Some(f) if f.is_finite() => { use num_traits::FromPrimitive;
// We fit in `f64` (lossy), so get a better initial guess from that.
BigUint::from_f64(f.sqrt()).unwrap()
}
_ => { // Try to guess by scaling down such that it does fit in `f64`. // With some (x * 2²ᵏ), its sqrt ≈ (√x * 2ᵏ) let extra_bits = bits - (f64::MAX_EXP as u64 - 1); let root_scale = (extra_bits + 1) / 2; let scale = root_scale * 2;
(self >> scale).sqrt() << root_scale
}
};
#[cfg(not(feature = "std"))] let guess = BigUint::one() << max_bits;
fixpoint(guess, max_bits, move |s| { let q = self / s; let t = s + q;
t >> 1
})
}
// If we fit in `u64`, compute the root that way. iflet Some(x) = self.to_u64() { return x.cbrt().into();
}
let bits = self.bits(); let max_bits = bits / 3 + 1;
#[cfg(feature = "std")] let guess = matchself.to_f64() {
Some(f) if f.is_finite() => { use num_traits::FromPrimitive;
// We fit in `f64` (lossy), so get a better initial guess from that.
BigUint::from_f64(f.cbrt()).unwrap()
}
_ => { // Try to guess by scaling down such that it does fit in `f64`. // With some (x * 2³ᵏ), its cbrt ≈ (∛x * 2ᵏ) let extra_bits = bits - (f64::MAX_EXP as u64 - 1); let root_scale = (extra_bits + 2) / 3; let scale = root_scale * 3;
(self >> scale).cbrt() << root_scale
}
};
#[cfg(not(feature = "std"))] let guess = BigUint::one() << max_bits;
fixpoint(guess, max_bits, move |s| { let q = self / (s * s); let t = (s << 1) + q;
t / 3u32
})
}
}
/// A generic trait for converting a value to a [`BigUint`]. pubtrait ToBigUint { /// Converts the value of `self` to a [`BigUint`]. fn to_biguint(&self) -> Option<BigUint>;
}
/// Creates and initializes a [`BigUint`]. /// /// The digits are in little-endian base matching `BigDigit`. #[inline] pub(crate) fn biguint_from_vec(digits: Vec<BigDigit>) -> BigUint {
BigUint { data: digits }.normalized()
}
impl BigUint { /// A constant `BigUint` with value 0, useful for static initialization. pubconst ZERO: Self = BigUint { data: Vec::new() };
/// Creates and initializes a [`BigUint`]. /// /// The base 2<sup>32</sup> digits are ordered least significant digit first. #[inline] pubfn new(digits: Vec<u32>) -> BigUint { letmut big = Self::ZERO;
/// Creates and initializes a [`BigUint`]. /// /// The base 2<sup>32</sup> digits are ordered least significant digit first. #[inline] pubfn from_slice(slice: &[u32]) -> BigUint { letmut big = Self::ZERO;
big.assign_from_slice(slice);
big
}
/// Assign a value to a [`BigUint`]. /// /// The base 2<sup>32</sup> digits are ordered least significant digit first. #[inline] pubfn assign_from_slice(&mutself, slice: &[u32]) { self.data.clear();
/// Creates and initializes a [`BigUint`]. /// /// The bytes are in big-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// assert_eq!(BigUint::from_bytes_be(b"A"), /// BigUint::parse_bytes(b"65", 10).unwrap()); /// assert_eq!(BigUint::from_bytes_be(b"AA"), /// BigUint::parse_bytes(b"16705", 10).unwrap()); /// assert_eq!(BigUint::from_bytes_be(b"AB"), /// BigUint::parse_bytes(b"16706", 10).unwrap()); /// assert_eq!(BigUint::from_bytes_be(b"Hello world!"), /// BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); /// ``` #[inline] pubfn from_bytes_be(bytes: &[u8]) -> BigUint { if bytes.is_empty() { Self::ZERO
} else { letmut v = bytes.to_vec();
v.reverse();
BigUint::from_bytes_le(&v)
}
}
/// Creates and initializes a [`BigUint`]. /// /// The bytes are in little-endian byte order. #[inline] pubfn from_bytes_le(bytes: &[u8]) -> BigUint { if bytes.is_empty() { Self::ZERO
} else {
convert::from_bitwise_digits_le(bytes, 8)
}
}
/// Creates and initializes a [`BigUint`]. The input slice must contain /// ascii/utf8 characters in [0-9a-zA-Z]. /// `radix` must be in the range `2...36`. /// /// The function `from_str_radix` from the `Num` trait provides the same logic /// for `&str` buffers. /// /// # Examples /// /// ``` /// use num_bigint::{BigUint, ToBigUint}; /// /// assert_eq!(BigUint::parse_bytes(b"1234", 10), ToBigUint::to_biguint(&1234)); /// assert_eq!(BigUint::parse_bytes(b"ABCD", 16), ToBigUint::to_biguint(&0xABCD)); /// assert_eq!(BigUint::parse_bytes(b"G", 16), None); /// ``` #[inline] pubfn parse_bytes(buf: &[u8], radix: u32) -> Option<BigUint> { let s = str::from_utf8(buf).ok()?;
BigUint::from_str_radix(s, radix).ok()
}
/// Creates and initializes a [`BigUint`]. Each `u8` of the input slice is /// interpreted as one digit of the number /// and must therefore be less than `radix`. /// /// The bytes are in big-endian byte order. /// `radix` must be in the range `2...256`. /// /// # Examples /// /// ``` /// use num_bigint::{BigUint}; /// /// let inbase190 = &[15, 33, 125, 12, 14]; /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); /// assert_eq!(a.to_radix_be(190), inbase190); /// ``` pubfn from_radix_be(buf: &[u8], radix: u32) -> Option<BigUint> {
convert::from_radix_be(buf, radix)
}
/// Creates and initializes a [`BigUint`]. Each `u8` of the input slice is /// interpreted as one digit of the number /// and must therefore be less than `radix`. /// /// The bytes are in little-endian byte order. /// `radix` must be in the range `2...256`. /// /// # Examples /// /// ``` /// use num_bigint::{BigUint}; /// /// let inbase190 = &[14, 12, 125, 33, 15]; /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); /// assert_eq!(a.to_radix_be(190), inbase190); /// ``` pubfn from_radix_le(buf: &[u8], radix: u32) -> Option<BigUint> {
convert::from_radix_le(buf, radix)
}
/// Returns the byte representation of the [`BigUint`] in big-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); /// assert_eq!(i.to_bytes_be(), vec![4, 101]); /// ``` #[inline] pubfn to_bytes_be(&self) -> Vec<u8> { letmut v = self.to_bytes_le();
v.reverse();
v
}
/// Returns the byte representation of the [`BigUint`] in little-endian byte order. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); /// assert_eq!(i.to_bytes_le(), vec![101, 4]); /// ``` #[inline] pubfn to_bytes_le(&self) -> Vec<u8> { ifself.is_zero() {
vec![0]
} else {
convert::to_bitwise_digits_le(self, 8)
}
}
/// Returns the `u32` digits representation of the [`BigUint`] ordered least significant digit /// first. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// assert_eq!(BigUint::from(1125u32).to_u32_digits(), vec![1125]); /// assert_eq!(BigUint::from(4294967295u32).to_u32_digits(), vec![4294967295]); /// assert_eq!(BigUint::from(4294967296u64).to_u32_digits(), vec![0, 1]); /// assert_eq!(BigUint::from(112500000000u64).to_u32_digits(), vec![830850304, 26]); /// ``` #[inline] pubfn to_u32_digits(&self) -> Vec<u32> { self.iter_u32_digits().collect()
}
/// Returns an iterator of `u32` digits representation of the [`BigUint`] ordered least /// significant digit first. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// assert_eq!(BigUint::from(1125u32).iter_u32_digits().collect::<Vec<u32>>(), vec![1125]); /// assert_eq!(BigUint::from(4294967295u32).iter_u32_digits().collect::<Vec<u32>>(), vec![4294967295]); /// assert_eq!(BigUint::from(4294967296u64).iter_u32_digits().collect::<Vec<u32>>(), vec![0, 1]); /// assert_eq!(BigUint::from(112500000000u64).iter_u32_digits().collect::<Vec<u32>>(), vec![830850304, 26]); /// ``` #[inline] pubfn iter_u32_digits(&self) -> U32Digits<'_> {
U32Digits::new(self.data.as_slice())
}
/// Returns an iterator of `u64` digits representation of the [`BigUint`] ordered least /// significant digit first. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// assert_eq!(BigUint::from(1125u32).iter_u64_digits().collect::<Vec<u64>>(), vec![1125]); /// assert_eq!(BigUint::from(4294967295u32).iter_u64_digits().collect::<Vec<u64>>(), vec![4294967295]); /// assert_eq!(BigUint::from(4294967296u64).iter_u64_digits().collect::<Vec<u64>>(), vec![4294967296]); /// assert_eq!(BigUint::from(112500000000u64).iter_u64_digits().collect::<Vec<u64>>(), vec![112500000000]); /// assert_eq!(BigUint::from(1u128 << 64).iter_u64_digits().collect::<Vec<u64>>(), vec![0, 1]); /// ``` #[inline] pubfn iter_u64_digits(&self) -> U64Digits<'_> {
U64Digits::new(self.data.as_slice())
}
/// Returns the integer formatted as a string in the given radix. /// `radix` must be in the range `2...36`. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// let i = BigUint::parse_bytes(b"ff", 16).unwrap(); /// assert_eq!(i.to_str_radix(16), "ff"); /// ``` #[inline] pubfn to_str_radix(&self, radix: u32) -> String { letmut v = to_str_radix_reversed(self, radix);
v.reverse(); unsafe { String::from_utf8_unchecked(v) }
}
/// Returns the integer in the requested base in big-endian digit order. /// The output is not given in a human readable alphabet but as a zero /// based `u8` number. /// `radix` must be in the range `2...256`. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_be(159), /// vec![2, 94, 27]); /// // 0xFFFF = 65535 = 2*(159^2) + 94*159 + 27 /// ``` #[inline] pubfn to_radix_be(&self, radix: u32) -> Vec<u8> { letmut v = convert::to_radix_le(self, radix);
v.reverse();
v
}
/// Returns the integer in the requested base in little-endian digit order. /// The output is not given in a human readable alphabet but as a zero /// based u8 number. /// `radix` must be in the range `2...256`. /// /// # Examples /// /// ``` /// use num_bigint::BigUint; /// /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159), /// vec![27, 94, 2]); /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) /// ``` #[inline] pubfn to_radix_le(&self, radix: u32) -> Vec<u8> {
convert::to_radix_le(self, radix)
}
/// Determines the fewest bits necessary to express the [`BigUint`]. #[inline] pubfn bits(&self) -> u64 { ifself.is_zero() { return0;
} let zeros: u64 = self.data.last().unwrap().leading_zeros().into(); self.data.len() as u64 * u64::from(big_digit::BITS) - zeros
}
/// Strips off trailing zero bigdigits - comparisons require the last element in the vector to /// be nonzero. #[inline] fn normalize(&mutself) { iflet Some(&0) = self.data.last() { let len = self.data.iter().rposition(|&d| d != 0).map_or(0, |i| i + 1); self.data.truncate(len);
} ifself.data.len() < self.data.capacity() / 4 { self.data.shrink_to_fit();
}
}
/// Returns `(self ^ exponent) % modulus`. /// /// Panics if the modulus is zero. pubfn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
power::modpow(self, exponent, modulus)
}
/// Returns the modular multiplicative inverse if it exists, otherwise `None`. /// /// This solves for `x` in the interval `[0, modulus)` such that `self * x ≡ 1 (mod modulus)`. /// The solution exists if and only if `gcd(self, modulus) == 1`. /// /// ``` /// use num_bigint::BigUint; /// use num_traits::{One, Zero}; /// /// let m = BigUint::from(383_u32); /// /// // Trivial cases /// assert_eq!(BigUint::zero().modinv(&m), None); /// assert_eq!(BigUint::one().modinv(&m), Some(BigUint::one())); /// let neg1 = &m - 1u32; /// assert_eq!(neg1.modinv(&m), Some(neg1)); /// /// let a = BigUint::from(271_u32); /// let x = a.modinv(&m).unwrap(); /// assert_eq!(x, BigUint::from(106_u32)); /// assert_eq!(x.modinv(&m).unwrap(), a); /// assert!((a * x % m).is_one()); /// ``` pubfn modinv(&self, modulus: &Self) -> Option<Self> { // Based on the inverse pseudocode listed here: // https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers // TODO: consider Binary or Lehmer's GCD algorithms for optimization.
assert!(
!modulus.is_zero(), "attempt to calculate with zero modulus!"
); if modulus.is_one() { return Some(Self::zero());
}
/// Returns the number of least-significant bits that are zero, /// or `None` if the entire number is zero. pubfn trailing_zeros(&self) -> Option<u64> { let i = self.data.iter().position(|&digit| digit != 0)?; let zeros: u64 = self.data[i].trailing_zeros().into();
Some(i as u64 * u64::from(big_digit::BITS) + zeros)
}
/// Returns the number of least-significant bits that are ones. pubfn trailing_ones(&self) -> u64 { iflet Some(i) = self.data.iter().position(|&digit| !digit != 0) { let ones: u64 = self.data[i].trailing_ones().into();
i as u64 * u64::from(big_digit::BITS) + ones
} else { self.data.len() as u64 * u64::from(big_digit::BITS)
}
}
/// Returns the number of one bits. pubfn count_ones(&self) -> u64 { self.data.iter().map(|&d| u64::from(d.count_ones())).sum()
}
/// Returns whether the bit in the given position is set pubfn bit(&self, bit: u64) -> bool { let bits_per_digit = u64::from(big_digit::BITS); iflet Some(digit_index) = (bit / bits_per_digit).to_usize() { iflet Some(digit) = self.data.get(digit_index) { let bit_mask = (1as BigDigit) << (bit % bits_per_digit); return (digit & bit_mask) != 0;
}
} false
}
/// Sets or clears the bit in the given position /// /// Note that setting a bit greater than the current bit length, a reallocation may be needed /// to store the new digits pubfn set_bit(&mutself, bit: u64, value: bool) { // Note: we're saturating `digit_index` and `new_len` -- any such case is guaranteed to // fail allocation, and that's more consistent than adding our own overflow panics. let bits_per_digit = u64::from(big_digit::BITS); let digit_index = (bit / bits_per_digit).to_usize().unwrap_or(usize::MAX); let bit_mask = (1as BigDigit) << (bit % bits_per_digit); if value { if digit_index >= self.data.len() { let new_len = digit_index.saturating_add(1); self.data.resize(new_len, 0);
} self.data[digit_index] |= bit_mask;
} elseif digit_index < self.data.len() { self.data[digit_index] &= !bit_mask; // the top bit may have been cleared, so normalize self.normalize();
}
}
}
impl num_traits::FromBytes for BigUint { type Bytes = [u8];
/// Convert a `u32` chunk (len is either 1 or 2) to a single `u64` digit #[inline] fn u32_chunk_to_u64(chunk: &[u32]) -> u64 { // raw could have odd length letmut digit = chunk[0] as u64; iflet Some(&hi) = chunk.get(1) {
digit |= (hi as u64) << 32;
}
digit
}
cfg_32_or_test!( /// Combine four `u32`s into a single `u128`. #[inline] fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 {
u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96)
}
);
cfg_32_or_test!( /// Split a single `u128` into four `u32`. #[inline] fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) {
(
(n >> 96) as u32,
(n >> 64) as u32,
(n >> 32) as u32,
n as u32,
)
}
);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.