#![expect(unused_unsafe, reason = "macro-generated code")]
use ::core::cmp::Ordering;
use ::core::mem::size_of;
mod intrinsics;
mod specialize;
mod utils;
pub use self::utils::Uint;
macro_rules! input {
(@pure $name:ident) => {
$name
};
($name:ident) => {
unsafe { $crate::llapi::utils::transmute::<T, _>($name) }
};
}
#[allow(unused_macro_rules, reason = "feature-dependant")]
macro_rules! output {
(@pure $value:expr) => {
$value
};
(@cast($var:ident) $value:expr) => {
unsafe { $crate::llapi::utils::transmute::<_, $var>($value) }
};
(@cast($var:ident, bool) $value:expr) => {
(output!(@cast($var) $value.0), $value.1)
};
(@cast($a:ident, $b:ident) $value:expr) => {
(output!(@cast($a) $value.0), output!(@cast($b) $value.1))
};
}
macro_rules! branch {
(
$transform:ident$(::<$($generic:tt),+>)?::$method:ident($($(@$arg_conv:ident)? $arg_name:ident),+)
->
@$ret_conv:ident$(($($ret_type:ident),+))?
) => {{
$(
let $arg_name = input!($(@$arg_conv)? $arg_name);
)+
let result = $crate::llapi::specialize::$transform$(::<$($generic),+>)?::$method(
$($arg_name),+
);
output!(@$ret_conv$(($($ret_type),+))? result)
}};
}
macro_rules! specialize {
(Int::$method:ident($($args:tt)+)) => {
specialize!(Int::$method($($args)+) -> @cast(T))
};
(Int::$method:ident($($args:tt)+) -> @$ret_conv:ident$(($($ret_type:ident),+))?) => {
match N {
1 => branch!(I8::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
2 => branch!(I16::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
4 => branch!(I32::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
8 => branch!(I64::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
16 => branch!(I128::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
3 => branch!(I24::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
5 => branch!(I40::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
6 => branch!(I48::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
7 => branch!(I56::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
9 => branch!(I72::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
10 => branch!(I80::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
11 => branch!(I88::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
12 => branch!(I96::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
13 => branch!(I104::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
14 => branch!(I112::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
15 => branch!(I120::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
#[cfg(feature = "portable_simd")]
32 => branch!(I64xN::<32, 4>::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
#[cfg(feature = "portable_simd")]
48 => branch!(I64xN::<48, 6>::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
#[cfg(feature = "portable_simd")]
64 => branch!(I64xN::<64, 8>::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
#[cfg(feature = "portable_simd")]
128 => branch!(I64xN::<128, 16>::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
_ => branch!(Int::<N>::$method($($args)+) -> @$ret_conv$(($($ret_type),+))?),
}
};
}
#[cfg(feature = "core_intrinsics")]
pub use ::core::intrinsics::unlikely;
#[cfg(not(feature = "core_intrinsics"))]
#[inline]
#[track_caller]
pub const fn unlikely(condition: bool) -> bool {
#[cold]
const fn cold() {}
if condition {
cold();
true
} else {
false
}
}
#[inline]
#[track_caller]
pub const fn cast_bytes<const UINT: bool, const N: usize, const M: usize>(
bytes: [u8; N],
) -> [u8; M] {
let mut out: [u8; M] = [0; M];
let mut src: *const u8 = bytes.as_ptr();
let mut dst: *mut u8 = out.as_mut_ptr();
if N < M {
if ::core::cfg!(target_endian = "big") {
dst = unsafe { dst.add(M - N) };
}
unsafe { ::core::ptr::copy_nonoverlapping(src, dst, N) }
if !UINT {
let shift: u32 = ((M - N) * 8) as u32;
out = unsafe { unchecked_shl::<_, M>(out, shift) };
out = unsafe { unchecked_ashr::<_, M>(out, shift) };
}
} else {
if ::core::cfg!(target_endian = "big") {
src = unsafe { src.add(N - M) };
}
unsafe { ::core::ptr::copy_nonoverlapping(src, dst, M) }
}
out
}
#[inline]
#[track_caller]
pub const fn band<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::band(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn bor<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::bor(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn bxor<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::bxor(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn bnot<T: Uint, const N: usize>(int: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::bnot(int))
}
#[inline]
#[track_caller]
pub const fn eq<T: Uint, const N: usize>(lhs: T, rhs: T) -> bool {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::eq(lhs, rhs) -> @pure)
}
#[inline]
#[track_caller]
pub const fn ucmp<T: Uint, const N: usize>(lhs: T, rhs: T) -> Ordering {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::ucmp(lhs, rhs) -> @pure)
}
#[inline]
#[track_caller]
pub const fn scmp<T: Uint, const N: usize>(lhs: T, rhs: T) -> Ordering {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::scmp(lhs, rhs) -> @pure)
}
#[inline]
#[track_caller]
pub const fn swap1<T: Uint, const N: usize>(int: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::swap1(int))
}
#[inline]
#[track_caller]
pub const fn swap8<T: Uint, const N: usize>(int: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::swap8(int))
}
#[inline]
#[track_caller]
pub const fn rotl<T: Uint, const N: usize>(int: T, bits: u32) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::rotl(int, @pure bits))
}
#[inline]
#[track_caller]
pub const fn rotr<T: Uint, const N: usize>(int: T, bits: u32) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::rotr(int, @pure bits))
}
#[inline]
#[track_caller]
pub const fn ctpop<T: Uint, const N: usize>(int: T) -> u32 {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::ctpop(int) -> @pure)
}
#[inline]
#[track_caller]
pub const fn ctlz<T: Uint, const N: usize>(int: T) -> u32 {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::ctlz(int) -> @pure)
}
#[inline]
#[track_caller]
pub const fn cttz<T: Uint, const N: usize>(int: T) -> u32 {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::cttz(int) -> @pure)
}
#[inline]
#[track_caller]
pub const unsafe fn ctlz_nonzero<T: Uint, const N: usize>(int: T) -> u32 {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::ctlz_nonzero(int) -> @pure) }
}
#[inline]
#[track_caller]
pub const unsafe fn cttz_nonzero<T: Uint, const N: usize>(int: T) -> u32 {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::cttz_nonzero(int) -> @pure) }
}
#[inline]
#[track_caller]
pub const fn overflowing_uadd<T: Uint, const N: usize>(lhs: T, rhs: T) -> (T, bool) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::overflowing_uadd(lhs, rhs) -> @cast(T, bool))
}
#[inline]
#[track_caller]
pub const fn overflowing_usub<T: Uint, const N: usize>(lhs: T, rhs: T) -> (T, bool) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::overflowing_usub(lhs, rhs) -> @cast(T, bool))
}
#[inline]
#[track_caller]
pub const fn overflowing_umul<T: Uint, const N: usize>(lhs: T, rhs: T) -> (T, bool) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::overflowing_umul(lhs, rhs) -> @cast(T, bool))
}
#[inline]
#[track_caller]
pub const fn overflowing_sadd<T: Uint, const N: usize>(lhs: T, rhs: T) -> (T, bool) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::overflowing_sadd(lhs, rhs) -> @cast(T, bool))
}
#[inline]
#[track_caller]
pub const fn overflowing_ssub<T: Uint, const N: usize>(lhs: T, rhs: T) -> (T, bool) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::overflowing_ssub(lhs, rhs) -> @cast(T, bool))
}
#[inline]
#[track_caller]
pub const fn overflowing_smul<T: Uint, const N: usize>(lhs: T, rhs: T) -> (T, bool) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::overflowing_smul(lhs, rhs) -> @cast(T, bool))
}
#[inline]
#[track_caller]
pub const fn saturating_uadd<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::saturating_uadd(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn saturating_usub<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::saturating_usub(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn saturating_sadd<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::saturating_sadd(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn saturating_ssub<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::saturating_ssub(lhs, rhs))
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_uadd<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_uadd(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_usub<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_usub(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_umul<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_umul(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_udiv<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_udiv(lhs, rhs)) }
}
#[cfg(feature = "exact_div")]
#[inline]
#[track_caller]
pub const unsafe fn unchecked_udiv_exact<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_udiv_exact(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_urem<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_urem(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_sadd<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_sadd(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_ssub<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_ssub(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_smul<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_smul(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_sdiv<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_sdiv(lhs, rhs)) }
}
#[cfg(feature = "exact_div")]
#[inline]
#[track_caller]
pub const unsafe fn unchecked_sdiv_exact<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_sdiv_exact(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_srem<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_srem(lhs, rhs)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_shl<T: Uint, const N: usize>(int: T, bits: u32) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_shl(int, @pure bits)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_lshr<T: Uint, const N: usize>(int: T, bits: u32) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_lshr(int, @pure bits)) }
}
#[inline]
#[track_caller]
pub const unsafe fn unchecked_ashr<T: Uint, const N: usize>(int: T, bits: u32) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_ashr(int, @pure bits)) }
}
#[cfg(feature = "funnel_shifts")]
#[inline]
#[track_caller]
pub const unsafe fn unchecked_fshl<T: Uint, const N: usize>(lhs: T, rhs: T, bits: u32) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_fshl(lhs, rhs, @pure bits)) }
}
#[cfg(feature = "funnel_shifts")]
#[inline]
#[track_caller]
pub const unsafe fn unchecked_fshr<T: Uint, const N: usize>(lhs: T, rhs: T, bits: u32) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::unchecked_fshr(lhs, rhs, @pure bits)) }
}
#[inline]
#[track_caller]
pub const fn wrapping_add<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::wrapping_add(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn wrapping_sub<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::wrapping_sub(lhs, rhs))
}
#[inline]
#[track_caller]
pub const fn wrapping_mul<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::wrapping_mul(lhs, rhs))
}
#[cfg(feature = "disjoint_bitor")]
#[inline]
#[track_caller]
pub const unsafe fn disjoint_bor<T: Uint, const N: usize>(lhs: T, rhs: T) -> T {
const {
assert!(size_of::<T>() == N);
}
unsafe { specialize!(Int::disjoint_bor(lhs, rhs)) }
}
#[cfg(feature = "bigint_helper_methods")]
#[inline]
#[track_caller]
pub const fn carrying_umul_uadd<T: Uint, const N: usize>(
lhs: T,
rhs: T,
add: T,
carry: T,
) -> (T, T) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::carrying_umul_uadd(lhs, rhs, add, carry) -> @cast(T, T))
}
#[cfg(feature = "bigint_helper_methods")]
#[inline]
#[track_caller]
pub const fn carrying_smul_sadd<T: Uint, U: Uint, const N: usize>(
lhs: T,
rhs: T,
add: T,
carry: T,
) -> (U, T) {
const {
assert!(size_of::<T>() == N);
}
specialize!(Int::carrying_smul_sadd(lhs, rhs, add, carry) -> @cast(U, T))
}