Skip to main content

lib_unknown/
rand.rs

1//! 硬件熵随机数:时间戳熵源(`probe`)、重播种(`seed`)与热路径输出(`next`),另含区间采样与 `fill_bytes`(`rand-expand`)。
2//!
3//! 需要启用 `"rand"` 特性。
4#![allow(unused)]
5
6use crate::crypto::base::{mix64, shuffle_with};
7use core::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
8// /dev/urandom参考
9// ❯ head -c 10M /dev/urandom > small_samples.bin
10// ❯ /home/zz/Documents/git/SP800-90B_EntropyAssessment/cpp/ea_non_iid -i -v -a small_samples.bin 8
11// Opening file: 'small_samples.bin' (SHA-256 hash 4466b8477a570ab30889532da827030cc389125bd484d43f8339cf00a23c90bd)
12// Loaded 10485760 samples of 256 distinct 8-bit-wide symbols
13// Number of Binary Symbols: 83886080
14//
15// Running non-IID tests...
16//
17// Running Most Common Value Estimate...
18// Bitstring MCV Estimate: mode = 41944627, p-hat = 0.50001891851425173, p_u = 0.50015953690906079
19//         Most Common Value Estimate (bit string) = 0.999540 / 1 bit(s)
20// Literal MCV Estimate: mode = 41721, p-hat = 0.003978824615478516, p_u = 0.0040289005228594642
21//         Most Common Value Estimate = 7.955398 / 8 bit(s)
22//
23// Running Entropic Statistic Estimates (bit strings only)...
24// Bitstring Collision Estimate: X-bar = 2.500075193522735, sigma-hat = 0.50000000179673953, p = 0.50857750043554861
25//         Collision Test Estimate (bit string) = 0.975460 / 1 bit(s)
26// Bitstring Markov Estimate: P_0 = 0.49998108148574827, P_1 = 0.50001891851425173, P_0,0 = 0.49996292450723928, P_0,1 = 0.50003707549276077, P_1,0 = 0.49999924900989107, P_1,1 = 0.50000075099010899, p_max = 2.952323724507251e-39
27//         Markov Test Estimate (bit string) = 0.999948 / 1 bit(s)
28// Bitstring Compression Estimate: X-bar = 5.2173562024019668, sigma-hat = 1.0155761472136569, p = 0.020720381304131674
29//         Compression Test Estimate (bit string) = 0.932134 / 1 bit(s)
30//
31// Running Tuple Estimates...
32// Bitstring t-Tuple Estimate: t = 22, p-hat_max = 0.519800544732285640763, p_u = 0.5199410528217940434775
33// Bitstring LRS Estimate: u = 23, v = 49, p-hat = 0.50048298953775729, p_u = 0.50062360786706038
34//         T-Tuple Test Estimate (bit string) = 0.943580 / 1 bit(s)
35// Literal t-Tuple Estimate: t = 2, p-hat_max = 0.004590882747638149776254, p_u = 0.004644655968621724387299
36// Literal LRS Estimate: u = 3, v = 5, p-hat = 0.0039149192648118801, p_u = 0.0039645929941324926
37//         T-Tuple Test Estimate = 7.750213 / 8 bit(s)
38//         LRS Test Estimate (bit string) = 0.998202 / 1 bit(s)
39//         LRS Test Estimate = 7.978612 / 8 bit(s)
40//
41// Running Predictor Estimates...
42// Bitstring MultiMCW Prediction Estimate: N = 83886017, Pglobal' = 0.50016892471455032 (C = 41945383) Plocal can't affect result (r = 26)
43//         Multi Most Common in Window (MultiMCW) Prediction Test Estimate (bit string) = 0.999513 / 1 bit(s)
44// Literal MultiMCW Prediction Estimate: N = 10485697, Pglobal' = 0.0039368902123073065 (C = 40762) Plocal = 0.0055718895656600631 (r = 4)
45//         Multi Most Common in Window (MultiMCW) Prediction Test Estimate = 7.487618 / 8 bit(s)
46// Bitstring Lag Prediction Estimate: N = 83886079, Pglobal' = 0.50024399072940884 (C = 41951711) Plocal can't affect result (r = 28)
47//         Lag Prediction Test Estimate (bit string) = 0.999296 / 1 bit(s)
48// Literal Lag Prediction Estimate: N = 10485759, Pglobal' = 0.003972280184949272 (C = 41131) Plocal = 0.0055718813178256762 (r = 4)
49//         Lag Prediction Test Estimate = 7.487620 / 8 bit(s)
50// Bitstring MultiMMC Prediction Estimate: N = 83886078, Pglobal' = 0.50009155185115994 (C = 41938923) Plocal can't affect result (r = 24)
51//         Multi Markov Model with Counting (MultiMMC) Prediction Test Estimate (bit string) = 0.999736 / 1 bit(s)
52// Literal MultiMMC Prediction Estimate: N = 10485758, Pglobal' = 0.0039454088113584813 (C = 40851) Plocal = 0.0055718814508428282 (r = 4)
53//         Multi Markov Model with Counting (MultiMMC) Prediction Test Estimate = 7.487620 / 8 bit(s)
54// Bitstring LZ78Y Prediction Estimate: N = 83886063, Pglobal' = 0.5000796607255481 (C = 41937918) Plocal can't affect result (r = 25)
55//         LZ78Y Prediction Test Estimate (bit string) = 0.999770 / 1 bit(s)
56// Literal LZ78Y Prediction Estimate: N = 10485743, Pglobal' = 0.0039455104269033141 (C = 40852) Plocal = 0.0055718834462567543 (r = 4)
57//         LZ78Y Prediction Test Estimate = 7.487619 / 8 bit(s)
58//
59// H_original: 7.487618
60// H_bitstring: 0.932134
61// min(H_original, 8 X H_bitstring): 7.457074
62
63// 主要熵源
64/// 采集硬件时间戳并归一化到 1GHz 的原始熵源。
65///
66/// 读取 x86(`RDTSC`)/aarch64(`CNTVCT_EL0`)/RISC-V(`rdtime`) 等计数器,
67/// 用 Q48 定点乘子换算为纳秒级单调时钟。
68/// 连续调用通常递增,但在虚拟化/热迁移下不保证严格单调;求差值请用 `wrapping_sub`。
69///
70/// # Feature Requirement
71///
72/// 需要启用 `"rand"` 特性。
73///
74/// # Examples
75///
76/// ```rust
77/// use lib_unknown::rand::probe;
78///
79/// let t1 = probe();
80/// let t2 = probe();
81/// let _delta_ns = t2.wrapping_sub(t1);
82/// ```
83#[inline(always)]
84pub fn probe() -> u64 {
85    const SHIFT: u8 = 48;
86    const TARGET_FREQ: u128 = 1_000_000_000; // 目标 1GHz (1 tick = 1 ns)
87    static MULTIPLIER_Q48: AtomicU64 = AtomicU64::new(0);
88    #[inline(always)]
89    fn raw_probe() -> u64 {
90        #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
91        {
92            #[cfg(target_arch = "x86_64")]
93            // SAFETY: `_rdtsc` 仅读取时间戳计数器,不访问内存,不影响内存安全。
94            unsafe {
95                core::arch::x86_64::_rdtsc()
96            }
97            #[cfg(target_arch = "x86")]
98            unsafe {
99                core::arch::x86::_rdtsc()
100            }
101        }
102
103        #[cfg(target_arch = "aarch64")]
104        {
105            let tsc: u64;
106            unsafe {
107                core::arch::asm!("mrs {}, cntvct_el0", out(reg) tsc, options(nomem, nostack))
108            };
109            tsc
110        }
111
112        #[cfg(target_arch = "arm")]
113        {
114            let mut lo: u32;
115            let mut hi: u32;
116            unsafe {
117                core::arch::asm!("mrrc p15, 1, {}, {}, c14", out(reg) lo, out(reg) hi, options(nomem, nostack))
118            };
119            ((hi as u64) << 32) | (lo as u64)
120        }
121
122        #[cfg(target_arch = "riscv64")]
123        {
124            let tsc: u64;
125            unsafe { core::arch::asm!("rdtime {}", out(reg) tsc, options(nomem, nostack)) };
126            tsc
127        }
128
129        #[cfg(target_arch = "riscv32")]
130        {
131            let mut hi: u32;
132            let mut lo: u32;
133            let mut hi2: u32;
134            unsafe {
135                core::arch::asm!(
136                "2:", "rdtimeh {hi}", "rdtime {lo}", "rdtimeh {hi2}", "bne {hi}, {hi2}, 2b",
137                hi = out(reg) hi, lo = out(reg) lo, hi2 = out(reg) hi2, options(nomem, nostack, preserves_flags)
138                );
139            }
140            ((hi as u64) << 32) | (lo as u64)
141        }
142
143        #[cfg(target_arch = "loongarch64")]
144        {
145            let tsc: u64;
146            unsafe { core::arch::asm!("rdtime.d {}, $r0", out(reg) tsc, options(nomem, nostack)) };
147            tsc
148        }
149
150        #[cfg(target_arch = "powerpc")]
151        {
152            let tsc: u64;
153            unsafe { core::arch::asm!("mftb {}", out(reg) tsc, options(nomem, nostack)) };
154            tsc
155        }
156
157        #[cfg(target_arch = "wasm32")]
158        {
159            #[cfg(target_os = "wasi")]
160            {
161                let mut timespec = core::mem::MaybeUninit::uninit();
162                unsafe {
163                    let _ = wasi::clock_time_get(wasi::CLOCKID_MONOTONIC, 1, timespec.as_mut_ptr());
164                    timespec.assume_init()
165                }
166            }
167            #[cfg(not(target_os = "wasi"))]
168            {
169                // Web 环境下,即使 no_std 也需要通过 ffi 引入 JS 运行时 API
170                #[wasm_bindgen::prelude::wasm_bindgen]
171                extern "C" {
172                    #[wasm_bindgen::prelude::wasm_bindgen(js_namespace = performance)]
173                    fn now() -> f64;
174                }
175                (now() * 1_000_000.0) as u64
176            }
177        }
178    }
179
180    fn autodetect_hardware_freq() -> u64 {
181        #[cfg(target_arch = "aarch64")]
182        {
183            let freq: u64;
184            unsafe {
185                core::arch::asm!("mrs {}, cntfrq_el0", out(reg) freq, options(nomem, nostack))
186            };
187            return freq;
188        }
189
190        #[cfg(target_arch = "loongarch64")]
191        {
192            let freq: u32;
193            // 龙芯 CPUCFG 指令索引 4,直接返回 CPU 定时器频率
194            unsafe {
195                core::arch::asm!("cpucfg {}, {}", out(reg) freq, in(reg) 4, options(nomem, nostack))
196            };
197            return freq as u64;
198        }
199
200        #[cfg(target_arch = "wasm32")]
201        {
202            return 1_000_000_000; // Web/WASI 已被我们在 raw_probe 中转为 1GHz
203        }
204
205        #[cfg(not(any(
206            target_arch = "aarch64",
207            target_arch = "loongarch64",
208            target_arch = "wasm32"
209        )))]
210        {
211            2_500_000_000
212        }
213    }
214
215    let raw = raw_probe();
216    let mut mult = MULTIPLIER_Q48.load(Ordering::Relaxed);
217
218    if mult == 0 {
219        let hz = autodetect_hardware_freq();
220        let final_mult = if hz == 0 {
221            1u64 << SHIFT
222        } else {
223            ((TARGET_FREQ << SHIFT) / hz as u128) as u64
224        };
225        mult = match MULTIPLIER_Q48.compare_exchange(
226            0,
227            final_mult,
228            Ordering::SeqCst,
229            Ordering::Relaxed,
230        ) {
231            Ok(_) => final_mult,
232            Err(existing) => existing,
233        };
234    }
235
236    ((raw as u128 * mult as u128) >> SHIFT) as u64
237}
238
239// 较低的熵源
240#[inline(never)]
241fn reg_sig() -> u64 {
242    let state: u64;
243    let gpr1: u64;
244    let gpr2: u64;
245    let gpr3: u64;
246    let code: u64;
247    let stack: u64;
248
249    // ==========================================
250    // 64位架构支持
251    // ==========================================
252    #[cfg(target_arch = "x86_64")]
253    // SAFETY: 仅读取标志寄存器、指令指针与栈指针到通用寄存器,
254    // 所有输出经 `out(reg)` 声明,无内存读写,无别名违反。
255    unsafe {
256        core::arch::asm!(
257        "pushfq",
258        "pop {0}",
259        "lea {1}, [rip]",
260        "mov {2}, rsp",
261        out(reg) state, out(reg) code, out(reg) stack,
262        out("rcx") gpr1, out("r10") gpr2, out("r11") gpr3,
263        );
264    }
265
266    #[cfg(target_arch = "aarch64")]
267    unsafe {
268        core::arch::asm!(
269        "mrs {0}, nzcv",
270        "adr {1}, .",
271        "mov {2}, sp",
272        out(reg) state, out(reg) code, out(reg) stack,
273        out("x1") gpr1, out("x2") gpr2, out("x3") gpr3,
274        options(nomem, nostack)
275        );
276    }
277
278    #[cfg(target_arch = "riscv64")]
279    unsafe {
280        core::arch::asm!(
281        "rdinstret {0}",
282        "auipc {1}, 0",
283        "mv {2}, sp",
284        out(reg) state, out(reg) code, out(reg) stack,
285        out("t0") gpr1, out("t1") gpr2, out("t2") gpr3,
286        options(nomem, nostack)
287        );
288    }
289
290    #[cfg(target_arch = "x86")]
291    unsafe {
292        let (s32, c32, sp32, g1, g2, g3): (u32, u32, u32, u32, u32, u32);
293        core::arch::asm!(
294        "pushfd",
295        "pop {0}",
296        "call 2f",
297        "2:",
298        "pop {1}",
299        "mov {2}, esp",
300        out(reg) s32, out(reg) c32, out(reg) sp32,
301        out("ecx") g1, out("edx") g2, out("edi") g3,
302        );
303        state = s32 as u64;
304        code = c32 as u64;
305        stack = sp32 as u64;
306        gpr1 = g1 as u64;
307        gpr2 = g2 as u64;
308        gpr3 = g3 as u64;
309    }
310
311    #[cfg(target_arch = "arm")]
312    unsafe {
313        let (s32, c32, sp32, g1, g2, g3): (u32, u32, u32, u32, u32, u32);
314        core::arch::asm!(
315        "mrs {0}, CPSR", // 读取当前程序状态寄存器
316        "mov {1}, pc",   // 32位ARM允许直接读取PC寄存器
317        "mov {2}, sp",
318        out(reg) s32, out(reg) c32, out(reg) sp32,
319        out("r1") g1, out("r2") g2, out("r3") g3,
320        options(nomem, nostack)
321        );
322        state = s32 as u64;
323        code = c32 as u64;
324        stack = sp32 as u64;
325        gpr1 = g1 as u64;
326        gpr2 = g2 as u64;
327        gpr3 = g3 as u64;
328    }
329
330    #[cfg(target_arch = "riscv32")]
331    unsafe {
332        let (s32, c32, sp32, g1, g2, g3): (u32, u32, u32, u32, u32, u32);
333        core::arch::asm!(
334        "rdinstret {0}", // RISC-V 32同样支持退休指令计数器
335        "auipc {1}, 0",
336        "mv {2}, sp",
337        out(reg) s32, out(reg) c32, out(reg) sp32,
338        out("t0") g1, out("t1") g2, out("t2") g3,
339        options(nomem, nostack)
340        );
341        state = s32 as u64;
342        code = c32 as u64;
343        stack = sp32 as u64;
344        gpr1 = g1 as u64;
345        gpr2 = g2 as u64;
346        gpr3 = g3 as u64;
347    }
348
349    #[cfg(not(any(
350        target_arch = "x86_64",
351        target_arch = "aarch64",
352        target_arch = "riscv64",
353        target_arch = "x86",
354        target_arch = "arm",
355        target_arch = "riscv32"
356    )))]
357    {
358        state = 0;
359        gpr1 = 0;
360        gpr2 = 0;
361        gpr3 = 0;
362        code = 0;
363        stack = 0;
364    }
365
366    let mut s = state.rotate_left(13);
367    s ^= gpr1.rotate_right(17);
368    s ^= gpr2.rotate_left(11);
369    s ^= gpr3.rotate_right(3);
370    s ^= code.rotate_left(17);
371    s ^= stack.rotate_right(5);
372    mix64(s)
373}
374
375// 10MB seed()产出测试
376// Loaded 10485760 samples of 256 distinct 8-bit-wide symbols
377// Number of Binary Symbols: 83886080
378//
379// Running non-IID tests...
380//
381// Running Most Common Value Estimate...
382// Bitstring MCV Estimate: mode = 41952873, p-hat = 0.50011721849441526, p_u = 0.50025783688546077
383//         Most Common Value Estimate (bit string) = 0.999256 / 1 bit(s)
384// Literal MCV Estimate: mode = 41493, p-hat = 0.0039570808410644533, p_u = 0.004007020276832818
385//         Most Common Value Estimate = 7.963254 / 8 bit(s)
386//
387// Running Entropic Statistic Estimates (bit strings only)...
388// Bitstring Collision Estimate: X-bar = 2.4998640044984755, sigma-hat = 0.4999999889553986, p = 0.51338519057718568
389//         Collision Test Estimate (bit string) = 0.961886 / 1 bit(s)
390// Bitstring Markov Estimate: P_0 = 0.49988278150558474, P_1 = 0.50011721849441526, P_0,0 = 0.49999291730758672, P_0,1 = 0.50000708269241323, P_1,0 = 0.49977268541298708, P_1,1 = 0.50022731458701286, p_max = 3.1140954007368964e-39
391//         Markov Test Estimate (bit string) = 0.999347 / 1 bit(s)
392// Bitstring Compression Estimate: X-bar = 5.2179921089068255, sigma-hat = 1.0151616484856194, p = 0.018763160395471878
393//         Compression Test Estimate (bit string) = 0.955992 / 1 bit(s)
394//
395// Running Tuple Estimates...
396// Bitstring t-Tuple Estimate: t = 22, p-hat_max = 0.5192926595069563040102, p_u = 0.5194331731846545434296
397// Bitstring LRS Estimate: u = 23, v = 50, p-hat = 0.50285994550643263, p_u = 0.50300056160100674
398//         T-Tuple Test Estimate (bit string) = 0.944990 / 1 bit(s)
399// Literal t-Tuple Estimate: t = 2, p-hat_max = 0.004528134246922033372418, p_u = 0.004581540398724434760821
400// Literal LRS Estimate: u = 3, v = 5, p-hat = 0.0039059863557037059, p_u = 0.0039556036033593406
401//         T-Tuple Test Estimate = 7.769952 / 8 bit(s)
402//         LRS Test Estimate (bit string) = 0.991368 / 1 bit(s)
403//         LRS Test Estimate = 7.981886 / 8 bit(s)
404//
405// Running Predictor Estimates...
406// Bitstring MultiMCW Prediction Estimate: N = 83886017, Pglobal' = 0.50017991581909249 (C = 41946305) Plocal can't affect result (r = 27)
407//         Multi Most Common in Window (MultiMCW) Prediction Test Estimate (bit string) = 0.999481 / 1 bit(s)
408// Literal MultiMCW Prediction Estimate: N = 10485697, Pglobal' = 0.0039609791527534998 (C = 41013) Plocal can't affect result (r = 3)
409//         Multi Most Common in Window (MultiMCW) Prediction Test Estimate = 7.979927 / 8 bit(s)
410// Bitstring Lag Prediction Estimate: N = 83886079, Pglobal' = 0.50005931169698126 (C = 41936219) Plocal can't affect result (r = 29)
411//         Lag Prediction Test Estimate (bit string) = 0.999829 / 1 bit(s)
412// Literal Lag Prediction Estimate: N = 10485759, Pglobal' = 0.0039561572050945742 (C = 40963) Plocal = 0.0055718813178256762 (r = 4)
413//         Lag Prediction Test Estimate = 7.487620 / 8 bit(s)
414// Bitstring MultiMMC Prediction Estimate: N = 83886078, Pglobal' = 0.50020497949238396 (C = 41948438) Plocal can't affect result (r = 26)
415//         Multi Markov Model with Counting (MultiMMC) Prediction Test Estimate (bit string) = 0.999409 / 1 bit(s)
416// Literal MultiMMC Prediction Estimate: N = 10485758, Pglobal' = 0.0039504952950308991 (C = 40904) Plocal = 0.0055718814508428282 (r = 4)
417//         Multi Markov Model with Counting (MultiMMC) Prediction Test Estimate = 7.487620 / 8 bit(s)
418// Bitstring LZ78Y Prediction Estimate: N = 83886063, Pglobal' = 0.5002201250591588 (C = 41949701) Plocal can't affect result (r = 28)
419//         LZ78Y Prediction Test Estimate (bit string) = 0.999365 / 1 bit(s)
420// Literal LZ78Y Prediction Estimate: N = 10485743, Pglobal' = 0.0039507888600843859 (C = 40907) Plocal = 0.0055718834462567543 (r = 4)
421//         LZ78Y Prediction Test Estimate = 7.487619 / 8 bit(s)
422//
423// H_original: 7.487619
424// H_bitstring: 0.944990
425// min(H_original, 8 X H_bitstring): 7.487619
426
427// RNG = RNG_stdin, seed = unknown
428// test set = core, folding = standard(unknown format)
429//
430// rng=RNG_stdin, seed=unknown
431// length= 32 megabytes (2^25 bytes), time= 2.6 seconds
432//   no anomalies in 163 test result(s)
433//
434// rng=RNG_stdin, seed=unknown
435// length= 64 megabytes (2^26 bytes), time= 5.5 seconds
436//   no anomalies in 174 test result(s)
437//
438// rng=RNG_stdin, seed=unknown
439// length= 128 megabytes (2^27 bytes), time= 11.1 seconds
440//   no anomalies in 187 test result(s)
441//
442// rng=RNG_stdin, seed=unknown
443// length= 256 megabytes (2^28 bytes), time= 21.8 seconds
444//   no anomalies in 201 test result(s)
445//
446// rng=RNG_stdin, seed=unknown
447// length= 512 megabytes (2^29 bytes), time= 43.1 seconds
448//   no anomalies in 216 test result(s)
449/// 混合多熵源生成 64 位种子。
450///
451/// 将 `probe` 时间戳、`reg_sig` 寄存器指纹与栈内存抖动混合搅拌,
452/// 适用于 `next` 的定期重播种。开销高于 `next`,勿用于热路径。
453///
454/// # Feature Requirement
455///
456/// 需要启用 `"rand"` 特性。
457///
458/// # Examples
459///
460/// ```rust
461/// use lib_unknown::rand::seed;
462///
463/// let s1 = seed();
464/// let s2 = seed();
465/// assert_ne!(s1, s2);
466/// ```
467pub fn seed() -> u64 {
468    use core::hint::black_box;
469
470    static COUNTER: AtomicUsize = AtomicUsize::new(0);
471    const STACK_MASK: usize = 767;
472    static CONFIG: (u8, u8, u8) = (32, 16, 8);
473
474    let c = COUNTER.fetch_add(1, Ordering::Relaxed) as u8;
475    let x = probe();
476    let y = reg_sig();
477    #[cfg(feature = "rand-safe-stack")]
478    let stack: core::mem::MaybeUninit<[u8; STACK_MASK]> = core::mem::MaybeUninit::uninit();
479    // SAFETY: 仅做指针取址与类型转换,未解引用,不访问内存。
480    let sp = unsafe {
481        #[cfg(feature = "rand-safe-stack")]
482        {
483            black_box(stack.as_ptr() as *const u8)
484        }
485        #[cfg(not(feature = "rand-safe-stack"))]
486        {
487            black_box(&c as *const u8) // 大多数情况下rust程序使用的栈大于767字节
488        }
489    };
490    // SAFETY: 有意读取调用栈邻近字节作为抖动熵源,仅 volatile 读、不写入;
491    // `rand-safe-stack` 特性下指针指向 767 字节栈缓冲。默认特性下读取范围可能超出单个局部变量
492    // (实践中落在相邻栈内存,属本模块已接受的熵采集行为,见模块头测试记录),调用方不得依赖所读内容。
493    let rs = |idx| unsafe { black_box(core::ptr::read_volatile(sp.add(idx))).saturating_add(2) };
494    let t2s = |t: u64, mut s: u64, i: u8| {
495        if t.rotate_left(i as u32) as u8 & 1 == 0 {
496            let idx = ((t as u16) & (STACK_MASK as u16)) as usize;
497            s = s.rotate_left(rs(idx) as u32);
498            let idx2 = (((s >> 16) as u16) & (STACK_MASK as u16)) as usize;
499            s = s.wrapping_mul(rs(idx2) as u64);
500        } else {
501            let idx = (((t >> 16) as u16) & (STACK_MASK as u16)) as usize;
502            s = s.rotate_right(rs(idx) as u32);
503            let idx2 = ((s as u16) & (STACK_MASK as u16)) as usize;
504            s = s.wrapping_mul(rs(idx2) as u64);
505        }
506
507        s = match s.rotate_left(i as u32) as u8 {
508            0 => s ^ 0x9e3779b97f4a7c15,
509            255 => s.wrapping_mul(probe().saturating_add(2)),
510            127 => s.rotate_right(7),
511            3 => s.wrapping_mul(STACK_MASK as u64),
512            7 => s.wrapping_add(0x9e3779b97f4a7c15),
513            32 => s.wrapping_mul(0x94d049bb133111eb),
514            _ => s,
515        };
516        s
517    };
518
519    let mut s = (x ^ y).rotate_right(c as u32);
520
521    for i in 0..black_box(CONFIG.0) {
522        if (s >> 8) as u8 > 127 {
523            continue;
524        }
525        let t1 = probe().wrapping_mul((i as u64 ^ s).wrapping_mul(0x9e3779b97f4a7c15));
526        s ^= t1;
527        s = t2s(t1, s, i);
528
529        for j in 0..black_box(CONFIG.1) {
530            if (s >> 16) as u8 <= 127 {
531                continue;
532            }
533            let t2 = probe().wrapping_mul(((i ^ j) as u64 ^ s).wrapping_mul(0x9e3779b97f4a7c15));
534            s ^= t2;
535            s = t2s(t2, s, i ^ j);
536
537            for k in 0..black_box(CONFIG.2) {
538                if (s >> 32) as u8 > 127 {
539                    continue;
540                }
541                let t3 =
542                    probe().wrapping_mul(((i ^ j ^ k) as u64 ^ s).wrapping_mul(0x9e3779b97f4a7c15));
543                s ^= t3;
544                s = t2s(t3, s, i ^ j ^ k);
545            }
546        }
547    }
548    mix64(s)
549}
550
551/// 使用系统熵打乱序列,并将所有权返回给调用者。
552///
553/// 基于 Fisher–Yates 洗牌(见 [`shuffle_with`],索引选取采用 Lemire 无偏约减),熵源取自 [`next`];
554/// 空序列与单元素序列保持不变。
555///
556/// # Feature Requirement
557///
558/// 需要启用 `"rand"` 特性。
559///
560/// # Examples
561///
562/// ```rust
563/// use lib_unknown::rand::shuffle;
564///
565/// let v = shuffle([0, 1, 2, 3, 4, 5, 6, 7]);
566/// assert_eq!(v.len(), 8);
567/// // 洗牌是原序列的一个置换:排序后应与原序列一致。
568/// let mut sorted = v;
569/// sorted.sort_unstable();
570/// assert_eq!(sorted, [0, 1, 2, 3, 4, 5, 6, 7]);
571/// ```
572pub fn shuffle<T, U>(mut table: U) -> U
573where
574    U: AsMut<[T]>,
575{
576    shuffle_with(table, next())
577}
578
579// RNG = RNG_stdin, seed = unknown
580// test set = core, folding = standard(unknown format)
581//
582// rng=RNG_stdin, seed=unknown
583// length= 256 megabytes (2^28 bytes), time= 3.6 seconds
584//   no anomalies in 201 test result(s)
585//
586// rng=RNG_stdin, seed=unknown
587// length= 512 megabytes (2^29 bytes), time= 7.4 seconds
588//   Test Name                         Raw       Processed     Evaluation
589//   [Low1/32]BCFN(2+1,13-5U)          R=  -7.0  p =1-1.8e-4   unusual
590//   ...and 215 test result(s) without anomalies
591//
592// rng=RNG_stdin, seed=unknown
593// length= 1 gigabyte (2^30 bytes), time= 14.7 seconds
594//   no anomalies in 231 test result(s)
595//
596// rng=RNG_stdin, seed=unknown
597// length= 2 gigabytes (2^31 bytes), time= 29.0 seconds
598//   no anomalies in 246 test result(s)
599//
600// rng=RNG_stdin, seed=unknown
601// length= 4 gigabytes (2^32 bytes), time= 57.4 seconds
602//   no anomalies in 261 test result(s)
603//
604// rng=RNG_stdin, seed=unknown
605// length= 8 gigabytes (2^33 bytes), time= 115 seconds
606//   no anomalies in 274 test result(s)
607//
608// rng=RNG_stdin, seed=unknown
609// length= 16 gigabytes (2^34 bytes), time= 234 seconds
610//   no anomalies in 287 test result(s)
611//
612// rng=RNG_stdin, seed=unknown
613// length= 32 gigabytes (2^35 bytes), time= 506 seconds
614//   no anomalies in 299 test result(s)
615/// 生成下一个 64 位随机数(热路径)。
616///
617/// 快路径为 `mix64` 搅拌计数器,每 1024 次调用或首次调用时用 `seed` 重播种。
618/// 线程安全,可在 `no_std` 下使用。
619///
620/// # Feature Requirement
621///
622/// 需要启用 `"rand"` 特性。
623///
624/// # Examples
625///
626/// ```rust
627/// use lib_unknown::rand::next;
628///
629/// let a = next();
630/// let b = next();
631/// assert_ne!(a, b);
632/// ```
633pub fn next() -> u64 {
634    static SEED: AtomicU64 = AtomicU64::new(0);
635    static COUNTER: AtomicUsize = AtomicUsize::new(0);
636    let c = COUNTER.fetch_add(1, Ordering::Relaxed);
637    let mut s = SEED.fetch_add(0x9e3779b97f4a7c15, Ordering::Relaxed);
638    if s == 0 || s == 0x9e3779b97f4a7c15 || c.is_multiple_of(1024) {
639        s ^= seed();
640        SEED.store(s, Ordering::Relaxed);
641        s
642    } else {
643        mix64(s)
644    }
645}
646
647// // 热路径开销与seed相当
648// // RNG = RNG_stdin, seed = unknown
649// // test set = core, folding = standard(unknown format)
650// //
651// // rng=RNG_stdin, seed=unknown
652// // length= 32 megabytes (2^25 bytes), time= 2.1 seconds
653// //   no anomalies in 163 test result(s)
654// //
655// // rng=RNG_stdin, seed=unknown
656// // length= 64 megabytes (2^26 bytes), time= 4.1 seconds
657// //   no anomalies in 174 test result(s)
658// //
659// // rng=RNG_stdin, seed=unknown
660// // length= 128 megabytes (2^27 bytes), time= 7.6 seconds
661// //   no anomalies in 187 test result(s)
662// //
663// // rng=RNG_stdin, seed=unknown
664// // length= 256 megabytes (2^28 bytes), time= 14.7 seconds
665// //   no anomalies in 201 test result(s)
666// //
667// // rng=RNG_stdin, seed=unknown
668// // length= 512 megabytes (2^29 bytes), time= 28.5 seconds
669// //   no anomalies in 216 test result(s)
670// //
671// // rng=RNG_stdin, seed=unknown
672// // length= 1 gigabyte (2^30 bytes), time= 55.7 seconds
673// //   no anomalies in 231 test result(s)
674// //
675// // rng=RNG_stdin, seed=unknown
676// // length= 2 gigabytes (2^31 bytes), time= 110 seconds
677// //   no anomalies in 246 test result(s)
678// pub fn next() -> u64 {
679//     static IV: u64 = 0x00001000808c0001;
680//
681//     // 全局密钥
682//     static K1: AtomicU64 = AtomicU64::new(0);
683//     static K2: AtomicU64 = AtomicU64::new(0);
684//     static INIT_STATE: AtomicUsize = AtomicUsize::new(0);
685//
686//     // 动态状态源
687//     static SEED1: AtomicU64 = AtomicU64::new(0);
688//     static SEED2: AtomicU64 = AtomicU64::new(0);
689//     static COUNTER: AtomicUsize = AtomicUsize::new(0);
690//
691//     #[inline]
692//     const fn round(x: [u64; 5], c: u64) -> [u64; 5] {
693//         let x0 = x[0] ^ x[4];
694//         let x2 = x[2] ^ x[1] ^ c;
695//         let x4 = x[4] ^ x[3];
696//         let tx0 = x0 ^ (!x[1] & x2);
697//         let tx1 = x[1] ^ (!x2 & x[3]);
698//         let tx2 = x2 ^ (!x[3] & x4);
699//         let tx3 = x[3] ^ (!x4 & x0);
700//         let tx4 = x4 ^ (!x0 & x[1]);
701//         let tx1 = tx1 ^ tx0;
702//         let tx3 = tx3 ^ tx2;
703//         let tx0 = tx0 ^ tx4;
704//         let x0 = tx0 ^ tx0.rotate_right(9);
705//         let x1 = tx1 ^ tx1.rotate_right(22);
706//         let x2 = tx2 ^ tx2.rotate_right(5);
707//         let x3 = tx3 ^ tx3.rotate_right(7);
708//         let x4 = tx4 ^ tx4.rotate_right(34);
709//         [
710//             tx0 ^ x0.rotate_right(19),
711//             tx1 ^ x1.rotate_right(39),
712//             !(tx2 ^ x2.rotate_right(1)),
713//             tx3 ^ x3.rotate_right(10),
714//             tx4 ^ x4.rotate_right(7),
715//         ]
716//     }
717//
718//     let c = COUNTER.fetch_add(1, Ordering::Relaxed) as u64;
719//
720//     let mut s1 = SEED1.fetch_add(0x9e3779b97f4a7c15, Ordering::Relaxed);
721//     let mut s2 = SEED2.fetch_add(0xbf58476d1ce4e5b9, Ordering::Relaxed);
722//
723//     if c == 0 || c & 1023 == 0 {
724//         let new_entropy = seed();
725//         SEED1.fetch_xor(new_entropy, Ordering::Relaxed);
726//         s1 ^= new_entropy;
727//     } else {
728//         s1 = mix64(s1);
729//         s2 = mix64(s2);
730//     }
731//
732//     let mut k1 = K1.load(Ordering::Acquire);
733//     let mut k2 = K2.load(Ordering::Acquire);
734//
735//     if k1 == 0 || k2 == 0 {
736//         match INIT_STATE.compare_exchange(0, 1, Ordering::Acquire, Ordering::Relaxed) {
737//             Ok(_) => {
738//                 k1 = seed();
739//                 k2 = seed();
740//
741//                 if k1 == 0 { k1 = 1; }
742//                 if k2 == 0 { k2 = 1; }
743//
744//                 K1.store(k1, Ordering::Release);
745//                 K2.store(k2, Ordering::Release);
746//                 INIT_STATE.store(2, Ordering::Release);
747//             }
748//             Err(_) => {
749//                 let mut spins = 0;
750//                 while INIT_STATE.load(Ordering::Acquire) != 2 {
751//                     core::hint::spin_loop();
752//                     spins += 1;
753//                     if spins > 10_000 { break; }
754//                 }
755//
756//                 k1 = K1.load(Ordering::Acquire);
757//                 k2 = K2.load(Ordering::Acquire);
758//                 if k1 == 0 { k1 = c ^ 0xDEADBEEF; }
759//                 if k2 == 0 { k2 = s1 ^ 0xCAFEBABE; }
760//             }
761//         }
762//     }
763//
764//     let mut state = [IV, k1, k2, s1 ^ c, s2];
765//
766//     let constants = [
767//         0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b,
768//     ];
769//     for &cst in &constants {
770//         state = round(state, cst);
771//     }
772//
773//     state[0]
774// }
775
776#[cfg(feature = "rand-expand")]
777/// 可随机生成的类型。
778///
779/// 熵源取自 [`next`]。各实现的取值语义:
780/// - 整数:取 `next()` 输出并截断为目标位宽(`as` 转换);
781/// - `bool`:取最低位;
782/// - 浮点(`f32` / `f64`):`[0, 1)` 区间内均匀分布。
783///
784/// # Feature Requirement
785///
786/// 需要启用 `"rand-expand"` 特性。
787///
788/// # Examples
789///
790/// ```rust
791/// use lib_unknown::rand::{Random, random};
792///
793/// let v: u64 = random();
794/// let _ = v;
795/// ```
796pub trait Random {
797    /// 生成一个该类型的随机值(语义见 trait 级文档)。
798    fn random() -> Self;
799}
800#[cfg(feature = "rand-expand")]
801/// 生成指定类型的随机值(`T::random()` 的便捷包装)。
802///
803/// # Feature Requirement
804///
805/// 需要启用 `"rand-expand"` 特性。
806///
807/// # Examples
808///
809/// ```rust
810/// use lib_unknown::rand::random;
811///
812/// let v: u32 = random();
813/// let _ = v;
814/// ```
815#[inline(always)]
816pub fn random<T: Random>() -> T {
817    T::random()
818}
819macro_rules! impl_random_int {
820    ($($t:ty),*) => {
821        $(
822            #[cfg(feature = "rand-expand")]
823            impl Random for $t {
824                #[inline(always)]
825                fn random() -> Self {
826                    next() as Self
827                }
828            }
829        )*
830    };
831}
832impl_random_int!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
833#[cfg(feature = "rand-expand")]
834impl Random for bool {
835    #[inline(always)]
836    fn random() -> Self {
837        (next() & 1) == 1
838    }
839}
840#[cfg(feature = "rand-expand")]
841impl Random for f64 {
842    #[inline(always)]
843    fn random() -> Self {
844        let fraction = next() >> 11;
845        fraction as f64 / (1u64 << 53) as f64
846    }
847}
848#[cfg(feature = "rand-expand")]
849impl Random for f32 {
850    #[inline(always)]
851    fn random() -> Self {
852        let fraction = (next() as u32) >> 8;
853        fraction as f32 / (1u32 << 24) as f32
854    }
855}
856
857#[cfg(feature = "rand-expand")]
858/// 用随机字节填充切片。
859///
860/// 按 8 字节分块以小端序写入(每块取一次 [`next`] 输出),
861/// 尾部不足 8 字节时截取新一次输出的前缀。
862///
863/// # Feature Requirement
864///
865/// 需要启用 `"rand-expand"` 特性。
866///
867/// # Examples
868///
869/// ```rust
870/// use lib_unknown::rand::fill_bytes;
871///
872/// let mut buf = [0u8; 16];
873/// fill_bytes(&mut buf);
874/// assert_eq!(buf.len(), 16);
875/// ```
876pub fn fill_bytes(dest: &mut [u8]) {
877    let (chunks, remainder) = dest.as_chunks_mut::<8>();
878    for chunk in chunks {
879        *chunk = next().to_le_bytes();
880    }
881    if !remainder.is_empty() {
882        let bytes = next().to_le_bytes();
883        remainder.copy_from_slice(&bytes[..remainder.len()]);
884    }
885}
886
887#[cfg(feature = "rand-expand")]
888/// 可从区间采样的类型。
889///
890/// - 整数区间采用拒绝采样实现无偏取模,不引入模偏差;
891/// - 浮点区间按 `start + random::<T>() * (end - start)` 缩放。
892///
893/// # Feature Requirement
894///
895/// 需要启用 `"rand-expand"` 特性。
896///
897/// # Examples
898///
899/// ```rust
900/// use lib_unknown::rand::random_range;
901///
902/// let v = random_range(0..10u32);
903/// assert!(v < 10);
904/// ```
905pub trait SampleRange {
906    /// 采样输出类型(与区间元素类型一致)。
907    type Output;
908    /// 执行一次采样(约束违反时 panic,见 [`random_range`])。
909    fn sample(self) -> Self::Output;
910}
911
912#[cfg(feature = "rand-expand")]
913/// 从区间中均匀采样一个随机值,整数用无偏取模实现。
914///
915/// 浮点闭区间(`..=`)的上界实际上不可达(`random::<T>() < 1` 恒成立),
916/// `start == end` 时直接返回该值。
917///
918/// # Feature Requirement
919///
920/// 需要启用 `"rand-expand"` 特性。
921///
922/// # Examples
923///
924/// ```rust
925/// use lib_unknown::rand::random_range;
926///
927/// let v = random_range(0..100u32);
928/// assert!(v < 100);
929/// ```
930///
931/// # Panics
932///
933/// - 当区间为空(`start >= end`,闭区间为 `start > end`)时发生 panic。
934#[inline(always)]
935pub fn random_range<R: SampleRange>(range: R) -> R::Output {
936    range.sample()
937}
938macro_rules! impl_sample_range_int {
939    ($($t:ty, $u:ty),*) => {
940        $(
941            // 支持半开区间 Range (..)
942            #[cfg(feature = "rand-expand")]
943            impl SampleRange for core::ops::Range<$t> {
944                type Output = $t;
945
946                #[inline]
947                fn sample(self) -> $t {
948                    assert!(self.start < self.end, "Invalid range: start must be less than end");
949
950                    let start = self.start as $u;
951                    let end = self.end as $u;
952                    let span = end.wrapping_sub(start);
953
954                    let threshold = span.wrapping_neg() % span;
955
956                    loop {
957                        let r = next() as $u;
958                        if r >= threshold {
959                            let offset = r % span;
960                            return start.wrapping_add(offset) as $t;
961                        }
962                    }
963                }
964            }
965
966            // 支持闭区间 RangeInclusive (..=)
967            #[cfg(feature = "rand-expand")]
968            impl SampleRange for core::ops::RangeInclusive<$t> {
969                type Output = $t;
970
971                #[inline]
972                fn sample(self) -> $t {
973                    let (start_val, end_val) = (*self.start(), *self.end());
974                    assert!(start_val <= end_val, "Invalid range: start must be less than or equal to end");
975
976                    if start_val == <$t>::MIN && end_val == <$t>::MAX {
977                        return next() as $t;
978                    }
979
980                    let start = start_val as $u;
981                    let end = end_val as $u;
982                    let span = end.wrapping_sub(start).wrapping_add(1);
983
984                    let threshold = span.wrapping_neg() % span;
985
986                    loop {
987                        let r = next() as $u;
988                        if r >= threshold {
989                            let offset = r % span;
990                            return start.wrapping_add(offset) as $t;
991                        }
992                    }
993                }
994            }
995        )*
996    };
997}
998
999impl_sample_range_int!(
1000    u8, u8, u16, u16, u32, u32, u64, u64, usize, usize, i8, u8, i16, u16, i32, u32, i64, u64,
1001    isize, usize
1002);
1003macro_rules! impl_sample_range_float {
1004    ($($t:ty),*) => {
1005        $(
1006            #[cfg(feature = "rand-expand")]
1007            impl SampleRange for core::ops::Range<$t> {
1008                type Output = $t;
1009                #[inline]
1010                fn sample(self) -> $t {
1011                    assert!(self.start < self.end, "Invalid range: start must be less than end");
1012                    self.start + random::<$t>() * (self.end - self.start)
1013                }
1014            }
1015
1016            #[cfg(feature = "rand-expand")]
1017            impl SampleRange for core::ops::RangeInclusive<$t> {
1018                type Output = $t;
1019                #[inline]
1020                fn sample(self) -> $t {
1021                    let (start, end) = (*self.start(), *self.end());
1022                    assert!(start <= end, "Invalid range: start must be less than or equal to end");
1023                    if start == end {
1024                        return start;
1025                    }
1026                    start + random::<$t>() * (end - start)
1027                }
1028            }
1029        )*
1030    };
1031}
1032
1033impl_sample_range_float!(f32, f64);
1034
1035#[cfg(test)]
1036#[allow(clippy::unwrap_used, clippy::expect_used)]
1037mod tests {
1038    use super::*;
1039
1040    #[cfg(feature = "std")]
1041    #[test]
1042    fn test() {
1043        for _ in 0..1024 {
1044            let a = std::time::Instant::now();
1045            let s = next();
1046            println!("{:<30}{:?}", s, a.elapsed());
1047        }
1048    }
1049}