#![no_std]
extern crate alloc;
use core::hint::unreachable_unchecked;
pub mod array_serialization;
pub mod linear_map;
#[must_use]
pub const fn ceil_div_usize(a: usize, b: usize) -> usize {
(a + b - 1) / b
}
#[must_use]
pub const fn log2_ceil_usize(n: usize) -> usize {
(usize::BITS - n.saturating_sub(1).leading_zeros()) as usize
}
#[must_use]
pub fn log2_ceil_u64(n: u64) -> u64 {
(u64::BITS - n.saturating_sub(1).leading_zeros()).into()
}
#[must_use]
#[inline]
pub fn log2_strict_usize(n: usize) -> usize {
let res = n.trailing_zeros();
assert_eq!(n.wrapping_shr(res), 1, "Not a power of two: {n}");
res as usize
}
#[must_use]
pub const fn indices_arr<const N: usize>() -> [usize; N] {
let mut indices_arr = [0; N];
let mut i = 0;
while i < N {
indices_arr[i] = i;
i += 1;
}
indices_arr
}
#[inline]
pub const fn reverse_bits(x: usize, n: usize) -> usize {
reverse_bits_len(x, n.trailing_zeros() as usize)
}
#[inline]
pub const fn reverse_bits_len(x: usize, bit_len: usize) -> usize {
x.reverse_bits()
.overflowing_shr(usize::BITS - bit_len as u32)
.0
}
pub fn reverse_slice_index_bits<F>(vals: &mut [F]) {
let n = vals.len();
if n == 0 {
return;
}
let log_n = log2_strict_usize(n);
for i in 0..n {
let j = reverse_bits_len(i, log_n);
if i < j {
vals.swap(i, j);
}
}
}
#[inline(always)]
pub fn assume(p: bool) {
debug_assert!(p);
if !p {
unsafe {
unreachable_unchecked();
}
}
}
#[inline(always)]
pub fn branch_hint() {
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "x86",
target_arch = "x86_64",
))]
unsafe {
core::arch::asm!("", options(nomem, nostack, preserves_flags));
}
}
pub trait VecExt<T> {
fn pushed_ref(&mut self, elem: T) -> &T;
fn pushed_mut(&mut self, elem: T) -> &mut T;
}
impl<T> VecExt<T> for alloc::vec::Vec<T> {
fn pushed_ref(&mut self, elem: T) -> &T {
self.push(elem);
self.last().unwrap()
}
fn pushed_mut(&mut self, elem: T) -> &mut T {
self.push(elem);
self.last_mut().unwrap()
}
}