Page 1 of 1

Coding a bitboard class

PostPosted: 16 Sep 2007, 14:13
by Matthias Gemuh
Given an 80-bit bitboard A, how do I code operators for "~A" and "&& A" ?
The commented lines fail.
I am not yet testing, but do you see any other errors ?



class BITBOARD {
protected:
UINT16 data16;
UINT64 data64;

public:
BITBOARD() { data16 = 0; data64 = 0ui64; }
BITBOARD(UINT16 dat16, UINT64 dat64) { data16 = dat16; data64 = dat64; }

UINT16 GetData16() const { return data16; }
UINT64 GetData64() const { return data64; }
void PutData16(UINT16 dat16) { data16 = dat16; }
void PutData64(UINT64 dat64) { data64 = dat64; }

BITBOARD operator & (BITBOARD BitA) const
{ return(BITBOARD((GetData16() & BitA.GetData16()), (GetData64() & BitA.GetData64()))); }
BITBOARD operator | (BITBOARD BitA) const
{ return(BITBOARD((GetData16() | BitA.GetData16()), (GetData64() | BitA.GetData64()))); }
BITBOARD operator ^ (BITBOARD BitA) const
{ return(BITBOARD((GetData16() ^ BitA.GetData16()), (GetData64() ^ BitA.GetData64()))); }

bool operator && (BITBOARD BitA) const
{ return((GetData16() || GetData64()) && (BitA.GetData16() || BitA.GetData64())); }
bool operator || (BITBOARD BitA) const
{ return(GetData16() || BitA.GetData16() || GetData64() || BitA.GetData64()); }
bool operator == (BITBOARD BitA) const
{ return((GetData16() == BitA.GetData16()) && (GetData64() == BitA.GetData64())); }
bool operator != (BITBOARD BitA) const
{ return((GetData16() != BitA.GetData16()) || (GetData64() != BitA.GetData64())); }

BITBOARD & operator = (BITBOARD BitA)
{ PutData16(BitA.GetData16()); PutData64(BitA.GetData64()); return(*this); }
BITBOARD & operator &= (BITBOARD BitA)
{ PutData16(GetData16() & BitA.GetData16()); PutData64(GetData64() & BitA.GetData64()); return(*this); }
BITBOARD & operator |= (BITBOARD BitA)
{ PutData16(GetData16() | BitA.GetData16()); PutData64(GetData64() | BitA.GetData64()); return(*this); }
BITBOARD & operator ^= (BITBOARD BitA)
{ PutData16(GetData16() ^ BitA.GetData16()); PutData64(GetData64() ^ BitA.GetData64()); return(*this); }

// BITBOARD operator ~ (*this) { return(BITBOARD((~GetData16()), (~GetData64()))); }
// bool operator && (*this) { return((GetData16()) || (GetData64())); }

};

Re: Coding a bitboard class

PostPosted: 16 Sep 2007, 15:54
by Matthias Gemuh
Not yet tested, but this may work:

BITBOARD operator ~ () { return(BITBOARD((~GetData16()), (~GetData64()))); }
friend bool operator && (bool bA, const BITBOARD A) { return((bA) && ((A.GetData16()) || (A.GetData64()))); }

Re: Coding a bitboard class

PostPosted: 16 Sep 2007, 16:35
by Matthias Gemuh
Given an 80-bit bitboard A, how do I code an operator for "(A)" to check for at least one set bit ?
The commented line seems to fail.
I am not yet testing, but do you see any other errors ?



