From c109a88ebe93ab7652c7cb4694cfc405568e5e50 Mon Sep 17 00:00:00 2001 From: Timothy Herchen Date: Tue, 2 Dec 2025 15:50:24 -0800 Subject: [PATCH 01/13] fix missing condition Fixes a bug in https://github.com/official-stockfish/Stockfish/pull/6453 https://github.com/official-stockfish/Stockfish/commit/abd835dcbc3a28481224f6253b00b7420d062513 The modifications to the DirtyThreats bitboards should only happen if PutPiece is true. This somehow didn't affect bench at the default parameters. Reference AVX2: ./stockfish.killdeer-fix.avx2 bench 64 1 23 Nodes searched : 178140156 Nodes/second : 1503152 before patch: ./stockfish.master.avx512icl bench 64 1 23 Nodes searched : 218349728 Nodes/second : 1743450 after patch: ./stockfish.killdeer-fix.avx512icl bench 64 1 23 Nodes searched : 178140156 Nodes/second : 1727520 passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 39328 W: 10293 L: 10080 D: 18955 Ptnml(0-2): 113, 4306, 10629, 4487, 129 https://tests.stockfishchess.org/tests/view/692fb2d8b23dfeae38d01c81 closes https://github.com/official-stockfish/Stockfish/pull/6463 Bench: 2912398 --- src/position.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 049c72682..b08cabf3f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1159,8 +1159,11 @@ void Position::update_piece_threats(Piece pc, if (!all_attackers) return; // Square s is threatened iff there's at least one attacker - dts->threatenedSqs |= square_bb(s); - dts->threateningSqs |= all_attackers; + if constexpr (PutPiece) + { + dts->threatenedSqs |= square_bb(s); + dts->threateningSqs |= all_attackers; + } DirtyThreat dt_template{NO_PIECE, pc, Square(0), s, PutPiece}; write_multiple_dirties(*this, all_attackers, From 5edfabd07029dc26228f4b22931b67be5402860a Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Mon, 17 Nov 2025 18:54:24 +0300 Subject: [PATCH 02/13] Fix Typo closes https://github.com/official-stockfish/Stockfish/pull/6436 No functional change --- src/history.h | 2 +- src/misc.cpp | 2 +- src/misc.h | 2 +- src/position.cpp | 2 +- src/search.cpp | 8 +------- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/history.h b/src/history.h index a605ae417..f0161b74e 100644 --- a/src/history.h +++ b/src/history.h @@ -100,7 +100,7 @@ using Stats = MultiArray, Sizes...>; // see https://www.chessprogramming.org/Butterfly_Boards using ButterflyHistory = Stats; -// LowPlyHistory is addressed by play and move's from and to squares, used +// LowPlyHistory is addressed by ply and move's from and to squares, used // to improve move ordering near the root using LowPlyHistory = Stats; diff --git a/src/misc.cpp b/src/misc.cpp index d21497280..886544b6c 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -44,7 +44,7 @@ constexpr std::string_view version = "dev"; // Our fancy logging facility. The trick here is to replace cin.rdbuf() and // cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We -// can toggle the logging of std::cout and std:cin at runtime whilst preserving +// can toggle the logging of std::cout and std::cin at runtime whilst preserving // usual I/O functionality, all without changing a single line of code! // Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81 diff --git a/src/misc.h b/src/misc.h index db5f701e9..32f5b047e 100644 --- a/src/misc.h +++ b/src/misc.h @@ -424,7 +424,7 @@ void move_to_front(std::vector& vec, Predicate pred) { #elif defined(_MSC_VER) #define sf_always_inline __forceinline #else - // do nothign for other compilers + // do nothing for other compilers #define sf_always_inline #endif diff --git a/src/position.cpp b/src/position.cpp index b08cabf3f..092e40fd4 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -911,7 +911,7 @@ void Position::do_move(Move m, if (more_than_one(pawns)) { - // If there are two pawns potentially being abled to capture and at least one + // If there are two pawns potentially being able to capture and at least one // is not pinned, ep is legal as there are no horizontal exposed checks if (!more_than_one(blockers_for_king(them) & pawns)) { diff --git a/src/search.cpp b/src/search.cpp index c31a08c49..5f60bafdc 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -699,18 +699,12 @@ Value Search::Worker::search( ss->ttPv = excludedMove ? ss->ttPv : PvNode || (ttHit && ttData.is_pv); ttCapture = ttData.move && pos.capture_stage(ttData.move); - // At this point, if excluded, skip straight to step 6, static eval. However, - // to save indentation, we list the condition in all code between here and there. - // Step 6. Static evaluation of the position Value unadjustedStaticEval = VALUE_NONE; const auto correctionValue = correction_value(*this, pos, ss); + // Skip early pruning when in check if (ss->inCheck) - { - // Skip early pruning when in check ss->staticEval = eval = (ss - 2)->staticEval; - improving = false; - } else if (excludedMove) unadjustedStaticEval = eval = ss->staticEval; else if (ss->ttHit) From 863c0ec6d00e7bb1f453ccebcf16e0883ca8f4ff Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Mon, 1 Dec 2025 23:14:00 +0300 Subject: [PATCH 03/13] Simplify piece threat calculation Passed STC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 105984 W: 27206 L: 27067 D: 51711 Ptnml(0-2): 260, 11556, 29245, 11647, 284 https://tests.stockfishchess.org/tests/view/6914798e7ca87818523317cf Passed LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 53028 W: 13635 L: 13456 D: 25937 Ptnml(0-2): 28, 5184, 15908, 5369, 25 https://tests.stockfishchess.org/tests/view/6918c5fc7ca8781852332312 closes https://github.com/official-stockfish/Stockfish/pull/6459 No functional change --- src/position.cpp | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 092e40fd4..3125d1f7a 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1108,35 +1108,8 @@ void Position::update_piece_threats(Piece pc, const Bitboard rAttacks = attacks_bb(s, occupied); const Bitboard bAttacks = attacks_bb(s, occupied); - Bitboard qAttacks = Bitboard(0); - if constexpr (ComputeRay) - qAttacks = rAttacks | bAttacks; - else if (type_of(pc) == QUEEN) - qAttacks = rAttacks | bAttacks; - - Bitboard threatened; - - switch (type_of(pc)) - { - case PAWN : - threatened = PseudoAttacks[color_of(pc)][s]; - break; - case BISHOP : - threatened = bAttacks; - break; - case ROOK : - threatened = rAttacks; - break; - case QUEEN : - threatened = qAttacks; - break; - - default : - threatened = PseudoAttacks[type_of(pc)][s]; - } - - threatened &= occupied; - Bitboard sliders = (rookQueens & rAttacks) | (bishopQueens & bAttacks); + Bitboard threatened = attacks_bb(pc, s, occupied) & occupied; + Bitboard sliders = (rookQueens & rAttacks) | (bishopQueens & bAttacks); Bitboard incoming_threats = (PseudoAttacks[KNIGHT][s] & knights) | (attacks_bb(s, WHITE) & blackPawns) | (attacks_bb(s, BLACK) & whitePawns) | (PseudoAttacks[KING][s] & kings); @@ -1189,7 +1162,7 @@ void Position::update_piece_threats(Piece pc, Piece slider = piece_on(sliderSq); const Bitboard ray = RayPassBB[sliderSq][s] & ~BetweenBB[sliderSq][s]; - const Bitboard discovered = ray & qAttacks & occupied; + const Bitboard discovered = ray & (rAttacks | bAttacks) & occupied; assert(!more_than_one(discovered)); if (discovered && (RayPassBB[sliderSq][s] & noRaysContaining) != noRaysContaining) From a98c3f687816348dd8d047dd9229171d23c1bfe8 Mon Sep 17 00:00:00 2001 From: Timothy Herchen Date: Mon, 1 Dec 2025 16:23:18 -0800 Subject: [PATCH 04/13] Small threat-related cleanups Remove a couple unused things, mark `noRaysContaining` as `[[maybe_unused]]` (suggested by Viz) to silence a warning on GCC 10, update a comment, and replace inline constants closes https://github.com/official-stockfish/Stockfish/pull/6460 No functional change --- src/nnue/nnue_accumulator.h | 1 - src/position.cpp | 8 ++++---- src/position.h | 2 +- src/types.h | 22 +++++++++------------- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/nnue/nnue_accumulator.h b/src/nnue/nnue_accumulator.h index 69ab49632..1ccab5f2f 100644 --- a/src/nnue/nnue_accumulator.h +++ b/src/nnue/nnue_accumulator.h @@ -157,7 +157,6 @@ class AccumulatorStack { [[nodiscard]] const AccumulatorState& latest() const noexcept; void reset() noexcept; - void push(const DirtyBoardData& dirtyBoardData) noexcept; std::pair push() noexcept; void pop() noexcept; diff --git a/src/position.cpp b/src/position.cpp index 3125d1f7a..cd778011f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1093,10 +1093,10 @@ void write_multiple_dirties(const Position& p, #endif template -void Position::update_piece_threats(Piece pc, - Square s, - DirtyThreats* const dts, - Bitboard noRaysContaining) { +void Position::update_piece_threats(Piece pc, + Square s, + DirtyThreats* const dts, + [[maybe_unused]] Bitboard noRaysContaining) const { const Bitboard occupied = pieces(); const Bitboard rookQueens = pieces(ROOK, QUEEN); const Bitboard bishopQueens = pieces(BISHOP, QUEEN); diff --git a/src/position.h b/src/position.h index 7a029ce18..e5d3f6d28 100644 --- a/src/position.h +++ b/src/position.h @@ -190,7 +190,7 @@ class Position { void update_piece_threats(Piece pc, Square s, DirtyThreats* const dts, - Bitboard noRaysContaining = -1ULL); + Bitboard noRaysContaining = -1ULL) const; void move_piece(Square from, Square to, DirtyThreats* const dts = nullptr); template void do_castling(Color us, diff --git a/src/types.h b/src/types.h index c6613f2f2..1bb8bd3cc 100644 --- a/src/types.h +++ b/src/types.h @@ -306,24 +306,25 @@ struct DirtyThreat { | (threatened_sq << ThreatenedSqOffset) | (pc_sq << PcSqOffset); } - Piece pc() const { return static_cast(data >> 20 & 0xf); } - Piece threatened_pc() const { return static_cast(data >> 16 & 0xf); } - Square threatened_sq() const { return static_cast(data >> 8 & 0xff); } - Square pc_sq() const { return static_cast(data & 0xff); } - bool add() const { return data >> 31; } + Piece pc() const { return static_cast(data >> PcOffset & 0xf); } + Piece threatened_pc() const { return static_cast(data >> ThreatenedPcOffset & 0xf); } + Square threatened_sq() const { return static_cast(data >> ThreatenedSqOffset & 0xff); } + Square pc_sq() const { return static_cast(data >> PcSqOffset & 0xff); } + bool add() const { return data >> 31; } uint32_t raw() const { return data; } private: uint32_t data; }; -using DirtyThreatList = ValueList; - // A piece can be involved in at most 8 outgoing attacks and 16 incoming attacks. // Moving a piece also can reveal at most 8 discovered attacks. // This implies that a non-castling move can change at most (8 + 16) * 3 + 8 = 80 features. // By similar logic, a castling move can change at most (5 + 1 + 3 + 9) * 2 = 36 features. -// Thus, 80 should work as an upper bound. +// Thus, 80 should work as an upper bound. Finally, 16 entries are added to accommodate +// unmasked vector stores near the end of the list. + +using DirtyThreatList = ValueList; struct DirtyThreats { DirtyThreatList list; @@ -333,11 +334,6 @@ struct DirtyThreats { Bitboard threatenedSqs, threateningSqs; }; -struct DirtyBoardData { - DirtyPiece dp; - DirtyThreats dts; -}; - #define ENABLE_INCR_OPERATORS_ON(T) \ constexpr T& operator++(T& d) { return d = T(int(d) + 1); } \ constexpr T& operator--(T& d) { return d = T(int(d) - 1); } From 8449e5eb9d082d6561e5a491a97e40e1f7532893 Mon Sep 17 00:00:00 2001 From: Daniel Monroe Date: Tue, 2 Dec 2025 12:56:35 -0500 Subject: [PATCH 05/13] Remove non-functional term in isShuffling closes https://github.com/official-stockfish/Stockfish/pull/6462 No functional change --- src/search.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5f60bafdc..c9d30ce30 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -141,9 +141,8 @@ void update_all_stats(const Position& pos, Move TTMove, int moveCount); -bool isShuffling(Move move, Stack* const ss, const Position& pos) { - if (type_of(pos.moved_piece(move)) == PAWN || pos.capture_stage(move) - || pos.rule50_count() < 10) +bool is_shuffling(Move move, Stack* const ss, const Position& pos) { + if (pos.capture_stage(move) || pos.rule50_count() < 10) return false; if (pos.state()->pliesFromNull <= 6 || ss->ply < 20) return false; @@ -1119,7 +1118,7 @@ moves_loop: // When in check, search starts here // and lower extension margins scale well. if (!rootNode && move == ttData.move && !excludedMove && depth >= 6 + ss->ttPv && is_valid(ttData.value) && !is_decisive(ttData.value) && (ttData.bound & BOUND_LOWER) - && ttData.depth >= depth - 3 && !isShuffling(move, ss, pos)) + && ttData.depth >= depth - 3 && !is_shuffling(move, ss, pos)) { Value singularBeta = ttData.value - (53 + 75 * (ss->ttPv && !PvNode)) * depth / 60; Depth singularDepth = newDepth / 2; From e1c919fd7eca39c00c23274f58e54606e8aa19c6 Mon Sep 17 00:00:00 2001 From: mstembera <5421953+mstembera@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:36:01 -0800 Subject: [PATCH 06/13] Fix one error and all warnings on MSVC 2026 The error is "C1001: Internal compiler error." in uci.cpp on line 370 of master. For some reason the compiler can't handle the std::size(hashfullAges) inside the lambda. Older MSVC versions had no problem. Most of the warnings are due to implicit type conversions "conversion from type A to type B, possible loss of data" many of which have been present for a while. closes https://github.com/official-stockfish/Stockfish/pull/6464 No functional change --- src/benchmark.cpp | 4 ++-- src/history.h | 8 +++++--- src/nnue/nnue_feature_transformer.h | 7 ++++--- src/syzygy/tbprobe.cpp | 4 ++-- src/thread.cpp | 4 ++-- src/timeman.cpp | 2 +- src/uci.cpp | 13 +++++++------ 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 136b4031e..039e384c9 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -454,7 +454,7 @@ BenchmarkSetup setup_benchmark(std::istream& is) { int desiredTimeS; if (!(is >> setup.threads)) - setup.threads = get_hardware_concurrency(); + setup.threads = int(get_hardware_concurrency()); else setup.originalInvocation += std::to_string(setup.threads); @@ -486,7 +486,7 @@ BenchmarkSetup setup_benchmark(std::istream& is) { int ply = 1; for (int i = 0; i < static_cast(game.size()); ++i) { - const float correctedTime = getCorrectedTime(ply); + const float correctedTime = float(getCorrectedTime(ply)); totalTime += correctedTime; ply += 1; } diff --git a/src/history.h b/src/history.h index f0161b74e..87004ead9 100644 --- a/src/history.h +++ b/src/history.h @@ -48,13 +48,15 @@ inline int pawn_history_index(const Position& pos) { return pos.pawn_key() & (PAWN_HISTORY_SIZE - 1); } -inline uint16_t pawn_correction_history_index(const Position& pos) { return pos.pawn_key(); } +inline uint16_t pawn_correction_history_index(const Position& pos) { + return uint16_t(pos.pawn_key()); +} -inline uint16_t minor_piece_index(const Position& pos) { return pos.minor_piece_key(); } +inline uint16_t minor_piece_index(const Position& pos) { return uint16_t(pos.minor_piece_key()); } template inline uint16_t non_pawn_index(const Position& pos) { - return pos.non_pawn_key(c); + return uint16_t(pos.non_pawn_key(c)); } // StatsEntry is the container of various numerical statistics. We use a class diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 1f328fff4..091ae074d 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -171,9 +171,10 @@ class FeatureTransformer { read_leb_128(stream, *combinedWeights); - std::copy(combinedWeights->begin(), - combinedWeights->begin() + ThreatInputDimensions * HalfDimensions, - std::begin(threatWeights)); + std::transform(combinedWeights->begin(), + combinedWeights->begin() + ThreatInputDimensions * HalfDimensions, + std::begin(threatWeights), + [](WeightType w) { return static_cast(w); }); std::copy(combinedWeights->begin() + ThreatInputDimensions * HalfDimensions, combinedWeights->begin() diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index c8ff60739..e3f7c0a18 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -584,7 +584,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) { // idx = k * d->span + idx % d->span (2) // // So from (1) and (2) we can compute idx - I(K): - int diff = idx % d->span - d->span / 2; + int diff = int(idx % d->span - d->span / 2); // Sum the above to offset to find the offset corresponding to our idx offset += diff; @@ -1092,7 +1092,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) { // See https://web.archive.org/web/20201106232444/http://www.larsson.dogma.net/dcc99.pdf std::vector visited(d->symlen.size()); - for (std::size_t sym = 0; sym < d->symlen.size(); ++sym) + for (Sym sym = 0; sym < d->symlen.size(); ++sym) if (!visited[sym]) d->symlen[sym] = set_symlen(d, sym, visited); diff --git a/src/thread.cpp b/src/thread.cpp index f87d7a94d..58840a874 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -283,8 +283,8 @@ void ThreadPool::start_thinking(const OptionsMap& options, { th->run_custom_job([&]() { th->worker->limits = limits; - th->worker->nodes = th->worker->tbHits = th->worker->nmpMinPly = - th->worker->bestMoveChanges = 0; + th->worker->nodes = th->worker->tbHits = th->worker->bestMoveChanges = 0; + th->worker->nmpMinPly = 0; th->worker->rootDepth = th->worker->completedDepth = 0; th->worker->rootMoves = rootMoves; th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState); diff --git a/src/timeman.cpp b/src/timeman.cpp index 5840e2556..e82a1f6bf 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -91,7 +91,7 @@ void TimeManagement::init(Search::LimitsType& limits, // If less than one second, gradually reduce mtg if (scaledTime < 1000) - centiMTG = scaledTime * 5.051; + centiMTG = int(scaledTime * 5.051); // Make sure timeLeft is > 0 since we may use it as a divisor TimePoint timeLeft = diff --git a/src/uci.cpp b/src/uci.cpp index 5bd235823..be7de97d7 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -313,8 +313,8 @@ void UCIEngine::benchmark(std::istream& args) { Benchmark::BenchmarkSetup setup = Benchmark::setup_benchmark(args); - const int numGoCommands = count_if(setup.commands.begin(), setup.commands.end(), - [](const std::string& s) { return s.find("go ") == 0; }); + const auto numGoCommands = count_if(setup.commands.begin(), setup.commands.end(), + [](const std::string& s) { return s.find("go ") == 0; }); TimePoint totalTime = 0; @@ -361,13 +361,14 @@ void UCIEngine::benchmark(std::istream& args) { int numHashfullReadings = 0; constexpr int hashfullAges[] = {0, 999}; // Only normal hashfull and touched hash. - int totalHashfull[std::size(hashfullAges)] = {0}; - int maxHashfull[std::size(hashfullAges)] = {0}; + constexpr int hashfullAgeCount = std::size(hashfullAges); + int totalHashfull[hashfullAgeCount] = {0}; + int maxHashfull[hashfullAgeCount] = {0}; auto updateHashfullReadings = [&]() { numHashfullReadings += 1; - for (int i = 0; i < static_cast(std::size(hashfullAges)); ++i) + for (int i = 0; i < hashfullAgeCount; ++i) { const int hashfull = engine.get_hashfull(hashfullAges[i]); maxHashfull[i] = std::max(maxHashfull[i], hashfull); @@ -554,7 +555,7 @@ int UCIEngine::to_cp(Value v, const Position& pos) { auto [a, b] = win_rate_params(pos); - return std::round(100 * int(v) / a); + return int(std::round(100 * int(v) / a)); } std::string UCIEngine::wdl(Value v, const Position& pos) { From e0e6fdf094d7b34750f99d3603943349ab7a57e9 Mon Sep 17 00:00:00 2001 From: Timothy Herchen Date: Tue, 2 Dec 2025 21:48:50 -0800 Subject: [PATCH 07/13] Tweak nnue_accumulator indexing ``` LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 92736 W: 24149 L: 23764 D: 44823 Ptnml(0-2): 280, 10056, 25334, 10395, 303 ``` The use of `IndexType` in the loops is suboptimal because it requires truncation to 32 bits, and thereby defeats some optimizations. Using `size_t` for the loop body works nicely, and a signed index into the index lists allows the compiler to assume the case `added.size() == UINT_MAX`, which would be an infinite loop, to not happen. Passed STC https://tests.stockfishchess.org/tests/live_elo/692fd98ab23dfeae38d01d98 closes https://github.com/official-stockfish/Stockfish/pull/6466 No functional change --- src/misc.h | 1 + src/nnue/nnue_accumulator.cpp | 113 ++++++++++++++++++---------------- 2 files changed, 62 insertions(+), 52 deletions(-) diff --git a/src/misc.h b/src/misc.h index 32f5b047e..c9951e555 100644 --- a/src/misc.h +++ b/src/misc.h @@ -134,6 +134,7 @@ class ValueList { public: std::size_t size() const { return size_; } + int ssize() const { return int(size_); } void push_back(const T& value) { assert(size_ < MaxSize); values_[size_++] = value; diff --git a/src/nnue/nnue_accumulator.cpp b/src/nnue/nnue_accumulator.cpp index 358a4b278..763fb7a5e 100644 --- a/src/nnue/nnue_accumulator.cpp +++ b/src/nnue/nnue_accumulator.cpp @@ -360,6 +360,8 @@ struct AccumulatorUpdateContext { vec_t acc[Tiling::NumRegs]; psqt_vec_t psqt[Tiling::NumPsqtRegs]; + const auto* threatWeights = &featureTransformer.threatWeights[0]; + for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) { auto* fromTile = reinterpret_cast(&fromAcc[j * Tiling::TileHeight]); @@ -368,12 +370,11 @@ struct AccumulatorUpdateContext { for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = fromTile[k]; - for (IndexType i = 0; i < removed.size(); ++i) + for (int i = 0; i < removed.ssize(); ++i) { - IndexType index = removed[i]; - const IndexType offset = Dimensions * index + j * Tiling::TileHeight; - auto* column = - reinterpret_cast(&featureTransformer.threatWeights[offset]); + size_t index = removed[i]; + const size_t offset = Dimensions * index; + auto* column = reinterpret_cast(&threatWeights[offset]); #ifdef USE_NEON for (IndexType k = 0; k < Tiling::NumRegs; k += 2) @@ -387,12 +388,11 @@ struct AccumulatorUpdateContext { #endif } - for (IndexType i = 0; i < added.size(); ++i) + for (int i = 0; i < added.ssize(); ++i) { - IndexType index = added[i]; - const IndexType offset = Dimensions * index + j * Tiling::TileHeight; - auto* column = - reinterpret_cast(&featureTransformer.threatWeights[offset]); + size_t index = added[i]; + const size_t offset = Dimensions * index; + auto* column = reinterpret_cast(&threatWeights[offset]); #ifdef USE_NEON for (IndexType k = 0; k < Tiling::NumRegs; k += 2) @@ -408,6 +408,8 @@ struct AccumulatorUpdateContext { for (IndexType k = 0; k < Tiling::NumRegs; k++) vec_store(&toTile[k], acc[k]); + + threatWeights += Tiling::TileHeight; } for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) @@ -420,22 +422,22 @@ struct AccumulatorUpdateContext { for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = fromTilePsqt[k]; - for (IndexType i = 0; i < removed.size(); ++i) + for (int i = 0; i < removed.ssize(); ++i) { - IndexType index = removed[i]; - const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; - auto* columnPsqt = reinterpret_cast( + size_t index = removed[i]; + const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast( &featureTransformer.threatPsqtWeights[offset]); for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]); } - for (IndexType i = 0; i < added.size(); ++i) + for (int i = 0; i < added.ssize(); ++i) { - IndexType index = added[i]; - const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; - auto* columnPsqt = reinterpret_cast( + size_t index = added[i]; + const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast( &featureTransformer.threatPsqtWeights[offset]); for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) @@ -691,6 +693,8 @@ void update_accumulator_refresh_cache(Color pers vec_t acc[Tiling::NumRegs]; psqt_vec_t psqt[Tiling::NumPsqtRegs]; + const auto* weights = &featureTransformer.weights[0]; + for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) { auto* accTile = @@ -700,33 +704,33 @@ void update_accumulator_refresh_cache(Color pers for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = entryTile[k]; - IndexType i = 0; - for (; i < std::min(removed.size(), added.size()); ++i) + int i = 0; + for (; i < std::min(removed.ssize(), added.ssize()); ++i) { - IndexType indexR = removed[i]; - const IndexType offsetR = Dimensions * indexR + j * Tiling::TileHeight; - auto* columnR = reinterpret_cast(&featureTransformer.weights[offsetR]); - IndexType indexA = added[i]; - const IndexType offsetA = Dimensions * indexA + j * Tiling::TileHeight; - auto* columnA = reinterpret_cast(&featureTransformer.weights[offsetA]); + size_t indexR = removed[i]; + const size_t offsetR = Dimensions * indexR; + auto* columnR = reinterpret_cast(&weights[offsetR]); + size_t indexA = added[i]; + const size_t offsetA = Dimensions * indexA; + auto* columnA = reinterpret_cast(&weights[offsetA]); for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = fused(acc[k], columnA[k], columnR[k]); } - for (; i < removed.size(); ++i) + for (; i < removed.ssize(); ++i) { - IndexType index = removed[i]; - const IndexType offset = Dimensions * index + j * Tiling::TileHeight; - auto* column = reinterpret_cast(&featureTransformer.weights[offset]); + size_t index = removed[i]; + const size_t offset = Dimensions * index; + auto* column = reinterpret_cast(&weights[offset]); for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = vec_sub_16(acc[k], column[k]); } - for (; i < added.size(); ++i) + for (; i < added.ssize(); ++i) { - IndexType index = added[i]; - const IndexType offset = Dimensions * index + j * Tiling::TileHeight; - auto* column = reinterpret_cast(&featureTransformer.weights[offset]); + size_t index = added[i]; + const size_t offset = Dimensions * index; + auto* column = reinterpret_cast(&weights[offset]); for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = vec_add_16(acc[k], column[k]); @@ -736,6 +740,8 @@ void update_accumulator_refresh_cache(Color pers vec_store(&entryTile[k], acc[k]); for (IndexType k = 0; k < Tiling::NumRegs; k++) vec_store(&accTile[k], acc[k]); + + weights += Tiling::TileHeight; } for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) @@ -748,21 +754,21 @@ void update_accumulator_refresh_cache(Color pers for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = entryTilePsqt[k]; - for (IndexType i = 0; i < removed.size(); ++i) + for (int i = 0; i < removed.ssize(); ++i) { - IndexType index = removed[i]; - const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; - auto* columnPsqt = + size_t index = removed[i]; + const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast(&featureTransformer.psqtWeights[offset]); for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]); } - for (IndexType i = 0; i < added.size(); ++i) + for (int i = 0; i < added.ssize(); ++i) { - IndexType index = added[i]; - const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; - auto* columnPsqt = + size_t index = added[i]; + const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast(&featureTransformer.psqtWeights[offset]); for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) @@ -820,6 +826,8 @@ void update_threats_accumulator_full(Color persp vec_t acc[Tiling::NumRegs]; psqt_vec_t psqt[Tiling::NumPsqtRegs]; + const auto* threatWeights = &featureTransformer.threatWeights[0]; + for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) { auto* accTile = @@ -828,14 +836,13 @@ void update_threats_accumulator_full(Color persp for (IndexType k = 0; k < Tiling::NumRegs; ++k) acc[k] = vec_zero(); - IndexType i = 0; + int i = 0; - for (; i < active.size(); ++i) + for (; i < active.ssize(); ++i) { - IndexType index = active[i]; - const IndexType offset = Dimensions * index + j * Tiling::TileHeight; - auto* column = - reinterpret_cast(&featureTransformer.threatWeights[offset]); + size_t index = active[i]; + const size_t offset = Dimensions * index; + auto* column = reinterpret_cast(&threatWeights[offset]); #ifdef USE_NEON for (IndexType k = 0; k < Tiling::NumRegs; k += 2) @@ -851,6 +858,8 @@ void update_threats_accumulator_full(Color persp for (IndexType k = 0; k < Tiling::NumRegs; k++) vec_store(&accTile[k], acc[k]); + + threatWeights += Tiling::TileHeight; } for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) @@ -861,11 +870,11 @@ void update_threats_accumulator_full(Color persp for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k) psqt[k] = vec_zero_psqt(); - for (IndexType i = 0; i < active.size(); ++i) + for (int i = 0; i < active.ssize(); ++i) { - IndexType index = active[i]; - const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; - auto* columnPsqt = + size_t index = active[i]; + const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; + auto* columnPsqt = reinterpret_cast(&featureTransformer.threatPsqtWeights[offset]); for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) From 955c927265c36396d6519a57b3d1e81a5c700420 Mon Sep 17 00:00:00 2001 From: Pieter te Brake Date: Mon, 8 Dec 2025 22:46:07 +0100 Subject: [PATCH 08/13] Removed redundant board updates Contrary to what the comment says, `remove_piece` does in fact set the relevant `board` elements to `NO_PIECE`. closes https://github.com/official-stockfish/Stockfish/pull/6471 No functional change --- src/position.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index cd778011f..a4286b86a 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1225,8 +1225,6 @@ void Position::do_castling(Color us, // Remove both pieces first since squares could overlap in Chess960 remove_piece(Do ? from : to, dts); remove_piece(Do ? rfrom : rto, dts); - board[Do ? from : to] = board[Do ? rfrom : rto] = - NO_PIECE; // remove_piece does not do this for us put_piece(make_piece(us, KING), Do ? to : from, dts); put_piece(make_piece(us, ROOK), Do ? rto : rfrom, dts); } From d92e6b458aa92f884862f28e89d0792203385dfd Mon Sep 17 00:00:00 2001 From: ppigazzini Date: Wed, 10 Dec 2025 15:15:28 +0100 Subject: [PATCH 09/13] chore(ci): bump runner to macos-15 closes https://github.com/official-stockfish/Stockfish/pull/6475 No functional change --- .github/ci/matrix.json | 24 ++++++++++++------------ .github/workflows/tests.yml | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/ci/matrix.json b/.github/ci/matrix.json index f72451f5b..e9215269b 100644 --- a/.github/ci/matrix.json +++ b/.github/ci/matrix.json @@ -20,8 +20,8 @@ "archive_ext": "tar" }, { - "name": "macOS 14 Apple Clang M1", - "os": "macos-14", + "name": "macOS 15 Apple Clang M1", + "os": "macos-15", "simple_name": "macos-m1", "compiler": "clang++", "comp": "clang", @@ -71,49 +71,49 @@ { "binaries": "x86-64", "config": { - "os": "macos-14" + "os": "macos-15" } }, { "binaries": "x86-64-sse41-popcnt", "config": { - "os": "macos-14" + "os": "macos-15" } }, { "binaries": "x86-64-avx2", "config": { - "os": "macos-14" + "os": "macos-15" } }, { "binaries": "x86-64-bmi2", "config": { - "os": "macos-14" + "os": "macos-15" } }, { "binaries": "x86-64-avxvnni", "config": { - "os": "macos-14" + "os": "macos-15" } }, { "binaries": "x86-64-avx512", "config": { - "os": "macos-14" + "os": "macos-15" } }, { "binaries": "x86-64-vnni512", "config": { - "os": "macos-14" + "os": "macos-15" } }, { "binaries": "x86-64-avx512icl", "config": { - "os": "macos-14" + "os": "macos-15" } }, { @@ -245,7 +245,7 @@ { "binaries": "armv8", "config": { - "os": "macos-14" + "os": "macos-15" } }, { @@ -275,7 +275,7 @@ { "binaries": "armv8-dotprod", "config": { - "os": "macos-14" + "os": "macos-15" } } ] diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c2280f0b4..f0da51e7e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -62,8 +62,8 @@ jobs: comp: clang run_64bit_tests: true shell: bash - - name: macOS 14 Apple Clang M1 - os: macos-14 + - name: macOS 15 Apple Clang M1 + os: macos-15 compiler: clang++ comp: clang run_64bit_tests: false From b4b01d0ca27808a5219b069520b89274416bca31 Mon Sep 17 00:00:00 2001 From: Daniel Monroe Date: Thu, 4 Dec 2025 23:30:13 -0500 Subject: [PATCH 10/13] Remove rootDepth condition in newDepth clamping Passed simplification STC LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 132256 W: 34462 L: 34347 D: 63447 Ptnml(0-2): 470, 15625, 33833, 15720, 480 https://tests.stockfishchess.org/tests/view/69325fe0a24a6df719fcca16 Passed simplification LTC LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 128220 W: 32503 L: 32392 D: 63325 Ptnml(0-2): 94, 13900, 35982, 14069, 65 https://tests.stockfishchess.org/tests/view/6934c2b3a24a6df719fcdf1e closes https://github.com/official-stockfish/Stockfish/pull/6472 Bench: 2926903 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index c9d30ce30..64f85bcbe 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1269,7 +1269,7 @@ moves_loop: // When in check, search starts here // decisive score handling improves mate finding and retrograde analysis. if (move == ttData.move && ((is_valid(ttData.value) && is_decisive(ttData.value) && ttData.depth > 0) - || (ttData.depth > 1 && rootDepth > 8))) + || ttData.depth > 1)) newDepth = std::max(newDepth, 1); value = -search(pos, ss + 1, -beta, -alpha, newDepth, false); From 32292d1e622d964ea011ecb87b2b758d35965823 Mon Sep 17 00:00:00 2001 From: sscg13 Date: Tue, 16 Dec 2025 17:30:15 -0800 Subject: [PATCH 11/13] Represent threat weights directly as i8 LEB128 adds no additional compression and adds extra complexity to the code currently. closes https://github.com/official-stockfish/Stockfish/pull/6479 No functional change --- src/evaluate.h | 2 +- src/nnue/nnue_feature_transformer.h | 34 +++++++---------------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/evaluate.h b/src/evaluate.h index 853aeb5b2..8ed2eb994 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -33,7 +33,7 @@ namespace Eval { // for the build process (profile-build and fishtest) to work. Do not change the // name of the macro or the location where this macro is defined, as it is used // in the Makefile/Fishtest. -#define EvalFileDefaultNameBig "nn-2962dca31855.nnue" +#define EvalFileDefaultNameBig "nn-c288c895ea92.nnue" #define EvalFileDefaultNameSmall "nn-37f18f62d772.nnue" namespace NNUE { diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 091ae074d..ce23bdf0e 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -164,23 +164,13 @@ class FeatureTransformer { if (UseThreats) { - auto combinedWeights = - std::make_unique>(); + read_little_endian(stream, threatWeights.data(), + ThreatInputDimensions * HalfDimensions); + read_leb_128(stream, weights); + auto combinedPsqtWeights = std::make_unique>(); - read_leb_128(stream, *combinedWeights); - - std::transform(combinedWeights->begin(), - combinedWeights->begin() + ThreatInputDimensions * HalfDimensions, - std::begin(threatWeights), - [](WeightType w) { return static_cast(w); }); - - std::copy(combinedWeights->begin() + ThreatInputDimensions * HalfDimensions, - combinedWeights->begin() - + (ThreatInputDimensions + InputDimensions) * HalfDimensions, - std::begin(weights)); - read_leb_128(stream, *combinedPsqtWeights); std::copy(combinedPsqtWeights->begin(), @@ -219,21 +209,13 @@ class FeatureTransformer { if (UseThreats) { - auto combinedWeights = - std::make_unique>(); + write_little_endian(stream, copy->threatWeights.data(), + ThreatInputDimensions * HalfDimensions); + write_leb_128(stream, copy->weights); + auto combinedPsqtWeights = std::make_unique>(); - std::copy(std::begin(copy->threatWeights), - std::begin(copy->threatWeights) + ThreatInputDimensions * HalfDimensions, - combinedWeights->begin()); - - std::copy(std::begin(copy->weights), - std::begin(copy->weights) + InputDimensions * HalfDimensions, - combinedWeights->begin() + ThreatInputDimensions * HalfDimensions); - - write_leb_128(stream, *combinedWeights); - std::copy(std::begin(copy->threatPsqtWeights), std::begin(copy->threatPsqtWeights) + ThreatInputDimensions * PSQTBuckets, combinedPsqtWeights->begin()); From 495296fc76cc380b216d577710c15cd1efef1a41 Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Fri, 21 Nov 2025 23:25:03 -0800 Subject: [PATCH 12/13] Remove Secondary TT Aging Passed VVLTC w/ STC Bounds: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 107006 W: 27676 L: 27326 D: 52004 Ptnml(0-2): 21, 9505, 34097, 9863, 17 https://tests.stockfishchess.org/tests/view/6939ac5b75b70713ef796f11 Passed VVLTC w/ LTC Bounds: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 263190 W: 67547 L: 66837 D: 128806 Ptnml(0-2): 32, 23939, 82942, 24651, 31 https://tests.stockfishchess.org/tests/view/692165823b03dd3a060e666d closes https://github.com/official-stockfish/Stockfish/pull/6480 Bench: 2800411 --- src/tt.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tt.cpp b/src/tt.cpp index 953348987..d7f7dbdef 100644 --- a/src/tt.cpp +++ b/src/tt.cpp @@ -110,8 +110,6 @@ void TTEntry::save( value16 = int16_t(v); eval16 = int16_t(ev); } - else if (depth8 + DEPTH_ENTRY_OFFSET >= 5 && Bound(genBound8 & 0x3) != BOUND_EXACT) - depth8--; } From c467fe5ba42545827d769c360aa404767308ac18 Mon Sep 17 00:00:00 2001 From: AliceRoselia <63040919+AliceRoselia@users.noreply.github.com> Date: Sun, 14 Dec 2025 14:14:27 +0700 Subject: [PATCH 13/13] Simplify futility pruning Passed non regression STC: https://tests.stockfishchess.org/tests/view/693e642c46f342e1ec20f68d LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 107968 W: 28080 L: 27937 D: 51951 Ptnml(0-2): 381, 12708, 27626, 12925, 344 Passed non regression LTC: https://tests.stockfishchess.org/tests/view/693ff10c46f342e1ec20fa6a LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 334266 W: 85271 L: 85370 D: 163625 Ptnml(0-2): 179, 36395, 94086, 36292, 181 closes https://github.com/official-stockfish/Stockfish/pull/6484 Bench: 2987379 --- src/search.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 64f85bcbe..adb7985d2 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -868,9 +868,8 @@ Value Search::Worker::search( auto futility_margin = [&](Depth d) { Value futilityMult = 76 - 23 * !ss->ttHit; - return futilityMult * d // - - 2474 * improving * futilityMult / 1024 // - - 331 * opponentWorsening * futilityMult / 1024 // + return futilityMult * d + - (2474 * improving + 331 * opponentWorsening) * futilityMult / 1024 // + std::abs(correctionValue) / 174665; };