#include <algorithm>
#include "bitboard.h"
-#include "bitcount.h"
#include "misc.h"
+uint8_t PopCnt16[1 << 16];
int SquareDistance[SQUARE_NB][SQUARE_NB];
Bitboard RookMasks [SQUARE_NB];
return Is64Bit ? (b * DeBruijn64) >> 58
: ((unsigned(b) ^ unsigned(b >> 32)) * DeBruijn32) >> 26;
}
+
+
+ // popcount16() counts the non-zero bits using SWAR-Popcount algorithm
+
+ uint8_t popcount16(uint16_t u) {
+ u -= (u >> 1) & 0x5555U;
+ u = ((u >> 2) & 0x3333U) + (u & 0x3333U);
+ u = ((u >> 4) + u) & 0x0F0FU;
+ return (u * 0x0101U) >> 8;
+ }
}
#ifdef NO_BSF
void Bitboards::init() {
+ for (unsigned i = 0; i < (1 << 16); ++i)
+ PopCnt16[i] = popcount16(i);
+
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
SquareBB[s] = 1ULL << s;
// the number of 1s of the mask. Hence we deduce the size of the shift to
// apply to the 64 or 32 bits word to get the index.
masks[s] = sliding_attack(deltas, s, 0) & ~edges;
- shifts[s] = (Is64Bit ? 64 : 32) - popcount<Max15>(masks[s]);
+ shifts[s] = (Is64Bit ? 64 : 32) - popcount(masks[s]);
// Use Carry-Rippler trick to enumerate all subsets of masks[s] and
// store the corresponding sliding attack bitboard in reference[].
do {
do
magics[s] = rng.sparse_rand<Bitboard>();
- while (popcount<Max15>((magics[s] * masks[s]) >> 56) < 6);
+ while (popcount((magics[s] * masks[s]) >> 56) < 6);
// A good magic must map every possible occupancy to an index that
// looks up the correct sliding attack in the attacks[s] database.
}
+/// popcount() counts the number of non-zero bits in a bitboard
+
+inline int popcount(Bitboard b) {
+
+#ifndef USE_POPCNT
+
+ extern uint8_t PopCnt16[1 << 16];
+ union { Bitboard bb; uint16_t u[4]; } v = { b };
+ return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
+
+#elif defined(_MSC_VER) && defined(__INTEL_COMPILER)
+
+ return _mm_popcnt_u64(b);
+
+#elif defined(_MSC_VER)
+
+ return (int)__popcnt64(b);
+
+#else // Assumed gcc or compatible compiler
+
+ return __builtin_popcountll(b);
+
+#endif
+}
+
+
/// lsb() and msb() return the least/most significant bit in a non-zero bitboard
#if defined(__GNUC__)
+++ /dev/null
-/*
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
-
- Stockfish is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Stockfish is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef BITCOUNT_H_INCLUDED
-#define BITCOUNT_H_INCLUDED
-
-#include <cassert>
-
-#include "types.h"
-
-enum BitCountType {
- CNT_64,
- CNT_64_MAX15,
- CNT_32,
- CNT_32_MAX15,
- CNT_HW_POPCNT
-};
-
-/// Determine at compile time the best popcount<> specialization according to
-/// whether the platform is 32 or 64 bit, the maximum number of non-zero
-/// bits to count and if the hardware popcnt instruction is available.
-const BitCountType Full = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64 : CNT_32;
-const BitCountType Max15 = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64_MAX15 : CNT_32_MAX15;
-
-
-/// popcount() counts the number of non-zero bits in a bitboard
-template<BitCountType> inline int popcount(Bitboard);
-
-template<>
-inline int popcount<CNT_64>(Bitboard b) {
- b -= (b >> 1) & 0x5555555555555555ULL;
- b = ((b >> 2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
- b = ((b >> 4) + b) & 0x0F0F0F0F0F0F0F0FULL;
- return (b * 0x0101010101010101ULL) >> 56;
-}
-
-template<>
-inline int popcount<CNT_64_MAX15>(Bitboard b) {
- b -= (b >> 1) & 0x5555555555555555ULL;
- b = ((b >> 2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
- return (b * 0x1111111111111111ULL) >> 60;
-}
-
-template<>
-inline int popcount<CNT_32>(Bitboard b) {
- unsigned w = unsigned(b >> 32), v = unsigned(b);
- v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
- w -= (w >> 1) & 0x55555555;
- v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
- w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
- v = ((v >> 4) + v + (w >> 4) + w) & 0x0F0F0F0F;
- return (v * 0x01010101) >> 24;
-}
-
-template<>
-inline int popcount<CNT_32_MAX15>(Bitboard b) {
- unsigned w = unsigned(b >> 32), v = unsigned(b);
- v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
- w -= (w >> 1) & 0x55555555;
- v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
- w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
- return ((v + w) * 0x11111111) >> 28;
-}
-
-template<>
-inline int popcount<CNT_HW_POPCNT>(Bitboard b) {
-
-#ifndef USE_POPCNT
-
- assert(false);
- return b != 0; // Avoid 'b not used' warning
-
-#elif defined(_MSC_VER) && defined(__INTEL_COMPILER)
-
- return _mm_popcnt_u64(b);
-
-#elif defined(_MSC_VER)
-
- return (int)__popcnt64(b);
-
-#else // Assumed gcc or compatible compiler
-
- return __builtin_popcountll(b);
-
-#endif
-}
-
-#endif // #ifndef BITCOUNT_H_INCLUDED
#include <cassert>
#include "bitboard.h"
-#include "bitcount.h"
#include "endgame.h"
#include "movegen.h"
#include <iomanip>
#include <sstream>
-#include "bitcount.h"
+#include "bitboard.h"
#include "evaluate.h"
#include "material.h"
#include "pawns.h"
{
ei.kingRing[Them] = b | shift_bb<Down>(b);
b &= ei.attackedBy[Us][PAWN];
- ei.kingAttackersCount[Us] = b ? popcount<Max15>(b) : 0;
+ ei.kingAttackersCount[Us] = b ? popcount(b) : 0;
ei.kingAdjacentZoneAttacksCount[Us] = ei.kingAttackersWeight[Us] = 0;
}
else
ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
bb = b & ei.attackedBy[Them][KING];
if (bb)
- ei.kingAdjacentZoneAttacksCount[Us] += popcount<Max15>(bb);
+ ei.kingAdjacentZoneAttacksCount[Us] += popcount(bb);
}
if (Pt == QUEEN)
| ei.attackedBy[Them][BISHOP]
| ei.attackedBy[Them][ROOK]);
- int mob = popcount<Pt == QUEEN ? Full : Max15>(b & mobilityArea[Us]);
+ int mob = popcount(b & mobilityArea[Us]);
mobility[Us] += MobilityBonus[Pt][mob];
{
Bitboard alignedPawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s];
if (alignedPawns)
- score += RookOnPawn * popcount<Max15>(alignedPawns);
+ score += RookOnPawn * popcount(alignedPawns);
}
// Bonus when on an open or semi-open file
// the pawn shelter (current 'score' value).
attackUnits = std::min(72, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
+ 9 * ei.kingAdjacentZoneAttacksCount[Them]
- + 27 * popcount<Max15>(undefended)
+ + 27 * popcount(undefended)
+ 11 * !!ei.pinnedPieces[Us]
- 64 * !pos.count<QUEEN>(Them)
- mg_value(score) / 8;
| ei.attackedBy[Them][KING];
if (b)
- attackUnits += QueenContactCheck * popcount<Max15>(b);
+ attackUnits += QueenContactCheck * popcount(b);
}
// Analyse the enemy's safe distance checks for sliders and knights
b = weak & ~ei.attackedBy[Them][ALL_PIECES];
if (b)
- score += Hanging * popcount<Max15>(b);
+ score += Hanging * popcount(b);
b = weak & ei.attackedBy[Us][KING];
if (b)
& ~ei.attackedBy[Us][PAWN];
if (b)
- score += ThreatByPawnPush * popcount<Max15>(b);
+ score += ThreatByPawnPush * popcount(b);
if (DoTrace)
Trace::add(THREAT, Us, score);
assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0);
// ...count safe + (behind & safe) with a single popcount
- int bonus = popcount<Full>((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
+ int bonus = popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
int weight = pos.count<KNIGHT>(Us) + pos.count<BISHOP>(Us)
+ pos.count<KNIGHT>(Them) + pos.count<BISHOP>(Them);
#include <cassert>
#include "bitboard.h"
-#include "bitcount.h"
#include "pawns.h"
#include "position.h"
#include "thread.h"
e->kingSquares[Us] = SQ_NONE;
e->semiopenFiles[Us] = 0xFF;
e->pawnAttacks[Us] = shift_bb<Right>(ourPawns) | shift_bb<Left>(ourPawns);
- e->pawnsOnSquares[Us][BLACK] = popcount<Max15>(ourPawns & DarkSquares);
+ e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares);
e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK];
// Loop through all pawns of the current color and score each pawn
e->key = key;
e->score = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e);
- e->asymmetry = popcount<Max15>(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]);
+ e->asymmetry = popcount(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]);
return e;
}
#include <iomanip>
#include <sstream>
-#include "bitcount.h"
+#include "bitboard.h"
#include "misc.h"
#include "movegen.h"
#include "position.h"
for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
{
- if (pieceCount[c][pt] != popcount<Full>(pieces(c, pt)))
+ if (pieceCount[c][pt] != popcount(pieces(c, pt)))
return false;
for (int i = 0; i < pieceCount[c][pt]; ++i)
#include "../movegen.h"
#include "../bitboard.h"
#include "../search.h"
-#include "../bitcount.h"
#include "tbprobe.h"
#include "tbcore.h"
color = !mirror ? WHITE : BLACK;
for (pt = KING; pt >= PAWN; --pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
*str++ = pchr[6 - pt];
*str++ = 'v';
color = ~color;
for (pt = KING; pt >= PAWN; --pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
*str++ = pchr[6 - pt];
*str++ = 0;
}
color = !mirror ? WHITE : BLACK;
for (pt = PAWN; pt <= KING; ++pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
key ^= Zobrist::psq[WHITE][pt][i - 1];
color = ~color;
for (pt = PAWN; pt <= KING; ++pt)
- for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
+ for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
key ^= Zobrist::psq[BLACK][pt][i - 1];
return key;