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