#[cfg(feature = "rand")]
use crate::rand::MutRandState;
use crate::{
ext::xmpz,
integer::Order,
misc::{self, AsOrPanic},
ops::DivRounding,
Assign,
};
use az::{Az, CheckedAs};
use core::{
cmp::Ordering,
fmt::{Display, Formatter, Result as FmtResult},
marker::PhantomData,
mem::{self, ManuallyDrop, MaybeUninit},
ops::{Add, AddAssign, Deref, Mul, MulAssign},
slice,
};
use gmp_mpfr_sys::gmp::{self, limb_t, mpz_t};
use libc::{c_char, c_int, c_long, c_void};
use std::error::Error;
#[cfg(feature = "rational")]
use {crate::rational::big::BorrowRational, gmp_mpfr_sys::gmp::mpq_t};
#[repr(transparent)]
pub struct Integer {
inner: mpz_t,
}
impl Integer {
#[inline]
pub(crate) 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) fn inner_data(&self) -> &[limb_t] {
let limbs = self
.inner
.size
.checked_abs()
.expect("overflow")
.as_or_panic::<usize>();
unsafe { slice::from_raw_parts(self.inner.d, limbs) }
}
}
static_assert_same_layout!(Integer, mpz_t);
static_assert_same_layout!(BorrowInteger<'_>, mpz_t);
impl Integer {
#[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
.as_or_panic::<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 as usize)
.checked_mul(gmp::LIMB_BITS as usize)
.expect("overflow");
if alloc_bits < req_bits {
unsafe {
gmp::mpz_realloc2(self.as_raw_mut(), req_bits.as_or_panic());
}
}
}
pub fn shrink_to_fit(&mut self) {
let used_limbs = self.inner.size.checked_abs().expect("overflow");
let req_limbs = if used_limbs == 0 { 1 } else { used_limbs };
if self.inner.alloc > req_limbs {
unsafe {
gmp::_mpz_realloc(self.as_raw_mut(), req_limbs.as_or_panic());
}
}
}
#[inline]
pub unsafe fn from_raw(raw: mpz_t) -> Self {
Integer { inner: raw }
}
#[inline]
pub const fn into_raw(self) -> mpz_t {
let ret = self.inner;
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;
gmp::mpz_import(
self.as_raw_mut(),
len,
order.order(),
bytes,
order.endian(),
nails,
src as *const c_void,
);
}
#[inline]
pub fn significant_digits<T: UnsignedPrimitive>(&self) -> usize {
xmpz::significant_bits(self).div_ceil(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::with_capacity(digit_count);
unsafe {
let digits_ptr = v.as_mut_ptr();
let mut count = MaybeUninit::uninit();
gmp::mpz_export(
digits_ptr as *mut c_void,
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 (zeros, digits) = if order.order() < 0 {
(dst.offset(digit_count.as_or_panic()), dst)
} else {
(dst, dst.offset(zero_count.as_or_panic()))
};
(zeros as *mut u8).write_bytes(0, zero_count * T::PRIVATE.bytes);
let mut count = MaybeUninit::uninit();
gmp::mpz_export(
digits as *mut c_void,
count.as_mut_ptr(),
order.order(),
T::PRIVATE.bytes,
order.endian(),
T::PRIVATE.nails,
self.as_raw(),
);
assert_eq!(count.assume_init(), digit_count);
}
#[inline]
pub fn from_f32(val: f32) -> Option<Self> {
Integer::from_f64(val.into())
}
#[inline]
pub fn from_f64(val: f64) -> Option<Self> {
if val.is_finite() {
unsafe {
let mut dst = MaybeUninit::uninit();
xmpz::init_set_f64(dst.as_mut_ptr(), val);
Some(dst.assume_init())
}
} else {
None
}
}
#[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)
}
#[inline]
pub fn to_i8(&self) -> Option<i8> {
if xmpz::fits_i8(self) {
Some(self.to_i8_wrapping())
} else {
None
}
}
#[inline]
pub fn to_i16(&self) -> Option<i16> {
if xmpz::fits_i16(self) {
Some(self.to_i16_wrapping())
} else {
None
}
}
#[inline]
pub fn to_i32(&self) -> Option<i32> {
if xmpz::fits_i32(self) {
Some(self.to_i32_wrapping())
} else {
None
}
}
#[inline]
pub fn to_i64(&self) -> Option<i64> {
if xmpz::fits_i64(self) {
Some(self.to_i64_wrapping())
} else {
None
}
}
#[inline]
pub fn to_i128(&self) -> Option<i128> {
if xmpz::fits_i128(self) {
Some(self.to_i128_wrapping())
} else {
None
}
}
#[inline]
pub fn to_isize(&self) -> Option<isize> {
#[cfg(target_pointer_width = "32")]
{
self.to_i32().map(Az::az)
}
#[cfg(target_pointer_width = "64")]
{
self.to_i64().map(Az::az)
}
}
#[inline]
pub fn to_u8(&self) -> Option<u8> {
if xmpz::fits_u8(self) {
Some(self.to_u8_wrapping())
} else {
None
}
}
#[inline]
pub fn to_u16(&self) -> Option<u16> {
if xmpz::fits_u16(self) {
Some(self.to_u16_wrapping())
} else {
None
}
}
#[inline]
pub fn to_u32(&self) -> Option<u32> {
if xmpz::fits_u32(self) {
Some(self.to_u32_wrapping())
} else {
None
}
}
#[inline]
pub fn to_u64(&self) -> Option<u64> {
if xmpz::fits_u64(self) {
Some(self.to_u64_wrapping())
} else {
None
}
}
#[inline]
pub fn to_u128(&self) -> Option<u128> {
if xmpz::fits_u128(self) {
Some(self.to_u128_wrapping())
} else {
None
}
}
#[inline]
pub fn to_usize(&self) -> Option<usize> {
#[cfg(target_pointer_width = "32")]
{
self.to_u32().map(Az::az)
}
#[cfg(target_pointer_width = "64")]
{
self.to_u64().map(Az::az)
}
}
#[inline]
pub fn to_i8_wrapping(&self) -> i8 {
self.to_u8_wrapping() as i8
}
#[inline]
pub fn to_i16_wrapping(&self) -> i16 {
self.to_u16_wrapping() as i16
}
#[inline]
pub fn to_i32_wrapping(&self) -> i32 {
self.to_u32_wrapping() as i32
}
#[inline]
pub fn to_i64_wrapping(&self) -> i64 {
self.to_u64_wrapping() as i64
}
#[inline]
pub fn to_i128_wrapping(&self) -> i128 {
self.to_u128_wrapping() as i128
}
#[inline]
pub fn to_isize_wrapping(&self) -> isize {
self.to_usize_wrapping() as isize
}
#[inline]
pub fn to_u8_wrapping(&self) -> u8 {
let u = xmpz::get_abs_u32(self) as u8;
if self.cmp0() == Ordering::Less {
u.wrapping_neg()
} else {
u
}
}
#[inline]
pub fn to_u16_wrapping(&self) -> u16 {
let u = xmpz::get_abs_u32(self) as u16;
if self.cmp0() == Ordering::Less {
u.wrapping_neg()
} else {
u
}
}
#[inline]
pub fn to_u32_wrapping(&self) -> u32 {
let u = xmpz::get_abs_u32(self);
if self.cmp0() == Ordering::Less {
u.wrapping_neg()
} else {
u
}
}
#[inline]
pub fn to_u64_wrapping(&self) -> u64 {
let u = xmpz::get_abs_u64(self);
if self.cmp0() == Ordering::Less {
u.wrapping_neg()
} else {
u
}
}
#[inline]
pub fn to_u128_wrapping(&self) -> u128 {
let u = xmpz::get_abs_u128(self);
if self.cmp0() == Ordering::Less {
u.wrapping_neg()
} else {
u
}
}
#[inline]
pub fn to_usize_wrapping(&self) -> usize {
#[cfg(target_pointer_width = "32")]
{
self.to_u32_wrapping().az()
}
#[cfg(target_pointer_width = "64")]
{
self.to_u64_wrapping().az()
}
}
#[inline]
pub fn to_f32(&self) -> f32 {
misc::trunc_f64_to_f32(self.to_f64())
}
#[inline]
pub fn to_f64(&self) -> f64 {
unsafe { gmp::mpz_get_d(self.as_raw()) }
}
#[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 mut exp: c_long = 0;
let f = unsafe { gmp::mpz_get_d_2exp(&mut exp, self.as_raw()) };
(f, exp.as_or_panic())
}
#[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]
pub fn assign_f32(&mut self, val: f32) -> Result<(), ()> {
self.assign_f64(val.into())
}
#[inline]
pub fn assign_f64(&mut self, val: f64) -> Result<(), ()> {
xmpz::set_f64(self, val)
}
pub fn as_neg(&self) -> BorrowInteger<'_> {
let mut raw = self.inner;
raw.size = raw.size.checked_neg().expect("overflow");
unsafe { BorrowInteger::from_raw(raw) }
}
pub fn as_abs(&self) -> BorrowInteger<'_> {
let mut raw = self.inner;
raw.size = raw.size.checked_abs().expect("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: &ONE as *const limb_t as *mut limb_t,
},
};
unsafe { BorrowRational::from_raw(raw_rational) }
}
#[inline]
pub fn is_even(&self) -> bool {
unsafe { gmp::mpz_even_p(self.as_raw()) != 0 }
}
#[inline]
pub fn is_odd(&self) -> bool {
unsafe { gmp::mpz_odd_p(self.as_raw()) != 0 }
}
#[inline]
pub fn is_divisible(&self, divisor: &Self) -> bool {
unsafe { gmp::mpz_divisible_p(self.as_raw(), divisor.as_raw()) != 0 }
}
#[inline]
pub fn is_divisible_u(&self, divisor: u32) -> bool {
unsafe { gmp::mpz_divisible_ui_p(self.as_raw(), divisor.into()) != 0 }
}
#[inline]
pub fn is_divisible_2pow(&self, b: u32) -> bool {
unsafe { gmp::mpz_divisible_2exp_p(self.as_raw(), b.into()) != 0 }
}
#[inline]
pub fn is_congruent(&self, c: &Self, divisor: &Self) -> bool {
unsafe { gmp::mpz_congruent_p(self.as_raw(), c.as_raw(), divisor.as_raw()) != 0 }
}
#[inline]
pub fn is_congruent_u(&self, c: u32, divisor: u32) -> bool {
unsafe { gmp::mpz_congruent_ui_p(self.as_raw(), c.into(), divisor.into()) != 0 }
}
#[inline]
pub fn is_congruent_2pow(&self, c: &Self, b: u32) -> bool {
unsafe { gmp::mpz_congruent_2exp_p(self.as_raw(), c.as_raw(), b.into()) != 0 }
}
#[inline]
pub fn is_perfect_power(&self) -> bool {
unsafe { gmp::mpz_perfect_power_p(self.as_raw()) != 0 }
}
#[inline]
pub fn is_perfect_square(&self) -> bool {
unsafe { gmp::mpz_perfect_square_p(self.as_raw()) != 0 }
}
#[inline]
pub fn is_power_of_two(&self) -> bool {
xmpz::power_of_two_p(self)
}
#[inline]
pub fn cmp0(&self) -> Ordering {
unsafe { gmp::mpz_sgn(self.as_raw()).cmp(&0) }
}
#[inline]
pub fn cmp_abs(&self, other: &Self) -> Ordering {
unsafe { gmp::mpz_cmpabs(self.as_raw(), other.as_raw()).cmp(&0) }
}
#[inline]
pub fn significant_bits(&self) -> u32 {
xmpz::significant_bits(self).as_or_panic()
}
#[inline]
pub fn signed_bits(&self) -> u32 {
xmpz::signed_bits(self)
}
#[inline]
pub fn count_ones(&self) -> Option<u32> {
xmpz::popcount(self)
}
#[inline]
pub fn count_zeros(&self) -> Option<u32> {
xmpz::zerocount(self)
}
#[inline]
pub fn find_zero(&self, start: u32) -> Option<u32> {
xmpz::scan0(self, start)
}
#[inline]
pub fn find_one(&self, start: u32) -> Option<u32> {
xmpz::scan1(self, start)
}
#[inline]
pub fn set_bit(&mut self, index: u32, val: bool) -> &mut Self {
unsafe {
if val {
gmp::mpz_setbit(self.as_raw_mut(), index.into());
} else {
gmp::mpz_clrbit(self.as_raw_mut(), index.into());
}
}
self
}
#[inline]
pub fn get_bit(&self, index: u32) -> bool {
unsafe { gmp::mpz_tstbit(self.as_raw(), index.into()) != 0 }
}
#[inline]
pub fn toggle_bit(&mut self, index: u32) -> &mut Self {
unsafe {
gmp::mpz_combit(self.as_raw_mut(), index.into());
}
self
}
#[inline]
pub fn hamming_dist(&self, other: &Self) -> Option<u32> {
xmpz::hamdist(self, other)
}
#[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]
pub fn abs(mut self) -> Self {
self.abs_mut();
self
}
#[inline]
pub fn abs_mut(&mut self) {
xmpz::abs(self, None);
}
#[inline]
pub fn abs_ref(&self) -> AbsIncomplete {
AbsIncomplete { ref_self: self }
}
#[inline]
pub fn signum(mut self) -> Self {
self.signum_mut();
self
}
#[inline]
pub fn signum_mut(&mut self) {
xmpz::signum(self, None)
}
#[inline]
pub fn signum_ref(&self) -> SignumIncomplete {
SignumIncomplete { ref_self: self }
}
#[inline]
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]
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, None, n)
}
pub fn keep_bits_ref(&self, n: u32) -> KeepBitsIncomplete {
KeepBitsIncomplete { ref_self: self, n }
}
#[inline]
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, None, n);
}
#[inline]
pub fn keep_signed_bits_ref(&self, n: u32) -> KeepSignedBitsIncomplete<'_> {
KeepSignedBitsIncomplete { ref_self: self, n }
}
#[inline]
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, None);
}
#[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, None, None);
}
#[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, None, None);
}
#[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, None, None);
}
#[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, None, None);
}
#[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, None, None);
}
#[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_u32(self, modulo)
}
#[inline]
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, None, divisor);
}
pub fn div_exact_from(&mut self, dividend: &Integer) {
xmpz::check_div0(self);
unsafe {
gmp::mpz_divexact(self.as_raw_mut(), dividend.as_raw(), self.as_raw());
}
}
#[inline]
pub fn div_exact_ref<'a>(&'a self, divisor: &'a Self) -> DivExactIncomplete<'_> {
DivExactIncomplete {
ref_self: self,
divisor,
}
}
#[inline]
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, None, 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]
pub fn invert_mut(&mut self, modulo: &Self) -> Result<(), ()> {
match self.invert_ref(modulo) {
Some(InvertIncomplete { sinverse, .. }) => {
xmpz::finish_invert(self, Some(&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]
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(()),
};
xmpz::pow_mod(self, sinverse.as_ref(), 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]
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, None, 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]
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, None, n);
}
#[inline]
pub fn root_ref(&self, n: u32) -> RootIncomplete<'_> {
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, None, n);
}
#[inline]
pub fn root_rem_ref(&self, n: u32) -> RootRemIncomplete<'_> {
RootRemIncomplete { ref_self: self, n }
}
#[inline]
pub fn square(mut self) -> Self {
self.square_mut();
self
}
#[inline]
pub fn square_mut(&mut self) {
xmpz::square(self, None);
}
#[inline]
pub fn square_ref(&self) -> SquareIncomplete<'_> {
SquareIncomplete { ref_self: self }
}
#[inline]
pub fn sqrt(mut self) -> Self {
self.sqrt_mut();
self
}
#[inline]
pub fn sqrt_mut(&mut self) {
xmpz::sqrt(self, None);
}
#[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, None);
}
#[inline]
pub fn sqrt_rem_ref(&self) -> SqrtRemIncomplete<'_> {
SqrtRemIncomplete { ref_self: self }
}
#[inline]
pub fn is_probably_prime(&self, reps: u32) -> IsPrime {
let p = unsafe { gmp::mpz_probab_prime_p(self.as_raw(), reps.as_or_panic()) };
match p {
0 => IsPrime::No,
1 => IsPrime::Probably,
2 => IsPrime::Yes,
_ => unreachable!(),
}
}
#[inline]
pub fn next_prime(mut self) -> Self {
self.next_prime_mut();
self
}
#[inline]
pub fn next_prime_mut(&mut self) {
xmpz::nextprime(self, None);
}
#[inline]
pub fn next_prime_ref(&self) -> NextPrimeIncomplete<'_> {
NextPrimeIncomplete { ref_self: self }
}
#[inline]
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, None, other);
}
#[inline]
pub fn gcd_ref<'a>(&'a self, other: &'a Self) -> GcdIncomplete<'_> {
GcdIncomplete {
ref_self: self,
other,
}
}
#[inline]
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_u32(self, None, other);
}
#[inline]
pub fn gcd_u_ref(&self, other: u32) -> GcdUIncomplete<'_> {
GcdUIncomplete {
ref_self: self,
other,
}
}
#[inline]
pub fn gcd_cofactors(mut self, mut other: Self, mut rop: Self) -> (Self, Self, Self) {
self.gcd_cofactors_mut(&mut other, &mut rop);
(self, other, rop)
}
#[inline]
pub fn gcd_cofactors_mut(&mut self, other: &mut Self, rop: &mut Self) {
xmpz::gcdext(self, other, Some(rop), None, None);
}
#[inline]
pub fn gcd_cofactors_ref<'a>(&'a self, other: &'a Self) -> GcdIncomplete<'_> {
GcdIncomplete {
ref_self: self,
other,
}
}
#[inline]
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, None, other);
}
#[inline]
pub fn lcm_ref<'a>(&'a self, other: &'a Self) -> LcmIncomplete<'_> {
LcmIncomplete {
ref_self: self,
other,
}
}
#[inline]
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_u32(self, None, other);
}
#[inline]
pub fn lcm_u_ref(&self, other: u32) -> LcmUIncomplete<'_> {
LcmUIncomplete {
ref_self: self,
other,
}
}
#[inline]
pub fn jacobi(&self, n: &Self) -> i32 {
unsafe { gmp::mpz_jacobi(self.as_raw(), n.as_raw()) as i32 }
}
#[inline]
pub fn legendre(&self, p: &Self) -> i32 {
unsafe { gmp::mpz_legendre(self.as_raw(), p.as_raw()) as i32 }
}
#[inline]
pub fn kronecker(&self, n: &Self) -> i32 {
unsafe { gmp::mpz_kronecker(self.as_raw(), n.as_raw()) as i32 }
}
#[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, None, factor)
}
#[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 {
FactorialIncomplete { n }
}
#[inline]
pub fn factorial_2(n: u32) -> Factorial2Incomplete {
Factorial2Incomplete { n }
}
#[inline]
pub fn factorial_m(n: u32, m: u32) -> FactorialMIncomplete {
FactorialMIncomplete { n, m }
}
#[inline]
pub fn primorial(n: u32) -> PrimorialIncomplete {
PrimorialIncomplete { n }
}
#[inline]
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, None, k);
}
#[inline]
pub fn binomial_ref(&self, k: u32) -> BinomialIncomplete<'_> {
BinomialIncomplete { ref_self: self, k }
}
#[inline]
pub fn binomial_u(n: u32, k: u32) -> BinomialUIncomplete {
BinomialUIncomplete { n, k }
}
#[inline]
pub fn fibonacci(n: u32) -> FibonacciIncomplete {
FibonacciIncomplete { n }
}
#[inline]
pub fn fibonacci_2(n: u32) -> FibonacciIncomplete {
FibonacciIncomplete { n }
}
#[inline]
pub fn lucas(n: u32) -> LucasIncomplete {
LucasIncomplete { n }
}
#[inline]
pub fn lucas_2(n: u32) -> LucasIncomplete {
LucasIncomplete { n }
}
#[cfg(feature = "rand")]
#[inline]
pub fn random_bits(bits: u32, rng: &mut dyn MutRandState) -> RandomBitsIncomplete {
RandomBitsIncomplete { bits, rng }
}
#[cfg(feature = "rand")]
#[inline]
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.private().0, None);
}
#[cfg(feature = "rand")]
#[inline]
pub fn random_below_ref<'a>(
&'a self,
rng: &'a mut dyn MutRandState,
) -> RandomBelowIncomplete<'a> {
RandomBelowIncomplete {
ref_self: self,
rng,
}
}
}
#[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> 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> 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);
}
}
}
#[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> 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> 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);
}
}
}
#[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> 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> 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: u32 } }
ref_math_op1! { Integer; xmpz::keep_signed_bits; struct KeepSignedBitsIncomplete { n: u32 } }
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, Some(base), src.exponent, src.modulo);
}
(None, Some(sinverse)) => {
debug_assert_eq!(src.exponent.cmp0(), Ordering::Less);
xmpz::pow_mod(self, Some(&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, Some(base), src.exponent, src.modulo);
dst
}
(None, Some(mut sinverse)) => {
debug_assert_eq!(src.exponent.cmp0(), Ordering::Less);
xmpz::pow_mod(&mut sinverse, None, 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, Some(src.ref_self), src.exponent, src.modulo);
}
}
from_assign! { SecurePowModIncomplete<'_> => Integer }
ref_math_op0! { Integer; xmpz::ui_pow_ui; struct UPowUIncomplete { base: u32, exponent: u32 } }
ref_math_op0! { Integer; xmpz::si_pow_ui; struct IPowUIncomplete { base: i32, exponent: u32 } }
ref_math_op1! { Integer; xmpz::root; struct RootIncomplete { n: u32 } }
ref_math_op1_2! { Integer; xmpz::rootrem; struct RootRemIncomplete { n: u32 } }
ref_math_op1! { Integer; xmpz::square; struct SquareIncomplete {} }
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_u32; struct GcdUIncomplete { other: u32 } }
impl From<GcdUIncomplete<'_>> for Option<u32> {
#[inline]
fn from(src: GcdUIncomplete) -> Self {
let gcd = xmpz::gcd_ui(None, Some(src.ref_self), src.other.into());
if gcd == 0 && src.ref_self.cmp0() != Ordering::Equal {
None
} else {
gcd.checked_as()
}
}
}
impl Assign<GcdIncomplete<'_>> for (&mut Integer, &mut Integer) {
#[inline]
fn assign(&mut self, src: GcdIncomplete<'_>) {
xmpz::gcdext(self.0, self.1, None, Some(src.ref_self), Some(src.other));
}
}
impl Assign<GcdIncomplete<'_>> for (Integer, Integer) {
#[inline]
fn assign(&mut self, src: GcdIncomplete<'_>) {
(&mut self.0, &mut self.1).assign(src);
}
}
from_assign! { GcdIncomplete<'_> => Integer, Integer }
impl Assign<GcdIncomplete<'_>> for (&mut Integer, &mut Integer, &mut Integer) {
#[inline]
fn assign(&mut self, src: GcdIncomplete<'_>) {
xmpz::gcdext(
self.0,
self.1,
Some(self.2),
Some(src.ref_self),
Some(src.other),
);
}
}
impl Assign<GcdIncomplete<'_>> for (Integer, Integer, Integer) {
#[inline]
fn assign(&mut self, src: GcdIncomplete<'_>) {
(&mut self.0, &mut self.1, &mut self.2).assign(src);
}
}
from_assign! { GcdIncomplete<'_> => Integer, Integer, Integer }
ref_math_op2! { Integer; xmpz::lcm; struct LcmIncomplete { other } }
ref_math_op1! { Integer; xmpz::lcm_u32; struct LcmUIncomplete { other: u32 } }
#[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, Some(&src.sinverse), src.modulo);
}
}
impl From<InvertIncomplete<'_>> for Integer {
#[inline]
fn from(mut src: InvertIncomplete<'_>) -> Self {
xmpz::finish_invert(&mut src.sinverse, None, 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, Some(src.ref_self), src.factor);
}
}
impl Assign<RemoveFactorIncomplete<'_>> for (Integer, u32) {
#[inline]
fn assign(&mut self, src: RemoveFactorIncomplete<'_>) {
(&mut self.0, &mut self.1).assign(src);
}
}
impl From<RemoveFactorIncomplete<'_>> for (Integer, u32) {
#[inline]
fn from(src: RemoveFactorIncomplete<'_>) -> Self {
let mut dst = (Integer::new(), 0u32);
(&mut dst.0, &mut dst.1).assign(src);
dst
}
}
ref_math_op0! { Integer; xmpz::fac_ui; struct FactorialIncomplete { n: u32 } }
ref_math_op0! { Integer; xmpz::twofac_ui; struct Factorial2Incomplete { n: u32 } }
ref_math_op0! { Integer; xmpz::mfac_uiui; struct FactorialMIncomplete { n: u32, m: u32 } }
ref_math_op0! { Integer; xmpz::primorial_ui; struct PrimorialIncomplete { n: u32 } }
ref_math_op1! { Integer; xmpz::bin_ui; struct BinomialIncomplete { k: u32 } }
ref_math_op0! { Integer; xmpz::bin_uiui; struct BinomialUIncomplete { n: u32, k: u32 } }
ref_math_op0! { Integer; xmpz::fib_ui; struct FibonacciIncomplete { n: u32 } }
impl Assign<FibonacciIncomplete> for (&mut Integer, &mut Integer) {
#[inline]
fn assign(&mut self, src: FibonacciIncomplete) {
unsafe {
gmp::mpz_fib2_ui(self.0.as_raw_mut(), self.1.as_raw_mut(), src.n.into());
}
}
}
impl Assign<FibonacciIncomplete> for (Integer, Integer) {
#[inline]
fn assign(&mut self, src: FibonacciIncomplete) {
(&mut self.0, &mut self.1).assign(src);
}
}
from_assign! { FibonacciIncomplete => Integer, Integer }
ref_math_op0! { Integer; xmpz::lucnum_ui; struct LucasIncomplete { n: u32 } }
impl Assign<LucasIncomplete> for (&mut Integer, &mut Integer) {
#[inline]
fn assign(&mut self, src: LucasIncomplete) {
unsafe {
gmp::mpz_lucnum2_ui(self.0.as_raw_mut(), self.1.as_raw_mut(), src.n.into());
}
}
}
impl Assign<LucasIncomplete> for (Integer, Integer) {
#[inline]
fn assign(&mut self, src: LucasIncomplete) {
(&mut self.0, &mut self.1).assign(src);
}
}
from_assign! { LucasIncomplete => Integer, Integer }
#[cfg(feature = "rand")]
pub struct RandomBitsIncomplete<'a> {
bits: u32,
rng: &'a mut dyn MutRandState,
}
#[cfg(feature = "rand")]
impl Assign<RandomBitsIncomplete<'_>> for Integer {
#[inline]
fn assign(&mut self, src: RandomBitsIncomplete) {
unsafe {
gmp::mpz_urandomb(self.as_raw_mut(), src.rng.private().0, src.bits.into());
}
}
}
#[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.private().0, Some(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
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct BorrowInteger<'a> {
inner: ManuallyDrop<Integer>,
phantom: PhantomData<&'a Integer>,
}
impl BorrowInteger<'_> {
pub(crate) unsafe fn from_raw<'a>(raw: mpz_t) -> BorrowInteger<'a> {
BorrowInteger {
inner: ManuallyDrop::new(Integer::from_raw(raw)),
phantom: PhantomData,
}
}
}
impl Deref for BorrowInteger<'_> {
type Target = Integer;
#[inline]
fn deref(&self) -> &Integer {
&*self.inner
}
}
pub(crate) fn req_chars(i: &Integer, radix: i32, extra: usize) -> usize {
assert!(radix >= 2 && radix <= 36, "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 as c_int,
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) {
if src.digits.is_empty() {
xmpz::set_0(self);
return;
}
xmpz::realloc_for_mpn_set_str(self, src.digits.len(), src.radix);
unsafe {
let size = gmp::mpn_set_str(
self.inner.d,
src.digits.as_ptr(),
src.digits.len(),
src.radix,
);
self.inner.size = (if src.is_negative { -size } else { size }).as_or_panic();
}
}
}
from_assign! { ParseIncomplete => Integer }
fn parse(bytes: &[u8], radix: i32) -> Result<ParseIncomplete, ParseIntegerError> {
use self::{ParseErrorKind as Kind, ParseIntegerError as Error};
assert!(radix >= 2 && radix <= 36, "radix out of range");
let bradix = radix.as_or_panic::<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(Debug)]
pub struct ParseIntegerError {
kind: ParseErrorKind,
}
#[derive(Debug)]
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 Error for ParseIntegerError {
fn description(&self) -> &str {
self.desc()
}
}
impl Display for ParseIntegerError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(self.desc(), f)
}
}
#[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 {}