Bitboard joke (C#)

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Henk
Posts: 7218
Joined: Mon May 27, 2013 10:31 am

Bitboard joke (C#)

Post by Henk »

Let BitBoard.coord.b5 = 33 in

(UInt64)(1 << (int)(BitBoard.coord.b5)) = 2
(UInt64)((UInt64)1 << (int)(BitBoard.coord.b5)) = 8589934592

This is the second time I was fooled with this. So easy to forget.
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Bitboard joke (C#)

Post by lucasart »

In C it's the same problem. It is so easy to write 1 << sq instead of 1ULL << sq.

I'm sure we all fell for that one, at least a few times, when typing code carelessly...
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
zullil
Posts: 6442
Joined: Tue Jan 09, 2007 12:31 am
Location: PA USA
Full name: Louis Zulli

Re: Bitboard joke (C#)

Post by zullil »

Henk wrote:Let BitBoard.coord.b5 = 33 in

(UInt64)(1 << (int)(BitBoard.coord.b5)) = 2
(UInt64)((UInt64)1 << (int)(BitBoard.coord.b5)) = 8589934592

This is the second time I was fooled with this. So easy to forget.
I made the same sort of error recently, when I experimented with using a bitboard (rather than a list) to store the locations of pinned pieces.

Don't count on 1 << (int)(BitBoard.coord.b5)) being 2 either. I think the result is "undefined" if an int is 32 bits; I guess the preprocessor and compiler determine what actually happens.

Here's an experiment:

Code: Select all

ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; cat ShiftTest.c 
#include <stdio.h>

int main&#40;)
&#123;
int N;

printf&#40;"How many bits N to left shift? ");
scanf&#40;"%d", &N&#41;;
printf&#40;"\n");

printf&#40;"1 << 33 = %d\n", 1 << 33&#41;;

printf&#40;"1 << N = %d\n", 1 << N&#41;;

return 0;
&#125;
ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; gcc -Wall -o shift_test ShiftTest.c 
ShiftTest.c&#58; In function 'main'&#58;
ShiftTest.c&#58;11&#58;1&#58; warning&#58; left shift count >= width of type &#91;enabled by default&#93;
ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; ./shift_test 
How many bits N to left shift? 33

1 << 33 = 0
1 << N = 2
User avatar
vittyvirus
Posts: 646
Joined: Wed Jun 18, 2014 2:30 pm
Full name: Fahad Syed

Re: Bitboard joke (C#)

Post by vittyvirus »

lucasart wrote:In C it's the same problem. It is so easy to write 1 << sq instead of 1ULL << sq.

I'm sure we all fell for that one, at least a few times, when typing code carelessly...
Yes! I fell into this often.
zullil
Posts: 6442
Joined: Tue Jan 09, 2007 12:31 am
Location: PA USA
Full name: Louis Zulli

Re: Bitboard joke (C#)

Post by zullil »

Code: Select all

ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; cat ShiftTest.c 
#include <stdio.h>

int main&#40;)
&#123;
int N;

printf&#40;"How many bits N to left shift? ");
scanf&#40;"%d", &N&#41;;
printf&#40;"\n");

printf&#40;"1U << 33 = %u\n", 1U << 33&#41;;

printf&#40;"1U << N = %u\n", 1U << N&#41;;

printf&#40;"1U after %d successive one-bit left shifts = ", N&#41;;
unsigned m = 1;
while&#40;N-- > 0&#41; m <<= 1;
printf&#40;"%u\n", m&#41;;

return 0;
&#125;
ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; gcc -Wall -o shift_test ShiftTest.c 
ShiftTest.c&#58; In function 'main'&#58;
ShiftTest.c&#58;11&#58;1&#58; warning&#58; left shift count >= width of type &#91;enabled by default&#93;
ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; ./shift_test 
How many bits N to left shift? 33

1U << 33 = 0
1U << N = 2
1U after 33 successive one-bit left shifts = 0
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Bitboard joke (C#)

Post by bob »

zullil wrote:

Code: Select all

ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; cat ShiftTest.c 
#include <stdio.h>

int main&#40;)
&#123;
int N;

printf&#40;"How many bits N to left shift? ");
scanf&#40;"%d", &N&#41;;
printf&#40;"\n");

printf&#40;"1U << 33 = %u\n", 1U << 33&#41;;

printf&#40;"1U << N = %u\n", 1U << N&#41;;

printf&#40;"1U after %d successive one-bit left shifts = ", N&#41;;
unsigned m = 1;
while&#40;N-- > 0&#41; m <<= 1;
printf&#40;"%u\n", m&#41;;

return 0;
&#125;
ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; gcc -Wall -o shift_test ShiftTest.c 
ShiftTest.c&#58; In function 'main'&#58;
ShiftTest.c&#58;11&#58;1&#58; warning&#58; left shift count >= width of type &#91;enabled by default&#93;
ProcyonLeo&#58; ~/Documents/Chess/Kirby&#93; ./shift_test 
How many bits N to left shift? 33

1U << 33 = 0
1U << N = 2
1U after 33 successive one-bit left shifts = 0
Shifting is the easiest way to introduce portability problems there is. Some machines (say a 32 bit intel box) uses the rightmost 5 bits of the shift counter (when stuck in a register). Other machines do not and anything left-shifted (or right-shifted) more than the word size will give zero.

Having had the pleasure(?) of running on just about every CPU ever produced, this leads to some interesting debugging. Even in the days of FORTRAN, Algol, Pascal and such, it was an issue frequently.

And then there is the right shift where (-4) >> 1 is -2, (-2) >> 1 is -1, (-1) >> 1 is -1, (-1) >> anything is -1. Not quite a "divide by two".
User avatar
Brunetti
Posts: 266
Joined: Tue Dec 08, 2009 1:37 pm
Location: Milan, Italy
Full name: Alex Brunetti

Re: Bitboard joke (C#)

Post by Brunetti »

Henk wrote:(UInt64)(1 << (int)(BitBoard.coord.b5)) = 2
(UInt64)((UInt64)1 << (int)(BitBoard.coord.b5)) = 8589934592
I solved the problem by using everywhere a constant instead of 1:

Code: Select all

const UInt64 bit0=1;
and this kind of error disappeared, while readability is still fine :)

Alex
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

For more readable code:

Post by sje »

Code: Select all

// Binary exponentiation &#40;single bit mask construction&#41;

#define BX&#40;base&#41;  &#40;1    << &#40;base&#41;)
#define BXL&#40;base&#41; &#40;1ULL << &#40;base&#41;)

// Binary exponentiation &#40;multiple bit mask construction&#41;

#define MX&#40;base&#41;  &#40;BX&#40;base&#41;  - 1&#41;
#define MXL&#40;base&#41; &#40;BXL&#40;base&#41; - 1ULL&#41;
zullil
Posts: 6442
Joined: Tue Jan 09, 2007 12:31 am
Location: PA USA
Full name: Louis Zulli

Re: For more readable code:

Post by zullil »

sje wrote:

Code: Select all

// Binary exponentiation &#40;single bit mask construction&#41;

#define BX&#40;base&#41;  &#40;1    << &#40;base&#41;)
#define BXL&#40;base&#41; &#40;1ULL << &#40;base&#41;)

// Binary exponentiation &#40;multiple bit mask construction&#41;

#define MX&#40;base&#41;  &#40;BX&#40;base&#41;  - 1&#41;
#define MXL&#40;base&#41; &#40;BXL&#40;base&#41; - 1ULL&#41;
Naming the parameter "base" seems odd (or maybe even perverse).
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: For more readable code:

Post by sje »

zullil wrote:
sje wrote:

Code: Select all

// Binary exponentiation &#40;single bit mask construction&#41;

#define BX&#40;base&#41;  &#40;1    << &#40;base&#41;)
#define BXL&#40;base&#41; &#40;1ULL << &#40;base&#41;)

// Binary exponentiation &#40;multiple bit mask construction&#41;

#define MX&#40;base&#41;  &#40;BX&#40;base&#41;  - 1&#41;
#define MXL&#40;base&#41; &#40;BXL&#40;base&#41; - 1ULL&#41;
Naming the parameter "base" seems odd (or maybe even perverse).
Gosh, that code fragment must be thirty years old; I've long forgotten the reasons for the name pick.