use crate::ext::xmpz;
use crate::integer::arith::MulIncomplete;
use crate::integer::{BorrowInteger, Order};
use crate::misc;
use crate::ops::{DivRounding, NegAssign, SubFrom};
#[cfg(feature = "rand")]
use crate::rand::MutRandState;
#[cfg(feature = "rational")]
use crate::rational::BorrowRational;
use crate::{Assign, Complete};
use az::{Az, Cast, CheckedCast, UnwrappedAs, UnwrappedCast, WrappingCast};
use core::cmp::Ordering;
use core::ffi::{c_char, c_uint, c_ulong};
use core::fmt::{Display, Formatter, Result as FmtResult};
use core::mem;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
#[cfg(feature = "rational")]
use core::ptr::NonNull;
use core::slice;
use gmp_mpfr_sys::gmp;
#[cfg(feature = "rational")]
use gmp_mpfr_sys::gmp::mpq_t;
use gmp_mpfr_sys::gmp::{bitcnt_t, limb_t, mpz_t};
use std::error::Error;
#[repr(transparent)]
pub struct Integer {
inner: mpz_t,
}
impl Integer {
#[inline]
pub(crate) const fn inner(&self) -> &mpz_t {
&self.inner
}
#[inline]
pub(crate) unsafe fn inner_mut(&mut self) -> &mut mpz_t {
&mut self.inner
}
#[inline]
pub(crate) const fn inner_data(&self) -> &[limb_t] {
let limbs = self.inner.size.unsigned_abs();
let limbs_usize = limbs as usize;
if limbs != limbs_usize as c_uint {
panic!("overflow");
}
unsafe { slice::from_raw_parts(self.inner.d.as_ptr(), limbs_usize) }
}
}
static_assert_same_layout!(Integer, mpz_t);
static_assert_same_layout!(BorrowInteger<'_>, mpz_t);
static_assert_same_size!(Integer, Option<Integer>);
impl Integer {
pub const ZERO: Integer = Integer::new();
#[inline]
pub const fn new() -> Self {
Integer {
inner: xmpz::owned_init(),
}
}
#[inline]
pub fn with_capacity(bits: usize) -> Self {
unsafe {
let mut dst = MaybeUninit::uninit();
xmpz::init2(dst.as_mut_ptr(), bits);
dst.assume_init()
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner
.alloc
.unwrapped_as::<usize>()
.checked_mul(gmp::LIMB_BITS.az::<usize>())
.expect("overflow")
}
pub fn reserve(&mut self, additional: usize) {
let used_bits = xmpz::significant_bits(self);
let req_bits = used_bits.checked_add(additional).expect("overflow");
let alloc_bits = (self.inner.alloc.az::<usize>())
.checked_mul(gmp::LIMB_BITS.az::<usize>())
.expect("overflow");
if alloc_bits < req_bits {
unsafe {
gmp::mpz_realloc2(self.as_raw_mut(), req_bits.unwrapped_cast());
}
}
}
pub fn shrink_to_fit(&mut self) {
self.shrink_to(0);
}
pub fn shrink_to(&mut self, min_capacity: usize) {
let min_limbs = DivRounding::div_ceil(min_capacity, gmp::LIMB_BITS.az::<usize>());
if min_limbs >= self.inner.alloc.unwrapped_as::<usize>() {
return;
}
let used_limbs = self.inner.size.checked_abs().expect("overflow");
if min_limbs > used_limbs.unwrapped_as::<usize>() {
unsafe {
gmp::_mpz_realloc(self.as_raw_mut(), min_limbs.unwrapped_cast());
}
} else if self.inner.alloc > used_limbs {
if used_limbs == 0 {
*self = Integer::ZERO;
} else {
unsafe {
gmp::_mpz_realloc(self.as_raw_mut(), used_limbs.unwrapped_cast());
}
}
}
}
#[inline]
pub const unsafe fn from_raw(raw: mpz_t) -> Self {
Integer { inner: raw }
}
#[inline]
pub const fn into_raw(self) -> mpz_t {
let ret = self.inner;
let _ = ManuallyDrop::new(self);
ret
}
#[inline]
pub const fn as_raw(&self) -> *const mpz_t {
&self.inner
}
#[inline]
pub fn as_raw_mut(&mut self) -> *mut mpz_t {
&mut self.inner
}
pub fn from_digits<T: UnsignedPrimitive>(digits: &[T], order: Order) -> Self {
let capacity = digits.len().checked_mul(T::PRIVATE.bits).expect("overflow");
let mut i = Integer::with_capacity(capacity);
i.assign_digits(digits, order);
i
}
pub fn assign_digits<T: UnsignedPrimitive>(&mut self, digits: &[T], order: Order) {
unsafe {
self.assign_digits_unaligned(digits.as_ptr(), digits.len(), order);
}
}
pub unsafe fn assign_digits_unaligned<T: UnsignedPrimitive>(
&mut self,
src: *const T,
len: usize,
order: Order,
) {
let bytes = mem::size_of::<T>();
let nails = 8 * bytes - T::PRIVATE.bits;
let raw = self.as_raw_mut();
let (order, endian) = (order.order(), order.endian());
let src = src.cast();
unsafe {
gmp::mpz_import(raw, len, order, bytes, endian, nails, src);
}
}
#[inline]
pub fn significant_digits<T: UnsignedPrimitive>(&self) -> usize {
DivRounding::div_ceil(xmpz::significant_bits(self), T::PRIVATE.bits)
}
pub fn to_digits<T: UnsignedPrimitive>(&self, order: Order) -> Vec<T> {
let digit_count = self.significant_digits::<T>();
let mut v = Vec::<T>::with_capacity(digit_count);
unsafe {
let digits_ptr = v.as_mut_ptr();
let mut count = MaybeUninit::uninit();
gmp::mpz_export(
digits_ptr.cast(),
count.as_mut_ptr(),
order.order(),
T::PRIVATE.bytes,
order.endian(),
T::PRIVATE.nails,
self.as_raw(),
);
assert_eq!(count.assume_init(), digit_count);
v.set_len(digit_count);
}
v
}
pub fn write_digits<T: UnsignedPrimitive>(&self, digits: &mut [T], order: Order) {
unsafe {
self.write_digits_unaligned(digits.as_mut_ptr(), digits.len(), order);
}
}
pub unsafe fn write_digits_unaligned<T: UnsignedPrimitive>(
&self,
dst: *mut T,
len: usize,
order: Order,
) {
let digit_count = self.significant_digits::<T>();
let zero_count = len.checked_sub(digit_count).expect("not enough capacity");
let zero_bytes = zero_count * T::PRIVATE.bytes;
let (zeros, digits) = if order.order() < 0 {
let offset = digit_count.unwrapped_cast();
(unsafe { dst.offset(offset) }, dst)
} else {
let offset = zero_count.unwrapped_cast();
(dst, unsafe { dst.offset(offset) })
};
unsafe {
(zeros.cast::<u8>()).write_bytes(0, zero_bytes);
}
let mut count = MaybeUninit::uninit();
let digits = digits.cast();
let count_ptr = count.as_mut_ptr();
let (order, endian) = (order.order(), order.endian());
let raw = self.as_raw();
unsafe {
gmp::mpz_export(
digits,
count_ptr,
order,
T::PRIVATE.bytes,
endian,
T::PRIVATE.nails,
raw,
);
}
assert_eq!(unsafe { count.assume_init() }, digit_count);
}
pub const fn as_limbs(&self) -> &[limb_t] {
self.inner_data()
}
#[inline]
pub fn from_f32(value: f32) -> Option<Self> {
value.checked_cast()
}
#[inline]
pub fn from_f64(value: f64) -> Option<Self> {
value.checked_cast()
}
#[inline]
pub fn from_str_radix(src: &str, radix: i32) -> Result<Self, ParseIntegerError> {
Ok(Integer::from(Integer::parse_radix(src, radix)?))
}
#[inline]
pub fn parse<S: AsRef<[u8]>>(src: S) -> Result<ParseIncomplete, ParseIntegerError> {
parse(src.as_ref(), 10)
}
#[inline]
pub fn parse_radix<S: AsRef<[u8]>>(
src: S,
radix: i32,
) -> Result<ParseIncomplete, ParseIntegerError> {
parse(src.as_ref(), radix)
}
pub unsafe fn assign_bytes_radix_unchecked(
&mut self,
bytes: &[u8],
radix: i32,
is_negative: bool,
) {
if bytes.is_empty() {
xmpz::set_0(self);
return;
}
xmpz::realloc_for_mpn_set_str(self, bytes.len(), radix);
unsafe {
let size = gmp::mpn_set_str(self.inner.d.as_ptr(), bytes.as_ptr(), bytes.len(), radix);
self.inner.size = (if is_negative { -size } else { size }).unwrapped_cast();
}
}
#[inline]
pub fn to_i8(&self) -> Option<i8> {
self.checked_cast()
}
#[inline]
pub fn to_i16(&self) -> Option<i16> {
self.checked_cast()
}
#[inline]
pub fn to_i32(&self) -> Option<i32> {
self.checked_cast()
}
#[inline]
pub fn to_i64(&self) -> Option<i64> {
self.checked_cast()
}
#[inline]
pub fn to_i128(&self) -> Option<i128> {
self.checked_cast()
}
#[inline]
pub fn to_isize(&self) -> Option<isize> {
self.checked_cast()
}
#[inline]
pub fn to_u8(&self) -> Option<u8> {
self.checked_cast()
}
#[inline]
pub fn to_u16(&self) -> Option<u16> {
self.checked_cast()
}
#[inline]
pub fn to_u32(&self) -> Option<u32> {
self.checked_cast()
}
#[inline]
pub fn to_u64(&self) -> Option<u64> {
self.checked_cast()
}
#[inline]
pub fn to_u128(&self) -> Option<u128> {
self.checked_cast()
}
#[inline]
pub fn to_usize(&self) -> Option<usize> {
self.checked_cast()
}
#[inline]
pub fn to_i8_wrapping(&self) -> i8 {
self.wrapping_cast()
}
#[inline]
pub fn to_i16_wrapping(&self) -> i16 {
self.wrapping_cast()
}
#[inline]
pub fn to_i32_wrapping(&self) -> i32 {
self.wrapping_cast()
}
#[inline]
pub fn to_i64_wrapping(&self) -> i64 {
self.wrapping_cast()
}
#[inline]
pub fn to_i128_wrapping(&self) -> i128 {
self.wrapping_cast()
}
#[inline]
pub fn to_isize_wrapping(&self) -> isize {
self.wrapping_cast()
}
#[inline]
pub fn to_u8_wrapping(&self) -> u8 {
self.wrapping_cast()
}
#[inline]
pub fn to_u16_wrapping(&self) -> u16 {
self.wrapping_cast()
}
#[inline]
pub fn to_u32_wrapping(&self) -> u32 {
self.wrapping_cast()
}
#[inline]
pub fn to_u64_wrapping(&self) -> u64 {
self.wrapping_cast()
}
#[inline]
pub fn to_u128_wrapping(&self) -> u128 {
self.wrapping_cast()
}
#[inline]
pub fn to_usize_wrapping(&self) -> usize {
self.wrapping_cast()
}
#[inline]
pub fn to_f32(&self) -> f32 {
self.cast()
}
#[inline]
pub fn to_f64(&self) -> f64 {
self.cast()
}
#[inline]
pub fn to_f32_exp(&self) -> (f32, u32) {
let (f, exp) = self.to_f64_exp();
let trunc_f = misc::trunc_f64_to_f32(f);
(trunc_f, exp)
}
#[inline]
pub fn to_f64_exp(&self) -> (f64, u32) {
let (f, exp) = xmpz::get_f64_2exp(self);
(f, exp.unwrapped_cast())
}
#[inline]
pub fn to_string_radix(&self, radix: i32) -> String {
let mut s = String::new();
append_to_string(&mut s, self, radix, false);
s
}
#[inline]
#[allow(clippy::result_unit_err)]
pub fn assign_f32(&mut self, val: f32) -> Result<(), ()> {
self.assign_f64(val.into())
}
#[inline]
#[allow(clippy::result_unit_err)]
pub fn assign_f64(&mut self, val: f64) -> Result<(), ()> {
xmpz::set_f64(self, val)
}
pub const fn as_neg(&self) -> BorrowInteger<'_> {
let mut raw = self.inner;
raw.size = match raw.size.checked_neg() {
Some(s) => s,
None => panic!("overflow"),
};
unsafe { BorrowInteger::from_raw(raw) }
}
pub const fn as_abs(&self) -> BorrowInteger<'_> {
let mut raw = self.inner;
raw.size = match raw.size.checked_abs() {
Some(s) => s,
None => panic!("overflow"),
};
unsafe { BorrowInteger::from_raw(raw) }
}
#[cfg(feature = "rational")]
pub const fn as_rational(&self) -> BorrowRational<'_> {
const ONE: limb_t = 1;
let raw_rational = mpq_t {
num: self.inner,
den: mpz_t {
alloc: 1,
size: 1,
d: unsafe { NonNull::new_unchecked((&ONE as *const limb_t).cast_mut()) },
},
};
unsafe { BorrowRational::from_raw(raw_rational) }
}
#[inline]
pub const fn is_even(&self) -> bool {
xmpz::even_p(self)
}
#[inline]
pub const fn is_odd(&self) -> bool {
xmpz::odd_p(self)
}
#[inline]
pub fn is_divisible(&self, divisor: &Self) -> bool {
xmpz::divisible_p(self, divisor)
}
#[inline]
pub fn is_divisible_u(&self, divisor: u32) -> bool {
xmpz::divisible_ui_p(self, divisor.into())
}
#[inline]
pub fn is_divisible_2pow(&self, b: u32) -> bool {
xmpz::divisible_2exp_p(self, b.into())
}
#[inline]
pub fn is_congruent(&self, c: &Self, divisor: &Self) -> bool {
xmpz::congruent_p(self, c, divisor)
}
#[inline]
pub fn is_congruent_u(&self, c: u32, divisor: u32) -> bool {
xmpz::congruent_ui_p(self, c.into(), divisor.into())
}
#[inline]
pub fn is_congruent_2pow(&self, c: &Self, b: u32) -> bool {
xmpz::congruent_2exp_p(self, c, b.into())
}
#[inline]
pub fn is_perfect_power(&self) -> bool {
xmpz::perfect_power_p(self)
}
#[inline]
pub fn is_perfect_square(&self) -> bool {
xmpz::perfect_square_p(self)
}
#[inline]
pub fn is_power_of_two(&self) -> bool {
xmpz::power_of_two_p(self)
}
#[inline]
pub const fn cmp0(&self) -> Ordering {
xmpz::sgn(self)
}
#[inline]
pub fn cmp_abs(&self, other: &Self) -> Ordering {
xmpz::cmpabs(self, other)
}
#[inline]
pub fn significant_bits(&self) -> u32 {
xmpz::significant_bits(self).unwrapped_cast()
}
#[inline]
pub fn signed_bits(&self) -> u32 {
xmpz::signed_bits(self).unwrapped_cast()
}
#[inline]
pub fn count_ones(&self) -> Option<u32> {
xmpz::popcount(self).map(UnwrappedCast::unwrapped_cast)
}
#[inline]
pub fn count_zeros(&self) -> Option<u32> {
xmpz::zerocount(self).map(UnwrappedCast::unwrapped_cast)
}
#[inline]
#[doc(alias = "trailing_ones")]
pub fn find_zero(&self, start: u32) -> Option<u32> {
xmpz::scan0(self, start.into()).map(UnwrappedCast::unwrapped_cast)
}
#[inline]
#[doc(alias = "trailing_zeros")]
pub fn find_one(&self, start: u32) -> Option<u32> {
xmpz::scan1(self, start.into()).map(UnwrappedCast::unwrapped_cast)
}
#[inline]
pub fn set_bit(&mut self, index: u32, val: bool) -> &mut Self {
if val {
xmpz::setbit(self, index.into());
} else {
xmpz::clrbit(self, index.into());
}
self
}
#[inline]
pub fn get_bit(&self, index: u32) -> bool {
xmpz::tstbit(self, index.into())
}
#[inline]
pub fn toggle_bit(&mut self, index: u32) -> &mut Self {
xmpz::combit(self, index.into());
self
}
#[inline]
pub fn hamming_dist(&self, other: &Self) -> Option<u32> {
xmpz::hamdist(self, other).map(UnwrappedCast::unwrapped_cast)
}
#[inline]
pub fn sum<'a, I>(values: I) -> SumIncomplete<'a, I>
where
I: Iterator<Item = &'a Self>,
{
SumIncomplete { values }
}
#[inline]
pub fn dot<'a, I>(values: I) -> DotIncomplete<'a, I>
where
I: Iterator<Item = (&'a Self, &'a Self)>,
{
DotIncomplete { values }
}
#[inline]
pub fn product<'a, I>(values: I) -> ProductIncomplete<'a, I>
where
I: Iterator<Item = &'a Self>,
{
ProductIncomplete { values }
}
#[inline]
#[must_use]
pub fn abs(mut self) -> Self {
self.abs_mut();
self
}
#[inline]
pub fn abs_mut(&mut self) {
xmpz::abs(self, ());
}
#[inline]
pub fn abs_ref(&self) -> AbsIncomplete {
AbsIncomplete { ref_self: self }
}
#[inline]
#[must_use]
pub fn signum(mut self) -> Self {
self.signum_mut();
self
}
#[inline]
pub fn signum_mut(&mut self) {
xmpz::signum(self, ())
}
#[inline]
pub fn signum_ref(&self) -> SignumIncomplete {
SignumIncomplete { ref_self: self }
}
#[inline]
#[must_use]
pub fn clamp<Min, Max>(mut self, min: &Min, max: &Max) -> Self
where
Self: PartialOrd<Min> + PartialOrd<Max> + for<'a> Assign<&'a Min> + for<'a> Assign<&'a Max>,
{
self.clamp_mut(min, max);
self
}
pub fn clamp_mut<Min, Max>(&mut self, min: &Min, max: &Max)
where
Self: PartialOrd<Min> + PartialOrd<Max> + for<'a> Assign<&'a Min> + for<'a> Assign<&'a Max>,
{
if (*self).lt(min) {
self.assign(min);
assert!(!(*self).gt(max), "minimum larger than maximum");
} else if (*self).gt(max) {
self.assign(max);
assert!(!(*self).lt(min), "minimum larger than maximum");
}
}
#[inline]
pub fn clamp_ref<'min, 'max, Min, Max>(
&self,
min: &'min Min,
max: &'max Max,
) -> ClampIncomplete<'_, 'min, 'max, Min, Max>
where
Self: PartialOrd<Min> + PartialOrd<Max> + for<'a> Assign<&'a Min> + for<'a> Assign<&'a Max>,
{
ClampIncomplete {
ref_self: self,
min,
max,
}
}
#[inline]
#[must_use]
pub fn keep_bits(mut self, n: u32) -> Self {
self.keep_bits_mut(n);
self
}
#[inline]
pub fn keep_bits_mut(&mut self, n: u32) {
xmpz::fdiv_r_2exp(self, (), n.into())
}
#[inline]
pub fn keep_bits_ref(&self, n: u32) -> KeepBitsIncomplete {
let n = n.into();
KeepBitsIncomplete { ref_self: self, n }
}
#[inline]
#[must_use]
pub fn keep_signed_bits(mut self, n: u32) -> Self {
self.keep_signed_bits_mut(n);
self
}
#[inline]
pub fn keep_signed_bits_mut(&mut self, n: u32) {
xmpz::keep_signed_bits(self, (), n.into());
}
#[inline]
pub fn keep_signed_bits_ref(&self, n: u32) -> KeepSignedBitsIncomplete<'_> {
let n = n.into();
KeepSignedBitsIncomplete { ref_self: self, n }
}
#[inline]
#[must_use]
pub fn next_power_of_two(mut self) -> Self {
self.next_power_of_two_mut();
self
}
#[inline]
pub fn next_power_of_two_mut(&mut self) {
xmpz::next_pow_of_two(self, ());
}
#[inline]
pub fn next_power_of_two_ref(&self) -> NextPowerOfTwoIncomplete<'_> {
NextPowerOfTwoIncomplete { ref_self: self }
}
#[inline]
pub fn div_rem(mut self, mut divisor: Self) -> (Self, Self) {
self.div_rem_mut(&mut divisor);
(self, divisor)
}
#[inline]
pub fn div_rem_mut(&mut self, divisor: &mut Self) {
xmpz::tdiv_qr(self, divisor, (), ());
}
#[inline]
pub fn div_rem_ref<'a>(&'a self, divisor: &'a Self) -> DivRemIncomplete<'_> {
DivRemIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
pub fn div_rem_ceil(mut self, mut divisor: Self) -> (Self, Self) {
self.div_rem_ceil_mut(&mut divisor);
(self, divisor)
}
#[inline]
pub fn div_rem_ceil_mut(&mut self, divisor: &mut Self) {
xmpz::cdiv_qr(self, divisor, (), ());
}
#[inline]
pub fn div_rem_ceil_ref<'a>(&'a self, divisor: &'a Self) -> DivRemCeilIncomplete<'_> {
DivRemCeilIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
pub fn div_rem_floor(mut self, mut divisor: Self) -> (Self, Self) {
self.div_rem_floor_mut(&mut divisor);
(self, divisor)
}
#[inline]
pub fn div_rem_floor_mut(&mut self, divisor: &mut Self) {
xmpz::fdiv_qr(self, divisor, (), ());
}
#[inline]
pub fn div_rem_floor_ref<'a>(&'a self, divisor: &'a Self) -> DivRemFloorIncomplete<'_> {
DivRemFloorIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
pub fn div_rem_round(mut self, mut divisor: Self) -> (Self, Self) {
self.div_rem_round_mut(&mut divisor);
(self, divisor)
}
#[inline]
pub fn div_rem_round_mut(&mut self, divisor: &mut Self) {
xmpz::rdiv_qr(self, divisor, (), ());
}
#[inline]
pub fn div_rem_round_ref<'a>(&'a self, divisor: &'a Self) -> DivRemRoundIncomplete<'_> {
DivRemRoundIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
pub fn div_rem_euc(mut self, mut divisor: Self) -> (Self, Self) {
self.div_rem_euc_mut(&mut divisor);
(self, divisor)
}
#[inline]
pub fn div_rem_euc_mut(&mut self, divisor: &mut Self) {
xmpz::ediv_qr(self, divisor, (), ());
}
#[inline]
pub fn div_rem_euc_ref<'a>(&'a self, divisor: &'a Self) -> DivRemEucIncomplete<'_> {
DivRemEucIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
pub fn mod_u(&self, modulo: u32) -> u32 {
xmpz::fdiv_ui(self, modulo.into()).wrapping_cast()
}
#[inline]
#[must_use]
pub fn div_exact(mut self, divisor: &Self) -> Self {
self.div_exact_mut(divisor);
self
}
#[inline]
pub fn div_exact_mut(&mut self, divisor: &Self) {
xmpz::divexact(self, (), divisor);
}
pub fn div_exact_from(&mut self, dividend: &Integer) {
xmpz::divexact(self, dividend, ());
}
#[inline]
pub fn div_exact_ref<'a>(&'a self, divisor: &'a Self) -> DivExactIncomplete<'_> {
DivExactIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
#[must_use]
pub fn div_exact_u(mut self, divisor: u32) -> Self {
self.div_exact_u_mut(divisor);
self
}
#[inline]
pub fn div_exact_u_mut(&mut self, divisor: u32) {
xmpz::divexact_u32(self, (), divisor);
}
#[inline]
pub fn div_exact_u_ref(&self, divisor: u32) -> DivExactUIncomplete<'_> {
DivExactUIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
pub fn invert(mut self, modulo: &Self) -> Result<Self, Self> {
match self.invert_mut(modulo) {
Ok(()) => Ok(self),
Err(()) => Err(self),
}
}
#[inline]
#[allow(clippy::result_unit_err)]
pub fn invert_mut(&mut self, modulo: &Self) -> Result<(), ()> {
match self.invert_ref(modulo) {
Some(InvertIncomplete { sinverse, .. }) => {
xmpz::finish_invert(self, &sinverse, modulo);
Ok(())
}
None => Err(()),
}
}
pub fn invert_ref<'a>(&'a self, modulo: &'a Self) -> Option<InvertIncomplete<'a>> {
xmpz::start_invert(self, modulo).map(|sinverse| InvertIncomplete { sinverse, modulo })
}
#[inline]
pub fn pow_mod(mut self, exponent: &Self, modulo: &Self) -> Result<Self, Self> {
match self.pow_mod_mut(exponent, modulo) {
Ok(()) => Ok(self),
Err(()) => Err(self),
}
}
#[inline]
#[allow(clippy::result_unit_err)]
pub fn pow_mod_mut(&mut self, exponent: &Self, modulo: &Self) -> Result<(), ()> {
let sinverse = match self.pow_mod_ref(exponent, modulo) {
Some(PowModIncomplete { sinverse, .. }) => sinverse,
None => return Err(()),
};
if let Some(sinverse) = &sinverse {
xmpz::pow_mod(self, sinverse, exponent, modulo);
} else {
xmpz::pow_mod(self, (), exponent, modulo);
}
Ok(())
}
pub fn pow_mod_ref<'a>(
&'a self,
exponent: &'a Self,
modulo: &'a Self,
) -> Option<PowModIncomplete<'a>> {
if exponent.cmp0() == Ordering::Less {
let sinverse = match self.invert_ref(modulo) {
Some(InvertIncomplete { sinverse, .. }) => sinverse,
None => return None,
};
Some(PowModIncomplete {
ref_self: None,
sinverse: Some(sinverse),
exponent,
modulo,
})
} else if modulo.cmp0() != Ordering::Equal {
Some(PowModIncomplete {
ref_self: Some(self),
sinverse: None,
exponent,
modulo,
})
} else {
None
}
}
#[inline]
#[must_use]
pub fn secure_pow_mod(mut self, exponent: &Self, modulo: &Self) -> Self {
self.secure_pow_mod_mut(exponent, modulo);
self
}
#[inline]
pub fn secure_pow_mod_mut(&mut self, exponent: &Self, modulo: &Self) {
xmpz::powm_sec(self, (), exponent, modulo);
}
#[inline]
pub fn secure_pow_mod_ref<'a>(
&'a self,
exponent: &'a Self,
modulo: &'a Self,
) -> SecurePowModIncomplete<'a> {
SecurePowModIncomplete {
ref_self: self,
exponent,
modulo,
}
}
#[inline]
pub fn u_pow_u(base: u32, exponent: u32) -> UPowUIncomplete {
UPowUIncomplete { base, exponent }
}
#[inline]
pub fn i_pow_u(base: i32, exponent: u32) -> IPowUIncomplete {
IPowUIncomplete { base, exponent }
}
#[inline]
#[must_use]
pub fn root(mut self, n: u32) -> Self {
self.root_mut(n);
self
}
#[inline]
pub fn root_mut(&mut self, n: u32) {
xmpz::root(self, (), n.into());
}
#[inline]
pub fn root_ref(&self, n: u32) -> RootIncomplete<'_> {
let n = n.into();
RootIncomplete { ref_self: self, n }
}
#[inline]
pub fn root_rem(mut self, mut remainder: Self, n: u32) -> (Self, Self) {
self.root_rem_mut(&mut remainder, n);
(self, remainder)
}
#[inline]
pub fn root_rem_mut(&mut self, remainder: &mut Self, n: u32) {
xmpz::rootrem(self, remainder, (), n.into());
}
#[inline]
pub fn root_rem_ref(&self, n: u32) -> RootRemIncomplete<'_> {
let n = n.into();
RootRemIncomplete { ref_self: self, n }
}
#[inline]
#[must_use]
pub fn square(mut self) -> Self {
self.square_mut();
self
}
#[inline]
pub fn square_mut(&mut self) {
xmpz::mul(self, (), ());
}
#[inline]
pub fn square_ref(&self) -> MulIncomplete<'_> {
self * self
}
#[inline]
#[must_use]
pub fn sqrt(mut self) -> Self {
self.sqrt_mut();
self
}
#[inline]
pub fn sqrt_mut(&mut self) {
xmpz::sqrt(self, ());
}
#[inline]
pub fn sqrt_ref(&self) -> SqrtIncomplete<'_> {
SqrtIncomplete { ref_self: self }
}
#[inline]
pub fn sqrt_rem(mut self, mut remainder: Self) -> (Self, Self) {
self.sqrt_rem_mut(&mut remainder);
(self, remainder)
}
#[inline]
pub fn sqrt_rem_mut(&mut self, remainder: &mut Self) {
xmpz::sqrtrem(self, remainder, ());
}
#[inline]
pub fn sqrt_rem_ref(&self) -> SqrtRemIncomplete<'_> {
SqrtRemIncomplete { ref_self: self }
}
#[inline]
pub fn is_probably_prime(&self, reps: u32) -> IsPrime {
match xmpz::probab_prime_p(self, reps.unwrapped_cast()) {
0 => IsPrime::No,
1 => IsPrime::Probably,
2 => IsPrime::Yes,
_ => unreachable!(),
}
}
#[inline]
#[must_use]
pub fn next_prime(mut self) -> Self {
self.next_prime_mut();
self
}
#[inline]
pub fn next_prime_mut(&mut self) {
xmpz::nextprime(self, ());
}
#[inline]
pub fn next_prime_ref(&self) -> NextPrimeIncomplete<'_> {
NextPrimeIncomplete { ref_self: self }
}
#[inline]
#[must_use]
pub fn gcd(mut self, other: &Self) -> Self {
self.gcd_mut(other);
self
}
#[inline]
pub fn gcd_mut(&mut self, other: &Self) {
xmpz::gcd(self, (), other);
}
#[inline]
pub fn gcd_ref<'a>(&'a self, other: &'a Self) -> GcdIncomplete<'_> {
GcdIncomplete {
ref_self: self,
other,
}
}
#[inline]
#[must_use]
pub fn gcd_u(mut self, other: u32) -> Self {
self.gcd_u_mut(other);
self
}
#[inline]
pub fn gcd_u_mut(&mut self, other: u32) {
xmpz::gcd_ui(self, (), other.into());
}
#[inline]
pub fn gcd_u_ref(&self, other: u32) -> GcdUIncomplete<'_> {
let other = other.into();
GcdUIncomplete {
ref_self: self,
other,
}
}
#[inline]
pub fn extended_gcd(mut self, mut other: Self, mut rop: Self) -> (Self, Self, Self) {
self.extended_gcd_mut(&mut other, &mut rop);
(self, other, rop)
}
#[inline]
pub fn extended_gcd_mut(&mut self, other: &mut Self, rop: &mut Self) {
xmpz::gcdext(self, other, Some(rop), (), ());
}
#[inline]
pub fn extended_gcd_ref<'a>(&'a self, other: &'a Self) -> GcdExtIncomplete<'_> {
GcdExtIncomplete {
ref_self: self,
other,
}
}
#[inline]
#[must_use]
pub fn lcm(mut self, other: &Self) -> Self {
self.lcm_mut(other);
self
}
#[inline]
pub fn lcm_mut(&mut self, other: &Self) {
xmpz::lcm(self, (), other);
}
#[inline]
pub fn lcm_ref<'a>(&'a self, other: &'a Self) -> LcmIncomplete<'_> {
LcmIncomplete {
ref_self: self,
other,
}
}
#[inline]
#[must_use]
pub fn lcm_u(mut self, other: u32) -> Self {
self.lcm_u_mut(other);
self
}
#[inline]
pub fn lcm_u_mut(&mut self, other: u32) {
xmpz::lcm_ui(self, (), other.into());
}
#[inline]
pub fn lcm_u_ref(&self, other: u32) -> LcmUIncomplete<'_> {
let other = other.into();
LcmUIncomplete {
ref_self: self,
other,
}
}
#[inline]
pub fn jacobi(&self, n: &Self) -> i32 {
xmpz::jacobi(self, n).cast()
}
#[inline]
pub fn legendre(&self, p: &Self) -> i32 {
xmpz::legendre(self, p).cast()
}
#[inline]
pub fn kronecker(&self, n: &Self) -> i32 {
xmpz::kronecker(self, n).cast()
}
#[inline]
pub fn remove_factor(mut self, factor: &Self) -> (Self, u32) {
let count = self.remove_factor_mut(factor);
(self, count)
}
#[inline]
pub fn remove_factor_mut(&mut self, factor: &Self) -> u32 {
xmpz::remove(self, (), factor).unwrapped_cast()
}
#[inline]
pub fn remove_factor_ref<'a>(&'a self, factor: &'a Self) -> RemoveFactorIncomplete<'a> {
RemoveFactorIncomplete {
ref_self: self,
factor,
}
}
#[inline]
pub fn factorial(n: u32) -> FactorialIncomplete {
let n = n.into();
FactorialIncomplete { n }
}
#[inline]
pub fn factorial_2(n: u32) -> Factorial2Incomplete {
let n = n.into();
Factorial2Incomplete { n }
}
#[inline]
pub fn factorial_m(n: u32, m: u32) -> FactorialMIncomplete {
let n = n.into();
let m = m.into();
FactorialMIncomplete { n, m }
}
#[inline]
pub fn primorial(n: u32) -> PrimorialIncomplete {
let n = n.into();
PrimorialIncomplete { n }
}
#[inline]
#[must_use]
pub fn binomial(mut self, k: u32) -> Self {
self.binomial_mut(k);
self
}
#[inline]
pub fn binomial_mut(&mut self, k: u32) {
xmpz::bin_ui(self, (), k.into());
}
#[inline]
pub fn binomial_ref(&self, k: u32) -> BinomialIncomplete<'_> {
let k = k.into();
BinomialIncomplete { ref_self: self, k }
}
#[inline]
pub fn binomial_u(n: u32, k: u32) -> BinomialUIncomplete {
let n = n.into();
let k = k.into();
BinomialUIncomplete { n, k }
}
#[inline]
pub fn fibonacci(n: u32) -> FibonacciIncomplete {
let n = n.into();
FibonacciIncomplete { n }
}
#[inline]
pub fn fibonacci_2(n: u32) -> Fibonacci2Incomplete {
let n = n.into();
Fibonacci2Incomplete { n }
}
#[inline]
pub fn lucas(n: u32) -> LucasIncomplete {
let n = n.into();
LucasIncomplete { n }
}
#[inline]
pub fn lucas_2(n: u32) -> Lucas2Incomplete {
let n = n.into();
Lucas2Incomplete { n }
}
#[cfg(feature = "rand")]
#[inline]
pub fn random_bits(bits: u32, rng: &mut dyn MutRandState) -> RandomBitsIncomplete {
let bits = bits.into();
RandomBitsIncomplete { bits, rng }
}
#[cfg(feature = "rand")]
#[inline]
#[must_use]
pub fn random_below(mut self, rng: &mut dyn MutRandState) -> Self {
self.random_below_mut(rng);
self
}
#[cfg(feature = "rand")]
#[inline]
pub fn random_below_mut(&mut self, rng: &mut dyn MutRandState) {
xmpz::urandomm(self, rng, ());
}
#[cfg(feature = "rand")]
#[inline]
pub fn random_below_ref<'a>(
&'a self,
rng: &'a mut dyn MutRandState,
) -> RandomBelowIncomplete<'a> {
RandomBelowIncomplete {
ref_self: self,
rng,
}
}
#[deprecated(since = "1.18.0", note = "renamed to `extended_gcd`")]
#[inline]
pub fn gcd_cofactors(self, other: Self, rop: Self) -> (Self, Self, Self) {
self.extended_gcd(other, rop)
}
#[deprecated(since = "1.18.0", note = "renamed to `extended_gcd_mut`")]
#[inline]
pub fn gcd_cofactors_mut(&mut self, other: &mut Self, rop: &mut Self) {
self.extended_gcd_mut(other, rop);
}
#[deprecated(since = "1.18.0", note = "renamed to `extended_gcd_ref`")]
#[inline]
pub fn gcd_cofactors_ref<'a>(&'a self, other: &'a Self) -> GcdExtIncomplete<'_> {
self.extended_gcd_ref(other)
}
}
#[derive(Debug)]
pub struct SumIncomplete<'a, I>
where
I: Iterator<Item = &'a Integer>,
{
values: I,
}
impl<'a, I> Assign<SumIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn assign(&mut self, mut src: SumIncomplete<'a, I>) {
match src.values.next() {
Some(first) => {
self.assign(first);
}
None => {
self.assign(0u32);
return;
}
}
self.add_assign(src);
}
}
impl<'a, I> From<SumIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn from(mut src: SumIncomplete<'a, I>) -> Self {
let mut dst = match src.values.next() {
Some(first) => first.clone(),
None => return Integer::new(),
};
dst.add_assign(src);
dst
}
}
impl<'a, I> Complete for SumIncomplete<'a, I>
where
I: Iterator<Item = &'a Integer>,
{
type Completed = Integer;
#[inline]
fn complete(self) -> Integer {
Integer::from(self)
}
}
impl<'a, I> Add<SumIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
type Output = Self;
#[inline]
fn add(mut self, rhs: SumIncomplete<'a, I>) -> Self {
self.add_assign(rhs);
self
}
}
impl<'a, I> Add<Integer> for SumIncomplete<'a, I>
where
I: Iterator<Item = &'a Integer>,
{
type Output = Integer;
#[inline]
fn add(self, mut rhs: Integer) -> Integer {
rhs.add_assign(self);
rhs
}
}
impl<'a, I> AddAssign<SumIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn add_assign(&mut self, src: SumIncomplete<'a, I>) {
for i in src.values {
self.add_assign(i);
}
}
}
impl<'a, I> Sub<SumIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
type Output = Self;
#[inline]
fn sub(mut self, rhs: SumIncomplete<'a, I>) -> Self {
self.sub_assign(rhs);
self
}
}
impl<'a, I> Sub<Integer> for SumIncomplete<'a, I>
where
I: Iterator<Item = &'a Integer>,
{
type Output = Integer;
#[inline]
fn sub(self, mut rhs: Integer) -> Integer {
rhs.neg_assign();
rhs.add_assign(self);
rhs
}
}
impl<'a, I> SubAssign<SumIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn sub_assign(&mut self, src: SumIncomplete<'a, I>) {
for i in src.values {
self.sub_assign(i);
}
}
}
impl<'a, I> SubFrom<SumIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn sub_from(&mut self, src: SumIncomplete<'a, I>) {
self.neg_assign();
self.add_assign(src);
}
}
#[derive(Debug)]
pub struct DotIncomplete<'a, I>
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
values: I,
}
impl<'a, I> Assign<DotIncomplete<'a, I>> for Integer
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
fn assign(&mut self, mut src: DotIncomplete<'a, I>) {
match src.values.next() {
Some(first) => {
self.assign(first.0 * first.1);
}
None => {
self.assign(0u32);
return;
}
}
self.add_assign(src);
}
}
impl<'a, I> From<DotIncomplete<'a, I>> for Integer
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
fn from(mut src: DotIncomplete<'a, I>) -> Self {
let mut dst = match src.values.next() {
Some(first) => Integer::from(first.0 * first.1),
None => return Integer::new(),
};
dst.add_assign(src);
dst
}
}
impl<'a, I> Complete for DotIncomplete<'a, I>
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
type Completed = Integer;
#[inline]
fn complete(self) -> Integer {
Integer::from(self)
}
}
impl<'a, I> Add<DotIncomplete<'a, I>> for Integer
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
type Output = Self;
#[inline]
fn add(mut self, rhs: DotIncomplete<'a, I>) -> Self {
self.add_assign(rhs);
self
}
}
impl<'a, I> Add<Integer> for DotIncomplete<'a, I>
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
type Output = Integer;
#[inline]
fn add(self, mut rhs: Integer) -> Integer {
rhs.add_assign(self);
rhs
}
}
impl<'a, I> AddAssign<DotIncomplete<'a, I>> for Integer
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
fn add_assign(&mut self, src: DotIncomplete<'a, I>) {
for i in src.values {
#[allow(clippy::suspicious_op_assign_impl)]
AddAssign::add_assign(self, i.0 * i.1);
}
}
}
impl<'a, I> Sub<DotIncomplete<'a, I>> for Integer
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
type Output = Self;
#[inline]
fn sub(mut self, rhs: DotIncomplete<'a, I>) -> Self {
self.sub_assign(rhs);
self
}
}
impl<'a, I> Sub<Integer> for DotIncomplete<'a, I>
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
type Output = Integer;
#[inline]
fn sub(self, mut rhs: Integer) -> Integer {
rhs.neg_assign();
rhs.add_assign(self);
rhs
}
}
impl<'a, I> SubAssign<DotIncomplete<'a, I>> for Integer
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
fn sub_assign(&mut self, src: DotIncomplete<'a, I>) {
for i in src.values {
#[allow(clippy::suspicious_op_assign_impl)]
SubAssign::sub_assign(self, i.0 * i.1);
}
}
}
impl<'a, I> SubFrom<DotIncomplete<'a, I>> for Integer
where
I: Iterator<Item = (&'a Integer, &'a Integer)>,
{
fn sub_from(&mut self, src: DotIncomplete<'a, I>) {
self.neg_assign();
self.add_assign(src);
}
}
#[derive(Debug)]
pub struct ProductIncomplete<'a, I>
where
I: Iterator<Item = &'a Integer>,
{
values: I,
}
impl<'a, I> Assign<ProductIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn assign(&mut self, mut src: ProductIncomplete<'a, I>) {
match src.values.next() {
Some(first) => {
self.assign(first);
}
None => {
self.assign(1u32);
return;
}
}
self.mul_assign(src);
}
}
impl<'a, I> From<ProductIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn from(mut src: ProductIncomplete<'a, I>) -> Self {
let mut dst = match src.values.next() {
Some(first) => first.clone(),
None => return Integer::from(1),
};
dst.mul_assign(src);
dst
}
}
impl<'a, I> Complete for ProductIncomplete<'a, I>
where
I: Iterator<Item = &'a Integer>,
{
type Completed = Integer;
#[inline]
fn complete(self) -> Integer {
Integer::from(self)
}
}
impl<'a, I> Mul<ProductIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
type Output = Self;
#[inline]
fn mul(mut self, rhs: ProductIncomplete<'a, I>) -> Self {
self.mul_assign(rhs);
self
}
}
impl<'a, I> Mul<Integer> for ProductIncomplete<'a, I>
where
I: Iterator<Item = &'a Integer>,
{
type Output = Integer;
#[inline]
fn mul(self, mut rhs: Integer) -> Integer {
rhs.mul_assign(self);
rhs
}
}
impl<'a, I> MulAssign<ProductIncomplete<'a, I>> for Integer
where
I: Iterator<Item = &'a Self>,
{
fn mul_assign(&mut self, mut src: ProductIncomplete<'a, I>) {
let mut other = match src.values.next() {
Some(next) => Integer::from(&*self * next),
None => return,
};
loop {
match src.values.next() {
Some(next) => {
self.assign(&other * next);
}
None => {
self.assign(other);
return;
}
}
match src.values.next() {
Some(next) => {
other.assign(&*self * next);
}
None => {
return;
}
}
if self.cmp0() == Ordering::Equal {
return;
}
}
}
}
ref_math_op1! { Integer; xmpz::abs; struct AbsIncomplete {} }
ref_math_op1! { Integer; xmpz::signum; struct SignumIncomplete {} }
#[derive(Debug)]
pub struct ClampIncomplete<'s, 'min, 'max, Min, Max>
where
Integer: PartialOrd<Min> + PartialOrd<Max> + for<'a> Assign<&'a Min> + for<'a> Assign<&'a Max>,
{
ref_self: &'s Integer,
min: &'min Min,
max: &'max Max,
}
impl<Min, Max> Assign<ClampIncomplete<'_, '_, '_, Min, Max>> for Integer
where
Self: PartialOrd<Min> + PartialOrd<Max> + for<'a> Assign<&'a Min> + for<'a> Assign<&'a Max>,
{
#[inline]
fn assign(&mut self, src: ClampIncomplete<Min, Max>) {
if src.ref_self.lt(src.min) {
self.assign(src.min);
assert!(!(*self).gt(src.max), "minimum larger than maximum");
} else if src.ref_self.gt(src.max) {
self.assign(src.max);
assert!(!(*self).lt(src.min), "minimum larger than maximum");
} else {
self.assign(src.ref_self);
}
}
}
impl<Min, Max> From<ClampIncomplete<'_, '_, '_, Min, Max>> for Integer
where
Self: PartialOrd<Min> + PartialOrd<Max> + for<'a> Assign<&'a Min> + for<'a> Assign<&'a Max>,
{
#[inline]
fn from(src: ClampIncomplete<Min, Max>) -> Self {
let mut dst = Integer::new();
dst.assign(src);
dst
}
}
ref_math_op1! { Integer; xmpz::fdiv_r_2exp; struct KeepBitsIncomplete { n: bitcnt_t } }
ref_math_op1! { Integer; xmpz::keep_signed_bits; struct KeepSignedBitsIncomplete { n: bitcnt_t } }
ref_math_op1! { Integer; xmpz::next_pow_of_two; struct NextPowerOfTwoIncomplete {} }
ref_math_op2_2! { Integer; xmpz::tdiv_qr; struct DivRemIncomplete { divisor } }
ref_math_op2_2! { Integer; xmpz::cdiv_qr; struct DivRemCeilIncomplete { divisor } }
ref_math_op2_2! { Integer; xmpz::fdiv_qr; struct DivRemFloorIncomplete { divisor } }
ref_math_op2_2! { Integer; xmpz::rdiv_qr; struct DivRemRoundIncomplete { divisor } }
ref_math_op2_2! { Integer; xmpz::ediv_qr; struct DivRemEucIncomplete { divisor } }
ref_math_op2! { Integer; xmpz::divexact; struct DivExactIncomplete { divisor } }
ref_math_op1! { Integer; xmpz::divexact_u32; struct DivExactUIncomplete { divisor: u32 } }
#[derive(Debug)]
pub struct PowModIncomplete<'a> {
ref_self: Option<&'a Integer>,
sinverse: Option<Integer>,
exponent: &'a Integer,
modulo: &'a Integer,
}
impl Assign<PowModIncomplete<'_>> for Integer {
#[inline]
fn assign(&mut self, src: PowModIncomplete<'_>) {
match (src.ref_self, src.sinverse) {
(Some(base), None) => {
debug_assert_ne!(src.exponent.cmp0(), Ordering::Less);
xmpz::pow_mod(self, base, src.exponent, src.modulo);
}
(None, Some(sinverse)) => {
debug_assert_eq!(src.exponent.cmp0(), Ordering::Less);
xmpz::pow_mod(self, &sinverse, src.exponent, src.modulo);
}
_ => unreachable!(),
}
}
}
impl From<PowModIncomplete<'_>> for Integer {
#[inline]
fn from(src: PowModIncomplete<'_>) -> Self {
match (src.ref_self, src.sinverse) {
(Some(base), None) => {
debug_assert_ne!(src.exponent.cmp0(), Ordering::Less);
let mut dst = Integer::new();
xmpz::pow_mod(&mut dst, base, src.exponent, src.modulo);
dst
}
(None, Some(mut sinverse)) => {
debug_assert_eq!(src.exponent.cmp0(), Ordering::Less);
xmpz::pow_mod(&mut sinverse, (), src.exponent, src.modulo);
sinverse
}
_ => unreachable!(),
}
}
}
pub struct SecurePowModIncomplete<'a> {
ref_self: &'a Integer,
exponent: &'a Integer,
modulo: &'a Integer,
}
impl Assign<SecurePowModIncomplete<'_>> for Integer {
#[inline]
fn assign(&mut self, src: SecurePowModIncomplete<'_>) {
xmpz::powm_sec(self, src.ref_self, src.exponent, src.modulo);
}
}
from_assign! { SecurePowModIncomplete<'_> => Integer }
ref_math_op0! { Integer; xmpz::u32_pow_u32; struct UPowUIncomplete { base: u32, exponent: u32 } }
ref_math_op0! { Integer; xmpz::i32_pow_u32; struct IPowUIncomplete { base: i32, exponent: u32 } }
ref_math_op1! { Integer; xmpz::root; struct RootIncomplete { n: c_ulong } }
ref_math_op1_2! { Integer; xmpz::rootrem; struct RootRemIncomplete { n: c_ulong } }
ref_math_op1! { Integer; xmpz::sqrt; struct SqrtIncomplete {} }
ref_math_op1_2! { Integer; xmpz::sqrtrem; struct SqrtRemIncomplete {} }
ref_math_op1! { Integer; xmpz::nextprime; struct NextPrimeIncomplete {} }
ref_math_op2! { Integer; xmpz::gcd; struct GcdIncomplete { other } }
ref_math_op1! { Integer; xmpz::gcd_ui; struct GcdUIncomplete { other: c_ulong } }
impl From<GcdUIncomplete<'_>> for Option<u32> {
#[inline]
fn from(src: GcdUIncomplete) -> Self {
let gcd = xmpz::gcd_opt_ui(None, src.ref_self, src.other.into());
if gcd == 0 && src.ref_self.cmp0() != Ordering::Equal {
None
} else {
gcd.checked_cast()
}
}
}
#[derive(Debug)]
pub struct GcdExtIncomplete<'a> {
ref_self: &'a Integer,
other: &'a Integer,
}
impl Assign<GcdExtIncomplete<'_>> for (&mut Integer, &mut Integer, &mut Integer) {
#[inline]
fn assign(&mut self, src: GcdExtIncomplete<'_>) {
xmpz::gcdext(self.0, self.1, Some(self.2), src.ref_self, src.other);
}
}
impl Assign<GcdExtIncomplete<'_>> for (Integer, Integer, Integer) {
#[inline]
fn assign(&mut self, src: GcdExtIncomplete<'_>) {
(&mut self.0, &mut self.1, &mut self.2).assign(src);
}
}
from_assign! { GcdExtIncomplete<'_> => Integer, Integer, Integer }
impl Assign<GcdExtIncomplete<'_>> for (&mut Integer, &mut Integer) {
#[inline]
fn assign(&mut self, src: GcdExtIncomplete<'_>) {
xmpz::gcdext(self.0, self.1, None, src.ref_self, src.other);
}
}
impl Assign<GcdExtIncomplete<'_>> for (Integer, Integer) {
#[inline]
fn assign(&mut self, src: GcdExtIncomplete<'_>) {
Assign::assign(&mut (&mut self.0, &mut self.1), src);
}
}
impl From<GcdExtIncomplete<'_>> for (Integer, Integer) {
#[inline]
fn from(src: GcdExtIncomplete<'_>) -> Self {
let mut dst = Self::default();
Assign::assign(&mut (&mut dst.0, &mut dst.1), src);
dst
}
}
ref_math_op2! { Integer; xmpz::lcm; struct LcmIncomplete { other } }
ref_math_op1! { Integer; xmpz::lcm_ui; struct LcmUIncomplete { other: c_ulong } }
#[derive(Debug)]
pub struct InvertIncomplete<'a> {
sinverse: Integer,
modulo: &'a Integer,
}
impl Assign<InvertIncomplete<'_>> for Integer {
#[inline]
fn assign(&mut self, src: InvertIncomplete<'_>) {
xmpz::finish_invert(self, &src.sinverse, src.modulo);
}
}
impl From<InvertIncomplete<'_>> for Integer {
#[inline]
fn from(mut src: InvertIncomplete<'_>) -> Self {
xmpz::finish_invert(&mut src.sinverse, (), src.modulo);
src.sinverse
}
}
#[derive(Debug)]
pub struct RemoveFactorIncomplete<'a> {
ref_self: &'a Integer,
factor: &'a Integer,
}
impl Assign<RemoveFactorIncomplete<'_>> for (&mut Integer, &mut u32) {
#[inline]
fn assign(&mut self, src: RemoveFactorIncomplete<'_>) {
*self.1 = xmpz::remove(self.0, src.ref_self, src.factor).unwrapped_cast();
}
}
impl Assign<RemoveFactorIncomplete<'_>> for (Integer, u32) {
#[inline]
fn assign(&mut self, src: RemoveFactorIncomplete<'_>) {
(&mut self.0, &mut self.1).assign(src);
}
}
from_assign! { RemoveFactorIncomplete<'_> => Integer, u32 }
ref_math_op0! { Integer; xmpz::fac_ui; struct FactorialIncomplete { n: c_ulong } }
ref_math_op0! { Integer; xmpz::twofac_ui; struct Factorial2Incomplete { n: c_ulong } }
ref_math_op0! { Integer; xmpz::mfac_uiui; struct FactorialMIncomplete { n: c_ulong, m: c_ulong } }
ref_math_op0! { Integer; xmpz::primorial_ui; struct PrimorialIncomplete { n: c_ulong } }
ref_math_op1! { Integer; xmpz::bin_ui; struct BinomialIncomplete { k: c_ulong } }
ref_math_op0! { Integer; xmpz::bin_uiui; struct BinomialUIncomplete { n: c_ulong, k: c_ulong } }
ref_math_op0! { Integer; xmpz::fib_ui; struct FibonacciIncomplete { n: c_ulong } }
ref_math_op0_2! { Integer; xmpz::fib2_ui; struct Fibonacci2Incomplete { n: c_ulong } }
ref_math_op0! { Integer; xmpz::lucnum_ui; struct LucasIncomplete { n: c_ulong } }
ref_math_op0_2! { Integer; xmpz::lucnum2_ui; struct Lucas2Incomplete { n: c_ulong } }
#[cfg(feature = "rand")]
pub struct RandomBitsIncomplete<'a> {
bits: bitcnt_t,
rng: &'a mut dyn MutRandState,
}
#[cfg(feature = "rand")]
impl Assign<RandomBitsIncomplete<'_>> for Integer {
#[inline]
fn assign(&mut self, src: RandomBitsIncomplete) {
xmpz::urandomb(self, src.rng, src.bits)
}
}
#[cfg(feature = "rand")]
impl From<RandomBitsIncomplete<'_>> for Integer {
#[inline]
fn from(src: RandomBitsIncomplete) -> Self {
let mut dst = Integer::new();
dst.assign(src);
dst
}
}
#[cfg(feature = "rand")]
pub struct RandomBelowIncomplete<'a> {
ref_self: &'a Integer,
rng: &'a mut dyn MutRandState,
}
#[cfg(feature = "rand")]
impl Assign<RandomBelowIncomplete<'_>> for Integer {
#[inline]
fn assign(&mut self, src: RandomBelowIncomplete) {
xmpz::urandomm(self, src.rng, src.ref_self);
}
}
#[cfg(feature = "rand")]
impl From<RandomBelowIncomplete<'_>> for Integer {
#[inline]
fn from(src: RandomBelowIncomplete) -> Self {
let mut dst = Integer::new();
dst.assign(src);
dst
}
}
pub(crate) fn req_chars(i: &Integer, radix: i32, extra: usize) -> usize {
assert!((2..=36).contains(&radix), "radix out of range");
let size = unsafe { gmp::mpz_sizeinbase(i.as_raw(), radix) };
let size_extra = size.checked_add(extra).expect("overflow");
if i.cmp0() == Ordering::Less {
size_extra.checked_add(1).expect("overflow")
} else {
size_extra
}
}
pub(crate) fn append_to_string(s: &mut String, i: &Integer, radix: i32, to_upper: bool) {
let size = req_chars(i, radix, 1);
s.reserve(size);
let reserved_ptr = s.as_ptr();
let case_radix = if to_upper { -radix } else { radix };
let orig_len = s.len();
unsafe {
let bytes = s.as_mut_vec();
let start = bytes.as_mut_ptr().add(orig_len);
gmp::mpz_get_str(cast_ptr_mut!(start, c_char), case_radix.cast(), i.as_raw());
let added = slice::from_raw_parts(start, size);
let nul_index = added.iter().position(|&x| x == 0).unwrap();
bytes.set_len(orig_len + nul_index);
}
debug_assert_eq!(reserved_ptr, s.as_ptr());
#[cfg(not(debug_assertions))]
{
let _ = reserved_ptr;
}
}
#[derive(Debug)]
pub struct ParseIncomplete {
is_negative: bool,
digits: Vec<u8>,
radix: i32,
}
impl Assign<ParseIncomplete> for Integer {
#[inline]
fn assign(&mut self, src: ParseIncomplete) {
unsafe {
self.assign_bytes_radix_unchecked(src.digits.as_slice(), src.radix, src.is_negative);
}
}
}
from_assign! { ParseIncomplete => Integer }
fn parse(bytes: &[u8], radix: i32) -> Result<ParseIncomplete, ParseIntegerError> {
use self::{ParseErrorKind as Kind, ParseIntegerError as Error};
assert!((2..=36).contains(&radix), "radix out of range");
let bradix = radix.unwrapped_as::<u8>();
let mut digits = Vec::with_capacity(bytes.len());
let mut has_sign = false;
let mut is_negative = false;
let mut has_digits = false;
for &b in bytes {
let digit = match b {
b'+' if !has_sign && !has_digits => {
has_sign = true;
continue;
}
b'-' if !has_sign && !has_digits => {
is_negative = true;
has_sign = true;
continue;
}
b'_' if has_digits => continue,
b' ' | b'\t' | b'\n' | 0x0b | 0x0c | 0x0d => continue,
b'0'..=b'9' => b - b'0',
b'a'..=b'z' => b - b'a' + 10,
b'A'..=b'Z' => b - b'A' + 10,
_ => bradix,
};
if digit >= bradix {
return Err(Error {
kind: Kind::InvalidDigit,
});
};
has_digits = true;
if digit > 0 || !digits.is_empty() {
digits.push(digit);
}
}
if !has_digits {
return Err(Error {
kind: Kind::NoDigits,
});
}
Ok(ParseIncomplete {
is_negative,
digits,
radix,
})
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ParseIntegerError {
kind: ParseErrorKind,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum ParseErrorKind {
InvalidDigit,
NoDigits,
}
impl ParseIntegerError {
fn desc(&self) -> &str {
use self::ParseErrorKind::*;
match self.kind {
InvalidDigit => "invalid digit found in string",
NoDigits => "string has no digits",
}
}
}
impl Display for ParseIntegerError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self.desc(), f)
}
}
impl Error for ParseIntegerError {
#[allow(deprecated)]
fn description(&self) -> &str {
self.desc()
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum IsPrime {
No,
Probably,
Yes,
}
pub trait UnsignedPrimitive: SealedUnsignedPrimitive {}
pub struct PrivateUnsignedPrimitive {
bytes: usize,
bits: usize,
nails: usize,
}
pub unsafe trait SealedUnsignedPrimitive: Sized {
const PRIVATE: PrivateUnsignedPrimitive = PrivateUnsignedPrimitive {
bytes: mem::size_of::<Self>(),
bits: mem::size_of::<Self>() * 8,
nails: 0,
};
}
impl UnsignedPrimitive for bool {}
unsafe impl SealedUnsignedPrimitive for bool {
const PRIVATE: PrivateUnsignedPrimitive = PrivateUnsignedPrimitive {
bytes: mem::size_of::<Self>(),
bits: 1,
nails: mem::size_of::<Self>() * 8 - 1,
};
}
impl UnsignedPrimitive for u8 {}
unsafe impl SealedUnsignedPrimitive for u8 {}
impl UnsignedPrimitive for u16 {}
unsafe impl SealedUnsignedPrimitive for u16 {}
impl UnsignedPrimitive for u32 {}
unsafe impl SealedUnsignedPrimitive for u32 {}
impl UnsignedPrimitive for u64 {}
unsafe impl SealedUnsignedPrimitive for u64 {}
impl UnsignedPrimitive for u128 {}
unsafe impl SealedUnsignedPrimitive for u128 {}
impl UnsignedPrimitive for usize {}
unsafe impl SealedUnsignedPrimitive for usize {}