use core::fmt;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
#[non_exhaustive]
pub enum FromStrRadixErrKind {
InvalidCharacter,
InvalidLength,
UnsupportedRadix,
}
#[derive(Debug)]
enum FromStrRadixErrSrc {
Hex(FromHexError),
Dec(FromDecStrErr),
}
impl fmt::Display for FromStrRadixErrSrc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FromStrRadixErrSrc::Dec(d) => write!(f, "{}", d),
FromStrRadixErrSrc::Hex(h) => write!(f, "{}", h),
}
}
}
#[derive(Debug)]
pub struct FromStrRadixErr {
kind: FromStrRadixErrKind,
source: Option<FromStrRadixErrSrc>,
}
impl FromStrRadixErr {
#[doc(hidden)]
pub fn unsupported() -> Self {
Self { kind: FromStrRadixErrKind::UnsupportedRadix, source: None }
}
pub fn kind(&self) -> FromStrRadixErrKind {
self.kind
}
}
impl fmt::Display for FromStrRadixErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(ref src) = self.source {
return write!(f, "{}", src);
}
match self.kind {
FromStrRadixErrKind::UnsupportedRadix => write!(f, "the given radix is not supported"),
FromStrRadixErrKind::InvalidCharacter => write!(f, "input contains an invalid character"),
FromStrRadixErrKind::InvalidLength => write!(f, "length not supported for radix or type"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for FromStrRadixErr {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self.source {
Some(FromStrRadixErrSrc::Dec(ref d)) => Some(d),
Some(FromStrRadixErrSrc::Hex(ref h)) => Some(h),
None => None,
}
}
}
impl From<FromDecStrErr> for FromStrRadixErr {
fn from(e: FromDecStrErr) -> Self {
let kind = match e {
FromDecStrErr::InvalidCharacter => FromStrRadixErrKind::InvalidCharacter,
FromDecStrErr::InvalidLength => FromStrRadixErrKind::InvalidLength,
};
Self { kind, source: Some(FromStrRadixErrSrc::Dec(e)) }
}
}
impl From<FromHexError> for FromStrRadixErr {
fn from(e: FromHexError) -> Self {
let kind = match e.inner {
hex::FromHexError::InvalidHexCharacter { .. } => FromStrRadixErrKind::InvalidCharacter,
hex::FromHexError::InvalidStringLength => FromStrRadixErrKind::InvalidLength,
hex::FromHexError::OddLength => FromStrRadixErrKind::InvalidLength,
};
Self { kind, source: Some(FromStrRadixErrSrc::Hex(e)) }
}
}
#[derive(Debug, PartialEq)]
pub enum FromDecStrErr {
InvalidCharacter,
InvalidLength,
}
impl fmt::Display for FromDecStrErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
FromDecStrErr::InvalidCharacter => "a character is not in the range 0-9",
FromDecStrErr::InvalidLength => "the number is too large for the type",
}
)
}
}
#[cfg(feature = "std")]
impl std::error::Error for FromDecStrErr {}
#[derive(Debug)]
pub struct FromHexError {
inner: hex::FromHexError,
}
impl fmt::Display for FromHexError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.inner)
}
}
#[cfg(feature = "std")]
impl std::error::Error for FromHexError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.inner)
}
}
#[doc(hidden)]
impl From<hex::FromHexError> for FromHexError {
fn from(inner: hex::FromHexError) -> Self {
Self { inner }
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_map_from {
($thing:ident, $from:ty, $to:ty) => {
impl From<$from> for $thing {
fn from(value: $from) -> $thing {
From::from(value as $to)
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_try_from_for_primitive {
($from:ident, $to:ty) => {
impl $crate::core_::convert::TryFrom<$from> for $to {
type Error = &'static str;
#[inline]
fn try_from(u: $from) -> $crate::core_::result::Result<$to, &'static str> {
let $from(arr) = u;
if !u.fits_word() || arr[0] > <$to>::max_value() as u64 {
Err(concat!("integer overflow when casting to ", stringify!($to)))
} else {
Ok(arr[0] as $to)
}
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! uint_overflowing_binop {
($name:ident, $n_words: tt, $self_expr: expr, $other: expr, $fn:expr) => {{
use $crate::core_ as core;
let $name(ref me) = $self_expr;
let $name(ref you) = $other;
let mut ret = [0u64; $n_words];
let mut carry = 0u64;
$crate::static_assertions::const_assert!(core::isize::MAX as usize / core::mem::size_of::<u64>() > $n_words);
use $crate::unroll;
unroll! {
for i in 0..$n_words {
use core::ptr;
if carry != 0 {
let (res1, overflow1) = ($fn)(me[i], you[i]);
let (res2, overflow2) = ($fn)(res1, carry);
ret[i] = res2;
carry = (overflow1 as u8 + overflow2 as u8) as u64;
} else {
let (res, overflow) = ($fn)(me[i], you[i]);
ret[i] = res;
carry = overflow as u64;
}
}
}
($name(ret), carry > 0)
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! uint_full_mul_reg {
($name:ident, 8, $self_expr:expr, $other:expr) => {
$crate::uint_full_mul_reg!($name, 8, $self_expr, $other, |a, b| a != 0 || b != 0);
};
($name:ident, $n_words:tt, $self_expr:expr, $other:expr) => {
$crate::uint_full_mul_reg!($name, $n_words, $self_expr, $other, |_, _| true);
};
($name:ident, $n_words:tt, $self_expr:expr, $other:expr, $check:expr) => {{
{
#![allow(unused_assignments)]
let $name(ref me) = $self_expr;
let $name(ref you) = $other;
let mut ret = [0u64; $n_words * 2];
use $crate::unroll;
unroll! {
for i in 0..$n_words {
let mut carry = 0u64;
let b = you[i];
unroll! {
for j in 0..$n_words {
if $check(me[j], carry) {
let a = me[j];
let (hi, low) = Self::split_u128(a as u128 * b as u128);
let overflow = {
let existing_low = &mut ret[i + j];
let (low, o) = low.overflowing_add(*existing_low);
*existing_low = low;
o
};
carry = {
let existing_hi = &mut ret[i + j + 1];
let hi = hi + overflow as u64;
let (hi, o0) = hi.overflowing_add(carry);
let (hi, o1) = hi.overflowing_add(*existing_hi);
*existing_hi = hi;
(o0 | o1) as u64
}
}
}
}
}
}
ret
}
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! uint_overflowing_mul {
($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => {{
let ret: [u64; $n_words * 2] = $crate::uint_full_mul_reg!($name, $n_words, $self_expr, $other);
let ret: [[u64; $n_words]; 2] = unsafe { $crate::core_::mem::transmute(ret) };
#[inline(always)]
fn any_nonzero(arr: &[u64; $n_words]) -> bool {
use $crate::unroll;
unroll! {
for i in 0..$n_words {
if arr[i] != 0 {
return true;
}
}
}
false
}
($name(ret[0]), any_nonzero(&ret[1]))
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! overflowing {
($op: expr, $overflow: expr) => {{
let (overflow_x, overflow_overflow) = $op;
$overflow |= overflow_overflow;
overflow_x
}};
($op: expr) => {{
let (overflow_x, _overflow_overflow) = $op;
overflow_x
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! panic_on_overflow {
($name: expr) => {
if $name {
panic!("arithmetic operation overflow")
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_mul_from {
($name: ty, $other: ident) => {
impl $crate::core_::ops::Mul<$other> for $name {
type Output = $name;
fn mul(self, other: $other) -> $name {
let bignum: $name = other.into();
let (result, overflow) = self.overflowing_mul(bignum);
$crate::panic_on_overflow!(overflow);
result
}
}
impl<'a> $crate::core_::ops::Mul<&'a $other> for $name {
type Output = $name;
fn mul(self, other: &'a $other) -> $name {
let bignum: $name = (*other).into();
let (result, overflow) = self.overflowing_mul(bignum);
$crate::panic_on_overflow!(overflow);
result
}
}
impl<'a> $crate::core_::ops::Mul<&'a $other> for &'a $name {
type Output = $name;
fn mul(self, other: &'a $other) -> $name {
let bignum: $name = (*other).into();
let (result, overflow) = self.overflowing_mul(bignum);
$crate::panic_on_overflow!(overflow);
result
}
}
impl<'a> $crate::core_::ops::Mul<$other> for &'a $name {
type Output = $name;
fn mul(self, other: $other) -> $name {
let bignum: $name = other.into();
let (result, overflow) = self.overflowing_mul(bignum);
$crate::panic_on_overflow!(overflow);
result
}
}
impl $crate::core_::ops::MulAssign<$other> for $name {
fn mul_assign(&mut self, other: $other) {
let result = *self * other;
*self = result
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_mul_for_primitive {
($name: ty, $other: ident) => {
impl $crate::core_::ops::Mul<$other> for $name {
type Output = $name;
fn mul(self, other: $other) -> $name {
let (result, carry) = self.overflowing_mul_u64(other as u64);
$crate::panic_on_overflow!(carry > 0);
result
}
}
impl<'a> $crate::core_::ops::Mul<&'a $other> for $name {
type Output = $name;
fn mul(self, other: &'a $other) -> $name {
let (result, carry) = self.overflowing_mul_u64(*other as u64);
$crate::panic_on_overflow!(carry > 0);
result
}
}
impl<'a> $crate::core_::ops::Mul<&'a $other> for &'a $name {
type Output = $name;
fn mul(self, other: &'a $other) -> $name {
let (result, carry) = self.overflowing_mul_u64(*other as u64);
$crate::panic_on_overflow!(carry > 0);
result
}
}
impl<'a> $crate::core_::ops::Mul<$other> for &'a $name {
type Output = $name;
fn mul(self, other: $other) -> $name {
let (result, carry) = self.overflowing_mul_u64(other as u64);
$crate::panic_on_overflow!(carry > 0);
result
}
}
impl $crate::core_::ops::MulAssign<$other> for $name {
fn mul_assign(&mut self, other: $other) {
let result = *self * (other as u64);
*self = result
}
}
};
}
#[macro_export]
macro_rules! construct_uint {
( $(#[$attr:meta])* $visibility:vis struct $name:ident (1); ) => {
$crate::construct_uint!{ @construct $(#[$attr])* $visibility struct $name (1); }
};
( $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => {
$crate::construct_uint! { @construct $(#[$attr])* $visibility struct $name ($n_words); }
impl $crate::core_::convert::From<u128> for $name {
fn from(value: u128) -> $name {
let mut ret = [0; $n_words];
ret[0] = value as u64;
ret[1] = (value >> 64) as u64;
$name(ret)
}
}
impl $crate::core_::convert::From<i128> for $name {
fn from(value: i128) -> $name {
match value >= 0 {
true => From::from(value as u128),
false => { panic!("Unsigned integer can't be created from negative value"); }
}
}
}
impl $name {
#[inline]
pub const fn low_u128(&self) -> u128 {
let &$name(ref arr) = self;
((arr[1] as u128) << 64) + arr[0] as u128
}
#[inline]
pub fn as_u128(&self) -> u128 {
let &$name(ref arr) = self;
for i in 2..$n_words {
if arr[i] != 0 {
panic!("Integer overflow when casting to u128")
}
}
self.low_u128()
}
}
impl $crate::core_::convert::TryFrom<$name> for u128 {
type Error = &'static str;
#[inline]
fn try_from(u: $name) -> $crate::core_::result::Result<u128, &'static str> {
let $name(arr) = u;
for i in 2..$n_words {
if arr[i] != 0 {
return Err("integer overflow when casting to u128");
}
}
Ok(((arr[1] as u128) << 64) + arr[0] as u128)
}
}
impl $crate::core_::convert::TryFrom<$name> for i128 {
type Error = &'static str;
#[inline]
fn try_from(u: $name) -> $crate::core_::result::Result<i128, &'static str> {
let err_str = "integer overflow when casting to i128";
let i = u128::try_from(u).map_err(|_| err_str)?;
if i > i128::max_value() as u128 {
Err(err_str)
} else {
Ok(i as i128)
}
}
}
};
( @construct $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => {
#[repr(C)]
$(#[$attr])*
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
$visibility struct $name (pub [u64; $n_words]);
impl AsRef<[u64]> for $name {
#[inline]
fn as_ref(&self) -> &[u64] {
&self.0
}
}
impl<'a> From<&'a $name> for $name {
fn from(x: &'a $name) -> $name {
*x
}
}
impl $name {
const WORD_BITS: usize = 64;
pub const MAX: $name = $name([u64::max_value(); $n_words]);
pub fn from_str_radix(txt: &str, radix: u32) -> Result<Self, $crate::FromStrRadixErr> {
let parsed = match radix {
10 => Self::from_dec_str(txt)?,
16 => core::str::FromStr::from_str(txt)?,
_ => return Err($crate::FromStrRadixErr::unsupported()),
};
Ok(parsed)
}
pub fn from_dec_str(value: &str) -> $crate::core_::result::Result<Self, $crate::FromDecStrErr> {
let mut res = Self::default();
for b in value.bytes().map(|b| b.wrapping_sub(b'0')) {
if b > 9 {
return Err($crate::FromDecStrErr::InvalidCharacter)
}
let (r, overflow) = res.overflowing_mul_u64(10);
if overflow > 0 {
return Err($crate::FromDecStrErr::InvalidLength);
}
let (r, overflow) = r.overflowing_add(b.into());
if overflow {
return Err($crate::FromDecStrErr::InvalidLength);
}
res = r;
}
Ok(res)
}
#[inline]
pub const fn low_u32(&self) -> u32 {
let &$name(ref arr) = self;
arr[0] as u32
}
#[inline]
pub const fn low_u64(&self) -> u64 {
let &$name(ref arr) = self;
arr[0]
}
#[inline]
pub fn as_u32(&self) -> u32 {
let &$name(ref arr) = self;
if !self.fits_word() || arr[0] > u32::max_value() as u64 {
panic!("Integer overflow when casting to u32")
}
self.as_u64() as u32
}
#[inline]
pub fn as_u64(&self) -> u64 {
let &$name(ref arr) = self;
if !self.fits_word() {
panic!("Integer overflow when casting to u64")
}
arr[0]
}
#[inline]
pub fn as_usize(&self) -> usize {
let &$name(ref arr) = self;
if !self.fits_word() || arr[0] > usize::max_value() as u64 {
panic!("Integer overflow when casting to usize")
}
arr[0] as usize
}
#[inline]
pub const fn is_zero(&self) -> bool {
let &$name(ref arr) = self;
let mut i = 0;
while i < $n_words { if arr[i] != 0 { return false; } else { i += 1; } }
return true;
}
#[inline]
fn fits_word(&self) -> bool {
let &$name(ref arr) = self;
for i in 1..$n_words { if arr[i] != 0 { return false; } }
return true;
}
#[inline]
pub fn bits(&self) -> usize {
let &$name(ref arr) = self;
for i in 1..$n_words {
if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; }
}
0x40 - arr[0].leading_zeros() as usize
}
#[inline]
pub const fn bit(&self, index: usize) -> bool {
let &$name(ref arr) = self;
arr[index / 64] & (1 << (index % 64)) != 0
}
pub fn leading_zeros(&self) -> u32 {
let mut r = 0;
for i in 0..$n_words {
let w = self.0[$n_words - i - 1];
if w == 0 {
r += 64;
} else {
r += w.leading_zeros();
break;
}
}
r
}
pub fn trailing_zeros(&self) -> u32 {
let mut r = 0;
for i in 0..$n_words {
let w = self.0[i];
if w == 0 {
r += 64;
} else {
r += w.trailing_zeros();
break;
}
}
r
}
#[inline]
pub const fn byte(&self, index: usize) -> u8 {
let &$name(ref arr) = self;
(arr[index / 8] >> (((index % 8)) * 8)) as u8
}
#[inline]
pub fn to_big_endian(&self, bytes: &mut [u8]) {
use $crate::byteorder::{ByteOrder, BigEndian};
debug_assert!($n_words * 8 == bytes.len());
for i in 0..$n_words {
BigEndian::write_u64(&mut bytes[8 * i..], self.0[$n_words - i - 1]);
}
}
#[inline]
pub fn to_little_endian(&self, bytes: &mut [u8]) {
use $crate::byteorder::{ByteOrder, LittleEndian};
debug_assert!($n_words * 8 == bytes.len());
for i in 0..$n_words {
LittleEndian::write_u64(&mut bytes[8 * i..], self.0[i]);
}
}
#[inline]
pub fn exp10(n: usize) -> Self {
match n {
0 => Self::from(1u64),
_ => Self::exp10(n - 1) * 10u32
}
}
#[inline]
pub const fn zero() -> Self {
Self([0; $n_words])
}
#[inline]
pub const fn one() -> Self {
let mut words = [0; $n_words];
words[0] = 1u64;
Self(words)
}
#[inline]
pub const fn max_value() -> Self {
Self::MAX
}
fn full_shl(self, shift: u32) -> [u64; $n_words + 1] {
debug_assert!(shift < Self::WORD_BITS as u32);
let mut u = [0u64; $n_words + 1];
let u_lo = self.0[0] << shift;
let u_hi = self >> (Self::WORD_BITS as u32 - shift);
u[0] = u_lo;
u[1..].copy_from_slice(&u_hi.0[..]);
u
}
fn full_shr(u: [u64; $n_words + 1], shift: u32) -> Self {
debug_assert!(shift < Self::WORD_BITS as u32);
let mut res = Self::zero();
for i in 0..$n_words {
res.0[i] = u[i] >> shift;
}
if shift > 0 {
for i in 1..=$n_words {
res.0[i - 1] |= u[i] << (Self::WORD_BITS as u32 - shift);
}
}
res
}
fn full_mul_u64(self, by: u64) -> [u64; $n_words + 1] {
let (prod, carry) = self.overflowing_mul_u64(by);
let mut res = [0u64; $n_words + 1];
res[..$n_words].copy_from_slice(&prod.0[..]);
res[$n_words] = carry;
res
}
fn div_mod_small(mut self, other: u64) -> (Self, Self) {
let mut rem = 0u64;
self.0.iter_mut().rev().for_each(|d| {
let (q, r) = Self::div_mod_word(rem, *d, other);
*d = q;
rem = r;
});
(self, rem.into())
}
fn div_mod_knuth(self, mut v: Self, n: usize, m: usize) -> (Self, Self) {
debug_assert!(self.bits() >= v.bits() && !v.fits_word());
debug_assert!(n + m <= $n_words);
let shift = v.0[n - 1].leading_zeros();
v <<= shift;
let mut u = self.full_shl(shift);
let mut q = Self::zero();
let v_n_1 = v.0[n - 1];
let v_n_2 = v.0[n - 2];
for j in (0..=m).rev() {
let u_jn = u[j + n];
let mut q_hat = if u_jn < v_n_1 {
let (mut q_hat, mut r_hat) = Self::div_mod_word(u_jn, u[j + n - 1], v_n_1);
loop {
let (hi, lo) = Self::split_u128(u128::from(q_hat) * u128::from(v_n_2));
if (hi, lo) <= (r_hat, u[j + n - 2]) {
break;
}
q_hat -= 1;
let (new_r_hat, overflow) = r_hat.overflowing_add(v_n_1);
r_hat = new_r_hat;
if overflow {
break;
}
}
q_hat
} else {
u64::max_value()
};
let q_hat_v = v.full_mul_u64(q_hat);
let c = Self::sub_slice(&mut u[j..], &q_hat_v[..n + 1]);
if c {
q_hat -= 1;
let c = Self::add_slice(&mut u[j..], &v.0[..n]);
u[j + n] = u[j + n].wrapping_add(u64::from(c));
}
q.0[j] = q_hat;
}
let remainder = Self::full_shr(u, shift);
(q, remainder)
}
fn words(bits: usize) -> usize {
debug_assert!(bits > 0);
1 + (bits - 1) / Self::WORD_BITS
}
pub fn div_mod(mut self, mut other: Self) -> (Self, Self) {
use $crate::core_::cmp::Ordering;
let my_bits = self.bits();
let your_bits = other.bits();
assert!(your_bits != 0, "division by zero");
if my_bits < your_bits {
return (Self::zero(), self);
}
if your_bits <= Self::WORD_BITS {
return self.div_mod_small(other.low_u64());
}
let (n, m) = {
let my_words = Self::words(my_bits);
let your_words = Self::words(your_bits);
(your_words, my_words - your_words)
};
self.div_mod_knuth(other, n, m)
}
pub fn integer_sqrt(&self) -> Self {
let one = Self::one();
if self <= &one {
return *self;
}
let shift: u32 = (self.bits() as u32 + 1) / 2;
let mut x_prev = one << shift;
loop {
let x = (x_prev + self / x_prev) >> 1;
if x >= x_prev {
return x_prev;
}
x_prev = x;
}
}
pub fn pow(self, expon: Self) -> Self {
if expon.is_zero() {
return Self::one()
}
let is_even = |x : &Self| x.low_u64() & 1 == 0;
let u_one = Self::one();
let mut y = u_one;
let mut n = expon;
let mut x = self;
while n > u_one {
if is_even(&n) {
x = x * x;
n = n >> 1usize;
} else {
y = x * y;
x = x * x;
n.0[$n_words-1] = n.0[$n_words-1] & ((!0u64)>>1);
n = n >> 1usize;
}
}
x * y
}
pub fn overflowing_pow(self, expon: Self) -> (Self, bool) {
if expon.is_zero() { return (Self::one(), false) }
let is_even = |x : &Self| x.low_u64() & 1 == 0;
let u_one = Self::one();
let mut y = u_one;
let mut n = expon;
let mut x = self;
let mut overflow = false;
while n > u_one {
if is_even(&n) {
x = $crate::overflowing!(x.overflowing_mul(x), overflow);
n = n >> 1usize;
} else {
y = $crate::overflowing!(x.overflowing_mul(y), overflow);
x = $crate::overflowing!(x.overflowing_mul(x), overflow);
n = (n - u_one) >> 1usize;
}
}
let res = $crate::overflowing!(x.overflowing_mul(y), overflow);
(res, overflow)
}
pub fn checked_pow(self, expon: $name) -> Option<$name> {
match self.overflowing_pow(expon) {
(_, true) => None,
(val, _) => Some(val),
}
}
#[inline(always)]
pub fn overflowing_add(self, other: $name) -> ($name, bool) {
$crate::uint_overflowing_binop!(
$name,
$n_words,
self,
other,
u64::overflowing_add
)
}
pub fn saturating_add(self, other: $name) -> $name {
match self.overflowing_add(other) {
(_, true) => $name::MAX,
(val, false) => val,
}
}
pub fn checked_add(self, other: $name) -> Option<$name> {
match self.overflowing_add(other) {
(_, true) => None,
(val, _) => Some(val),
}
}
#[inline(always)]
pub fn overflowing_sub(self, other: $name) -> ($name, bool) {
$crate::uint_overflowing_binop!(
$name,
$n_words,
self,
other,
u64::overflowing_sub
)
}
pub fn saturating_sub(self, other: $name) -> $name {
match self.overflowing_sub(other) {
(_, true) => $name::zero(),
(val, false) => val,
}
}
pub fn checked_sub(self, other: $name) -> Option<$name> {
match self.overflowing_sub(other) {
(_, true) => None,
(val, _) => Some(val),
}
}
pub fn abs_diff(self, other: $name) -> $name {
if self > other {
self.overflowing_sub(other).0
} else {
other.overflowing_sub(self).0
}
}
#[inline(always)]
pub fn overflowing_mul(self, other: $name) -> ($name, bool) {
$crate::uint_overflowing_mul!($name, $n_words, self, other)
}
pub fn saturating_mul(self, other: $name) -> $name {
match self.overflowing_mul(other) {
(_, true) => $name::MAX,
(val, false) => val,
}
}
pub fn checked_mul(self, other: $name) -> Option<$name> {
match self.overflowing_mul(other) {
(_, true) => None,
(val, _) => Some(val),
}
}
pub fn checked_div(self, other: $name) -> Option<$name> {
if other.is_zero() {
None
} else {
Some(self / other)
}
}
pub fn checked_rem(self, other: $name) -> Option<$name> {
if other.is_zero() {
None
} else {
Some(self % other)
}
}
pub fn overflowing_neg(self) -> ($name, bool) {
if self.is_zero() {
(self, false)
} else {
(!self + 1, true)
}
}
pub fn checked_neg(self) -> Option<$name> {
match self.overflowing_neg() {
(_, true) => None,
(zero, false) => Some(zero),
}
}
#[inline(always)]
fn div_mod_word(hi: u64, lo: u64, y: u64) -> (u64, u64) {
debug_assert!(hi < y);
let x = (u128::from(hi) << 64) + u128::from(lo);
let y = u128::from(y);
((x / y) as u64, (x % y) as u64)
}
#[inline(always)]
fn add_slice(a: &mut [u64], b: &[u64]) -> bool {
Self::binop_slice(a, b, u64::overflowing_add)
}
#[inline(always)]
fn sub_slice(a: &mut [u64], b: &[u64]) -> bool {
Self::binop_slice(a, b, u64::overflowing_sub)
}
#[inline(always)]
fn binop_slice(a: &mut [u64], b: &[u64], binop: impl Fn(u64, u64) -> (u64, bool) + Copy) -> bool {
let mut c = false;
a.iter_mut().zip(b.iter()).for_each(|(x, y)| {
let (res, carry) = Self::binop_carry(*x, *y, c, binop);
*x = res;
c = carry;
});
c
}
#[inline(always)]
fn binop_carry(a: u64, b: u64, c: bool, binop: impl Fn(u64, u64) -> (u64, bool)) -> (u64, bool) {
let (res1, overflow1) = b.overflowing_add(u64::from(c));
let (res2, overflow2) = binop(a, res1);
(res2, overflow1 || overflow2)
}
#[inline(always)]
const fn mul_u64(a: u64, b: u64, carry: u64) -> (u64, u64) {
let (hi, lo) = Self::split_u128(a as u128 * b as u128 + carry as u128);
(lo, hi)
}
#[inline(always)]
const fn split(a: u64) -> (u64, u64) {
(a >> 32, a & 0xFFFF_FFFF)
}
#[inline(always)]
const fn split_u128(a: u128) -> (u64, u64) {
((a >> 64) as _, (a & 0xFFFFFFFFFFFFFFFF) as _)
}
fn overflowing_mul_u64(mut self, other: u64) -> (Self, u64) {
let mut carry = 0u64;
for d in self.0.iter_mut() {
let (res, c) = Self::mul_u64(*d, other, carry);
*d = res;
carry = c;
}
(self, carry)
}
pub fn from_big_endian(slice: &[u8]) -> Self {
use $crate::byteorder::{ByteOrder, BigEndian};
assert!($n_words * 8 >= slice.len());
let mut padded = [0u8; $n_words * 8];
padded[$n_words * 8 - slice.len() .. $n_words * 8].copy_from_slice(&slice);
let mut ret = [0; $n_words];
for i in 0..$n_words {
ret[$n_words - i - 1] = BigEndian::read_u64(&padded[8 * i..]);
}
$name(ret)
}
pub fn from_little_endian(slice: &[u8]) -> Self {
use $crate::byteorder::{ByteOrder, LittleEndian};
assert!($n_words * 8 >= slice.len());
let mut padded = [0u8; $n_words * 8];
padded[0..slice.len()].copy_from_slice(&slice);
let mut ret = [0; $n_words];
for i in 0..$n_words {
ret[i] = LittleEndian::read_u64(&padded[8 * i..]);
}
$name(ret)
}
fn fmt_hex(&self, f: &mut $crate::core_::fmt::Formatter, is_lower: bool) -> $crate::core_::fmt::Result {
let &$name(ref data) = self;
if self.is_zero() {
return f.pad_integral(true, "0x", "0");
}
let mut latch = false;
let mut buf = [0_u8; $n_words * 16];
let mut i = 0;
for ch in data.iter().rev() {
for x in 0..16 {
let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64);
if !latch {
latch = nibble != 0;
}
if latch {
let nibble = match nibble {
0..=9 => nibble as u8 + b'0',
_ if is_lower => nibble as u8 - 10 + b'a',
_ => nibble as u8 - 10 + b'A',
};
buf[i] = nibble;
i += 1;
}
}
}
let s = unsafe {
$crate::core_::str::from_utf8_unchecked(&buf[0..i])
};
f.pad_integral(true, "0x", s)
}
}
impl $crate::core_::convert::From<$name> for [u8; $n_words * 8] {
fn from(number: $name) -> Self {
let mut arr = [0u8; $n_words * 8];
number.to_big_endian(&mut arr);
arr
}
}
impl $crate::core_::convert::From<[u8; $n_words * 8]> for $name {
fn from(bytes: [u8; $n_words * 8]) -> Self {
Self::from(&bytes)
}
}
impl<'a> $crate::core_::convert::From<&'a [u8; $n_words * 8]> for $name {
fn from(bytes: &[u8; $n_words * 8]) -> Self {
Self::from(&bytes[..])
}
}
impl $crate::core_::default::Default for $name {
fn default() -> Self {
$name::zero()
}
}
impl $crate::core_::convert::From<u64> for $name {
fn from(value: u64) -> $name {
let mut ret = [0; $n_words];
ret[0] = value;
$name(ret)
}
}
$crate::impl_map_from!($name, u8, u64);
$crate::impl_map_from!($name, u16, u64);
$crate::impl_map_from!($name, u32, u64);
$crate::impl_map_from!($name, usize, u64);
impl $crate::core_::convert::From<i64> for $name {
fn from(value: i64) -> $name {
match value >= 0 {
true => From::from(value as u64),
false => { panic!("Unsigned integer can't be created from negative value"); }
}
}
}
$crate::impl_map_from!($name, i8, i64);
$crate::impl_map_from!($name, i16, i64);
$crate::impl_map_from!($name, i32, i64);
$crate::impl_map_from!($name, isize, i64);
impl<'a> $crate::core_::convert::From<&'a [u8]> for $name {
fn from(bytes: &[u8]) -> $name {
Self::from_big_endian(bytes)
}
}
$crate::impl_try_from_for_primitive!($name, u8);
$crate::impl_try_from_for_primitive!($name, u16);
$crate::impl_try_from_for_primitive!($name, u32);
$crate::impl_try_from_for_primitive!($name, usize);
$crate::impl_try_from_for_primitive!($name, u64);
$crate::impl_try_from_for_primitive!($name, i8);
$crate::impl_try_from_for_primitive!($name, i16);
$crate::impl_try_from_for_primitive!($name, i32);
$crate::impl_try_from_for_primitive!($name, isize);
$crate::impl_try_from_for_primitive!($name, i64);
impl<T> $crate::core_::ops::Add<T> for $name where T: Into<$name> {
type Output = $name;
fn add(self, other: T) -> $name {
let (result, overflow) = self.overflowing_add(other.into());
$crate::panic_on_overflow!(overflow);
result
}
}
impl<'a, T> $crate::core_::ops::Add<T> for &'a $name where T: Into<$name> {
type Output = $name;
fn add(self, other: T) -> $name {
*self + other
}
}
impl $crate::core_::ops::AddAssign<$name> for $name {
fn add_assign(&mut self, other: $name) {
let (result, overflow) = self.overflowing_add(other);
$crate::panic_on_overflow!(overflow);
*self = result
}
}
impl<T> $crate::core_::ops::Sub<T> for $name where T: Into<$name> {
type Output = $name;
#[inline]
fn sub(self, other: T) -> $name {
let (result, overflow) = self.overflowing_sub(other.into());
$crate::panic_on_overflow!(overflow);
result
}
}
impl<'a, T> $crate::core_::ops::Sub<T> for &'a $name where T: Into<$name> {
type Output = $name;
fn sub(self, other: T) -> $name {
*self - other
}
}
impl $crate::core_::ops::SubAssign<$name> for $name {
fn sub_assign(&mut self, other: $name) {
let (result, overflow) = self.overflowing_sub(other);
$crate::panic_on_overflow!(overflow);
*self = result
}
}
$crate::impl_mul_from!($name, $name);
$crate::impl_mul_for_primitive!($name, u8);
$crate::impl_mul_for_primitive!($name, u16);
$crate::impl_mul_for_primitive!($name, u32);
$crate::impl_mul_for_primitive!($name, u64);
$crate::impl_mul_for_primitive!($name, usize);
$crate::impl_mul_for_primitive!($name, i8);
$crate::impl_mul_for_primitive!($name, i16);
$crate::impl_mul_for_primitive!($name, i32);
$crate::impl_mul_for_primitive!($name, i64);
$crate::impl_mul_for_primitive!($name, isize);
impl<T> $crate::core_::ops::Div<T> for $name where T: Into<$name> {
type Output = $name;
fn div(self, other: T) -> $name {
let other: Self = other.into();
self.div_mod(other).0
}
}
impl<'a, T> $crate::core_::ops::Div<T> for &'a $name where T: Into<$name> {
type Output = $name;
fn div(self, other: T) -> $name {
*self / other
}
}
impl<T> $crate::core_::ops::DivAssign<T> for $name where T: Into<$name> {
fn div_assign(&mut self, other: T) {
*self = *self / other.into();
}
}
impl<T> $crate::core_::ops::Rem<T> for $name where T: Into<$name> + Copy {
type Output = $name;
fn rem(self, other: T) -> $name {
let mut sub_copy = self;
sub_copy %= other;
sub_copy
}
}
impl<'a, T> $crate::core_::ops::Rem<T> for &'a $name where T: Into<$name> + Copy {
type Output = $name;
fn rem(self, other: T) -> $name {
*self % other
}
}
impl<T> $crate::core_::ops::RemAssign<T> for $name where T: Into<$name> + Copy {
fn rem_assign(&mut self, other: T) {
let other: Self = other.into();
let rem = self.div_mod(other).1;
*self = rem;
}
}
impl $crate::core_::ops::BitAnd<$name> for $name {
type Output = $name;
#[inline]
fn bitand(self, other: $name) -> $name {
let $name(ref arr1) = self;
let $name(ref arr2) = other;
let mut ret = [0u64; $n_words];
for i in 0..$n_words {
ret[i] = arr1[i] & arr2[i];
}
$name(ret)
}
}
impl $crate::core_::ops::BitAndAssign<$name> for $name {
fn bitand_assign(&mut self, rhs: $name) {
*self = *self & rhs;
}
}
impl $crate::core_::ops::BitXor<$name> for $name {
type Output = $name;
#[inline]
fn bitxor(self, other: $name) -> $name {
let $name(ref arr1) = self;
let $name(ref arr2) = other;
let mut ret = [0u64; $n_words];
for i in 0..$n_words {
ret[i] = arr1[i] ^ arr2[i];
}
$name(ret)
}
}
impl $crate::core_::ops::BitXorAssign<$name> for $name {
fn bitxor_assign(&mut self, rhs: $name) {
*self = *self ^ rhs;
}
}
impl $crate::core_::ops::BitOr<$name> for $name {
type Output = $name;
#[inline]
fn bitor(self, other: $name) -> $name {
let $name(ref arr1) = self;
let $name(ref arr2) = other;
let mut ret = [0u64; $n_words];
for i in 0..$n_words {
ret[i] = arr1[i] | arr2[i];
}
$name(ret)
}
}
impl $crate::core_::ops::BitOrAssign<$name> for $name {
fn bitor_assign(&mut self, rhs: $name) {
*self = *self | rhs;
}
}
impl $crate::core_::ops::Not for $name {
type Output = $name;
#[inline]
fn not(self) -> $name {
let $name(ref arr) = self;
let mut ret = [0u64; $n_words];
for i in 0..$n_words {
ret[i] = !arr[i];
}
$name(ret)
}
}
impl<T> $crate::core_::ops::Shl<T> for $name where T: Into<$name> {
type Output = $name;
fn shl(self, shift: T) -> $name {
let shift = shift.into().as_usize();
let $name(ref original) = self;
let mut ret = [0u64; $n_words];
let word_shift = shift / 64;
let bit_shift = shift % 64;
for i in word_shift..$n_words {
ret[i] = original[i - word_shift] << bit_shift;
}
if bit_shift > 0 {
for i in word_shift+1..$n_words {
ret[i] += original[i - 1 - word_shift] >> (64 - bit_shift);
}
}
$name(ret)
}
}
impl<'a, T> $crate::core_::ops::Shl<T> for &'a $name where T: Into<$name> {
type Output = $name;
fn shl(self, shift: T) -> $name {
*self << shift
}
}
impl<T> $crate::core_::ops::ShlAssign<T> for $name where T: Into<$name> {
fn shl_assign(&mut self, shift: T) {
*self = *self << shift;
}
}
impl<T> $crate::core_::ops::Shr<T> for $name where T: Into<$name> {
type Output = $name;
fn shr(self, shift: T) -> $name {
let shift = shift.into().as_usize();
let $name(ref original) = self;
let mut ret = [0u64; $n_words];
let word_shift = shift / 64;
let bit_shift = shift % 64;
for i in word_shift..$n_words {
ret[i - word_shift] = original[i] >> bit_shift;
}
if bit_shift > 0 {
for i in word_shift+1..$n_words {
ret[i - word_shift - 1] += original[i] << (64 - bit_shift);
}
}
$name(ret)
}
}
impl<'a, T> $crate::core_::ops::Shr<T> for &'a $name where T: Into<$name> {
type Output = $name;
fn shr(self, shift: T) -> $name {
*self >> shift
}
}
impl<T> $crate::core_::ops::ShrAssign<T> for $name where T: Into<$name> {
fn shr_assign(&mut self, shift: T) {
*self = *self >> shift;
}
}
impl $crate::core_::cmp::Ord for $name {
fn cmp(&self, other: &$name) -> $crate::core_::cmp::Ordering {
self.as_ref().iter().rev().cmp(other.as_ref().iter().rev())
}
}
impl $crate::core_::cmp::PartialOrd for $name {
fn partial_cmp(&self, other: &$name) -> Option<$crate::core_::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl $crate::core_::fmt::Debug for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
$crate::core_::fmt::Display::fmt(self, f)
}
}
impl $crate::core_::fmt::Display for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
if self.is_zero() {
return $crate::core_::write!(f, "0");
}
let mut buf = [0_u8; $n_words*20];
let mut i = buf.len() - 1;
let mut current = *self;
let ten = $name::from(10);
loop {
let digit = (current % ten).low_u64() as u8;
buf[i] = digit + b'0';
current = current / ten;
if current.is_zero() {
break;
}
i -= 1;
}
let s = unsafe {
$crate::core_::str::from_utf8_unchecked(&buf[i..])
};
f.pad_integral(true, "", s)
}
}
impl $crate::core_::fmt::LowerHex for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
self.fmt_hex(f, true)
}
}
impl $crate::core_::fmt::UpperHex for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
self.fmt_hex(f, false)
}
}
impl $crate::core_::str::FromStr for $name {
type Err = $crate::FromHexError;
fn from_str(value: &str) -> $crate::core_::result::Result<$name, Self::Err> {
let value = value.strip_prefix("0x").unwrap_or(value);
const BYTES_LEN: usize = $n_words * 8;
const MAX_ENCODED_LEN: usize = BYTES_LEN * 2;
let mut bytes = [0_u8; BYTES_LEN];
let encoded = value.as_bytes();
if encoded.len() > MAX_ENCODED_LEN {
return Err($crate::hex::FromHexError::InvalidStringLength.into());
}
if encoded.len() % 2 == 0 {
let out = &mut bytes[BYTES_LEN - encoded.len() / 2..];
$crate::hex::decode_to_slice(encoded, out).map_err(Self::Err::from)?;
} else {
let mut s = [b'0'; MAX_ENCODED_LEN];
s[MAX_ENCODED_LEN - encoded.len()..].copy_from_slice(encoded);
let encoded = &s[MAX_ENCODED_LEN - encoded.len() - 1..];
let out = &mut bytes[BYTES_LEN - encoded.len() / 2..];
$crate::hex::decode_to_slice(encoded, out).map_err(Self::Err::from)?;
}
let bytes_ref: &[u8] = &bytes;
Ok(From::from(bytes_ref))
}
}
impl $crate::core_::convert::From<&'static str> for $name {
fn from(s: &'static str) -> Self {
s.parse().unwrap()
}
}
$crate::impl_quickcheck_arbitrary_for_uint!($name, ($n_words * 8));
$crate::impl_arbitrary_for_uint!($name, ($n_words * 8));
}
}
#[cfg(feature = "quickcheck")]
#[macro_export]
#[doc(hidden)]
macro_rules! impl_quickcheck_arbitrary_for_uint {
($uint: ty, $n_bytes: tt) => {
impl $crate::quickcheck::Arbitrary for $uint {
fn arbitrary(g: &mut $crate::quickcheck::Gen) -> Self {
let p = usize::arbitrary(g) % 100;
let range =
if p < 10 {
$n_bytes
} else if p < 20 {
$n_bytes / 2
} else {
$n_bytes / 5
};
let range = $crate::core_::cmp::max(range, 1);
let size: usize = usize::arbitrary(g) % range;
let res: [u8; $n_bytes] = $crate::core_::array::from_fn(|i| {
if i > size {
0
} else {
u8::arbitrary(g)
}
});
res.as_ref().into()
}
}
};
}
#[cfg(not(feature = "quickcheck"))]
#[macro_export]
#[doc(hidden)]
macro_rules! impl_quickcheck_arbitrary_for_uint {
($uint: ty, $n_bytes: tt) => {};
}
#[cfg(feature = "arbitrary")]
#[macro_export]
#[doc(hidden)]
macro_rules! impl_arbitrary_for_uint {
($uint: ty, $n_bytes: tt) => {
impl $crate::arbitrary::Arbitrary<'_> for $uint {
fn arbitrary(u: &mut $crate::arbitrary::Unstructured<'_>) -> $crate::arbitrary::Result<Self> {
let mut res = [0u8; $n_bytes];
u.fill_buffer(&mut res)?;
Ok(Self::from(res))
}
}
};
}
#[cfg(not(feature = "arbitrary"))]
#[macro_export]
#[doc(hidden)]
macro_rules! impl_arbitrary_for_uint {
($uint: ty, $n_bytes: tt) => {};
}