Moderator: Andres Valverde
Heurist wrote:The bitset class template looks convenient for a lot of reasons, but I've only seen it mentioned once or twice in passing with regard to chess programming. Is there some horrible problem with the class I should be aware of?
I haven't run any tests on the bitwise operator speeds, but sizeof(bitset<64>) returns 8, so it's not exactly a memory hog.
I originally asked this over at the chess-engines group, but this place seems much more lively.
Thanks
#ifndef INCLUDE_CBITBOARD_HPP_
#define INCLUDE_CBITBOARD_HPP_
#include "ui64.hpp"
#include "Constantes.hpp"
#include "OutilsDeDebugage.hpp"
#include <iostream>
namespace MatMoi
{
////////////////////////////////////////////////////////////////////////////
/// <summary>Repr?sente un bitboard.</summary>
/// <remarks>
/// Cette classe d?finit un Bitboard. Essentiellement la classe est un
/// ?wrapper? pour un entier de 64 bits, mais elle contient quelques
/// fonctions sp?ciales.
/// </remarks>
////////////////////////////////////////////////////////////////////////////
class CBitboard
{
friend std::ostream& operator<<(std::ostream& out, const CBitboard& bitboard);
// L'entier de 64 bits
ui64 m_ui64;
public:
/////////////////////////////////////////////////////////////////////////
/// <summary>Constructeur ? partir d'un ui64</summary>
/// <param name="valeur">
/// Entier de 64 bits, valeur de d?part de l'objet</param>
/////////////////////////////////////////////////////////////////////////
inline CBitboard(ui64 valeur = 0)
{
m_ui64 = valeur;
};
/////////////////////////////////////////////////////////////////////////
/// <summary>Surcharge de l'op?rateur =</summary>
/// <remarks>
/// Cette surcharge de l'op?rateur ?gale permet d'affecter des ui64 ? un
/// CBitboard. Cette surcharge ainsi que celle de l'op?rateur de cast en
/// ui64 permet d'utiliser un objet CBitboard comme s'il s'agissait d'un
/// ui64.
/// </remarks>
/// <param name="valeur">
/// Entier de 64 bits a affecter ? l'objet</param>
/// <returns>
/// Une r?f?rence ? l'objet en cours. Permet les affectations en cascades
/// </returns>
/////////////////////////////////////////////////////////////////////////
inline CBitboard& operator=(ui64 valeur)
{
m_ui64 = valeur;
return *this;
};
/////////////////////////////////////////////////////////////////////////
/// <summary>Surcharge de l'op?rateur de cast en ui64.</summary>
/// <remarks>
/// Cette surcharge permet de transformer automatiquement l'objet en ui64.
/// De cette fa?on il est possible d'utiliser les op?rateur standards de
/// l'ui64 sur les objets de type CBitboard.
/// </remarks>
/////////////////////////////////////////////////////////////////////////
inline operator ui64() const
{
return m_ui64;
};
/////////////////////////////////////////////////////////////////////////
/// <summary>Retourne le bit le moin significatif ? 1.</summary>
/// <remarks>
/// Cette fonction retourne le bit le moin significatif qui est ? 1.
/// </remarks>
/// <returns>La position du bit.</returns>
/////////////////////////////////////////////////////////////////////////
inline unsigned int GetLSB() const
{
return BitSearch(m_ui64);
};
/////////////////////////////////////////////////////////////////////////
/// <summary>Retourne le bit le plus significatif ? 1.</summary>
/// <remarks>
/// Cette fonction retourne le bit le plus significatif qui est ? 1.
/// </remarks>
/// <returns>La position du bit.</returns>
/////////////////////////////////////////////////////////////////////////
//unsigned int GetMSB();
/////////////////////////////////////////////////////////////////////////
/// <summary>Retire et retourne le bit le moin significatif ? 1.</summary>
/// <remarks>
/// Cette fonction met ? z?ro le bit le moin significatif ? 1 et retourne
/// la position qu'il avait.
/// </remarks>
/// <returns>La position du bit.</returns>
/////////////////////////////////////////////////////////////////////////
inline unsigned int RemoveLSB()
{
return BitSearchAndReset(m_ui64);
};
/////////////////////////////////////////////////////////////////////////
/// <summary>Retire et retourne le bit le plus significatif ? 1.</summary>
/// <remarks>
/// Cette fonction met ? z?ro le bit le plus significatif ? 1 et retourne
/// la position qu'il avait.
/// </remarks>
/// <returns>La position du bit.</returns>
/////////////////////////////////////////////////////////////////////////
//unsigned int RemoveMSB();
/////////////////////////////////////////////////////////////////////////
/// <summary>Retourne le nombre de bit ? 1.</summary>
/// <returns>Le nombre de bits ? 1.</returns>
/////////////////////////////////////////////////////////////////////////
inline int GetPopCount() const
{
return BitCount(m_ui64);
};
/////////////////////////////////////////////////////////////////////////
/// <summary>
/// Met le bit dont la position est pass?e en param?tre ? 1.</summary>
/// <param name="uiPosition">
/// Position du bit ? mettre ? 1.</param>
/////////////////////////////////////////////////////////////////////////
void SetBit(unsigned int uiPosition)
{
Assertion(uiPosition <= 63);
m_ui64 = m_ui64 | gbitPositions[uiPosition];
};
/////////////////////////////////////////////////////////////////////////
/// <summary>
/// Met le bit dont la position est pass?e en param?tre ? 0.</summary>
/// <param name="uiPosition">
/// Position du bit ? mettre ? 0.</param>
/////////////////////////////////////////////////////////////////////////
void UnsetBit(unsigned int uiPosition)
{
Assertion(uiPosition <= 63);
m_ui64 = m_ui64 & (~gbitPositions[uiPosition]);
};
/////////////////////////////////////////////////////////////////////////
/// <summary>Retourne l'?tat d'un bit.</summary>
/// <remarks>
/// Cette fonction retourne l'?tat du bit dont la position est pass? en
/// param?tre.
/// </remarks>
/// <param name="uiPosition">
/// Position du bit dont on veut connaitre l'?tat.</param>
/// <returns>Vrai si le bit est ? 1. Faux sinon.</returns>
/////////////////////////////////////////////////////////////////////////
bool GetBit(unsigned int uiPosition) const
{
Assertion(uiPosition <= 63);
return (m_ui64 & gbitPositions[uiPosition]) != 0;
};
/////////////////////////////////////////////////////////////////////////
/// <summary>Change l'?tat d'un bit.</summary>
/// <remarks>
/// Cette fonction change l'?tat du bit dont la position est pass? en
/// param?tre.
/// </remarks>
/// <param name="uiPosition">
/// Position du bit dont on veut changer l'?tat</param>
/////////////////////////////////////////////////////////////////////////
void SwitchBit(unsigned int uiPosition)
{
Assertion(uiPosition <= 63);
m_ui64 = m_ui64 ^ gbitPositions[uiPosition];
};
};
////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Affiche un CBitboard sur le flux dans un format binaire.</summary>
/// <remarks>
/// Cette fonction affiche l'?tat du bitboard sur le flux de sortie pass?e
/// en param?tre dans un format binaire. Par example :
/// <c>
/// - - X - - - - -
/// X X - X - X - X
/// - X X X - X X X
/// X X X - X - X X
/// X X - - X - - X
/// - X - X X - - X
/// - X - X - - X -
/// X - - - X - - X
/// </c>
/// </remarks>
/// <param name="out">
/// Flux de sortie sur lequel on doit afficher le Bitboard.</param>
/// <param name="bitboard">
/// Le CBitboard ? afficher</param>
/// <returns>
/// Une r?f?rence vers le flux de sortie pass? en param?tre.</returns>
////////////////////////////////////////////////////////////////////////////
std::ostream& operator<<(std::ostream& out, const CBitboard& bitboard);
} // namespace MatMoi
#endif // INCLUDE_CBITBOARD_HPP_
#include "CBitboard.hpp"
#include <iostream>
namespace MatMoi
{
std::ostream& operator<<(std::ostream& out, const CBitboard& bitboard)
{
unsigned int i;
unsigned int j;
for (i = 0; i < 64; i+=8)
{
out <<'\t';
for (j = 0; j < 8; j++)
{
if (bitboard.GetBit(i+j))
{
out <<'X' <<' ';
}
else
{
out <<'-' <<' ';
}
}
out <<std::endl;
}
return out;
}
} // namespace MatMoi
#ifndef INCLUDE_UI64_HPP_
#define INCLUDE_UI64_HPP_
#include "Configuration.hpp"
namespace MatMoi
{
// On d?finit le type ui64
#if defined(_MSC_VER)
typedef unsigned __int64 ui64;
# define ULL(x) x##ui64
#else
typedef unsigned long long ui64;
# define ULL(x) x##ll
#endif
////////////////////////////////////////////////////////////////////////////
// Les fonctions suivantes (BitCount, BitSearchAndReset et BitSearch) sont
// copi? d'un message de Gerd Isenberg sur le Computer Chess Club.
// http://chessprogramming.org/cccsearch/ccc.php?art_id=236134
////////////////////////////////////////////////////////////////////////////
#define LOWBOARD(bb) (*((unsigned int*)&(bb)))
#define HIGHBOARD(bb) (*(((unsigned int*)&(bb))+1))
inline int BitCount (ui64 bb)
#if defined(_M_IX86) && UTILISER_ASSEMBLEUR == ON
{
__asm
{
mov ecx, dword ptr bb
xor eax, eax
test ecx, ecx
jz l1
l0: lea edx, [ecx-1]
inc eax
and ecx, edx
jnz l0
l1: mov ecx, dword ptr bb+4
test ecx, ecx
jz l3
l2: lea edx, [ecx-1]
inc eax
and ecx, edx
jnz l2
l3:
}
}
#else
{
static const unsigned int m1 = 0x55555555;
static const unsigned int m2 = 0x33333333;
static const unsigned int m3 = 0x0f0f0f0f;
unsigned int l = LOWBOARD(bb);
unsigned int h = HIGHBOARD(bb);
l = l - ((l>>1) & m1);
h = h - ((h>>1) & m1);
l = (l & m2) + ((l>>2) & m2);
h = (h & m2) + ((h>>2) & m2);
l = (l & m3) + ((l>>4) & m3);
h = (h & m3) + ((h>>4) & m3);
l = (l & 0x0ffff) + (l>>16);
h = (h & 0x0ffff) + (h>>16);
return ((l & 0x0ff) + (l>>8) + (h & 0x0ff) + (h>>8));
}
#endif
inline unsigned int BitSearchAndReset(ui64 &bb)
{
#if defined(_M_IX86) && UTILISER_ASSEMBLEUR == ON
__asm
{
mov edx, [bb]
bsf eax, [edx+4]
xor eax, 32
bsf eax, [edx]
btr [edx],eax
}
# else
ui64 lsbb = bb & (-(__int64)bb);
bb ^= lsbb;
unsigned int lsb = LOWBOARD(lsbb) | HIGHBOARD(lsbb);
return ((((((((((HIGHBOARD(lsbb)!=0) <<1)
+((lsb & 0xffff0000)!=0))<<1)
+((lsb & 0xff00ff00)!=0))<<1)
+((lsb & 0xf0f0f0f0)!=0))<<1)
+((lsb & 0xcccccccc)!=0))<<1)
+((lsb & 0xaaaaaaaa)!=0);
# endif
}
inline unsigned int BitSearch(ui64 bb)
{
#if defined(_M_IX86) && UTILISER_ASSEMBLEUR == ON
__asm
{
bsf eax,[bb+4]
xor eax, 32
bsf eax,[bb]
}
# else
ui64 lsbb = bb & (-(__int64)bb);
unsigned int lsb = LOWBOARD(lsbb) | HIGHBOARD(lsbb);
return ((((((((((HIGHBOARD(lsbb)!=0) <<1)
+((lsb & 0xffff0000)!=0))<<1)
+((lsb & 0xff00ff00)!=0))<<1)
+((lsb & 0xf0f0f0f0)!=0))<<1)
+((lsb & 0xcccccccc)!=0))<<1)
+((lsb & 0xaaaaaaaa)!=0);
# endif
}
} // namespace MatMoi
#endif // #ifndef INCLUDE_UI64_HPP_
inline
int BitCount (BitBoard bb)
{
unsigned int w = bb >> 32, v = bb;
v = v - ((v >> 1) & 0x55555555);
w = w - ((w >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
w = (w & 0x33333333) + ((w >> 2) & 0x33333333);
v = (v + (v >> 4)) & 0x0F0F0F0F;
w = (w + (w >> 4)) & 0x0F0F0F0F;
v = ((v+w) * 0x01010101) >> 24;
return v;
}
extern const unsigned int lsz64_tbl[64];
#define CACHE_LINE 64
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
const unsigned int CACHE_ALIGN lsz64_tbl[64] =
{
63,30, 3,32,59,14,11,33,
60,24,50, 9,55,19,21,34,
61,29, 2,53,51,23,41,18,
56,28, 1,43,46,27, 0,35,
62,31,58, 4, 5,49,54, 6,
15,52,12,40, 7,42,45,16,
25,57,48,13,10,39, 8,44,
20,47,38,22,17,37,36,26,
};
// precondition: bb not null
inline
unsigned int BitSearch(BitBoard bb)
{
BitBoard b = bb ^ (bb - 1);
unsigned int fold = ((unsigned int) b) ^ ((unsigned int)(b>>32));
return lsz64_tbl[(fold * 0x78291ACF) >> (32-6)];
}
// precondition: bb not null
inline
unsigned int BitSearchAndReset(BitBoard &bb)
{
BitBoard b = bb ^ (bb - 1);
bb = bb & (bb - 1);
unsigned int fold = ((unsigned int) b) ^ ((unsigned int)(b>>32));
return lsz64_tbl[(fold * 0x78291ACF) >> (32-6)];
}
Beth Stoy wrote:I'm not used to efficiency being the deciding factor in the programs I work on, so I have a lot to learn before my little chess program will be competitive.
Is there a good place to find out how efficient different types are, without running my own tests? It seems like one of those things other people just 'know'.
Dann Corbit wrote:On the other hand, the bit twiddle stuff is also FUN.
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
bitset<64> my64 = 4096;
cout<<"\n"<<my64;
return 0;
}
0000000000000000000000000000000000000000000000000001000000000000
bitset<64> my64 = (1<<46);
0000000000000000000000000000000000000000000000000000000000000000
bitset<64> my64 = ((unsigned __int64) 1<<46);
Tony van Roon-Werten wrote:It's the 1 that is 32 bit
- Code: Select all
bitset<64> my64 = ((unsigned __int64) 1<<46);
should do the trick.
Tony
int main()
{
bitset<64> my64 = ( (unsigned __int64)1<<31);
cout<<"\n"<<my64;
return 0;
}
0000000000000000000000000000000010000000000000000000000000000000
int main()
{
bitset<64> my64 = ( (unsigned __int64)1<<32);
cout<<"\n"<<my64;
return 0;
}
0000000000000000000000000000000000000000000000000000000000000000
bitset<64> my64 = ( (unsigned __int64)1<<32);
bitset<64> my64 = (1ull<<32);
Tony van Roon-Werten wrote:It's the 1 that is 32 bit
- Code: Select all
bitset<64> my64 = ((unsigned __int64) 1<<46);
should do the trick.
Tony
bitset<64> my64; // empty set
my64.set(46);
cout<<my64<<"\n";
cout<<"my64 has "<<my64.count()<<" bit set\n";
bitset<64> my64; // empty set
my64.set(46);
cout<<my64<<"\n";
cout<<"my64 has "<<my64.count()<<" bit set, which is ";
cout<<" bit number "<<my64._Find_first()<<"\n";
bitset<64> my32; // empty set
my32.set(8);
cout<<my32<<"\n";
cout<<"my32 has "<<my32.count()<<" bit set, which is ";
cout<<" bit number "<<my32._Find_first()<<"\n";
0000000000000000010000000000000000000000000000000000000000000000
my64 has 1 bit set, which is bit number 46
0000000000000000000000000000000000000000000000000000000100000000
my32 has 1 bit set, which is bit number 8
Return to Programming and Technical Discussions
Users browsing this forum: No registered users and 27 guests