//! xoshiro256++ 伪随机数生成器
//!
//! 非线程安全：多核环境下调用方需自行同步
#![no_std]

use core::sync::atomic::{AtomicU64, Ordering};

static STATE: [AtomicU64; 4] = [
    AtomicU64::new(0x1469_ABE1_2345_6789),
    AtomicU64::new(0x9876_5432_FEDC_BA98),
    AtomicU64::new(0xABCD_EF01_2345_6789),
    AtomicU64::new(0xFEDC_BA98_7654_3210),
];

/// 生成 64 位伪随机数
#[inline]
pub fn rand64() -> u64 {
    let mut s = load_state();
    let result = next(&mut s);
    store_state(&s);
    result
}

/// 生成 32 位伪随机数
#[inline]
pub fn rand32() -> u32 {
    (rand64() >> 32) as u32
}

/// 用 64 位种子初始化状态（通过 `SplitMix64` 扩展为 256 位）
#[inline]
pub fn srand(seed: u64) {
    let seed = if seed == 0 { 1 } else { seed };
    let mut sm = seed;
    let s = [splitmix64(&mut sm), splitmix64(&mut sm), splitmix64(&mut sm), splitmix64(&mut sm)];
    store_state(&s);
}

/// 生成 `[0, bound)` 范围内的均匀随机数
///
/// # Panics
/// `bound == 0`
#[inline]
pub fn rand_range(bound: u64) -> u64 {
    debug_assert!(bound > 0);
    let threshold = bound.wrapping_neg() % bound;
    loop {
        let r = rand64();
        if r >= threshold {
            return r % bound;
        }
    }
}

#[inline]
fn next(s: &mut [u64; 4]) -> u64 {
    let result = (s[0].wrapping_add(s[3])).rotate_left(23).wrapping_add(s[0]);
    let t = s[1] << 17;

    s[2] ^= s[0];
    s[3] ^= s[1];
    s[1] ^= s[2];
    s[0] ^= s[3];

    s[2] ^= t;
    s[3] = s[3].rotate_left(45);

    result
}

#[inline]
fn splitmix64(state: &mut u64) -> u64 {
    *state = state.wrapping_add(0x9E37_79B9_7F4A_7C15);
    let mut z = *state;
    z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
    z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
    z ^ (z >> 31)
}

#[inline]
fn load_state() -> [u64; 4] {
    [
        STATE[0].load(Ordering::Relaxed),
        STATE[1].load(Ordering::Relaxed),
        STATE[2].load(Ordering::Relaxed),
        STATE[3].load(Ordering::Relaxed),
    ]
}

#[inline]
fn store_state(s: &[u64; 4]) {
    STATE[0].store(s[0], Ordering::Relaxed);
    STATE[1].store(s[1], Ordering::Relaxed);
    STATE[2].store(s[2], Ordering::Relaxed);
    STATE[3].store(s[3], Ordering::Relaxed);
}
