#![allow(non_snake_case)]
use crate::ported::modules::random::getrandom_buffer;
use crate::ported::utils::zwarn;
pub fn _zclz64(x: u64) -> i32 {
let mut n: i32 = 0; let mut x = x;
if x == 0 { return 64; }
if (x & 0xFFFF_FFFF_0000_0000) == 0 { n += 32; x <<= 32; }
if (x & 0xFFFF_0000_0000_0000) == 0 { n += 16; x <<= 16; }
if (x & 0xFF00_0000_0000_0000) == 0 { n += 8; x <<= 8; }
if (x & 0xF000_0000_0000_0000) == 0 { n += 4; x <<= 4; }
if (x & 0xC000_0000_0000_0000) == 0 { n += 2; x <<= 2; }
if (x & 0x8000_0000_0000_0000) == 0 { n += 1; }
n }
pub fn random_64bit() -> u64 {
let r: u64; let mut buf = [0u8; 8];
if getrandom_buffer(&mut buf).is_err() {
zwarn("zsh/random: Can't get sufficient random data."); return 1; }
r = u64::from_ne_bytes(buf);
r }
pub fn random_real() -> f64 {
let mut exponent: i32 = 0; let mut significand: u64 = 0; let mut r: u64 = 0; let shift: u32;
while significand == 0 { exponent -= 64;
significand = random_64bit();
if exponent < -1074 { return 0.0; }
}
shift = clz64(significand) as u32; if shift != 0 { r = random_64bit();
exponent -= shift as i32; significand <<= shift; significand |= r >> (64 - shift); }
significand |= 1;
(significand as f64) * (2.0_f64).powi(exponent)
}
#[inline]
pub fn clz64(x: u64) -> i32 {
if x == 0 { 64 } else { x.leading_zeros() as i32 }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn clz64_matches_zclz64() {
for x in [0u64, 1, 0xff, 0xff00, u64::MAX, 0x8000_0000_0000_0000] {
assert_eq!(clz64(x), _zclz64(x), "input 0x{:016x}", x);
}
}
#[test]
fn zclz64_zero_is_64() {
assert_eq!(_zclz64(0), 64);
}
#[test]
fn zclz64_msb_is_zero() {
assert_eq!(_zclz64(0x8000_0000_0000_0000), 0);
}
#[test]
fn random_real_in_range() {
for _ in 0..100 {
let r = random_real();
assert!((0.0..1.0).contains(&r), "out of range: {}", r);
}
}
#[test]
fn random_64bit_returns_value() {
let _ = random_64bit();
}
#[test]
fn zclz64_lsb_only_is_63() {
assert_eq!(_zclz64(1), 63);
}
#[test]
fn zclz64_matches_leading_zeros_across_all_single_bits() {
for bit in 0..64u32 {
let x = 1u64 << bit;
assert_eq!(_zclz64(x), x.leading_zeros() as i32,
"mismatch at single-bit input 1<<{}", bit);
}
}
#[test]
fn zclz64_low_bit_anchors_match_position() {
assert_eq!(_zclz64(0b1), 63); assert_eq!(_zclz64(0b10), 62); assert_eq!(_zclz64(0b100), 61); assert_eq!(_zclz64(0b1000), 60); assert_eq!(_zclz64(0b1_0000), 59); assert_eq!(_zclz64(0b1000_0000), 56); }
#[test]
fn zclz64_msb_only_returns_zero() {
let x = 1u64 << 63;
assert_eq!(_zclz64(x), 0);
assert_eq!(clz64(x), 0);
assert_eq!(x.leading_zeros() as i32, 0);
}
#[test]
fn zclz64_matches_leading_zeros_across_diverse_inputs() {
for x in [
0u64, 1, 2, 3, 0xff, 0x100, 0xff00, 0xffff,
0x12345678_9abcdef0, 0xdeadbeef, 0xcafebabe_cafebabe,
(1 << 31), (1 << 32), (1 << 33), (1 << 62),
u64::MAX, u64::MAX - 1, 0x5555_5555_5555_5555,
0xAAAA_AAAA_AAAA_AAAA, 0x8000_0000_0000_0001,
] {
assert_eq!(_zclz64(x), x.leading_zeros() as i32,
"mismatch at 0x{:016x}", x);
}
}
#[test]
fn clz64_zero_returns_64_not_undef() {
assert_eq!(clz64(0), 64);
}
#[test]
fn random_real_produces_some_nonzero_values() {
let mut saw_nonzero = false;
for _ in 0..50 {
if random_real() != 0.0 {
saw_nonzero = true;
break;
}
}
assert!(saw_nonzero,
"50 consecutive 0.0 outputs from random_real — entropy pump broken");
}
#[test]
fn random_real_produces_distinct_outputs() {
use std::collections::HashSet;
let mut seen: HashSet<u64> = HashSet::new();
for _ in 0..100 {
seen.insert(random_real().to_bits());
}
assert!(seen.len() >= 5,
"100 draws produced only {} distinct outputs — distribution broken",
seen.len());
}
#[test]
fn random_64bit_produces_non_sentinel_values() {
let mut saw_real = false;
for _ in 0..20 {
let r = random_64bit();
if r != 0 && r != 1 {
saw_real = true;
break;
}
}
assert!(saw_real, "every random_64bit returned the failure sentinel — getrandom broken?");
}
}