#[cfg(any(feature = "xx-wide", feature = "d924", feature = "d1232"))]
pub(crate) const MAX_WORK_N: usize = 64;
#[cfg(all(
not(any(feature = "xx-wide", feature = "d924", feature = "d1232")),
any(feature = "x-wide", feature = "d462", feature = "d616")
))]
pub(crate) const MAX_WORK_N: usize = 32;
#[cfg(all(
not(any(
feature = "xx-wide", feature = "d924", feature = "d1232",
feature = "x-wide", feature = "d462", feature = "d616"
)),
any(
feature = "wide", feature = "d57", feature = "d76", feature = "d115",
feature = "d153", feature = "d230", feature = "d307"
)
))]
pub(crate) const MAX_WORK_N: usize = 16;
#[cfg(not(any(
feature = "xx-wide", feature = "d924", feature = "d1232",
feature = "x-wide", feature = "d462", feature = "d616",
feature = "wide", feature = "d57", feature = "d76", feature = "d115",
feature = "d153", feature = "d230", feature = "d307"
)))]
pub(crate) const MAX_WORK_N: usize = 2;
pub(crate) const fn max_n_limbs(mult: usize) -> usize {
mult * MAX_WORK_N + MAX_WORK_N.div_ceil(2)
}
#[cfg(feature = "exact-scratch-nightly")]
pub(crate) const fn n_limbs(mult: usize, n: usize) -> usize {
mult * n + (n + 1) / 2
}
#[inline]
pub(crate) const fn is_zero(a: &[u64]) -> bool {
let mut i = 0;
while i < a.len() {
if a[i] != 0 {
return false;
}
i += 1;
}
true
}
#[inline]
pub(crate) const fn is_zero_fixed<const L: usize>(a: &[u64; L]) -> bool {
let mut i = 0;
while i < L {
if a[i] != 0 {
return false;
}
i += 1;
}
true
}
#[inline]
pub(crate) const fn eq(a: &[u64], b: &[u64]) -> bool {
let n = if a.len() > b.len() { a.len() } else { b.len() };
let mut i = 0;
while i < n {
let av = if i < a.len() { a[i] } else { 0 };
let bv = if i < b.len() { b[i] } else { 0 };
if av != bv {
return false;
}
i += 1;
}
true
}
#[inline]
pub(crate) const fn cmp(a: &[u64], b: &[u64]) -> i32 {
let n = if a.len() > b.len() { a.len() } else { b.len() };
let mut i = n;
while i > 0 {
i -= 1;
let av = if i < a.len() { a[i] } else { 0 };
let bv = if i < b.len() { b[i] } else { 0 };
if av < bv {
return -1;
}
if av > bv {
return 1;
}
}
0
}
#[inline]
pub(crate) const fn cmp_fixed<const L: usize>(a: &[u64; L], b: &[u64; L]) -> i32 {
let mut i = L;
while i > 0 {
i -= 1;
if a[i] < b[i] {
return -1;
}
if a[i] > b[i] {
return 1;
}
}
0
}
#[inline]
pub(crate) const fn cmp_cross(a: &[u64], b: &[u64]) -> i32 {
let la = a.len();
let lb = b.len();
let max = if la > lb { la } else { lb };
let mut i = max;
while i > 0 {
i -= 1;
let av = if i < la { a[i] } else { 0 };
let bv = if i < lb { b[i] } else { 0 };
if av < bv {
return -1;
}
if av > bv {
return 1;
}
}
0
}
#[inline]
pub(crate) const fn bit_len(a: &[u64]) -> u32 {
let mut i = a.len();
while i > 0 {
i -= 1;
if a[i] != 0 {
return (i as u32) * 64 + (64 - a[i].leading_zeros());
}
}
0
}
#[inline]
pub(crate) const fn bit_len_fixed<const L: usize>(a: &[u64; L]) -> u32 {
let mut i = L;
while i > 0 {
i -= 1;
if a[i] != 0 {
return (i as u32) * 64 + (64 - a[i].leading_zeros());
}
}
0
}
#[inline]
pub(crate) const fn add_assign(a: &mut [u64], b: &[u64]) -> bool {
let mut carry: u64 = 0;
let mut i = 0;
while i < a.len() {
let bv = if i < b.len() { b[i] } else { 0 };
let (s1, c1) = a[i].overflowing_add(bv);
let (s2, c2) = s1.overflowing_add(carry);
a[i] = s2;
carry = (c1 as u64) + (c2 as u64);
i += 1;
}
carry != 0
}
#[inline]
pub(crate) const fn add_assign_fixed<const L: usize>(a: &mut [u64; L], b: &[u64; L]) -> bool {
let mut carry: u64 = 0;
let mut i = 0;
while i < L {
let (s1, c1) = a[i].overflowing_add(b[i]);
let (s2, c2) = s1.overflowing_add(carry);
a[i] = s2;
carry = (c1 as u64) + (c2 as u64);
i += 1;
}
carry != 0
}
#[inline]
pub(crate) const fn sub_assign(a: &mut [u64], b: &[u64]) -> bool {
let mut borrow: u64 = 0;
let mut i = 0;
while i < a.len() {
let bv = if i < b.len() { b[i] } else { 0 };
let (d1, b1) = a[i].overflowing_sub(bv);
let (d2, b2) = d1.overflowing_sub(borrow);
a[i] = d2;
borrow = (b1 as u64) + (b2 as u64);
i += 1;
}
borrow != 0
}
#[inline]
pub(crate) const fn sub_assign_fixed<const L: usize>(a: &mut [u64; L], b: &[u64; L]) -> bool {
let mut borrow: u64 = 0;
let mut i = 0;
while i < L {
let (d1, b1) = a[i].overflowing_sub(b[i]);
let (d2, b2) = d1.overflowing_sub(borrow);
a[i] = d2;
borrow = (b1 as u64) + (b2 as u64);
i += 1;
}
borrow != 0
}
#[inline]
pub(crate) const fn shl_fixed<const L: usize>(a: &[u64; L], shift: u32, out: &mut [u64; L]) {
let mut z = 0;
while z < L {
out[z] = 0;
z += 1;
}
let limb_shift = (shift / 64) as usize;
let bit = shift % 64;
let mut i = 0;
while i < L {
let dst = i + limb_shift;
if dst < L {
if bit == 0 {
out[dst] |= a[i];
} else {
out[dst] |= a[i] << bit;
if dst + 1 < L {
out[dst + 1] |= a[i] >> (64 - bit);
}
}
}
i += 1;
}
}
#[inline]
pub(crate) const fn shr_fixed<const L: usize>(a: &[u64; L], shift: u32, out: &mut [u64; L]) {
let mut z = 0;
while z < L {
out[z] = 0;
z += 1;
}
let limb_shift = (shift / 64) as usize;
let bit = shift % 64;
let mut i = limb_shift;
while i < L {
let dst = i - limb_shift;
if dst < L {
if bit == 0 {
out[dst] |= a[i];
} else {
out[dst] |= a[i] >> bit;
if dst >= 1 {
out[dst - 1] |= a[i] << (64 - bit);
}
}
}
i += 1;
}
}
pub(crate) const fn shl(a: &[u64], shift: u32, out: &mut [u64]) {
let mut z = 0;
while z < out.len() {
out[z] = 0;
z += 1;
}
let limb_shift = (shift / 64) as usize;
let bit = shift % 64;
let mut i = 0;
while i < a.len() {
let dst = i + limb_shift;
if dst < out.len() {
if bit == 0 {
out[dst] |= a[i];
} else {
out[dst] |= a[i] << bit;
if dst + 1 < out.len() {
out[dst + 1] |= a[i] >> (64 - bit);
}
}
}
i += 1;
}
}
pub(crate) const fn shr(a: &[u64], shift: u32, out: &mut [u64]) {
let mut z = 0;
while z < out.len() {
out[z] = 0;
z += 1;
}
let limb_shift = (shift / 64) as usize;
let bit = shift % 64;
let mut i = limb_shift;
while i < a.len() {
let dst = i - limb_shift;
if dst < out.len() {
if bit == 0 {
out[dst] |= a[i];
} else {
out[dst] |= a[i] >> bit;
if dst >= 1 {
out[dst - 1] |= a[i] << (64 - bit);
}
}
}
i += 1;
}
}
#[inline]
pub(crate) const fn shl1(a: &mut [u64]) -> u64 {
let mut carry: u64 = 0;
let mut i = 0;
while i < a.len() {
let new_carry = a[i] >> 63;
a[i] = (a[i] << 1) | carry;
carry = new_carry;
i += 1;
}
carry
}
#[inline]
pub(crate) const fn fit_one(a: &[u64]) -> bool {
fit_k(a, 1)
}
#[inline]
pub(crate) const fn fit_k(a: &[u64], k: usize) -> bool {
let mut i = k;
while i < a.len() {
if a[i] != 0 {
return false;
}
i += 1;
}
true
}
#[inline]
pub(crate) const fn scmp(a_neg: bool, a: &[u64], b_neg: bool, b: &[u64]) -> i32 {
match (a_neg, b_neg) {
(true, false) => -1,
(false, true) => 1,
_ => cmp(a, b),
}
}