diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index d2d6cfe67..8f340d61f 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -4,4 +4,8 @@ # Post commit formatting fixes 0fca5605fa2e5e7240fde5e1aae50952b2612231 -08ed4c90db31959521b7ef3186c026edd1e90307 \ No newline at end of file +08ed4c90db31959521b7ef3186c026edd1e90307 + +# Ignore commits related to integer type renamings +dd3e1c4a50fd358c8bf8051c9ef73219669ff6c0 +6e4e03fd282d5e1cba514197bf1ef326c990f0d2 diff --git a/AUTHORS b/AUTHORS index 8c5767fae..8e4241384 100644 --- a/AUTHORS +++ b/AUTHORS @@ -12,8 +12,8 @@ Hisayori Noda (nodchip) # All other authors of Stockfish code (in alphabetical order) 87flowers Aditya (absimaldata) +Adrian Ladoni (AdrianGHUB15) Adrian Petrescu (apetresc) -Adrian (AdrianGHUB15) Ahmed Kerimov (wcdbmv) Ajith Chandy Jose (ajithcj) AK-Khan02 @@ -63,11 +63,11 @@ Cody Ho (aesrentai) CSTENTOR Dale Weiler (graphitemaster) Dalton Hanaway (dhanaway) +Dan Schmidt (dfannius) Daniel Axtens (daxtens) Daniel Dugovic (ddugovic) Daniel Monroe (daniel-monroe) Daniel Samek (DanSamek) -Dan Schmidt (dfannius) Dariusz Orzechowski (dorzechowski) David (dav1312) David Zar @@ -92,9 +92,9 @@ Fanael Linithien (Fanael) fanon Fauzi Akram Dabat (fauzi2) Felix Wittmann -gamander Gabriele Lombardo (gabe) Gahtan Nahdi +gamander Gary Heckman (gheckman) George Sobala (gsobala) gguliash @@ -105,8 +105,8 @@ Gontran Lemaire (gonlem) Goodkov Vasiliy Aleksandrovich (goodkov) Gregor Cramer GuardianRM -Guy Vreuls (gvreuls) Günther Demetz (pb00067, pb00068) +Guy Vreuls (gvreuls) Henri Wiechers Hiraoka Takuya (HiraokaTakuya) homoSapiensSapiens @@ -119,8 +119,8 @@ Jan Ondruš (hxim) Jared Kish (Kurtbusch, kurt22i) Jarrod Torriero (DU-jdto) Jasper Shovelton (Beanie496) -Jean-Francois Romang (jromang) Jean Gauthier (OuaisBla) +Jean-Francois Romang (jromang) Jekaa Jerry Donald Watson (jerrydonaldwatson) jjoshua2 @@ -128,10 +128,10 @@ Jonathan Buladas Dumale (SFisGOD) Jonathan Calovski (Mysseno) Jonathan McDermid (jonathanmcdermid) Joost VandeVondele (vondele) +Jörg Oster (joergoster) Joseph Ellis (jhellis3) Joseph R. Prostko Jost Triller (tsoj) -Jörg Oster (joergoster) Julian Willemer (NightlyKing) jundery Justin Blanchard (UncombedCoconut) @@ -189,8 +189,8 @@ Muzhen J (XInTheDark) Mafanwei Nathan Rugg (nmrugg) Nguyen Pham (nguyenpham) -Nicklas Persson (NicklasPersson) Nick Pelling (nickpelling) +Nicklas Persson (NicklasPersson) Nicolas Duhamel (nikloskoda) Niklas Fiekas (niklasf) Nikolay Kostov (NikolayIT) @@ -198,11 +198,11 @@ Norman Schmidt (FireFather) notruck Nour Berakdar (Nonlinear) Ofek Shochat (OfekShochat, ghostway) -Ondrej Mosnáček (WOnder93) +Ömer Faruk Tutkun (OmerFarukTutkun) Ondřej Mišina (AndrovT) +Ondrej Mosnáček (WOnder93) Onur Zungur (zungur) Oskar Werkelin Ahlin -Ömer Faruk Tutkun (OmerFarukTutkun) Pablo Vazquez Panthee Pascal Romaret @@ -224,13 +224,13 @@ Richard Lloyd (Richard-Lloyd) Robert Nürnberg (robertnurnberg) Rodrigo Exterckötter Tjäder Rodrigo Roim (roim) -Ronald de Man (syzygy1, syzygy) Ron Britvich (Britvich) +Ronald de Man (syzygy1, syzygy) rqs Rui Coelho (ruicoelhopedro) rustam-cpp -Ryan Lefkowitz (rlefko) Ryan Hirsch +Ryan Lefkowitz (rlefko) Ryan Schmitt Ryan Takker Sami Kiminki (skiminki) @@ -262,9 +262,9 @@ Timothy Herchen (anematode) Ting-Hsuan Huang (fffelix-huang) tobi437a Tobias Steinmann -Tomasz Sobczyk (Sopel97) Tom Truscott Tom Vijlbrief (tomtor) +Tomasz Sobczyk (Sopel97) Tony Wang (TonyCongqianWang) Torsten Franz (torfranz, tfranzer) Torsten Hellwig (Torom) diff --git a/src/attacks.cpp b/src/attacks.cpp index 809d8b7dd..4da27ce90 100644 --- a/src/attacks.cpp +++ b/src/attacks.cpp @@ -70,7 +70,7 @@ static void init_magics(Magic magics[][2]) { // Sliding attacks within a rank, indexed by the slider's file and the // 8-bit rank occupancy, yielding the 8-bit attack set on that rank -[[maybe_unused]] constexpr auto RankAttacks = []() { +constexpr auto RankAttacks = []() { std::array, FILE_NB> table{}; for (int file = 0; file < 8; ++file) for (int occ = 0; occ < 256; ++occ) @@ -117,8 +117,7 @@ void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]) { m.attacks = s == SQ_A1 ? table : magics[s - 1][pt - BISHOP].attacks + size; size = 0; - Bitboard b = 0; - [[maybe_unused]] Bitboard prevSliding = -1; + Bitboard b = 0; do { occupancy[size] = b; diff --git a/src/attacks.h b/src/attacks.h index 2a4c77843..63e6902f2 100644 --- a/src/attacks.h +++ b/src/attacks.h @@ -102,10 +102,10 @@ struct alignas(32) DualMagic { // // When using hyperbola quintessence, file, diagonal and antidiagonal attacks // can use a byte reversal rather than a full bit reversal (because all squares - // reside in different bytes). Rank atttacks cannot. Thus, for rank attacks + // reside in different bytes). Rank attacks cannot. Thus, for rank attacks // only, we use a compact lookup table indexed by the 8 bits of the rank's occupancy. std::pair both_attacks_bb(Bitboard occupied) const { - // Byteswap within 64-bit elements + // Byteswap within 128-bit elements const auto bswap = [](__m256i v) { return _mm256_shuffle_epi8(v, _mm256_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, @@ -270,7 +270,7 @@ inline Bitboard attacks_bb(Square s, Color c = COLOR_NB) { // Returns the attacks by the given piece // assuming the board is occupied according to the passed Bitboard. -// Sliding piece attacks do not continue passed an occupied square. +// Sliding piece attacks do not continue past an occupied square. template inline Bitboard attacks_bb(Square s, Bitboard occupied) { @@ -306,7 +306,7 @@ inline Bitboard attacks_bb(Square s, Bitboard occupied) { // Returns the attacks by the given piece // assuming the board is occupied according to the passed Bitboard. -// Sliding piece attacks do not continue passed an occupied square. +// Sliding piece attacks do not continue past an occupied square. inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) { assert(pt != PAWN && is_ok(s)); @@ -318,7 +318,7 @@ inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) { case ROOK : return attacks_bb(s, occupied); case QUEEN : - return attacks_bb(s, occupied) | attacks_bb(s, occupied); + return attacks_bb(s, occupied); default : return PseudoAttacks[pt][s]; } diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 985f25659..cd5af4c75 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -485,7 +485,7 @@ BenchmarkSetup setup_benchmark(std::istream& is) { float totalTime = 0; for (const auto& game : BenchmarkPositions) for (usize i = 0; i < game.size(); ++i) - totalTime += float(getCorrectedTime(i + 1)); + totalTime += float(getCorrectedTime(int(i + 1))); float timeScaleFactor = static_cast(desiredTimeS * 1000) / totalTime; diff --git a/src/bitboard.cpp b/src/bitboard.cpp index c732dd3d2..94f667b2a 100644 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@ -23,7 +23,6 @@ namespace Stockfish { u8 PopCnt16[1 << 16]; -u8 SquareDistance[SQUARE_NB][SQUARE_NB]; // Returns an ASCII representation of a bitboard suitable // to be printed to standard output. Useful for debugging. @@ -46,16 +45,10 @@ std::string Bitboards::pretty(Bitboard b) { return s; } -// Initializes various bitboard tables. It is called at -// startup and relies on global objects to be already zero-initialized. +// Initializes the popcount table at startup. void Bitboards::init() { - for (unsigned i = 0; i < (1 << 16); ++i) PopCnt16[i] = u8(std::bitset<16>(i).count()); - - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) - for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) - SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2)); } } // namespace Stockfish diff --git a/src/bitboard.h b/src/bitboard.h index 4332ef275..836035b33 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -21,9 +21,7 @@ #include #include -#include #include -#include #include #include "types.h" @@ -66,7 +64,6 @@ constexpr Bitboard Rank7BB = Rank1BB << (8 * 6); constexpr Bitboard Rank8BB = Rank1BB << (8 * 7); extern u8 PopCnt16[1 << 16]; -extern u8 SquareDistance[SQUARE_NB][SQUARE_NB]; constexpr Bitboard square_bb(Square s) { assert(is_ok(s)); @@ -133,30 +130,8 @@ constexpr Bitboard pawn_single_push_bb(Color c, Bitboard b) { return c == WHITE ? shift(b) : shift(b); } -// distance() functions return the distance between x and y, defined as the -// number of steps for a king in x to reach y. - -template -inline int distance(Square x, Square y); - -template<> -inline int distance(Square x, Square y) { - return std::abs(file_of(x) - file_of(y)); -} - -template<> -inline int distance(Square x, Square y) { - return std::abs(rank_of(x) - rank_of(y)); -} - -template<> -inline int distance(Square x, Square y) { - return SquareDistance[x][y]; -} - inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); } - constexpr int constexpr_popcount(Bitboard b) { b = b - ((b >> 1) & 0x5555555555555555ULL); b = (b & 0x3333333333333333ULL) + ((b >> 2) & 0x3333333333333333ULL); diff --git a/src/engine.cpp b/src/engine.cpp index 42a04c8a3..db38ef200 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -164,7 +164,7 @@ void Engine::search_clear() { tt.clear(threads); threads.clear(); - // @TODO wont work with multiple instances + // TODO: does not work with multiple instances Tablebases::init(options["SyzygyPath"]); // Free mapped files } diff --git a/src/history.h b/src/history.h index d5a23e516..fc54cbee3 100644 --- a/src/history.h +++ b/src/history.h @@ -54,7 +54,10 @@ static_assert((CORRHIST_BASE_SIZE & (CORRHIST_BASE_SIZE - 1)) == 0, // when we update values with the << operator template struct StatsEntry { - static_assert(std::is_arithmetic_v, "Not an arithmetic type"); + static_assert(std::is_integral_v && std::is_signed_v, "Not a signed integer type"); + static_assert(D > 0 && D <= std::numeric_limits::max() + && D <= std::numeric_limits::max() / D, + "D can lead to overflows"); private: std::conditional_t, T> entry; diff --git a/src/movepick.cpp b/src/movepick.cpp index 5be46dc71..b97508a1b 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -190,7 +190,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, int th, const CapturePieceTo // Assigns a numerical value to each move in a list, used for sorting. // Captures are ordered by Most Valuable Victim (MVV), preferring captures -// with a good history. Quiets moves are ordered using the history tables. +// with a good history. Quiet moves are ordered using the history tables. template ExtMove* MovePicker::score(const MoveList& ml) { diff --git a/src/nnue/features/full_threats.cpp b/src/nnue/features/full_threats.cpp index 6761fe63e..468c168a8 100644 --- a/src/nnue/features/full_threats.cpp +++ b/src/nnue/features/full_threats.cpp @@ -256,10 +256,10 @@ void FullThreats::append_active_indices(Color perspective, const Position& pos, { Piece attacker = make_piece(c, pt); Bitboard bb = pos.pieces(c, pt); + Bitboard targets = pt == KNIGHT || pt == QUEEN ? queenTargets : minorSliderTargets; while (bb) { Square from = pop_lsb(bb); - Bitboard targets = pt == KNIGHT || pt == QUEEN ? queenTargets : minorSliderTargets; Bitboard attacks = Attacks::attacks_bb(pt, from, occupied) & targets; while (attacks) { diff --git a/src/nnue/network.h b/src/nnue/network.h index df102079c..4bcae5276 100644 --- a/src/nnue/network.h +++ b/src/nnue/network.h @@ -109,7 +109,7 @@ class Network { }; -} // namespace Stockfish +} // namespace Stockfish::Eval::NNUE template<> struct std::hash { diff --git a/src/nnue/nnue_architecture.h b/src/nnue/nnue_architecture.h index 0ca1518b2..c06d520c6 100644 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@ -73,8 +73,8 @@ struct NetworkArchitecture { hashValue ^= TransformedFeatureDimensions * 2; hashValue = decltype(fc_0)::get_hash_value(hashValue); - // TODO: considerincluding hash value of ac_sqr_0 in the overall hash value. - // For now omitted on purpose because hash value is not written by trainer yet + // TODO: consider including hash value of ac_sqr_0 in the overall hash value. + // For now omitted on purpose because hash value is not written by trainer (yet) hashValue = decltype(ac_0)::get_hash_value(hashValue); hashValue = decltype(fc_1)::get_hash_value(hashValue); hashValue = decltype(ac_1)::get_hash_value(hashValue); diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 9e2c61d25..7edf2b6c8 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -252,7 +252,7 @@ class FeatureTransformer { // means our pairwise product is zero. If we perform packus and // remove the lower-side clip for the second element, then our // product before packus will be negative, and is zeroed on pack. - // The two operation produce equivalent results, but the second + // The two operations produce equivalent results, but the second // one (using packus) saves one max operation per pair. // But here we run into a problem: mullo does not preserve the diff --git a/src/nnue/nnz_helper.h b/src/nnue/nnz_helper.h index 7033ad54e..6a13e1c72 100644 --- a/src/nnue/nnz_helper.h +++ b/src/nnue/nnz_helper.h @@ -42,7 +42,7 @@ struct NNZInfo { indices[i] = {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23, 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31}; for (u16& m : indices[i]) - m += i * Dimensions / 8; + m += u16(i * Dimensions / 8); } return indices; }(); @@ -85,9 +85,10 @@ struct NNZInfo { count += popcount(nnzMask); indices = _mm512_add_epi16(indices, increment); #else + const __m512i increment = _mm512_set1_epi32(16); + for (auto neurons : {neurons1, neurons2}) { - const __m512i increment = _mm512_set1_epi32(16); // Get a bitmask and gather non zero indices const __mmask16 nnzMask = _mm512_test_epi32_mask(neurons, neurons); const __m512i nnzV = _mm512_maskz_compress_epi32(nnzMask, indices); @@ -162,6 +163,6 @@ struct NNZInfo { NNZCursor make_cursor(bool perspective) { return {*this, perspective}; } #endif }; -} // namespace Stockfish +} // namespace Stockfish::Eval::NNUE #endif diff --git a/src/nnue/simd.h b/src/nnue/simd.h index 39e102fd3..bbaec0800 100644 --- a/src/nnue/simd.h +++ b/src/nnue/simd.h @@ -59,9 +59,7 @@ namespace Stockfish::Eval::NNUE::SIMD { #ifdef USE_AVX512 using vec_t = __m512i; using vec_i8_t = __m256i; -using vec128_t = __m128i; using psqt_vec_t = __m256i; -using vec_uint_t = __m512i; #define vec_load(a) _mm512_load_si512(a) #define vec_store(a, b) _mm512_store_si512(a, b) #define vec_convert_8_16(a) _mm512_cvtepi8_epi16(a) @@ -81,24 +79,15 @@ using vec_uint_t = __m512i; #define vec_sub_psqt_32(a, b) _mm256_sub_epi32(a, b) #define vec_zero_psqt() _mm256_setzero_si256() - #ifdef USE_SSSE3 - #define vec_nnz(a) _mm512_cmpgt_epi32_mask(a, _mm512_setzero_si512()) - #endif + #define vec_nnz(a) _mm512_cmpgt_epi32_mask(a, _mm512_setzero_si512()) - #define vec128_zero _mm_setzero_si128() - #define vec128_set_16(a) _mm_set1_epi16(a) - #define vec128_load(a) _mm_load_si128(a) - #define vec128_storeu(a, b) _mm_storeu_si128(a, b) - #define vec128_add(a, b) _mm_add_epi16(a, b) #define NumRegistersSIMD 16 #define MaxChunkSize 64 #elif USE_AVX2 using vec_t = __m256i; using vec_i8_t = __m128i; -using vec128_t = __m128i; using psqt_vec_t = __m256i; -using vec_uint_t = __m256i; #define vec_load(a) _mm256_load_si256(a) #define vec_store(a, b) _mm256_store_si256(a, b) #define vec_convert_8_16(a) _mm256_cvtepi8_epi16(a) @@ -118,31 +107,16 @@ using vec_uint_t = __m256i; #define vec_sub_psqt_32(a, b) _mm256_sub_epi32(a, b) #define vec_zero_psqt() _mm256_setzero_si256() - #ifdef USE_SSSE3 - #if defined(USE_VNNI) && !defined(USE_AVXVNNI) - #define vec_nnz(a) _mm256_cmpgt_epi32_mask(a, _mm256_setzero_si256()) - #else - #define vec_nnz(a) \ - _mm256_movemask_ps( \ - _mm256_castsi256_ps(_mm256_cmpgt_epi32(a, _mm256_setzero_si256()))) - #endif - #endif - - #define vec128_zero _mm_setzero_si128() - #define vec128_set_16(a) _mm_set1_epi16(a) - #define vec128_load(a) _mm_load_si128(a) - #define vec128_storeu(a, b) _mm_storeu_si128(a, b) - #define vec128_add(a, b) _mm_add_epi16(a, b) + #define vec_nnz(a) \ + _mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpgt_epi32(a, _mm256_setzero_si256()))) #define NumRegistersSIMD 12 #define MaxChunkSize 32 #elif USE_SSE2 using vec_t = __m128i; -using vec_i8_t = u64; // for the correct size -- will be loaded into an xmm reg -using vec128_t = __m128i; +using vec_i8_t = u64; using psqt_vec_t = __m128i; -using vec_uint_t = __m128i; #define vec_load(a) (*(a)) #define vec_store(a, b) *(a) = (b) #define vec_add_16(a, b) _mm_add_epi16(a, b) @@ -186,12 +160,6 @@ inline __m128i vec_convert_8_16(u64 x) { } #endif - #define vec128_zero _mm_setzero_si128() - #define vec128_set_16(a) _mm_set1_epi16(a) - #define vec128_load(a) _mm_load_si128(a) - #define vec128_storeu(a, b) _mm_storeu_si128(a, b) - #define vec128_add(a, b) _mm_add_epi16(a, b) - #define NumRegistersSIMD (Is64Bit ? 12 : 6) #define MaxChunkSize 16 @@ -205,8 +173,6 @@ using vec_i32x4_t __attribute__((may_alias)) = int32x4_t; using vec_t __attribute__((may_alias)) = int16x8_t; using vec_i8_t __attribute__((may_alias)) = int8x16_t; using psqt_vec_t __attribute__((may_alias)) = int32x4_t; -using vec128_t __attribute__((may_alias)) = uint16x8_t; -using vec_uint_t __attribute__((may_alias)) = uint32x4_t; #define vec_load(a) (*(a)) #define vec_store(a, b) *(a) = (b) #define vec_add_16(a, b) vaddq_s16(a, b) @@ -224,15 +190,6 @@ using vec_uint_t __attribute__((may_alias)) = uint32x4_t; #define vec_sub_psqt_32(a, b) vsubq_s32(a, b) #define vec_zero_psqt() psqt_vec_t{0} -static constexpr u32 Mask[4] = {1, 2, 4, 8}; - #define vec_nnz(a) \ - vaddvq_u32(vandq_u32(vtstq_u32((uint32x4_t) a, (uint32x4_t) a), vld1q_u32(Mask))) - #define vec128_zero vdupq_n_u16(0) - #define vec128_set_16(a) vdupq_n_u16(a) - #define vec128_load(a) vld1q_u16(reinterpret_cast(a)) - #define vec128_storeu(a, b) vst1q_u16(reinterpret_cast(a), b) - #define vec128_add(a, b) vaddq_u16(a, b) - #define NumRegistersSIMD 16 #define MaxChunkSize 16 @@ -245,9 +202,7 @@ inline int16x8_t vsubw_high_s8(int16x8_t a, int8x16_t b) { return vsubw_s8(a, vg #elif USE_LASX using vec_t = __m256i; using vec_i8_t = __m128i; -using vec128_t = __m128i; using psqt_vec_t = __m256i; -using vec_uint_t = __m256i; inline __m256i lasx_load256(const __m256i* a) { return __lasx_xvld(reinterpret_cast(a), 0); @@ -293,12 +248,6 @@ inline __m256i lasx_packus_32(__m256i a, __m256i b) { #define vec_mulhi_8 __lasx_xvmuh_bu #define vec_srli_8 __lasx_xvsrli_b - #define vec128_zero __lsx_vldi(0) - #define vec128_set_16(a) __lsx_vreplgr2vr_h(a) - #define vec128_load(a) (*(a)) - #define vec128_storeu(a, b) *(a) = (b) - #define vec128_add(a, b) __lsx_vadd_h(a, b) - #define NumRegistersSIMD 24 #define MaxChunkSize 32 @@ -328,9 +277,7 @@ inline int lasx_vec_nnz(__m256i a) { #elif USE_LSX using vec_t = __m128i; using vec_i8_t = u64; -using vec128_t = __m128i; using psqt_vec_t = __m128i; -using vec_uint_t = __m128i; inline __m128i lsx_packus_16(__m128i a, __m128i b) { #if defined(__clang__) && defined(__has_builtin) && __has_builtin(__builtin_lsx_vssrani_bu_h) @@ -381,12 +328,6 @@ inline __m128i vec_convert_8_16(u64 x) { #define vec_mulhi_8 __lsx_vmuh_bu #define vec_srli_8 __lsx_vsrli_b - #define vec128_zero __lsx_vldi(0) - #define vec128_set_16(a) __lsx_vreplgr2vr_h(a) - #define vec128_load(a) (*(a)) - #define vec128_storeu(a, b) *(a) = (b) - #define vec128_add(a, b) __lsx_vadd_h(a, b) - #define NumRegistersSIMD 24 #define MaxChunkSize 16 diff --git a/src/position.cpp b/src/position.cpp index b9c6eeaac..0c89e6417 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -113,8 +113,8 @@ inline int H1(Key h) { return h & 0x1fff; } inline int H2(Key h) { return (h >> 16) & 0x1fff; } // Cuckoo tables with Zobrist hashes of valid reversible moves, and the moves themselves -std::array cuckoo; -std::array cuckooMove; +static std::array cuckoo; +static std::array cuckooMove; // Initializes at startup the various arrays used to compute hash keys void Position::init() { @@ -305,7 +305,7 @@ Position::set(const string& fenStr, bool isChess960, StateInfo* si) { // if an inner rook is associated with the castling right, the castling tag is // replaced by the file letter of the involved rook, as for the Shredder-FEN. // - // NOTE: Due to the prevalnce of incorrect (or missing) castling rights the + // NOTE: Due to the prevalence of incorrect (or missing) castling rights the // validation is less strict. However, incorrect castling rights are still sanitized. int num_castling_rights = 0; for (;;) @@ -421,7 +421,7 @@ Position::set(const string& fenStr, bool isChess960, StateInfo* si) { ss >> std::skipws >> st->rule50 >> gamePly; // Normally values larger than 99 would be pointless but we do support ignoring 50 move rule for TB purposes. - // Limit at 2**15 as it's used multiplicativly with position evaluation during search. + // Limit at 2**15 as it's used multiplicatively with position evaluation during search. if (st->rule50 < 0 || st->rule50 > 32767) return PositionSetError("Unsupported position. Rule50 counter out of range."); @@ -1636,21 +1636,16 @@ bool Position::material_key_is_ok() const { return compute_material_key() == st- // This is meant to be helpful when debugging. bool Position::pos_is_ok() const { - constexpr bool Fast = false; // fast or full check? - if ((sideToMove != WHITE && sideToMove != BLACK) || piece_on(square(WHITE)) != W_KING || piece_on(square(BLACK)) != B_KING || (ep_square() != SQ_NONE && relative_rank(sideToMove, ep_square()) != RANK_6)) assert(0 && "pos_is_ok: Default"); - if (Fast) - return true; - - if (pieceCount[W_KING] != 1 || pieceCount[B_KING] != 1 + if (count(WHITE) != 1 || count(BLACK) != 1 || attackers_to_exist(square(~sideToMove), pieces(), sideToMove)) assert(0 && "pos_is_ok: Kings"); - if ((pieces(PAWN) & (Rank1BB | Rank8BB)) || pieceCount[W_PAWN] > 8 || pieceCount[B_PAWN] > 8) + if ((pieces(PAWN) & (Rank1BB | Rank8BB)) || count(WHITE) > 8 || count(BLACK) > 8) assert(0 && "pos_is_ok: Pawns"); @@ -1679,7 +1674,6 @@ bool Position::pos_is_ok() const { if (p1 != p2 && (pieces(p1) & pieces(p2))) assert(0 && "pos_is_ok: Bitboards"); - for (Piece pc : Pieces) if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))) || pieceCount[pc] != std::count(board.begin(), board.end(), pc)) @@ -1691,7 +1685,7 @@ bool Position::pos_is_ok() const { if (!can_castle(cr)) continue; - if (piece_on(castlingRookSquare[cr]) != make_piece(c, ROOK) + if (piece_on(castling_rook_square(cr)) != make_piece(c, ROOK) || castlingRightsMask[castlingRookSquare[cr]] != cr || (castlingRightsMask[square(c)] & cr) != cr) assert(0 && "pos_is_ok: Castling"); diff --git a/src/position.h b/src/position.h index 96ccb3258..7316075cb 100644 --- a/src/position.h +++ b/src/position.h @@ -177,6 +177,7 @@ class Position { int rule50_count() const; Value non_pawn_material(Color c) const; Value non_pawn_material() const; + bool dtz_is_dtm() const; // Pawnless && (3-men || 4-men-minors-only) // Position consistency check, for debugging bool pos_is_ok() const; @@ -344,6 +345,11 @@ inline int Position::rule50_count() const { return st->rule50; } inline bool Position::is_chess960() const { return chess960; } +inline bool Position::dtz_is_dtm() const { + return !count() + && (count() == 3 || (count() == 4 && !pieces(QUEEN, ROOK))); +} + inline bool Position::capture(Move m) const { assert(m.is_ok()); diff --git a/src/search.cpp b/src/search.cpp index 0af3c10ff..d6ec50aba 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -146,6 +146,8 @@ void update_all_stats(const Position& pos, Move ttMove, bool PvNode); +// Detect shuffling moves in order to limit search explosions +// Added in #6447 as non-regression, and so its parameters should not be tuned bool is_shuffling(Move move, Stack* const ss, const Position& pos) { if (pos.capture_stage(move) || pos.rule50_count() < 10) return false; @@ -249,9 +251,9 @@ void Search::Worker::start_searching() { // Send PV info if it has changed since last output in iterative_deepening(). if (!uciPvSent || bestThread != this) - main_manager()->pv(*bestThread, threads, tt, bestThread->rootDepth); + main_manager()->output_pv(*bestThread, threads, tt, bestThread->rootDepth); - // In rare cases, pv() may change the ponder move through syzygy_extend_pv(). + // In rare cases, output_pv() may change the ponder move through syzygy_extend_pv(). std::string ponder; if (bestThread->rootMoves[0].pv.size() > 1) ponder = UCIEngine::move(bestThread->rootMoves[0].pv[1], rootPos.is_chess960()); @@ -347,8 +349,7 @@ bool Search::Worker::iterative_deepening() { rootMoves[i].previousScoreExact = i < multiPV; } - usize pvFirst = 0; - pvLast = 0; + usize pvFirst = pvLast = 0; if (!threads.increaseDepth) searchAgainCounter++; @@ -411,7 +412,7 @@ bool Search::Worker::iterative_deepening() { // at nodes > 10M (rather than depth N, which can be reached quickly) if (mainThread && multiPV == 1 && (bestValue <= alpha || bestValue >= beta) && nodes > NODES_LIMIT_OUTPUT) - main_manager()->pv(*this, threads, tt, rootDepth); + main_manager()->output_pv(*this, threads, tt, rootDepth); // In case of failing low/high increase aspiration window and re-search, // otherwise exit the loop. @@ -491,7 +492,7 @@ bool Search::Worker::iterative_deepening() { if (mainThread && !threads.stop && (pvIdx + 1 == multiPV || nodes > NODES_LIMIT_OUTPUT)) { - main_manager()->pv(*this, threads, tt, rootDepth); + main_manager()->output_pv(*this, threads, tt, rootDepth); uciPvSent = (pvIdx + 1 == multiPV); } @@ -587,9 +588,9 @@ bool Search::Worker::iterative_deepening() { double totalTime = mainThread->tm.optimum() * fallingEval * reduction * bestMoveInstability * highBestMoveEffort; - // Cap used time in case of a single legal move for a better viewer experience if (rootMoves.size() == 1) - totalTime = std::min(561.7, totalTime); + // Cap used time to 0.5s for a better viewer experience + totalTime = std::min(500.0, totalTime); auto elapsedTime = elapsed(); @@ -700,7 +701,7 @@ void Search::Worker::clear() { // Main search function for both PV and non-PV nodes template Value Search::Worker::search( - Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode) { + Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, const bool cutNode) { constexpr bool PvNode = nodeType != NonPV; constexpr bool rootNode = nodeType == Root; @@ -1917,7 +1918,7 @@ void update_all_stats(const Position& pos, if (!PvNode) // Important: don't remove the cast to a 64-bit number else the multiplication // can overflow on 32-bit platforms which would change the bench signature - bonus += bonus * u64(quietsSearched.size() + capturesSearched.size()) / 256; + bonus += int(bonus * u64(quietsSearched.size() + capturesSearched.size()) / 256); if (!pos.capture_stage(bestMove)) { @@ -2175,7 +2176,7 @@ void syzygy_extend_pv(const OptionsMap& options, // Finding a draw in this function is an exceptional case, that cannot happen when rule50 is false or // during engine game play, since we have a winning score, and play correctly // with TB support. However, it can be that a position is draw due to the 50 move - // rule if it has been been reached on the board with a non-optimal 50 move counter + // rule if it has been reached on the board with a non-optimal 50 move counter // (e.g. 8/8/6k1/3B4/3K4/4N3/8/8 w - - 54 106 ) which TB with dtz counter rounding // cannot always correctly rank. See also // https://github.com/official-stockfish/Stockfish/issues/5175#issuecomment-2058893495 @@ -2196,10 +2197,10 @@ void syzygy_extend_pv(const OptionsMap& options, << sync_endl; } -void SearchManager::pv(Search::Worker& worker, - const ThreadPool& threads, - const TranspositionTable& tt, - Depth depth) { +void SearchManager::output_pv(Search::Worker& worker, + const ThreadPool& threads, + const TranspositionTable& tt, + Depth depth) { const auto nodes = threads.nodes_searched(); auto& rootMoves = worker.rootMoves; diff --git a/src/search.h b/src/search.h index 57fab15ca..eefb8c80b 100644 --- a/src/search.h +++ b/src/search.h @@ -282,10 +282,10 @@ class SearchManager: public ISearchManager { void check_time(Search::Worker& worker) override; - void pv(Search::Worker& worker, - const ThreadPool& threads, - const TranspositionTable& tt, - Depth depth); + void output_pv(Search::Worker& worker, + const ThreadPool& threads, + const TranspositionTable& tt, + Depth depth); Stockfish::TimeManagement tm; double originalTimeAdjust; @@ -353,7 +353,8 @@ class Worker { // This is the main search function, for both PV and non-PV nodes template - Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode); + Value + search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, const bool cutNode); // Quiescence search function, which is called by the main search template diff --git a/src/shm.h b/src/shm.h index 0e4e22a21..af9254dc8 100644 --- a/src/shm.h +++ b/src/shm.h @@ -40,11 +40,6 @@ #include "shm_linux.h" #endif -#if defined(__ANDROID__) - #include - #define SF_MAX_SEM_NAME_LEN NAME_MAX -#endif - #include "types.h" #include "memory.h" diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 08b8999d2..24dda0d7e 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1802,14 +1802,10 @@ Config Tablebases::rank_root_moves(const OptionsMap& options, config.probeDepth = 0; } - if (config.cardinality >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING)) + if (config.cardinality >= pos.count() && !pos.can_castle(ANY_CASTLING)) { // Use DTZ to rank the moves if checkmate is the only zeroing move - rankDTZ = - rankDTZ - || (!pos.pieces(PAWN) - && (popcount(pos.pieces()) == 3 - || (popcount(pos.pieces()) == 4 && !(pos.pieces(QUEEN) | pos.pieces(ROOK))))); + rankDTZ = rankDTZ || pos.dtz_is_dtm(); // Rank moves using DTZ tables, bail out if time_abort flags zeitnot config.rootInTB = diff --git a/src/types.h b/src/types.h index b6d503fb0..c4eb1f8c1 100644 --- a/src/types.h +++ b/src/types.h @@ -58,7 +58,7 @@ // _WIN32 Building on Windows (any) // _WIN64 Building on Windows 64 bit -// Enforce minimum GCC version + // Enforce minimum GCC version #if defined(__GNUC__) && !defined(__clang__) \ && (__GNUC__ < 9 || (__GNUC__ == 9 && __GNUC_MINOR__ < 3)) #error "Stockfish requires GCC 9.3 or later for correct compilation" @@ -190,6 +190,10 @@ constexpr bool is_mated(Value value) { constexpr bool is_mate_or_mated(Value value) { return is_mate(value) || is_mated(value); } +constexpr Value mate_in(int ply) { return VALUE_MATE - ply; } + +constexpr Value mated_in(int ply) { return -VALUE_MATE + ply; } + // In the code, we make the assumption that these values // are such that non_pawn_material() can be used to uniquely // identify the material on the board. @@ -377,10 +381,6 @@ constexpr CastlingRights operator&(Color c, CastlingRights cr) { return CastlingRights((c == WHITE ? WHITE_CASTLING : BLACK_CASTLING) & cr); } -constexpr Value mate_in(int ply) { return VALUE_MATE - ply; } - -constexpr Value mated_in(int ply) { return -VALUE_MATE + ply; } - constexpr Square make_square(File f, Rank r) { return Square((r << 3) + f); } constexpr Piece make_piece(Color c, PieceType pt) { return Piece((c << 3) + pt); } @@ -454,10 +454,6 @@ class Move { return Square(data & 0x3F); } - // Same as to_sq() but without assertion, for branchless code paths - // where the result is masked/ignored when move is not ok - constexpr Square to_sq_unchecked() const { return Square(data & 0x3F); } - constexpr MoveType type_of() const { return MoveType(data & (3 << 14)); } constexpr PieceType promotion_type() const { return PieceType(((data >> 12) & 3) + KNIGHT); }