class BITBOARD {
protected:
UINT16 data16;
UINT64 data64;

public:
BITBOARD() { data16 = 0; data64 = 0ui64; }
BITBOARD(UINT16 dat16, UINT64 dat64) { data16 = dat16; data64 = dat64; }

UINT16 GetData16() const { return data16; }
UINT64 GetData64() const { return data64; }
void PutData16(UINT16 dat16) { data16 = dat16; }
void PutData64(UINT64 dat64) { data64 = dat64; }

BITBOARD operator & (BITBOARD BitA) const
{ return(BITBOARD((GetData16() & BitA.GetData16()), (GetData64() & BitA.GetData64()))); }
BITBOARD operator | (BITBOARD BitA) const
{ return(BITBOARD((GetData16() | BitA.GetData16()), (GetData64() | BitA.GetData64()))); }
BITBOARD operator ^ (BITBOARD BitA) const
{ return(BITBOARD((GetData16() ^ BitA.GetData16()), (GetData64() ^ BitA.GetData64()))); }

friend bool operator && (const BITBOARD A, const BITBOARD B)
{ return((A.GetData16() || A.GetData64()) && (B.GetData16() || B.GetData64())); }
friend bool operator || (const BITBOARD A, const BITBOARD B)
{ return(A.GetData16() || B.GetData16() || A.GetData64() || B.GetData64()); }
friend bool operator == (const BITBOARD A, const BITBOARD B)
{ return((A.GetData16() == B.GetData16()) && (A.GetData64() == B.GetData64())); }
friend bool operator != (const BITBOARD A, const BITBOARD B)
{ return((A.GetData16() != B.GetData16()) || (A.GetData64() != B.GetData64())); }

BITBOARD & operator = (BITBOARD BitA)
{ PutData16(BitA.GetData16()); PutData64(BitA.GetData64()); return(*this); }
BITBOARD & operator &= (BITBOARD BitA)
{ PutData16(GetData16() & BitA.GetData16()); PutData64(GetData64() & BitA.GetData64()); return(*this); }
BITBOARD & operator |= (BITBOARD BitA)
{ PutData16(GetData16() | BitA.GetData16()); PutData64(GetData64() | BitA.GetData64()); return(*this); }
BITBOARD & operator ^= (BITBOARD BitA)
{ PutData16(GetData16() ^ BitA.GetData16()); PutData64(GetData64() ^ BitA.GetData64()); return(*this); }

// bool operator () () { return((GetData16()) || (GetData64())); }
BITBOARD operator ~ () { return(BITBOARD((~GetData16()), (~GetData64()))); }
friend bool operator && (bool bA, const BITBOARD A) { return((bA) && ((A.GetData16()) || (A.GetData64()))); }

};

Re: Coding a bitboard class

PostPosted: 16 Sep 2007, 18:10
by Aleks Peshkov
1) Good interface should hide implementation details, so GetData16() and PutData64() is no-no!
2) C++ style does not recommend to overload (&&), (||) and (,) operators.
Given an 80-bit bitboard A, how do I code an operator for "(A)" to check for at least one set bit ?

You need to have (operator bool).
Code: Select all
operator bool () const { return (data64 | data16) != 0; }

3) I personally prefer to implement 80-bit set as structure of 3 x 32 bits. How you share 80 bit inside 96 bits is not important. You only need to be careful with (~) operator that is equivalent to XOR with your 80 significant bit constant.
4) It is much better to pass const references, not copies.
Code: Select all
BITBOARD& ^= (const BITBOARD& b) {
    data64 ^= b.data64;
    data16 ^= b.data16;
    return *this;
}


I suggest you to look how std::complex numbers and std::bitset template are declared in Standard C++ Library.

Re: Coding a bitboard class

PostPosted: 16 Sep 2007, 19:57
by Matthias Gemuh
Thanks a lot, Alex.

If I pass values by reference, can I still use the bitboard operators on referenced variables ? I mean:

BITBOARD& ^= (const BITBOARD& b)

void FunctionX(const BITBOARD& b)
{
BITBOARD a;
...
a ^= b; <--- referencing referenced "b" is ok ?
...
}


BTW, I thought using UINT64 may speed up the class on 64-Bit architecture.


Regards,
Matthias.

Re: Coding a bitboard class

PostPosted: 16 Sep 2007, 20:47
by Aleks Peshkov
Code: Select all
void FunctionX(const BITBOARD& b)
{
  a ^= b;   <--- referencing referenced "b" is ok ?
}

Ok.

BTW, I thought using UINT64 may speed up the class on 64-Bit architecture.
May be, you are right. If your specially target to 64-bit, then 2x64bit become much better. 2x64 is probably better then 3x32 even in 32-bit architecture. Your should not worry too early about actual implementation of the BITBOARD before you be able to test speed of real games.

