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.
Bitboard joke (C#)
Moderators: hgm, Rebel, chrisw
-
- Posts: 3232
- Joined: Mon May 31, 2010 1:29 pm
- Full name: lucasart
Re: Bitboard joke (C#)
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...
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.
-
- Posts: 6442
- Joined: Tue Jan 09, 2007 12:31 am
- Location: PA USA
- Full name: Louis Zulli
Re: Bitboard joke (C#)
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.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.
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: ~/Documents/Chess/Kirby] cat ShiftTest.c
#include <stdio.h>
int main()
{
int N;
printf("How many bits N to left shift? ");
scanf("%d", &N);
printf("\n");
printf("1 << 33 = %d\n", 1 << 33);
printf("1 << N = %d\n", 1 << N);
return 0;
}
ProcyonLeo: ~/Documents/Chess/Kirby] gcc -Wall -o shift_test ShiftTest.c
ShiftTest.c: In function 'main':
ShiftTest.c:11:1: warning: left shift count >= width of type [enabled by default]
ProcyonLeo: ~/Documents/Chess/Kirby] ./shift_test
How many bits N to left shift? 33
1 << 33 = 0
1 << N = 2
-
- Posts: 646
- Joined: Wed Jun 18, 2014 2:30 pm
- Full name: Fahad Syed
Re: Bitboard joke (C#)
Yes! I fell into this often.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...
-
- Posts: 6442
- Joined: Tue Jan 09, 2007 12:31 am
- Location: PA USA
- Full name: Louis Zulli
Re: Bitboard joke (C#)
Code: Select all
ProcyonLeo: ~/Documents/Chess/Kirby] cat ShiftTest.c
#include <stdio.h>
int main()
{
int N;
printf("How many bits N to left shift? ");
scanf("%d", &N);
printf("\n");
printf("1U << 33 = %u\n", 1U << 33);
printf("1U << N = %u\n", 1U << N);
printf("1U after %d successive one-bit left shifts = ", N);
unsigned m = 1;
while(N-- > 0) m <<= 1;
printf("%u\n", m);
return 0;
}
ProcyonLeo: ~/Documents/Chess/Kirby] gcc -Wall -o shift_test ShiftTest.c
ShiftTest.c: In function 'main':
ShiftTest.c:11:1: warning: left shift count >= width of type [enabled by default]
ProcyonLeo: ~/Documents/Chess/Kirby] ./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
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: Bitboard joke (C#)
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.zullil wrote:Code: Select all
ProcyonLeo: ~/Documents/Chess/Kirby] cat ShiftTest.c #include <stdio.h> int main() { int N; printf("How many bits N to left shift? "); scanf("%d", &N); printf("\n"); printf("1U << 33 = %u\n", 1U << 33); printf("1U << N = %u\n", 1U << N); printf("1U after %d successive one-bit left shifts = ", N); unsigned m = 1; while(N-- > 0) m <<= 1; printf("%u\n", m); return 0; } ProcyonLeo: ~/Documents/Chess/Kirby] gcc -Wall -o shift_test ShiftTest.c ShiftTest.c: In function 'main': ShiftTest.c:11:1: warning: left shift count >= width of type [enabled by default] ProcyonLeo: ~/Documents/Chess/Kirby] ./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
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".
-
- Posts: 266
- Joined: Tue Dec 08, 2009 1:37 pm
- Location: Milan, Italy
- Full name: Alex Brunetti
Re: Bitboard joke (C#)
I solved the problem by using everywhere a constant instead of 1:Henk wrote:(UInt64)(1 << (int)(BitBoard.coord.b5)) = 2
(UInt64)((UInt64)1 << (int)(BitBoard.coord.b5)) = 8589934592
Code: Select all
const UInt64 bit0=1;
Alex
-
- Posts: 4675
- Joined: Mon Mar 13, 2006 7:43 pm
For more readable code:
Code: Select all
// Binary exponentiation (single bit mask construction)
#define BX(base) (1 << (base))
#define BXL(base) (1ULL << (base))
// Binary exponentiation (multiple bit mask construction)
#define MX(base) (BX(base) - 1)
#define MXL(base) (BXL(base) - 1ULL)
-
- Posts: 6442
- Joined: Tue Jan 09, 2007 12:31 am
- Location: PA USA
- Full name: Louis Zulli
Re: For more readable code:
Naming the parameter "base" seems odd (or maybe even perverse).sje wrote:Code: Select all
// Binary exponentiation (single bit mask construction) #define BX(base) (1 << (base)) #define BXL(base) (1ULL << (base)) // Binary exponentiation (multiple bit mask construction) #define MX(base) (BX(base) - 1) #define MXL(base) (BXL(base) - 1ULL)
-
- Posts: 4675
- Joined: Mon Mar 13, 2006 7:43 pm
Re: For more readable code:
Gosh, that code fragment must be thirty years old; I've long forgotten the reasons for the name pick.zullil wrote:Naming the parameter "base" seems odd (or maybe even perverse).sje wrote:Code: Select all
// Binary exponentiation (single bit mask construction) #define BX(base) (1 << (base)) #define BXL(base) (1ULL << (base)) // Binary exponentiation (multiple bit mask construction) #define MX(base) (BX(base) - 1) #define MXL(base) (BXL(base) - 1ULL)