tanton_engine/tables/
mod.rs1pub mod butterfly;
2pub mod capture_piece_history;
3pub mod continuation;
4pub mod counter_move;
5pub mod material;
6pub mod pawn_table;
7
8use std::alloc::{alloc_zeroed, dealloc, Layout};
9use std::mem;
10use std::ops::*;
11use std::ptr;
12use std::ptr::NonNull;
13
14pub mod prelude {
15 pub use super::butterfly::ButterflyHistory;
17 pub use super::capture_piece_history::CapturePieceToHistory;
18 pub use super::continuation::{ContinuationHistory, PieceToHistory};
19 pub use super::counter_move::CounterMoveHistory;
20 pub use super::{NumStatBoard, NumStatCube, StatBoard};
21}
22
23pub trait StatBoard<T, IDX>: Sized + IndexMut<IDX, Output = T>
27where
28 T: Copy + Clone + Sized,
29{
30 const FILL: T;
31
32 fn new() -> Self {
33 unsafe { mem::zeroed() }
34 }
35
36 fn clear(&mut self) {
37 self.fill(Self::FILL);
38 }
39
40 fn fill(&mut self, val: T) {
41 let num: usize = mem::size_of::<Self>() / mem::size_of::<T>();
42
43 unsafe {
44 let ptr: *mut T = self as *mut Self as *mut T;
45 for i in 0..num {
46 ptr::write(ptr.add(i), val);
47 }
48 }
49 }
50}
51
52pub trait NumStatBoard<IDX>: StatBoard<i16, IDX> {
53 const D: i16;
54 fn update(&mut self, idx: IDX, bonus: i16) {
55 assert!(bonus.abs() <= Self::D); let entry = self.index_mut(idx);
57 *entry += bonus * 32 - (*entry) * bonus.abs() / Self::D;
58 }
59}
60
61pub trait NumStatCube<IDX>: StatBoard<i16, IDX> {
62 const D: i32;
63 const W: i32;
64
65 fn update(&mut self, idx: IDX, bonus: i32) {
66 assert!(bonus.abs() <= Self::D);
67 let entry = self.index_mut(idx);
68 *entry += (bonus * Self::W - (*entry) as i32 * bonus.abs() / Self::D) as i16;
69 assert!(((*entry) as i32).abs() <= Self::D * Self::W);
70 }
71}
72
73pub struct TableBase<T: Sized + TableBaseConst> {
81 table: NonNull<T>,
82}
83
84pub trait TableBaseConst {
85 const ENTRY_COUNT: usize;
86}
87
88impl<T: Sized + TableBaseConst> TableBase<T> {
89 pub fn new() -> Option<TableBase<T>> {
96 if T::ENTRY_COUNT.count_ones() != 1 {
97 None
98 } else {
99 unsafe {
100 let table = TableBase {
101 table: TableBase::alloc(),
102 };
103 Some(table)
104 }
105 }
106 }
107
108 #[inline(always)]
110 pub fn get_mut(&mut self, key: u64) -> &mut T {
111 unsafe { &mut *self.get_ptr(key) }
112 }
113
114 #[inline(always)]
121 pub unsafe fn get_ptr(&self, key: u64) -> *mut T {
122 let index: usize = (key & (T::ENTRY_COUNT as u64 - 1)) as usize;
123 self.table.as_ptr().offset(index as isize)
124 }
125
126 pub fn clear(&mut self) {
127 unsafe {
128 let t_ptr = self.get_ptr(0);
129 ptr::write_bytes(t_ptr, 0, T::ENTRY_COUNT);
130 }
131 }
132
133 unsafe fn alloc() -> NonNull<T> {
135 let layout = Layout::array::<T>(T::ENTRY_COUNT).unwrap();
136 let ptr = alloc_zeroed(layout);
137 let new_ptr = ptr.cast();
138 NonNull::new(new_ptr as *mut T).unwrap()
139 }
140
141 unsafe fn de_alloc(&mut self) {
143 let ptr: NonNull<u8> = mem::transmute(self.table);
144 dealloc(ptr.as_ptr(), Layout::array::<T>(T::ENTRY_COUNT).unwrap());
145 }
146}
147
148impl<T: Sized + TableBaseConst> Drop for TableBase<T> {
149 fn drop(&mut self) {
150 unsafe {
151 self.de_alloc();
152 }
153 }
154}