summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
fae5727)
Use operator const T&() instead of operator T() to avoid possible
costly hidden copies of non-scalar nested types.
Currently StatsEntry has a single member T, so assuming
sizeof(StatsEntry) == sizeof(T) it happens to work, but it's
better to use the size of the proper entry type in std::fill.
Note that current code works because std::array items are ensured
to be allocated in contiguous memory and there is no padding among
nested arrays. The latter condition does not seem to be strictly
enforced by the standard, so be careful here.
Finally use address-of operator instead of get() to fully hide the
wrapper class StatsEntry at calling sites. For completness add
the arrow operator too and simplify the C++ code a bit more.
Same binary code as previous master under the Clang compiler.
No functional change.
template<typename T, int D>
class StatsEntry {
template<typename T, int D>
class StatsEntry {
- static const bool IsInt = std::is_integral<T>::value;
- typedef typename std::conditional<IsInt, int, T>::type TT;
-
- T* get() { return &entry; }
void operator=(const T& v) { entry = v; }
void operator=(const T& v) { entry = v; }
- operator TT() const { return entry; }
+ T* operator&() { return &entry; }
+ T* operator->() { return &entry; }
+ operator const T&() const { return entry; }
void operator<<(int bonus) {
void operator<<(int bonus) {
- assert(abs(bonus) <= D); // Ensure range is [-D, D]
+ assert(abs(bonus) <= D); // Ensure range is [-D, D]
static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
entry += bonus - entry * abs(bonus) / D;
static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
entry += bonus - entry * abs(bonus) / D;
template <typename T, int D, int Size, int... Sizes>
struct Stats : public std::array<Stats<T, D, Sizes...>, Size>
{
template <typename T, int D, int Size, int... Sizes>
struct Stats : public std::array<Stats<T, D, Sizes...>, Size>
{
- T* get() { return this->at(0).get(); }
+ typedef Stats<T, D, Size, Sizes...> stats;
- T* p = get();
- std::fill(p, p + sizeof(*this) / sizeof(*p), v);
+
+ // For standard-layout 'this' points to first struct member
+ assert(std::is_standard_layout<stats>::value);
+
+ typedef StatsEntry<T, D> entry;
+ entry* p = reinterpret_cast<entry*>(this);
+ std::fill(p, p + sizeof(*this) / sizeof(entry), v);
}
};
template <typename T, int D, int Size>
}
};
template <typename T, int D, int Size>
-struct Stats<T, D, Size> : public std::array<StatsEntry<T, D>, Size> {
- T* get() { return this->at(0).get(); }
-};
+struct Stats<T, D, Size> : public std::array<StatsEntry<T, D>, Size> {};
/// In stats table, D=0 means that the template parameter is not used
enum StatsParams { NOT_USED = 0 };
/// In stats table, D=0 means that the template parameter is not used
enum StatsParams { NOT_USED = 0 };
std::memset(ss-4, 0, 7 * sizeof(Stack));
for (int i = 4; i > 0; i--)
std::memset(ss-4, 0, 7 * sizeof(Stack));
for (int i = 4; i > 0; i--)
- (ss-i)->continuationHistory = this->continuationHistory[NO_PIECE][0].get(); // Use as sentinel
+ (ss-i)->continuationHistory = &this->continuationHistory[NO_PIECE][0]; // Use as sentinel
bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
(ss+1)->ply = ss->ply + 1;
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
(ss+1)->ply = ss->ply + 1;
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
- ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get();
+ ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
Square prevSq = to_sq((ss-1)->currentMove);
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
Square prevSq = to_sq((ss-1)->currentMove);
Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
ss->currentMove = MOVE_NULL;
Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
ss->currentMove = MOVE_NULL;
- ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get();
+ ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
probCutCount++;
ss->currentMove = move;
probCutCount++;
ss->currentMove = move;
- ss->continuationHistory = thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)].get();
+ ss->continuationHistory = &thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)];
assert(depth >= 5 * ONE_PLY);
assert(depth >= 5 * ONE_PLY);
// Update the current move (this must be done after singular extension search)
ss->currentMove = move;
// Update the current move (this must be done after singular extension search)
ss->currentMove = move;
- ss->continuationHistory = thisThread->continuationHistory[movedPiece][to_sq(move)].get();
+ ss->continuationHistory = &thisThread->continuationHistory[movedPiece][to_sq(move)];
// Step 15. Make the move
pos.do_move(move, st, givesCheck);
// Step 15. Make the move
pos.do_move(move, st, givesCheck);
Thread* thisThread = pos.this_thread();
(ss+1)->ply = ss->ply + 1;
ss->currentMove = bestMove = MOVE_NONE;
Thread* thisThread = pos.this_thread();
(ss+1)->ply = ss->ply + 1;
ss->currentMove = bestMove = MOVE_NONE;
- ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get();
+ ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
inCheck = pos.checkers();
moveCount = 0;
inCheck = pos.checkers();
moveCount = 0;
}
ss->currentMove = move;
}
ss->currentMove = move;
- ss->continuationHistory = thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)].get();
+ ss->continuationHistory = &thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)];
// Make and search the move
pos.do_move(move, st, givesCheck);
// Make and search the move
pos.do_move(move, st, givesCheck);
for (auto& to : continuationHistory)
for (auto& h : to)
for (auto& to : continuationHistory)
for (auto& h : to)
- continuationHistory[NO_PIECE][0].get()->fill(Search::CounterMovePruneThreshold - 1);
+ continuationHistory[NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
}
/// Thread::start_searching() wakes up the thread that will start the search
}
/// Thread::start_searching() wakes up the thread that will start the search