mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 00:33:09 +00:00
Assorted headers cleanup
Mostly comments fixing and other small things. No functional change.
This commit is contained in:
parent
b97df4c236
commit
4eb2d8ce09
17 changed files with 132 additions and 123 deletions
|
@ -22,6 +22,7 @@
|
||||||
#define BITCOUNT_H_INCLUDED
|
#define BITCOUNT_H_INCLUDED
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
enum BitCountType {
|
enum BitCountType {
|
||||||
|
@ -94,7 +95,7 @@ inline int popcount<CNT_HW_POPCNT>(Bitboard b) {
|
||||||
|
|
||||||
return (int)__popcnt64(b);
|
return (int)__popcnt64(b);
|
||||||
|
|
||||||
#else
|
#else // Assumed gcc or compatible compiler
|
||||||
|
|
||||||
return __builtin_popcountll(b);
|
return __builtin_popcountll(b);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ enum EndgameType {
|
||||||
|
|
||||||
|
|
||||||
// Scaling functions
|
// Scaling functions
|
||||||
SCALE_FUNS,
|
SCALING_FUNCTIONS,
|
||||||
|
|
||||||
KBPsK, // KB and pawns vs K
|
KBPsK, // KB and pawns vs K
|
||||||
KQKRPs, // KQ vs KR and pawns
|
KQKRPs, // KQ vs KR and pawns
|
||||||
|
@ -81,7 +81,7 @@ struct EndgameBase {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<EndgameType E, typename T = typename eg_fun<(E > SCALE_FUNS)>::type>
|
template<EndgameType E, typename T = typename eg_fun<(E > SCALING_FUNCTIONS)>::type>
|
||||||
struct Endgame : public EndgameBase<T> {
|
struct Endgame : public EndgameBase<T> {
|
||||||
|
|
||||||
explicit Endgame(Color c) : strongSide(c), weakSide(~c) {}
|
explicit Endgame(Color c) : strongSide(c), weakSide(~c) {}
|
||||||
|
@ -94,8 +94,8 @@ private:
|
||||||
|
|
||||||
|
|
||||||
/// The Endgames class stores the pointers to endgame evaluation and scaling
|
/// The Endgames class stores the pointers to endgame evaluation and scaling
|
||||||
/// base objects in two std::map typedefs. We then use polymorphism to invoke
|
/// base objects in two std::map. We use polymorphism to invoke the actual
|
||||||
/// the actual endgame function by calling its virtual operator().
|
/// endgame function by calling its virtual operator().
|
||||||
|
|
||||||
class Endgames {
|
class Endgames {
|
||||||
|
|
||||||
|
@ -114,8 +114,9 @@ public:
|
||||||
Endgames();
|
Endgames();
|
||||||
~Endgames();
|
~Endgames();
|
||||||
|
|
||||||
template<typename T> T probe(Key key, T& eg)
|
template<typename T> T probe(Key key, T& eg) {
|
||||||
{ return eg = map(eg).count(key) ? map(eg)[key] : NULL; }
|
return eg = map(eg).count(key) ? map(eg)[key] : NULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #ifndef ENDGAME_H_INCLUDED
|
#endif // #ifndef ENDGAME_H_INCLUDED
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#ifndef EVALUATE_H_INCLUDED
|
#ifndef EVALUATE_H_INCLUDED
|
||||||
#define EVALUATE_H_INCLUDED
|
#define EVALUATE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
class Position;
|
class Position;
|
||||||
|
|
|
@ -49,9 +49,9 @@ struct Entry {
|
||||||
// the position. For instance, in KBP vs K endgames, the scaling function looks
|
// the position. For instance, in KBP vs K endgames, the scaling function looks
|
||||||
// for rook pawns and wrong-colored bishops.
|
// for rook pawns and wrong-colored bishops.
|
||||||
ScaleFactor scale_factor(const Position& pos, Color c) const {
|
ScaleFactor scale_factor(const Position& pos, Color c) const {
|
||||||
|
return !scalingFunction[c]
|
||||||
return !scalingFunction[c] || (*scalingFunction[c])(pos) == SCALE_FACTOR_NONE
|
|| (*scalingFunction[c])(pos) == SCALE_FACTOR_NONE ? ScaleFactor(factor[c])
|
||||||
? ScaleFactor(factor[c]) : (*scalingFunction[c])(pos);
|
: (*scalingFunction[c])(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
|
|
|
@ -237,7 +237,7 @@ namespace {
|
||||||
&& !(PseudoAttacks[Pt][from] & target & ci->checkSq[Pt]))
|
&& !(PseudoAttacks[Pt][from] & target & ci->checkSq[Pt]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (unlikely(ci->dcCandidates) && (ci->dcCandidates & from))
|
if (ci->dcCandidates && (ci->dcCandidates & from))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
class Position;
|
||||||
|
|
||||||
enum GenType {
|
enum GenType {
|
||||||
CAPTURES,
|
CAPTURES,
|
||||||
QUIETS,
|
QUIETS,
|
||||||
|
@ -31,7 +33,14 @@ enum GenType {
|
||||||
LEGAL
|
LEGAL
|
||||||
};
|
};
|
||||||
|
|
||||||
class Position;
|
struct ExtMove {
|
||||||
|
Move move;
|
||||||
|
Value value;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator<(const ExtMove& f, const ExtMove& s) {
|
||||||
|
return f.value < s.value;
|
||||||
|
}
|
||||||
|
|
||||||
template<GenType>
|
template<GenType>
|
||||||
ExtMove* generate(const Position& pos, ExtMove* moveList);
|
ExtMove* generate(const Position& pos, ExtMove* moveList);
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct Entry {
|
||||||
Score pawns_score() const { return score; }
|
Score pawns_score() const { return score; }
|
||||||
Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
|
Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
|
||||||
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
|
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
|
||||||
|
int pawn_span(Color c) const { return pawnSpan[c]; }
|
||||||
|
|
||||||
int semiopen_file(Color c, File f) const {
|
int semiopen_file(Color c, File f) const {
|
||||||
return semiopenFiles[c] & (1 << f);
|
return semiopenFiles[c] & (1 << f);
|
||||||
|
@ -44,10 +45,6 @@ struct Entry {
|
||||||
return semiopenFiles[c] & (leftSide ? (1 << f) - 1 : ~((1 << (f + 1)) - 1));
|
return semiopenFiles[c] & (leftSide ? (1 << f) - 1 : ~((1 << (f + 1)) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
int pawn_span(Color c) const {
|
|
||||||
return pawnSpan[c];
|
|
||||||
}
|
|
||||||
|
|
||||||
int pawns_on_same_color_squares(Color c, Square s) const {
|
int pawns_on_same_color_squares(Color c, Square s) const {
|
||||||
return pawnsOnSquares[c][!!(DarkSquares & s)];
|
return pawnsOnSquares[c][!!(DarkSquares & s)];
|
||||||
}
|
}
|
||||||
|
|
|
@ -641,7 +641,7 @@ bool Position::gives_check(Move m, const CheckInfo& ci) const {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Is there a discovered check?
|
// Is there a discovered check?
|
||||||
if ( unlikely(ci.dcCandidates)
|
if ( ci.dcCandidates
|
||||||
&& (ci.dcCandidates & from)
|
&& (ci.dcCandidates & from)
|
||||||
&& !aligned(from, to, ci.ksq))
|
&& !aligned(from, to, ci.ksq))
|
||||||
return true;
|
return true;
|
||||||
|
@ -870,7 +870,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
||||||
st->checkersBB |= to;
|
st->checkersBB |= to;
|
||||||
|
|
||||||
// Discovered checks
|
// Discovered checks
|
||||||
if (unlikely(ci.dcCandidates) && (ci.dcCandidates & from))
|
if (ci.dcCandidates && (ci.dcCandidates & from))
|
||||||
{
|
{
|
||||||
if (pt != ROOK)
|
if (pt != ROOK)
|
||||||
st->checkersBB |= attacks_from<ROOK>(king_square(them)) & pieces(us, QUEEN, ROOK);
|
st->checkersBB |= attacks_from<ROOK>(king_square(them)) & pieces(us, QUEEN, ROOK);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef> // For offsetof()
|
#include <cstddef> // For offsetof()
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "bitboard.h"
|
#include "bitboard.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
|
@ -584,7 +584,7 @@ namespace {
|
||||||
else if (ttHit)
|
else if (ttHit)
|
||||||
{
|
{
|
||||||
// Never assume anything on values stored in TT
|
// Never assume anything on values stored in TT
|
||||||
if ((ss->staticEval = eval = tte->eval_value()) == VALUE_NONE)
|
if ((ss->staticEval = eval = tte->eval()) == VALUE_NONE)
|
||||||
eval = ss->staticEval = evaluate(pos);
|
eval = ss->staticEval = evaluate(pos);
|
||||||
|
|
||||||
// Can ttValue be used as a better position evaluation?
|
// Can ttValue be used as a better position evaluation?
|
||||||
|
@ -1165,7 +1165,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
||||||
if (ttHit)
|
if (ttHit)
|
||||||
{
|
{
|
||||||
// Never assume anything on values stored in TT
|
// Never assume anything on values stored in TT
|
||||||
if ((ss->staticEval = bestValue = tte->eval_value()) == VALUE_NONE)
|
if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE)
|
||||||
ss->staticEval = bestValue = evaluate(pos);
|
ss->staticEval = bestValue = evaluate(pos);
|
||||||
|
|
||||||
// Can ttValue be used as a better position evaluation?
|
// Can ttValue be used as a better position evaluation?
|
||||||
|
|
30
src/search.h
30
src/search.h
|
@ -20,7 +20,7 @@
|
||||||
#ifndef SEARCH_H_INCLUDED
|
#ifndef SEARCH_H_INCLUDED
|
||||||
#define SEARCH_H_INCLUDED
|
#define SEARCH_H_INCLUDED
|
||||||
|
|
||||||
#include <memory>
|
#include <memory> // For std::auto_ptr
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -32,9 +32,9 @@ struct SplitPoint;
|
||||||
|
|
||||||
namespace Search {
|
namespace Search {
|
||||||
|
|
||||||
/// The Stack struct keeps track of the information we need to remember from
|
/// Stack struct keeps track of the information we need to remember from nodes
|
||||||
/// nodes shallower and deeper in the tree during the search. Each search thread
|
/// shallower and deeper in the tree during the search. Each search thread has
|
||||||
/// has its own array of Stack objects, indexed by the current ply.
|
/// its own array of Stack objects, indexed by the current ply.
|
||||||
|
|
||||||
struct Stack {
|
struct Stack {
|
||||||
SplitPoint* splitPoint;
|
SplitPoint* splitPoint;
|
||||||
|
@ -49,18 +49,16 @@ struct Stack {
|
||||||
bool skipEarlyPruning;
|
bool skipEarlyPruning;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// RootMove struct is used for moves at the root of the tree. For each root move
|
||||||
|
/// we store a score and a PV (really a refutation in the case of moves which
|
||||||
|
/// fail low). Score is normally set at -VALUE_INFINITE for all non-pv moves.
|
||||||
|
|
||||||
/// RootMove struct is used for moves at the root of the tree. For each root
|
|
||||||
/// move we store a score, a node count, and a PV (really a refutation in the
|
|
||||||
/// case of moves which fail low). Score is normally set at -VALUE_INFINITE for
|
|
||||||
/// all non-pv moves.
|
|
||||||
struct RootMove {
|
struct RootMove {
|
||||||
|
|
||||||
RootMove(Move m) : score(-VALUE_INFINITE), previousScore(-VALUE_INFINITE), pv(1, m) {}
|
RootMove(Move m) : score(-VALUE_INFINITE), previousScore(-VALUE_INFINITE), pv(1, m) {}
|
||||||
|
|
||||||
bool operator<(const RootMove& m) const { return score > m.score; } // Ascending sort
|
bool operator<(const RootMove& m) const { return score > m.score; } // Ascending sort
|
||||||
bool operator==(const Move& m) const { return pv[0] == m; }
|
bool operator==(const Move& m) const { return pv[0] == m; }
|
||||||
|
|
||||||
void insert_pv_in_tt(Position& pos);
|
void insert_pv_in_tt(Position& pos);
|
||||||
|
|
||||||
Value score;
|
Value score;
|
||||||
|
@ -70,24 +68,26 @@ struct RootMove {
|
||||||
|
|
||||||
typedef std::vector<RootMove> RootMoveVector;
|
typedef std::vector<RootMove> RootMoveVector;
|
||||||
|
|
||||||
/// The LimitsType struct stores information sent by GUI about available time
|
/// LimitsType struct stores information sent by GUI about available time to
|
||||||
/// to search the current move, maximum depth/time, if we are in analysis mode
|
/// search the current move, maximum depth/time, if we are in analysis mode or
|
||||||
/// or if we have to ponder while it's our opponent's turn to move.
|
/// if we have to ponder while it's our opponent's turn to move.
|
||||||
|
|
||||||
struct LimitsType {
|
struct LimitsType {
|
||||||
|
|
||||||
LimitsType() { // Using memset on a std::vector is undefined behavior
|
LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC
|
||||||
nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = movestogo =
|
nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = movestogo =
|
||||||
depth = movetime = mate = infinite = ponder = 0;
|
depth = movetime = mate = infinite = ponder = 0;
|
||||||
}
|
}
|
||||||
bool use_time_management() const { return !(mate | movetime | depth | nodes | infinite); }
|
|
||||||
|
bool use_time_management() const {
|
||||||
|
return !(mate | movetime | depth | nodes | infinite);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Move> searchmoves;
|
std::vector<Move> searchmoves;
|
||||||
int time[COLOR_NB], inc[COLOR_NB], movestogo, depth, movetime, mate, infinite, ponder;
|
int time[COLOR_NB], inc[COLOR_NB], movestogo, depth, movetime, mate, infinite, ponder;
|
||||||
int64_t nodes;
|
int64_t nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// The SignalsType struct stores volatile flags updated during the search
|
/// The SignalsType struct stores volatile flags updated during the search
|
||||||
/// typically in an async fashion e.g. to stop the search by the GUI.
|
/// typically in an async fashion e.g. to stop the search by the GUI.
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ void ThreadBase::wait_for(volatile const bool& condition) {
|
||||||
// Thread c'tor makes some init but does not launch any execution thread that
|
// Thread c'tor makes some init but does not launch any execution thread that
|
||||||
// will be started only when c'tor returns.
|
// will be started only when c'tor returns.
|
||||||
|
|
||||||
Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC
|
Thread::Thread() /* : splitPoints() */ { // Initialization of non POD broken in MSVC
|
||||||
|
|
||||||
searching = false;
|
searching = false;
|
||||||
maxPly = splitPointsSize = 0;
|
maxPly = splitPointsSize = 0;
|
||||||
|
|
24
src/thread.h
24
src/thread.h
|
@ -29,9 +29,14 @@
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "search.h"
|
#include "search.h"
|
||||||
|
|
||||||
|
struct Thread;
|
||||||
|
|
||||||
const int MAX_THREADS = 128;
|
const int MAX_THREADS = 128;
|
||||||
const int MAX_SPLITPOINTS_PER_THREAD = 8;
|
const int MAX_SPLITPOINTS_PER_THREAD = 8;
|
||||||
|
|
||||||
|
/// Mutex and ConditionVariable struct are wrappers of the low level locking
|
||||||
|
/// machinery and are modeled after the corresponding C++11 classes.
|
||||||
|
|
||||||
struct Mutex {
|
struct Mutex {
|
||||||
Mutex() { lock_init(l); }
|
Mutex() { lock_init(l); }
|
||||||
~Mutex() { lock_destroy(l); }
|
~Mutex() { lock_destroy(l); }
|
||||||
|
@ -57,7 +62,9 @@ private:
|
||||||
WaitCondition c;
|
WaitCondition c;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Thread;
|
|
||||||
|
/// SplitPoint struct stores information shared by the threads searching in
|
||||||
|
/// parallel below the same split point. It is populated at splitting time.
|
||||||
|
|
||||||
struct SplitPoint {
|
struct SplitPoint {
|
||||||
|
|
||||||
|
@ -74,7 +81,7 @@ struct SplitPoint {
|
||||||
MovePicker* movePicker;
|
MovePicker* movePicker;
|
||||||
SplitPoint* parentSplitPoint;
|
SplitPoint* parentSplitPoint;
|
||||||
|
|
||||||
// Shared data
|
// Shared variable data
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
std::bitset<MAX_THREADS> slavesMask;
|
std::bitset<MAX_THREADS> slavesMask;
|
||||||
volatile bool allSlavesSearching;
|
volatile bool allSlavesSearching;
|
||||||
|
@ -121,9 +128,9 @@ struct Thread : public ThreadBase {
|
||||||
Depth depth, int moveCount, MovePicker* movePicker, int nodeType, bool cutNode);
|
Depth depth, int moveCount, MovePicker* movePicker, int nodeType, bool cutNode);
|
||||||
|
|
||||||
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
|
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
|
||||||
|
Pawns::Table pawnsTable;
|
||||||
Material::Table materialTable;
|
Material::Table materialTable;
|
||||||
Endgames endgames;
|
Endgames endgames;
|
||||||
Pawns::Table pawnsTable;
|
|
||||||
Position* activePosition;
|
Position* activePosition;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
int maxPly;
|
int maxPly;
|
||||||
|
@ -143,10 +150,13 @@ struct MainThread : public Thread {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimerThread : public ThreadBase {
|
struct TimerThread : public ThreadBase {
|
||||||
|
|
||||||
|
static const int Resolution = 5; // Millisec between two check_time() calls
|
||||||
|
|
||||||
TimerThread() : run(false) {}
|
TimerThread() : run(false) {}
|
||||||
virtual void idle_loop();
|
virtual void idle_loop();
|
||||||
|
|
||||||
bool run;
|
bool run;
|
||||||
static const int Resolution = 5; // msec between two check_time() calls
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,10 +166,10 @@ struct TimerThread : public ThreadBase {
|
||||||
|
|
||||||
struct ThreadPool : public std::vector<Thread*> {
|
struct ThreadPool : public std::vector<Thread*> {
|
||||||
|
|
||||||
void init(); // No c'tor and d'tor, threads rely on globals that should
|
void init(); // No c'tor and d'tor, threads rely on globals that should be
|
||||||
void exit(); // be initialized and are valid during the whole thread lifetime.
|
void exit(); // initialized and are valid during the whole thread lifetime.
|
||||||
|
|
||||||
MainThread* main() { return static_cast<MainThread*>((*this)[0]); }
|
MainThread* main() { return static_cast<MainThread*>(at(0)); }
|
||||||
void read_uci_options();
|
void read_uci_options();
|
||||||
Thread* available_slave(const Thread* master) const;
|
Thread* available_slave(const Thread* master) const;
|
||||||
void wait_for_think_finished();
|
void wait_for_think_finished();
|
||||||
|
|
10
src/tt.cpp
10
src/tt.cpp
|
@ -32,6 +32,8 @@ TranspositionTable TT; // Our global transposition table
|
||||||
|
|
||||||
void TranspositionTable::resize(size_t mbSize) {
|
void TranspositionTable::resize(size_t mbSize) {
|
||||||
|
|
||||||
|
assert(sizeof(TTCluster) == CacheLineSize / 2);
|
||||||
|
|
||||||
size_t newClusterCount = size_t(1) << msb((mbSize * 1024 * 1024) / sizeof(TTCluster));
|
size_t newClusterCount = size_t(1) << msb((mbSize * 1024 * 1024) / sizeof(TTCluster));
|
||||||
|
|
||||||
if (newClusterCount == clusterCount)
|
if (newClusterCount == clusterCount)
|
||||||
|
@ -40,7 +42,7 @@ void TranspositionTable::resize(size_t mbSize) {
|
||||||
clusterCount = newClusterCount;
|
clusterCount = newClusterCount;
|
||||||
|
|
||||||
free(mem);
|
free(mem);
|
||||||
mem = calloc(clusterCount * sizeof(TTCluster) + CACHE_LINE_SIZE - 1, 1);
|
mem = calloc(clusterCount * sizeof(TTCluster) + CacheLineSize - 1, 1);
|
||||||
|
|
||||||
if (!mem)
|
if (!mem)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +51,7 @@ void TranspositionTable::resize(size_t mbSize) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
table = (TTCluster*)((uintptr_t(mem) + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1));
|
table = (TTCluster*)((uintptr_t(mem) + CacheLineSize - 1) & ~(CacheLineSize - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,7 +77,7 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
|
||||||
TTEntry* const tte = first_entry(key);
|
TTEntry* const tte = first_entry(key);
|
||||||
const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster
|
const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster
|
||||||
|
|
||||||
for (unsigned i = 0; i < TTClusterSize; ++i)
|
for (int i = 0; i < TTClusterSize; ++i)
|
||||||
if (!tte[i].key16 || tte[i].key16 == key16)
|
if (!tte[i].key16 || tte[i].key16 == key16)
|
||||||
{
|
{
|
||||||
if (tte[i].key16)
|
if (tte[i].key16)
|
||||||
|
@ -86,7 +88,7 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
|
||||||
|
|
||||||
// Find an entry to be replaced according to the replacement strategy
|
// Find an entry to be replaced according to the replacement strategy
|
||||||
TTEntry* replace = tte;
|
TTEntry* replace = tte;
|
||||||
for (unsigned i = 1; i < TTClusterSize; ++i)
|
for (int i = 1; i < TTClusterSize; ++i)
|
||||||
if ( (( tte[i].genBound8 & 0xFC) == generation8 || tte[i].bound() == BOUND_EXACT)
|
if ( (( tte[i].genBound8 & 0xFC) == generation8 || tte[i].bound() == BOUND_EXACT)
|
||||||
- ((replace->genBound8 & 0xFC) == generation8)
|
- ((replace->genBound8 & 0xFC) == generation8)
|
||||||
- (tte[i].depth8 < replace->depth8) < 0)
|
- (tte[i].depth8 < replace->depth8) < 0)
|
||||||
|
|
43
src/tt.h
43
src/tt.h
|
@ -23,7 +23,7 @@
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
/// The TTEntry is the 10 bytes transposition table entry, defined as below:
|
/// TTEntry struct is the 10 bytes transposition table entry, defined as below:
|
||||||
///
|
///
|
||||||
/// key 16 bit
|
/// key 16 bit
|
||||||
/// move 16 bit
|
/// move 16 bit
|
||||||
|
@ -37,7 +37,7 @@ struct TTEntry {
|
||||||
|
|
||||||
Move move() const { return (Move )move16; }
|
Move move() const { return (Move )move16; }
|
||||||
Value value() const { return (Value)value16; }
|
Value value() const { return (Value)value16; }
|
||||||
Value eval_value() const { return (Value)evalValue; }
|
Value eval() const { return (Value)eval16; }
|
||||||
Depth depth() const { return (Depth)depth8; }
|
Depth depth() const { return (Depth)depth8; }
|
||||||
Bound bound() const { return (Bound)(genBound8 & 0x3); }
|
Bound bound() const { return (Bound)(genBound8 & 0x3); }
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ struct TTEntry {
|
||||||
|
|
||||||
key16 = (uint16_t)(k >> 48);
|
key16 = (uint16_t)(k >> 48);
|
||||||
value16 = (int16_t)v;
|
value16 = (int16_t)v;
|
||||||
evalValue = (int16_t)ev;
|
eval16 = (int16_t)ev;
|
||||||
genBound8 = (uint8_t)(g | b);
|
genBound8 = (uint8_t)(g | b);
|
||||||
depth8 = (int8_t)d;
|
depth8 = (int8_t)d;
|
||||||
}
|
}
|
||||||
|
@ -59,22 +59,11 @@ private:
|
||||||
uint16_t key16;
|
uint16_t key16;
|
||||||
uint16_t move16;
|
uint16_t move16;
|
||||||
int16_t value16;
|
int16_t value16;
|
||||||
int16_t evalValue;
|
int16_t eval16;
|
||||||
uint8_t genBound8;
|
uint8_t genBound8;
|
||||||
int8_t depth8;
|
int8_t depth8;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// TTCluster is a 32 bytes cluster of TT entries consisting of:
|
|
||||||
///
|
|
||||||
/// 3 x TTEntry (3 x 10 bytes)
|
|
||||||
/// padding (2 bytes)
|
|
||||||
|
|
||||||
static const unsigned TTClusterSize = 3;
|
|
||||||
|
|
||||||
struct TTCluster {
|
|
||||||
TTEntry entry[TTClusterSize];
|
|
||||||
char padding[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A TranspositionTable consists of a power of 2 number of clusters and each
|
/// A TranspositionTable consists of a power of 2 number of clusters and each
|
||||||
/// cluster consists of TTClusterSize number of TTEntry. Each non-empty entry
|
/// cluster consists of TTClusterSize number of TTEntry. Each non-empty entry
|
||||||
|
@ -84,15 +73,27 @@ struct TTCluster {
|
||||||
|
|
||||||
class TranspositionTable {
|
class TranspositionTable {
|
||||||
|
|
||||||
|
static const int CacheLineSize = 64;
|
||||||
|
static const int TTClusterSize = 3;
|
||||||
|
|
||||||
|
struct TTCluster {
|
||||||
|
TTEntry entry[TTClusterSize];
|
||||||
|
char padding[2]; // Align to the cache line size
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~TranspositionTable() { free(mem); }
|
~TranspositionTable() { free(mem); }
|
||||||
void new_search() { generation8 += 4; } // Lower 2 bits are used by Bound
|
void new_search() { generation8 += 4; } // Lower 2 bits are used by Bound
|
||||||
uint8_t generation() const { return generation8; }
|
uint8_t generation() const { return generation8; }
|
||||||
TTEntry* probe(const Key key, bool& found) const;
|
TTEntry* probe(const Key key, bool& found) const;
|
||||||
TTEntry* first_entry(const Key key) const;
|
|
||||||
void resize(size_t mbSize);
|
void resize(size_t mbSize);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
// The lowest order bits of the key are used to get the index of the cluster
|
||||||
|
TTEntry* first_entry(const Key key) const {
|
||||||
|
return &table[(size_t)key & (clusterCount - 1)].entry[0];
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t clusterCount;
|
size_t clusterCount;
|
||||||
TTCluster* table;
|
TTCluster* table;
|
||||||
|
@ -102,14 +103,4 @@ private:
|
||||||
|
|
||||||
extern TranspositionTable TT;
|
extern TranspositionTable TT;
|
||||||
|
|
||||||
|
|
||||||
/// TranspositionTable::first_entry() returns a pointer to the first entry of
|
|
||||||
/// a cluster given a position. The lowest order bits of the key are used to
|
|
||||||
/// get the index of the cluster inside the table.
|
|
||||||
|
|
||||||
inline TTEntry* TranspositionTable::first_entry(const Key key) const {
|
|
||||||
|
|
||||||
return &table[(size_t)key & (clusterCount - 1)].entry[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #ifndef TT_H_INCLUDED
|
#endif // #ifndef TT_H_INCLUDED
|
||||||
|
|
66
src/types.h
66
src/types.h
|
@ -20,20 +20,19 @@
|
||||||
#ifndef TYPES_H_INCLUDED
|
#ifndef TYPES_H_INCLUDED
|
||||||
#define TYPES_H_INCLUDED
|
#define TYPES_H_INCLUDED
|
||||||
|
|
||||||
/// For Linux and OSX configuration is done automatically using Makefile. To get
|
/// When compiling with provided Makefile (e.g. for Linux and OSX), configuration
|
||||||
/// started type 'make help'.
|
/// is done automatically. To get started type 'make help'.
|
||||||
///
|
///
|
||||||
/// For Windows, part of the configuration is detected automatically, but some
|
/// When Makefile is not used (e.g. with Microsoft Visual Studio) some switches
|
||||||
/// switches need to be set manually:
|
/// need to be set manually:
|
||||||
///
|
///
|
||||||
/// -DNDEBUG | Disable debugging mode. Always use this.
|
/// -DNDEBUG | Disable debugging mode. Always use this for release.
|
||||||
///
|
///
|
||||||
/// -DNO_PREFETCH | Disable use of prefetch asm-instruction. A must if you want
|
/// -DNO_PREFETCH | Disable use of prefetch asm-instruction. You may need this to
|
||||||
/// | the executable to run on some very old machines.
|
/// | run on some very old machines.
|
||||||
///
|
///
|
||||||
/// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works
|
/// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works
|
||||||
/// | only in 64-bit mode. For compiling requires hardware with
|
/// | only in 64-bit mode and requires hardware with popcnt support.
|
||||||
/// | popcnt support.
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
@ -42,30 +41,34 @@
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#define unlikely(x) (x) // For code annotation purposes
|
/// Predefined macros hell:
|
||||||
|
///
|
||||||
|
/// __GNUC__ Compiler is gcc, Clang or Intel on Linux
|
||||||
|
/// __INTEL_COMPILER Compiler is Intel
|
||||||
|
/// _MSC_VER Compiler is MSVC or Intel on Windows
|
||||||
|
/// _WIN32 Building on Windows (any)
|
||||||
|
/// _WIN64 Building on Windows 64 bit
|
||||||
|
|
||||||
#if defined(_WIN64) && !defined(IS_64BIT)
|
#if defined(_WIN64) && !defined(IS_64BIT) // Last condition means Makefile is not used
|
||||||
# include <intrin.h> // MSVC popcnt and bsfq instrinsics
|
# include <intrin.h> // MSVC popcnt and bsfq instrinsics
|
||||||
# define IS_64BIT
|
# define IS_64BIT
|
||||||
# define USE_BSFQ
|
# define USE_BSFQ
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_POPCNT) && defined(_MSC_VER) && defined(__INTEL_COMPILER)
|
#if defined(USE_POPCNT) && defined(__INTEL_COMPILER) && defined(_MSC_VER)
|
||||||
# include <nmmintrin.h> // Intel header for _mm_popcnt_u64() intrinsic
|
# include <nmmintrin.h> // Intel header for _mm_popcnt_u64() intrinsic
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
|
||||||
|
# include <xmmintrin.h> // Intel and Microsoft header for _mm_prefetch()
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(USE_PEXT)
|
#if defined(USE_PEXT)
|
||||||
# include <immintrin.h> // Header for _pext_u64() intrinsic
|
# include <immintrin.h> // Header for _pext_u64() intrinsic
|
||||||
#else
|
#else
|
||||||
# define _pext_u64(b, m) (0)
|
# define _pext_u64(b, m) (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
|
|
||||||
# include <xmmintrin.h> // Intel and Microsoft header for _mm_prefetch()
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#define CACHE_LINE_SIZE 64
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# define FORCE_INLINE __forceinline
|
# define FORCE_INLINE __forceinline
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
@ -251,9 +254,9 @@ enum Rank {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// The Score enum stores a middlegame and an endgame value in a single integer
|
/// Score enum stores a middlegame and an endgame value in a single integer.
|
||||||
/// (enum). The least significant 16 bits are used to store the endgame value
|
/// The least significant 16 bits are used to store the endgame value and
|
||||||
/// and the upper 16 bits are used to store the middlegame value. The compiler
|
/// the upper 16 bits are used to store the middlegame value. The compiler
|
||||||
/// is free to choose the enum type as long as it can store the data, so we
|
/// is free to choose the enum type as long as it can store the data, so we
|
||||||
/// ensure that Score is an integer type by assigning some big int values.
|
/// ensure that Score is an integer type by assigning some big int values.
|
||||||
enum Score {
|
enum Score {
|
||||||
|
@ -262,13 +265,15 @@ enum Score {
|
||||||
SCORE_ENSURE_INTEGER_SIZE_N = INT_MIN
|
SCORE_ENSURE_INTEGER_SIZE_N = INT_MIN
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Score make_score(int mg, int eg) { return Score((mg << 16) + eg); }
|
inline Score make_score(int mg, int eg) {
|
||||||
|
return Score((mg << 16) + eg);
|
||||||
|
}
|
||||||
|
|
||||||
/// Extracting the signed lower and upper 16 bits is not so trivial because
|
/// Extracting the signed lower and upper 16 bits is not so trivial because
|
||||||
/// according to the standard a simple cast to short is implementation defined
|
/// according to the standard a simple cast to short is implementation defined
|
||||||
/// and so is a right shift of a signed integer.
|
/// and so is a right shift of a signed integer.
|
||||||
inline Value mg_value(Score s) {
|
inline Value mg_value(Score s) {
|
||||||
return Value(((s + 0x8000) & ~0xffff) / 0x10000);
|
return Value(((s + 0x8000) & ~0xFFFF) / 0x10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value eg_value(Score s) {
|
inline Value eg_value(Score s) {
|
||||||
|
@ -285,8 +290,6 @@ inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \
|
||||||
inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; } \
|
inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; } \
|
||||||
inline T& operator*=(T& d, int i) { return d = T(int(d) * i); }
|
inline T& operator*=(T& d, int i) { return d = T(int(d) * i); }
|
||||||
|
|
||||||
ENABLE_BASE_OPERATORS_ON(Score)
|
|
||||||
|
|
||||||
#define ENABLE_FULL_OPERATORS_ON(T) \
|
#define ENABLE_FULL_OPERATORS_ON(T) \
|
||||||
ENABLE_BASE_OPERATORS_ON(T) \
|
ENABLE_BASE_OPERATORS_ON(T) \
|
||||||
inline T& operator++(T& d) { return d = T(int(d) + 1); } \
|
inline T& operator++(T& d) { return d = T(int(d) + 1); } \
|
||||||
|
@ -304,6 +307,8 @@ ENABLE_FULL_OPERATORS_ON(Square)
|
||||||
ENABLE_FULL_OPERATORS_ON(File)
|
ENABLE_FULL_OPERATORS_ON(File)
|
||||||
ENABLE_FULL_OPERATORS_ON(Rank)
|
ENABLE_FULL_OPERATORS_ON(Rank)
|
||||||
|
|
||||||
|
ENABLE_BASE_OPERATORS_ON(Score)
|
||||||
|
|
||||||
#undef ENABLE_FULL_OPERATORS_ON
|
#undef ENABLE_FULL_OPERATORS_ON
|
||||||
#undef ENABLE_BASE_OPERATORS_ON
|
#undef ENABLE_BASE_OPERATORS_ON
|
||||||
|
|
||||||
|
@ -324,15 +329,6 @@ inline Score operator/(Score s, int i) {
|
||||||
|
|
||||||
extern Value PieceValue[PHASE_NB][PIECE_NB];
|
extern Value PieceValue[PHASE_NB][PIECE_NB];
|
||||||
|
|
||||||
struct ExtMove {
|
|
||||||
Move move;
|
|
||||||
Value value;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator<(const ExtMove& f, const ExtMove& s) {
|
|
||||||
return f.value < s.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Color operator~(Color c) {
|
inline Color operator~(Color c) {
|
||||||
return Color(c ^ BLACK);
|
return Color(c ^ BLACK);
|
||||||
}
|
}
|
||||||
|
@ -429,7 +425,7 @@ inline Move make(Square from, Square to, PieceType pt = KNIGHT) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_ok(Move m) {
|
inline bool is_ok(Move m) {
|
||||||
return from_sq(m) != to_sq(m); // Catch also MOVE_NULL and MOVE_NONE
|
return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #ifndef TYPES_H_INCLUDED
|
#endif // #ifndef TYPES_H_INCLUDED
|
||||||
|
|
|
@ -50,8 +50,8 @@ public:
|
||||||
Option(const char* v, OnChange = NULL);
|
Option(const char* v, OnChange = NULL);
|
||||||
Option(int v, int min, int max, OnChange = NULL);
|
Option(int v, int min, int max, OnChange = NULL);
|
||||||
|
|
||||||
Option& operator=(const std::string& v);
|
Option& operator=(const std::string&);
|
||||||
void operator<<(const Option& o);
|
void operator<<(const Option&);
|
||||||
operator int() const;
|
operator int() const;
|
||||||
operator std::string() const;
|
operator std::string() const;
|
||||||
|
|
||||||
|
@ -66,7 +66,6 @@ private:
|
||||||
|
|
||||||
void init(OptionsMap&);
|
void init(OptionsMap&);
|
||||||
void loop(int argc, char* argv[]);
|
void loop(int argc, char* argv[]);
|
||||||
|
|
||||||
std::string value(Value v);
|
std::string value(Value v);
|
||||||
std::string square(Square s);
|
std::string square(Square s);
|
||||||
std::string move(Move m, bool chess960);
|
std::string move(Move m, bool chess960);
|
||||||
|
|
Loading…
Add table
Reference in a new issue