nak: Add an implementation of the ACORN random number generator
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30275>
This commit is contained in:

committed by
Marge Bot

parent
cd7128c2e3
commit
9e25b6c0ff
81
src/nouveau/compiler/acorn/lib.rs
Normal file
81
src/nouveau/compiler/acorn/lib.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright © 2022 Collabora, Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Generated by random.org
|
||||
const INIT_DATA: [u16; 64] = [
|
||||
8235, 45378, 61861, 23858, 42241, 27301, 23697, 15333, 52828, 39161, 46572,
|
||||
7478, 11198, 4926, 21736, 23781, 37217, 20323, 32754, 61367, 12882, 35352,
|
||||
29343, 26458, 62858, 44415, 35786, 58466, 45062, 30330, 30350, 35134,
|
||||
28228, 36077, 26793, 27223, 52219, 52544, 3565, 56253, 40962, 40833, 35607,
|
||||
46482, 64735, 31252, 44165, 40273, 46825, 15929, 27160, 1106, 59035, 48146,
|
||||
47365, 19901, 37178, 35614, 29628, 23344, 11328, 60105, 28727, 344,
|
||||
];
|
||||
|
||||
/// An implementation of the ACORN random number generator
|
||||
///
|
||||
/// See also http://acorn.wikramaratna.org/concept.html
|
||||
///
|
||||
/// This isn't cryptographically secure but it's easy and fast and good enough
|
||||
/// for generating test data. More importantly, we own the implementation so it
|
||||
/// won't change with random library or compiler upgrades.
|
||||
pub struct Acorn {
|
||||
y_n: [u64; Self::K],
|
||||
}
|
||||
|
||||
impl Acorn {
|
||||
const ORD: usize = 60;
|
||||
const K: usize = 16;
|
||||
|
||||
pub fn new() -> Self {
|
||||
let mut y_0 = [0_u64; Self::K];
|
||||
for m in 0..Self::K {
|
||||
y_0[m] |= u64::from(INIT_DATA[m * 4 + 0]) << 0;
|
||||
y_0[m] |= u64::from(INIT_DATA[m * 4 + 1]) << 16;
|
||||
y_0[m] |= u64::from(INIT_DATA[m * 4 + 2]) << 32;
|
||||
y_0[m] |= u64::from(INIT_DATA[m * 4 + 3]) << 48;
|
||||
y_0[m] &= (1u64 << Self::ORD) - 1;
|
||||
}
|
||||
// For good randomness, the seed should be odd
|
||||
assert!(y_0[0] % 2 == 1);
|
||||
Acorn { y_n: y_0 }
|
||||
}
|
||||
|
||||
fn next_u60(&mut self) -> u64 {
|
||||
// y_n[0] remains uncanged
|
||||
for m in 1..Self::K {
|
||||
// We go in increasing M so y_n[m] is y_(n-1)[m] when we read it but
|
||||
// self.y_n[m - 1] is what it says it is
|
||||
self.y_n[m] = (self.y_n[m] + self.y_n[m - 1]) % (1 << Self::ORD);
|
||||
}
|
||||
self.y_n[Self::K - 1]
|
||||
}
|
||||
|
||||
pub fn get_uint(&mut self, bits: usize) -> u64 {
|
||||
if bits <= Self::ORD {
|
||||
self.next_u60() >> (Self::ORD - bits)
|
||||
} else {
|
||||
let hi = self.next_u60() << (bits - Self::ORD);
|
||||
hi | self.get_uint(bits - Self::ORD)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bool(&mut self) -> bool {
|
||||
self.get_uint(1) != 0
|
||||
}
|
||||
|
||||
pub fn get_u8(&mut self) -> u8 {
|
||||
self.get_uint(8) as u8
|
||||
}
|
||||
|
||||
pub fn get_u16(&mut self) -> u16 {
|
||||
self.get_uint(16) as u16
|
||||
}
|
||||
|
||||
pub fn get_u32(&mut self) -> u32 {
|
||||
self.get_uint(32) as u32
|
||||
}
|
||||
|
||||
pub fn get_u64(&mut self) -> u64 {
|
||||
self.get_uint(64)
|
||||
}
|
||||
}
|
@@ -66,6 +66,18 @@ libnak_c_files = files(
|
||||
'nak_memstream.c',
|
||||
)
|
||||
|
||||
_libacorn_rs = static_library(
|
||||
'acorn',
|
||||
files('acorn/lib.rs'),
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
rust_abi : 'rust',
|
||||
rust_args : nak_rust_args,
|
||||
)
|
||||
|
||||
idep_acorn_rs = declare_dependency(
|
||||
link_with : _libacorn_rs,
|
||||
)
|
||||
|
||||
_libbitview_rs = static_library(
|
||||
'bitview',
|
||||
files('bitview/lib.rs'),
|
||||
|
Reference in New Issue
Block a user