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