Re: Coding a bitboard class

PostPosted: 16 Sep 2007, 21:54
by Matthias Gemuh
Thanks !

Through some reflex, I misspelled your name as "Alex" :o .

Matthias.

Re: Coding a bitboard class

PostPosted: 18 Nov 2007, 18:22
by BrettVsop
Why is it 80bit? What is the purpose of the extra 16bit variable?

Re: Coding a bitboard class

PostPosted: 18 Nov 2007, 19:02
by Tord Romstad
BrettVsop wrote:Why is it 80bit? What is the purpose of the extra 16bit variable?

Simple: The board has 80 squares (10x8).

Tord

Re: Coding a bitboard class

PostPosted: 18 Nov 2007, 21:50
by BrettVsop
Oh. This is for a chess variant? Does c++ not support a 80 bit integer?

Re: Coding a bitboard class

PostPosted: 10 Dec 2007, 06:50
by GothicChessInventor
Matthias Gemuh wrote:Given an 80-bit bitboard A, how do I code operators for "~A" and "&& A" ?
The commented lines fail.
I am not yet testing, but do you see any other errors ?


I used operator overloading and just redefined the meaning of:

&, ^, |, >>, <<, >>=, <<= etc.

You define your 80-bit item as a struct composed of a 16-bit and 64-bit portion.

Let me know if you would like to see some of the code in Gothic Vortex.

Image

Re: Coding a bitboard class

PostPosted: 10 Dec 2007, 15:53
by Matthias Gemuh
GothicChessInventor wrote:
Matthias Gemuh wrote:Given an 80-bit bitboard A, how do I code operators for "~A" and "&& A" ?
The commented lines fail.
I am not yet testing, but do you see any other errors ?


I used operator overloading and just redefined the meaning of:

&, ^, |, >>, <<, >>=, <<= etc.

You define your 80-bit item as a struct composed of a 16-bit and 64-bit portion.

Let me know if you would like to see some of the code in Gothic Vortex.





Hi Ed,
yes you can send me code snippet as private mail.
Please include ROW() and COL(), for I now use:

#define ROW(x) (((x)-((x)%10)) / 10)
#define COL(x) (x % 10)

In ArcBishop, I use this very slow, unoptimized class:


