-// DTZ tables don't store valid scores for moves that reset the rule50 counter
-// like captures and pawn moves but we can easily recover the correct dtz of the
-// previous move if we know the position's WDL score.
-int dtz_before_zeroing(WDLScore wdl) {
- return wdl == WDLWin ? 1 :
- wdl == WDLCursedWin ? 101 :
- wdl == WDLBlessedLoss ? -101 :
- wdl == WDLLoss ? -1 : 0;
-}
-
-// Return the sign of a number (-1, 0, 1)
-template <typename T> int sign_of(T val) {
- return (T(0) < val) - (val < T(0));
-}
-
-// Numbers in little endian used by sparseIndex[] to point into blockLength[]
-struct SparseEntry {
- char block[4]; // Number of block
- char offset[2]; // Offset within the block
-};
-
-static_assert(sizeof(SparseEntry) == 6, "SparseEntry must be 6 bytes");
-
-typedef uint16_t Sym; // Huffman symbol
-
-struct LR {
- enum Side { Left, Right, Value };
-
- uint8_t lr[3]; // The first 12 bits is the left-hand symbol, the second 12
- // bits is the right-hand symbol. If symbol has length 1,
- // then the first byte is the stored value.
- template<Side S>
- Sym get() {
- return S == Left ? ((lr[1] & 0xF) << 8) | lr[0] :
- S == Right ? (lr[2] << 4) | (lr[1] >> 4) :
- S == Value ? lr[0] : (assert(false), Sym(-1));
- }
-};
-
-static_assert(sizeof(LR) == 3, "LR tree entry must be 3 bytes");
-
-struct PairsData {
- int flags;
- size_t sizeofBlock; // Block size in bytes
- size_t span; // About every span values there is a SparseIndex[] entry
- int blocksNum; // Number of blocks in the TB file
- int maxSymLen; // Maximum length in bits of the Huffman symbols
- int minSymLen; // Minimum length in bits of the Huffman symbols
- Sym* lowestSym; // lowestSym[l] is the symbol of length l with the lowest value
- LR* btree; // btree[sym] stores the left and right symbols that expand sym
- uint16_t* blockLength; // Number of stored positions (minus one) for each block: 1..65536
- int blockLengthSize; // Size of blockLength[] table: padded so it's bigger than blocksNum
- SparseEntry* sparseIndex; // Partial indices into blockLength[]
- size_t sparseIndexSize; // Size of SparseIndex[] table
- uint8_t* data; // Start of Huffman compressed data
- std::vector<uint64_t> base64; // base64[l - min_sym_len] is the 64bit-padded lowest symbol of length l
- std::vector<uint8_t> symlen; // Number of values (-1) represented by a given Huffman symbol: 1..256
- Piece pieces[TBPIECES]; // Position pieces: the order of pieces defines the groups
- uint64_t groupIdx[TBPIECES+1]; // Start index used for the encoding of the group's pieces
- int groupLen[TBPIECES+1]; // Number of pieces in a given group: KRKN -> (3, 1)
- uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLBlessedLoss (used in DTZ)
-};
-
-template<TBType Type>
-struct TBEntry {
- typedef typename std::conditional<Type == WDL, WDLScore, int>::type Result;
-
- static constexpr int Sides = Type == WDL ? 2 : 1;
-
- std::atomic_bool ready;
- void* baseAddress;
- uint8_t* map;
- uint64_t mapping;
- Key key;
- Key key2;
- int pieceCount;
- bool hasPawns;
- bool hasUniquePieces;
- uint8_t pawnCount[2]; // [Lead color / other color]
- PairsData items[Sides][4]; // [wtm / btm][FILE_A..FILE_D or 0]
-
- PairsData* get(int stm, int f) {
- return &items[stm % Sides][hasPawns ? f : 0];
- }
-
- TBEntry() : ready(false), baseAddress(nullptr) {}
- explicit TBEntry(const std::string& code);
- explicit TBEntry(const TBEntry<WDL>& wdl);
- ~TBEntry();
-};
-
-template<>
-TBEntry<WDL>::TBEntry(const std::string& code) : TBEntry() {
-
- StateInfo st;
- Position pos;
-
- key = pos.set(code, WHITE, &st).material_key();
- pieceCount = popcount(pos.pieces());
- hasPawns = pos.pieces(PAWN);
-
- hasUniquePieces = false;
- for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt < KING; ++pt)
- if (popcount(pos.pieces(c, pt)) == 1)
- hasUniquePieces = true;
-
- if (hasPawns) {
- // Set the leading color. In case both sides have pawns the leading color
- // is the side with less pawns because this leads to better compression.
- bool c = !pos.count<PAWN>(BLACK)
- || ( pos.count<PAWN>(WHITE)
- && pos.count<PAWN>(BLACK) >= pos.count<PAWN>(WHITE));
-
- pawnCount[0] = pos.count<PAWN>(c ? WHITE : BLACK);
- pawnCount[1] = pos.count<PAWN>(c ? BLACK : WHITE);
- }
-
- key2 = pos.set(code, BLACK, &st).material_key();
-}
-
-template<>
-TBEntry<DTZ>::TBEntry(const TBEntry<WDL>& wdl) : TBEntry() {
-
- key = wdl.key;
- key2 = wdl.key2;
- pieceCount = wdl.pieceCount;
- hasPawns = wdl.hasPawns;
- hasUniquePieces = wdl.hasUniquePieces;
-
- if (hasPawns) {
- pawnCount[0] = wdl.pawnCount[0];
- pawnCount[1] = wdl.pawnCount[1];
- }
-}