refactor: random
uses a rust 1.83 feature so that the const fn works better
This commit is contained in:
parent
71594051f5
commit
36753f6ecb
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "beta-2024-11-17"
|
10
src/hash.rs
10
src/hash.rs
@ -13,22 +13,22 @@ Copyright © 2024 dogeystamp <dogeystamp@disroot.org>
|
||||
|
||||
//! Zobrist hash implementation.
|
||||
|
||||
use crate::random::{random_arr_2d_64, random_arr_64};
|
||||
use crate::random::Pcg64Random;
|
||||
use crate::{
|
||||
Board, CastleRights, ColPiece, Color, Square, BOARD_WIDTH, N_COLORS, N_PIECES, N_SQUARES,
|
||||
};
|
||||
|
||||
const PIECE_KEYS: [[[u64; N_SQUARES]; N_PIECES]; N_COLORS] =
|
||||
[random_arr_2d_64(11), random_arr_2d_64(22)];
|
||||
[Pcg64Random::new(11).random_arr_2d_64(), Pcg64Random::new(22).random_arr_2d_64()];
|
||||
|
||||
// 4 bits in castle perms -> 16 keys
|
||||
const CASTLE_KEYS: [u64; 16] = random_arr_64(33);
|
||||
const CASTLE_KEYS: [u64; 16] = Pcg64Random::new(33).random_arr_64();
|
||||
|
||||
// ep can be specified by the file
|
||||
const EP_KEYS: [u64; BOARD_WIDTH] = random_arr_64(44);
|
||||
const EP_KEYS: [u64; BOARD_WIDTH] = Pcg64Random::new(44).random_arr_64();
|
||||
|
||||
// current turn
|
||||
const COL_KEY: [u64; N_COLORS] = random_arr_64(55);
|
||||
const COL_KEY: [u64; N_COLORS] = Pcg64Random::new(55).random_arr_64();
|
||||
|
||||
/// Zobrist hash state.
|
||||
///
|
||||
|
@ -21,7 +21,7 @@ pub mod eval;
|
||||
pub mod fen;
|
||||
mod hash;
|
||||
pub mod movegen;
|
||||
mod random;
|
||||
pub mod random;
|
||||
pub mod search;
|
||||
|
||||
use crate::fen::{FromFen, ToFen, START_POSITION};
|
||||
|
123
src/random.rs
123
src/random.rs
@ -1,77 +1,82 @@
|
||||
//! Rust port by dogeystamp <dogeystamp@disroot.org> of
|
||||
//! the pcg64 dxsm random number generator (https://dotat.at/@/2023-06-21-pcg64-dxsm.html)
|
||||
|
||||
struct Pcg64Random {
|
||||
pub struct Pcg64Random {
|
||||
state: u128,
|
||||
inc: u128,
|
||||
}
|
||||
|
||||
/// Generates an array of random numbers.
|
||||
///
|
||||
/// The `rng` parameter only sets the initial state. This function is deterministic and pure.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The array of random numbers, plus the RNG state at the end.
|
||||
const fn pcg64_dxsm<const N: usize>(mut rng: Pcg64Random) -> ([u64; N], Pcg64Random) {
|
||||
let mut ret = [0; N];
|
||||
|
||||
const MUL: u64 = 15750249268501108917;
|
||||
|
||||
let mut i = 0;
|
||||
while i < N {
|
||||
let state: u128 = rng.state;
|
||||
rng.state = state.wrapping_mul(MUL as u128).wrapping_add(rng.inc);
|
||||
let mut hi: u64 = (state >> 64) as u64;
|
||||
let lo: u64 = (state | 1) as u64;
|
||||
hi ^= hi >> 32;
|
||||
hi &= MUL;
|
||||
hi ^= hi >> 48;
|
||||
hi = hi.wrapping_mul(lo);
|
||||
ret[i] = hi;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
(ret, rng)
|
||||
}
|
||||
|
||||
/// Make an RNG state "sane".
|
||||
const fn pcg64_seed(mut rng: Pcg64Random) -> Pcg64Random {
|
||||
// ensure rng.inc is odd
|
||||
rng.inc = (rng.inc << 1) | 1;
|
||||
rng.state += rng.inc;
|
||||
// one iteration of random
|
||||
let (_, rng) = pcg64_dxsm::<1>(rng);
|
||||
rng.rand();
|
||||
rng
|
||||
}
|
||||
|
||||
/// Generate array of random numbers, based on a seed.
|
||||
///
|
||||
/// This function is pure and deterministic, and also works at compile-time rather than at runtime.
|
||||
///
|
||||
/// Example (generate 10 random numbers):
|
||||
///
|
||||
///```rust
|
||||
/// use crate::random::random_arr_64;
|
||||
/// const ARR: [u64; 10] = random_arr_64(123456);
|
||||
///```
|
||||
pub const fn random_arr_64<const N: usize>(seed: u128) -> [u64; N] {
|
||||
let rng = pcg64_seed(Pcg64Random {
|
||||
// chosen by fair dice roll
|
||||
state: 24437033748623976104561743679864923857,
|
||||
inc: seed,
|
||||
});
|
||||
pcg64_dxsm(rng).0
|
||||
}
|
||||
|
||||
/// Generate 2D array of random numbers based on a seed.
|
||||
pub const fn random_arr_2d_64<const N: usize, const M: usize>(seed: u128) -> [[u64; N]; M] {
|
||||
let mut ret = [[0; N]; M];
|
||||
let mut i = 0;
|
||||
while i < M {
|
||||
ret[i] = random_arr_64(seed);
|
||||
i += 1;
|
||||
impl Pcg64Random {
|
||||
pub const fn new(seed: u128) -> Self {
|
||||
pcg64_seed(Pcg64Random {
|
||||
// chosen by fair dice roll
|
||||
state: 24437033748623976104561743679864923857,
|
||||
inc: seed,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a single random number.
|
||||
pub const fn rand(&mut self) -> u64 {
|
||||
const MUL: u64 = 15750249268501108917;
|
||||
|
||||
let state: u128 = self.state;
|
||||
self.state = state.wrapping_mul(MUL as u128).wrapping_add(self.inc);
|
||||
let mut hi: u64 = (state >> 64) as u64;
|
||||
let lo: u64 = (state | 1) as u64;
|
||||
hi ^= hi >> 32;
|
||||
hi &= MUL;
|
||||
hi ^= hi >> 48;
|
||||
hi = hi.wrapping_mul(lo);
|
||||
|
||||
hi
|
||||
}
|
||||
|
||||
/// Generate array of random numbers, based on a seed.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A tuple with the random number array, and the RNG state afterwards so you can reuse it in later
|
||||
/// calls (otherwise you'll get the same result if you're using the same seed.)
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
///```rust
|
||||
/// use chess_inator::random::Pcg64Random;
|
||||
///
|
||||
/// // generate 3 random numbers
|
||||
/// const ARR: [u64; 3] = Pcg64Random::new(123456).random_arr_64();
|
||||
/// assert_eq!(ARR, [4526545874411451611, 1124465636717751929, 12699417402402334336])
|
||||
///```
|
||||
pub const fn random_arr_64<const N: usize>(&mut self) -> [u64; N] {
|
||||
let mut ret = [0; N];
|
||||
let mut i = 0;
|
||||
while i < N {
|
||||
let num = self.rand();
|
||||
ret[i] = num;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/// Generate 2D array of random numbers based on a seed.
|
||||
pub const fn random_arr_2d_64<const N: usize, const M: usize>(&mut self) -> [[u64; N]; M] {
|
||||
let mut ret = [[0; N]; M];
|
||||
let mut i = 0;
|
||||
while i < M {
|
||||
ret[i] = self.random_arr_64();
|
||||
i += 1;
|
||||
}
|
||||
ret
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user