class BITBOARD {
protected:
UINT16 data16;
UINT64 data64;

public:
BITBOARD() { data16 = (UINT16)0; data64 = 0ui64; }
BITBOARD(UINT16 dat16, UINT64 dat64) { data16 = (UINT16)dat16; data64 = (UINT64)dat64; }

UINT16 GetData16() const { return((UINT16) data16); }
UINT64 GetData64() const { return((UINT64) data64); }
void PutData16(UINT16 dat16) { data16 = (UINT16)dat16; }
void PutData64(UINT64 dat64) { data64 = (UINT64)dat64; }

BITBOARD operator & (BITBOARD const BitA) const
{ return(BITBOARD(((UINT16)data16 & BitA.GetData16()), ((UINT64)data64 & BitA.GetData64()))); }
BITBOARD operator | (BITBOARD const BitA) const
{ return(BITBOARD(((UINT16)data16 | BitA.GetData16()), ((UINT64)data64 | BitA.GetData64()))); }
BITBOARD operator ^ (BITBOARD const BitA) const
{ return(BITBOARD(((UINT16)data16 ^ BitA.GetData16()), ((UINT64)data64 ^ BitA.GetData64()))); }
BITBOARD operator << (UINT16 k) const {
if (k == 0) return(*this);
else if (k <= 16) return(BITBOARD((UINT16)(((UINT64)data16 << k) | ((UINT64)data64 >> (64-k))), ((UINT64)data64 << k)));
else if (k <= 64) return(BITBOARD((UINT16)((UINT64)data64 >> (64-k)), ((UINT64)data64 << k)));
else return(BITBOARD((UINT16)((UINT64)data64 << (k-64)), ((UINT64)data64 << k)));
}
BITBOARD operator >> (UINT16 k) const {
if (k == 0) return(*this);
else if (k <= 15) return(BITBOARD(((UINT16)data16 >> k), (((UINT64)data16 << (64-k)) | ((UINT64)data64 >> k))));
else if (k <= 63) return(BITBOARD((UINT16)0, (((UINT64)data16 << (64-k)) | ((UINT64)data64 >> k))));
else return(BITBOARD((UINT16)0, ((UINT64)data16 >> (k-64))));
}

friend bool operator && (const BITBOARD& const A, const BITBOARD& const B)
{ return((A.GetData16() || A.GetData64()) && (B.GetData16() || B.GetData64())); }
friend bool operator || (const BITBOARD& const A, const BITBOARD& const B)
{ return(A.GetData16() || B.GetData16() || A.GetData64() || B.GetData64()); }
friend bool operator == (const BITBOARD& const A, const BITBOARD& const B)
{ return((A.GetData16() == B.GetData16()) && (A.GetData64() == B.GetData64())); }
friend bool operator != (const BITBOARD& const A, const BITBOARD& const B)
{ return((A.GetData16() != B.GetData16()) || (A.GetData64() != B.GetData64())); }

friend BITBOARD operator & (const UINT64 A, const BITBOARD& const B) { return(BITBOARD(0, (A & B.GetData64()))); }
friend BITBOARD operator | (const UINT64 A, const BITBOARD& const B) { return(BITBOARD(0, (A | B.GetData64()))); }
friend BITBOARD operator & (const BITBOARD& const A, const UINT64 B) { return(BITBOARD(0, (B & A.GetData64()))); }
friend BITBOARD operator | (const BITBOARD& const A, const UINT64 B) { return(BITBOARD(0, (B | A.GetData64()))); }

BITBOARD & operator = (BITBOARD const BitA)
{ data16 = (UINT16)BitA.GetData16(); data64 = (UINT64)BitA.GetData64(); return(*this); }
BITBOARD & operator = (UINT64 A) { data16 = (UINT16)0; data64 = (UINT64)A; return(*this); }
BITBOARD & operator &= (BITBOARD const BitA)
{ data16 = (UINT16)(data16 & BitA.GetData16()); data64 = (UINT64)(data64 & BitA.GetData64()); return(*this); }
BITBOARD & operator |= (BITBOARD const BitA)
{ data16 = (UINT16)(data16 | BitA.GetData16()); data64 = (UINT64)(data64 | BitA.GetData64()); return(*this); }
BITBOARD & operator ^= (BITBOARD const BitA)
{ data16 = (UINT16)(data16 ^ BitA.GetData16()); data64 = (UINT64)(data64 ^ BitA.GetData64()); return(*this); }

bool operator == (UINT64 A) { return((data16 == 0) && (data64 == A)); }
friend bool IsEmpty(BITBOARD BitA) { return((BitA.GetData16() == 0) && (BitA.GetData64() == 0ui64)); }
friend bool IsNotEmpty(BITBOARD BitA) { return((BitA.GetData16()) || (BitA.GetData64())); }
// operator bool () const { return((data64 | data16) != 0ui64); }
BITBOARD operator ~ () { return(BITBOARD((~data16), (~data64))); }

bool GetBit(int nBit) const
{
if( nBit < 64 ) return (data64 & (1ui64 << nBit)) != 0ui64;
return (data16 & (1 << (nBit - 64))) != 0;
}
void SetBit(int nBit)
{
if( nBit < 64 ) data64 = data64 | (1ui64 << nBit);
else data16 = data16 | (1 << (nBit - 64));
}
void ClearBit(int nBit)
{
if( nBit < 64 ) data64 = data64 & (0xFFFFFFFFFFFFFFFFui64 ^ (1ui64 << nBit));
else data16 = data16 & (0xFFFF ^ (1 << (nBit - 64)));
}
void ToggleBit(int nBit)
{
if( nBit < 64 ) data64 = data64 ^ (1ui64 << nBit);
else data16 = data16 ^ (1 << (nBit - 64));
}

};





Best,
Matthias.