use core::sync::atomic::{AtomicU32, Ordering};
pub const NULL_INDEX: i32 = -1;
pub const SECRET_COOKIE: i32 = 1152023;
static LENGTH_UNITS_PER_METER_BITS: AtomicU32 = AtomicU32::new(0x3F80_0000);
pub fn set_length_units_per_meter(length_units: f32) {
debug_assert!(crate::math_functions::is_valid_float(length_units) && length_units > 0.0);
LENGTH_UNITS_PER_METER_BITS.store(length_units.to_bits(), Ordering::Relaxed);
}
pub fn get_length_units_per_meter() -> f32 {
f32::from_bits(LENGTH_UNITS_PER_METER_BITS.load(Ordering::Relaxed))
}
static STALL_THRESHOLD_BITS: AtomicU32 = AtomicU32::new(0x7F7F_FFFF);
pub fn set_stall_threshold(seconds: f32) {
debug_assert!(crate::math_functions::is_valid_float(seconds) && seconds > 0.0);
STALL_THRESHOLD_BITS.store(seconds.to_bits(), Ordering::Relaxed);
}
pub fn get_stall_threshold() -> f32 {
f32::from_bits(STALL_THRESHOLD_BITS.load(Ordering::Relaxed))
}
pub fn is_double_precision() -> bool {
cfg!(feature = "double-precision")
}
pub fn ctz32(block: u32) -> u32 {
block.trailing_zeros()
}
pub fn clz32(value: u32) -> u32 {
value.leading_zeros()
}
pub fn ctz64(block: u64) -> u32 {
block.trailing_zeros()
}
pub fn pop_count64(block: u64) -> i32 {
block.count_ones() as i32
}
pub fn is_power_of2(x: i32) -> bool {
(x & (x - 1)) == 0
}
pub fn bounding_power_of2(x: i32) -> i32 {
if x <= 1 {
return 1;
}
32 - clz32((x as u32) - 1) as i32
}
pub fn round_up_power_of2(x: i32) -> i32 {
if x <= 1 {
return 1;
}
1 << (32 - clz32((x as u32) - 1))
}
pub fn lower_power_of_2_exponent(x: i32) -> i32 {
debug_assert!(x > 0);
let clz = clz32(x as u32) as i32;
31 - clz
}
pub const HASH_INIT: u32 = 5381;
pub fn hash(hash: u32, data: &[u8]) -> u32 {
let mut result = hash;
let mut i = 0;
let count = data.len();
while i + 8 <= count {
let word = u64::from_le_bytes(data[i..i + 8].try_into().unwrap());
result = result
.wrapping_shl(5)
.wrapping_add(result)
.wrapping_add(word as u32);
result = result
.wrapping_shl(5)
.wrapping_add(result)
.wrapping_add((word >> 32) as u32);
i += 8;
}
while i < count {
result = result
.wrapping_shl(5)
.wrapping_add(result)
.wrapping_add(data[i] as u32);
i += 1;
}
result
}
pub fn non_zero_hash(hash: u32) -> u32 {
if hash != 0 {
hash
} else {
1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bit_helpers() {
assert_eq!(ctz32(0b1000), 3);
assert_eq!(clz32(1), 31);
assert_eq!(clz32(9), 31 - 3);
assert_eq!(ctz64(1u64 << 40), 40);
assert_eq!(pop_count64(0xFFFF_FFFF_FFFF_FFFF), 64);
assert!(is_power_of2(8));
assert!(!is_power_of2(6));
assert_eq!(round_up_power_of2(5), 8);
assert_eq!(round_up_power_of2(1), 1);
assert_eq!(bounding_power_of2(5), 3);
assert_eq!(lower_power_of_2_exponent(9), 3);
}
#[test]
fn stall_threshold_round_trip() {
assert_eq!(get_stall_threshold(), f32::MAX);
set_stall_threshold(0.001);
assert_eq!(get_stall_threshold(), 0.001);
set_stall_threshold(f32::MAX);
assert_eq!(get_stall_threshold(), f32::MAX);
}
}