X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsyzygy%2Ftbprobe.cpp;h=d13e90183508b5b28f06a8c7cd75b3b78d6735b9;hb=ee22b61f5e90a180af942828feb83cef90ea5683;hp=43fc0f1c210b288cdb48ed7c26eea72edbc157ed;hpb=c0bb0415394179e9c771cc96a9da6724fc14c167;p=stockfish diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 43fc0f1c..d13e9018 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -125,18 +125,39 @@ struct PairsData { int groupLen[TBPIECES+1]; // Number of pieces in a given group: KRKN -> (3, 1) }; -// Helper struct to avoid to manually define entry copy c'tor as we should -// because default one is not compatible with std::atomic_bool. +// Helper struct to avoid manually defining entry copy constructor as we +// should because the default one is not compatible with std::atomic_bool. struct Atomic { Atomic() = default; Atomic(const Atomic& e) { ready = e.ready.load(); } // MSVC 2013 wants assignment within body std::atomic_bool ready; }; -struct WDLEntry : public Atomic { - WDLEntry(const std::string& code); - ~WDLEntry(); +// We define types for the different parts of the WLDEntry and DTZEntry with +// corresponding specializations for pieces or pawns. + +struct WLDEntryPiece { + PairsData* precomp; +}; + +struct WDLEntryPawn { + uint8_t pawnCount[2]; // [Lead color / other color] + WLDEntryPiece file[2][4]; // [wtm / btm][FILE_A..FILE_D] +}; + +struct DTZEntryPiece { + PairsData* precomp; + uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLCursedLoss + uint8_t* map; +}; + +struct DTZEntryPawn { + uint8_t pawnCount[2]; + DTZEntryPiece file[4]; + uint8_t* map; +}; +struct TBEntry : public Atomic { void* baseAddress; uint64_t mapping; Key key; @@ -144,46 +165,24 @@ struct WDLEntry : public Atomic { int pieceCount; bool hasPawns; bool hasUniquePieces; +}; + +// Now the main types: WDLEntry and DTZEntry +struct WDLEntry : public TBEntry { + WDLEntry(const std::string& code); + ~WDLEntry(); union { - struct { - PairsData* precomp; - } pieceTable[2]; // [wtm / btm] - - struct { - uint8_t pawnCount[2]; // [Lead color / other color] - struct { - PairsData* precomp; - } file[2][4]; // [wtm / btm][FILE_A..FILE_D] - } pawnTable; + WLDEntryPiece pieceTable[2]; // [wtm / btm] + WDLEntryPawn pawnTable; }; }; -struct DTZEntry : public Atomic { +struct DTZEntry : public TBEntry { DTZEntry(const WDLEntry& wdl); ~DTZEntry(); - - void* baseAddress; - uint64_t mapping; - Key key; - Key key2; - int pieceCount; - bool hasPawns; - bool hasUniquePieces; union { - struct { - PairsData* precomp; - uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLCursedLoss - uint8_t* map; - } pieceTable; - - struct { - uint8_t pawnCount[2]; - struct { - PairsData* precomp; - uint16_t map_idx[4]; - } file[4]; - uint8_t* map; - } pawnTable; + DTZEntryPiece pieceTable; + DTZEntryPawn pawnTable; }; }; @@ -229,17 +228,23 @@ template inline void swap_byte(T& x) { char tmp, *c = (char*)&x; - if (Half) // Fix a MSVC 2015 warning - for (int i = 0; i < Half; ++i) - tmp = c[i], c[i] = c[End - i], c[End - i] = tmp; + for (int i = 0; i < Half; ++i) + tmp = c[i], c[i] = c[End - i], c[End - i] = tmp; } +template<> inline void swap_byte(uint8_t&) {} template T number(void* addr) { const union { uint32_t i; char c[4]; } Le = { 0x01020304 }; const bool IsLittleEndian = (Le.c[0] == 4); - T v = *((T*)addr); + T v; + + if ((uintptr_t)addr & (alignof(T) - 1)) // Unaligned pointer (very rare) + std::memcpy(&v, addr, sizeof(T)); + else + v = *((T*)addr); + if (LE != IsLittleEndian) swap_byte(v); return v; @@ -1061,10 +1066,10 @@ void do_init(Entry& e, T& p, uint8_t* data) { enum { Split = 1, HasPawns = 2 }; - uint8_t flags = *data++; + assert(e.hasPawns == !!(*data & HasPawns)); + assert((e.key != e.key2) == !!(*data & Split)); - assert(e.hasPawns == !!(flags & HasPawns)); - assert((e.key != e.key2) == !!(flags & Split)); + data++; // First byte stores flags const int Sides = IsWDL && (e.key != e.key2) ? 2 : 1; const File MaxFile = e.hasPawns ? FILE_D : FILE_A; @@ -1201,7 +1206,7 @@ WDLScore search(Position& pos, ProbeState* result) { moveCount++; - pos.do_move(move, st, pos.gives_check(move)); + pos.do_move(move, st); value = -search(pos, result); pos.undo_move(move); @@ -1285,6 +1290,7 @@ void Tablebases::init(const std::string& paths) { for (int idx = 0; idx < 10; idx++) for (Square s1 = SQ_A1; s1 <= SQ_D4; ++s1) if (MapA1D1D4[s1] == idx && (idx || s1 == SQ_B1)) // SQ_B1 is mapped to 0 + { for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) if ((StepAttacksBB[KING][s1] | s1) & s2) continue; // Illegal position @@ -1297,6 +1303,7 @@ void Tablebases::init(const std::string& paths) { else MapKK[idx][s2] = code++; + } // Legal positions with both kings on diagonal are encoded as last ones for (auto p : bothOnDiagonal) @@ -1447,7 +1454,7 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) { { bool zeroing = pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN; - pos.do_move(move, st, pos.gives_check(move)); + pos.do_move(move, st); // For zeroing moves we want the dtz of the move _before_ doing it, // otherwise we will get the dtz of the next move sequence. Search the @@ -1521,7 +1528,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& // Probe each move for (size_t i = 0; i < rootMoves.size(); ++i) { Move move = rootMoves[i].pv[0]; - pos.do_move(move, st, pos.gives_check(move)); + pos.do_move(move, st); int v = 0; if (pos.checkers() && dtz > 0) { @@ -1657,7 +1664,7 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Val // Probe each move for (size_t i = 0; i < rootMoves.size(); ++i) { Move move = rootMoves[i].pv[0]; - pos.do_move(move, st, pos.gives_check(move)); + pos.do_move(move, st); WDLScore v = -Tablebases::probe_wdl(pos, &result); pos.undo_move(move);