1
0
Fork 0

const lookup table

This commit is contained in:
Paul-Nicolas Madelaine 2025-10-22 22:59:53 +02:00
parent 752150107e
commit 0d22c59cc3
8 changed files with 573 additions and 542 deletions

View file

@ -1,193 +1,7 @@
use crate::bitboard::*;
use crate::board::*;
use crate::rays::Rays;
use crate::board::Square;
const BISHOP_SHR: u8 = 55;
const ROOK_SHR: u8 = 52;
pub(crate) struct Magics {
bishop: BySquare<Magic>,
rook: BySquare<Magic>,
table: Box<[Bitboard]>,
}
#[derive(Clone, Copy)]
struct Magic {
premask: Bitboard,
factor: u64,
offset: isize,
}
impl Magics {
pub(crate) fn compute(rays: &Rays) -> Self {
let mut data = Vec::new();
let mut aux =
|shr,
factors: fn(Square) -> u64,
make_table: fn(&Rays, Square) -> (Bitboard, Vec<(Bitboard, Bitboard)>)| {
BySquare::new(|square| {
let (premask, table) = make_table(rays, square);
let factor = factors(square);
let offset = fill_table(&mut data, shr, factor, table);
Magic {
premask,
factor,
offset,
}
})
};
let bishop = aux(BISHOP_SHR, bishop_factors, make_bishop_table);
let rook = aux(ROOK_SHR, rook_factors, make_rook_table);
let mut table = Box::new_uninit_slice(data.len());
for (i, entry) in data.into_iter().enumerate() {
table[i].write(entry);
}
Self {
bishop,
rook,
table: unsafe { table.assume_init() },
}
}
#[inline]
pub(crate) fn bishop(&self, square: Square, blockers: Bitboard) -> Bitboard {
unsafe { self.get_unchecked(BISHOP_SHR, *self.bishop.get(square), blockers) }
}
#[inline]
pub(crate) fn rook(&self, square: Square, blockers: Bitboard) -> Bitboard {
unsafe { self.get_unchecked(ROOK_SHR, *self.rook.get(square), blockers) }
}
#[inline]
unsafe fn get_unchecked(&self, shr: u8, magic: Magic, blockers: Bitboard) -> Bitboard {
let Magic {
premask,
factor,
offset,
} = magic;
*self.table.get_unchecked(
((hash(shr, factor, blockers | premask) as isize).unchecked_add(offset)) as usize,
)
}
}
fn fill_table(
data: &mut Vec<Bitboard>,
shr: u8,
factor: u64,
table: Vec<(Bitboard, Bitboard)>,
) -> isize {
let offset = data.len() as isize
- table
.iter()
.map(|(x, _)| hash(shr, factor, *x) as isize)
.min()
.unwrap();
for (x, y) in &table {
let i = (hash(shr, factor, *x) as isize + offset) as usize;
while data.len() <= i {
data.push(Bitboard::new());
}
if data[i] != Bitboard::new() && data[i] != *y {
panic!();
}
data[i] = *y;
}
offset
}
fn make_bishop_table(rays: &Rays, square: Square) -> (Bitboard, Vec<(Bitboard, Bitboard)>) {
let mut premask = Bitboard::new();
for direction in [
Direction::NorthWest,
Direction::SouthWest,
Direction::SouthEast,
Direction::NorthEast,
] {
premask |= rays.ray(square, direction);
}
premask &= !Rank::First.bitboard();
premask &= !Rank::Eighth.bitboard();
premask &= !File::A.bitboard();
premask &= !File::H.bitboard();
let mut table = make_table(premask, |blockers| {
let mut res = Bitboard::new();
for direction in [
Direction::NorthWest,
Direction::SouthWest,
Direction::SouthEast,
Direction::NorthEast,
] {
res |= rays.blocked(square, direction, blockers);
}
res
});
premask = !premask;
for (x, _) in &mut table {
*x |= premask;
}
(premask, table)
}
fn make_rook_table(rays: &Rays, square: Square) -> (Bitboard, Vec<(Bitboard, Bitboard)>) {
let mut premask = Bitboard::new();
premask |= rays.ray(square, Direction::North) & !Rank::Eighth.bitboard();
premask |= rays.ray(square, Direction::West) & !File::A.bitboard();
premask |= rays.ray(square, Direction::South) & !Rank::First.bitboard();
premask |= rays.ray(square, Direction::East) & !File::H.bitboard();
let mut table = make_table(premask, |blockers| {
let mut res = Bitboard::new();
for direction in [
Direction::North,
Direction::West,
Direction::South,
Direction::East,
] {
res |= rays.blocked(square, direction, blockers);
}
res
});
premask = !premask;
for (x, _) in &mut table {
*x |= premask;
}
(premask, table)
}
fn make_table<T, F>(premask: Bitboard, f: F) -> Vec<(Bitboard, T)>
where
F: Fn(Bitboard) -> T,
{
let mut res = Vec::new();
let mut subset: u64 = 0;
loop {
subset = subset.wrapping_sub(premask.0) & premask.0;
let x = Bitboard(subset);
let y = f(x);
res.push((x, y));
if subset == 0 {
break;
}
}
res
}
fn hash(shr: u8, factor: u64, x: Bitboard) -> usize {
(x.0.wrapping_mul(factor) >> shr) as usize
}
fn bishop_factors(square: Square) -> u64 {
pub(crate) const BISHOP_SHR: u8 = 55;
pub(crate) const fn bishop_factor(square: Square) -> u64 {
match square {
Square::A1 => 0x0000404040404040,
Square::B1 => 0x0040C100081000E8,
@ -256,7 +70,8 @@ fn bishop_factors(square: Square) -> u64 {
}
}
fn rook_factors(square: Square) -> u64 {
pub(crate) const ROOK_SHR: u8 = 52;
pub(crate) const fn rook_factor(square: Square) -> u64 {
match square {
Square::A1 => 0x002000A28110000C,
Square::B1 => 0x0018000C01060001,