How to implement bitboards?.. and some more questions

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
vittyvirus
Posts: 646
Joined: Wed Jun 18, 2014 2:30 pm
Full name: Fahad Syed

How to implement bitboards?.. and some more questions

Post by vittyvirus »

I want to use bitboard board representation system. I discovered (believe it or not) bitboards on my own but then was in a sweat to find a fast way of accessing individual elements in bitboards. So I moved to one-dimensional bitboard like arrays because its easier and faster to access individual elements like:

Code: Select all

square[32] = BPAWN; // square no. 32 now contains a black pawn
But I after discovering bitboards on internet and seeing their advantage in speed, I've decided to move to bitboard board rep. system. Here's my code:

Code: Select all

// board.h
#include <string>
#include <string.h>
#ifndef BOARD_INC
#define BOARD_INC
#include "func.h"
#include "names.h"
	
const unsigned short BLANK = 0, WPAWN = 1, WKNIGHT = 2, WBISHOP = 3, WROOK = 4, WQUEEN = 5, WKING = 6 ;
const unsigned short BPAWN = 7, BKNIGHT = 8, BBISHOP = 9, BROOK = 10, BQUEEN = 11, BKING = 12 ;
const unsigned short WHITE = 1, BLACK = 2;

class Board &#123;
public&#58;
	unsigned short WP&#91;64&#93;, WQ&#91;64&#93;, WK&#91;64&#93;, WN&#91;64&#93;, WB&#91;64&#93;, WR&#91;64&#93;;
	unsigned short BP&#91;64&#93;, BQ&#91;64&#93;, BK&#91;64&#93;, BN&#91;64&#93;, BB&#91;64&#93;, BR&#91;64&#93;;
	unsigned short allBoard&#91;64&#93;, W_Pieces&#91;64&#93;, B_Pieces&#91;64&#93;;
	unsigned short WCCOO, WCCOOO, BCCOO, BCCOOO;	//WCCOO = White Can Castle O-O &#40;King side&#41;
												//BCCOOO = Black Can Castle O-O-O &#40;Queen side&#41;
												//...etc...
	unsigned short colorToMove;
	unsigned short epSq; //enPassant square no.
	unsigned int hmslcopm; //hmslcopm = Half-Moves Since Last Capture Or Pawn Move
	unsigned int moveNum; //The current move number in game

	void setFEN&#40;const char fen&#91;&#93;);
	void setPieces&#40;const unsigned short state&#91;&#93;);
	void displayBoard&#40;);
	void doMove&#40;const unsigned short &fromSq, const unsigned short &toSq&#41;;
	void parseMove&#40;const char move&#91;&#93;);
	&#125;;

#endif

Code: Select all

// board.cpp
#include <iostream>
#include <cstdlib> //for atio&#40;)

#include "board.h"
#include "func.h"
#include "names.h"

//Some test positions for fen parser&#58;
//rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
//r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 0 3
//r1bqk1nr/ppppbppp/2n5/4p3/4P3/5N2/PPPPBPPP/RNBQK2R w KQkq - 0 4
//rnbqkbnr/ppp3pp/8/2Pppp2/4P3/8/PP1P1PPP/RNBQKBNR w KQkq D5 0 4

void Board&#58;&#58;setFEN&#40;const char fen&#91;&#93;) &#123;
	//fill up all arrays with 0&#58;
	for&#40;register short foo = 0; foo < 64; ++foo&#41; &#123;
		Board&#58;&#58;allBoard&#91;foo&#93; = 0;
		Board&#58;&#58;BB&#91;foo&#93; = 0;
		Board&#58;&#58;BK&#91;foo&#93; = 0;
		Board&#58;&#58;BN&#91;foo&#93; = 0;
		Board&#58;&#58;BP&#91;foo&#93; = 0;
		Board&#58;&#58;BQ&#91;foo&#93; = 0;
		Board&#58;&#58;BR&#91;foo&#93; = 0;
		Board&#58;&#58;B_Pieces&#91;foo&#93; = 0;
		Board&#58;&#58;WB&#91;foo&#93; = 0;
		Board&#58;&#58;WK&#91;foo&#93; = 0;
		Board&#58;&#58;WN&#91;foo&#93; = 0;
		Board&#58;&#58;WP&#91;foo&#93; = 0;
		Board&#58;&#58;WQ&#91;foo&#93; = 0;
		Board&#58;&#58;WR&#91;foo&#93; = 0;
		Board&#58;&#58;W_Pieces&#91;foo&#93; = 0;
	&#125;
	unsigned short task = 1, sq; //task = 1 =&#40;in human language&#41; read first part of the fen string
	short rank, file;
	unsigned short result&#91;64&#93;;
	//Initialize all the elements of array result to BLANK
	for&#40;short foo = 0; foo < 64; ++foo&#41;
		result&#91;foo&#93; = BLANK;
	short j = 0;
	register short i = 0;
	while&#40;&#40;j <= 64&#41; && &#40;fen&#91;i&#93; != ' ')) &#123;
		//Thanks to Thomas Petzke for the next two lines of code
		file = 1 + &#40;j % 8&#41;;
		rank = 8 - &#40;j / 8&#41;;
		sq = toSquare&#40;file, rank&#41;;
		switch&#40;fen&#91;i&#93;) &#123;
		case 'p'&#58;
			result&#91;j&#93; = BPAWN;
			break;
		case 'n'&#58;
			result&#91;j&#93; = BKNIGHT;
			break;
		case 'b'&#58;
			result&#91;j&#93; = BBISHOP;
			break;
		case 'r'&#58;
			result&#91;j&#93; = BROOK;
			break;
		case 'q'&#58;
			result&#91;j&#93; = BQUEEN;
			break;
		case 'k'&#58;
			result&#91;j&#93; = BKING;
			break;
		case 'P'&#58;
			result&#91;j&#93; = WPAWN;
			break;
		case 'N'&#58;
			result&#91;j&#93; = WKNIGHT;
			break;
		case 'B'&#58;
			result&#91;j&#93; = WBISHOP;
			break;
		case 'R'&#58;
			result&#91;j&#93; = WROOK;
			break;
		case 'Q'&#58;
			result&#91;j&#93; = WQUEEN;
			break;
		case 'K'&#58;
			result&#91;j&#93; = WKING;
			break;
		case '/'&#58;
			--j;
			break;
		case '1'&#58;
			break;
		case '2'&#58;
			++j;
			break;
		case '3'&#58;
			j += 2;
			break;
		case '4'&#58;
			j += 3;
			break;
		case '5'&#58;
			j += 4;
			break;
		case '6'&#58;
			j += 5;
			break;
		case '7'&#58;
			j += 6;
			break;
		case '8'&#58;
			j += 7;
			break;
		&#125;
		++j;
		++i; //Just to get some extra lines of code &#58;)
	&#125;
	setPieces&#40;result&#41;;

	//to avoid fen parse errors, increment i until it doesn't point to ' ' or blank space
	for&#40;short foo = i; fen&#91;foo&#93; == ' '; ++foo&#41;
		++i;

	Board&#58;&#58;colorToMove = &#40;fen&#91;i&#93; == 'b') ? BLACK &#58; WHITE; //so that default is white

	//to avoid fen parse errors, increment i until it doesn't point to ' ' or blank space.
	for&#40;short foo = i; fen&#91;foo&#93; == ' '; ++foo&#41;
		++i;

	//Set up castling&#58;
	for&#40;short foo = i; fen&#91;foo&#93; != EOF; ++foo&#41; &#123; //search through all the rest of fen
		Board&#58;&#58;colorToMove = &#40;fen&#91;foo&#93; == 'b') ? BLACK &#58; WHITE; //so that default is white
		if&#40;fen&#91;foo&#93; == 'K')
			WCCOO = 1;
		if&#40;fen&#91;foo&#93; == 'Q')
			WCCOOO = 1;
		if&#40;fen&#91;foo&#93; == 'k')
			BCCOO = 1;
		if&#40;fen&#91;foo&#93; == 'q')
			BCCOOO = 1;
	&#125;
	
	//increment i till it gets out of blank chars
	for&#40;short foo = i; fen&#91;foo&#93; != ' '; ++foo&#41;
		++i;
	//i should now point to a blank char, and i+1 would point to the castling part.
	//So, increment i till it again points to blank char ' '
	for&#40;short foo = i; fen&#91;foo&#93; == ' '; ++foo&#41;
		++i;
	//to avoid fen parse errors, increment i until it doesn't point to ' ' or blank space.
	for&#40;short foo = i; fen&#91;foo&#93; != ' '; ++foo&#41;
		++i;
	//increment i till it points to a non blank char ' '
	for&#40;short foo = i; fen&#91;foo&#93; == ' '; ++foo&#41;
		++i;
	//Now we are in the enPassant Part&#58;
	if&#40;&#40;fen&#91;i&#93; >= 'a') && &#40;fen&#91;i&#93; <= 'h')) &#123; //if file numbers are given in small letters
		file = fen&#91;i++&#93; - 96;
		rank = fen&#91;i&#93; - 48;
		Board&#58;&#58;epSq = toSquare&#40;file, rank&#41;;
	&#125;
	else if&#40;&#40;fen&#91;i&#93; >= 'A') && &#40;fen&#91;i&#93; <= 'H')) &#123;
		file = fen&#91;i++&#93; - 64;
		rank = fen&#91;i&#93; - 48;
		Board&#58;&#58;epSq = toSquare&#40;file, rank&#41;;
	&#125;
	++i;
	//to avoid fen parse errors, increment i till it points to a non blank char ' '
	for&#40;short foo = i; fen&#91;foo&#93; == ' '; ++foo&#41;
		++i;
	Board&#58;&#58;hmslcopm = atoi&#40;&fen&#91;i&#93;);
	//increment i to get out of non blank chars or ' '
	for&#40;short foo = i; fen&#91;foo&#93; != ' '; ++foo&#41;
		++i;
	//Now, to avoid fen parse errors, increment i till it points to a non blank char ' '
	for&#40;short foo = i; fen&#91;foo&#93; == ' '; ++foo&#41;
		++i;
	Board&#58;&#58;moveNum = atoi&#40;&fen&#91;i&#93;);
&#125;

void Board&#58;&#58;setPieces&#40;const unsigned short state&#91;&#93;) &#123;
	//set pieces in separate arrays for every piece
	for&#40;short i = 0; i < 64; ++i&#41; &#123;
		if&#40;state&#91;i&#93; == BLANK&#41; &#123; //Blank square
			continue; //Do nothing 
		&#125;
		else if&#40;state&#91;i&#93; == WPAWN&#41; &#123;
			Board&#58;&#58;WP&#91;i&#93; = WPAWN;
		&#125;
		else if&#40;state&#91;i&#93; == WKNIGHT&#41; &#123;
			Board&#58;&#58;WN&#91;i&#93; = WKNIGHT;
		&#125;
		else if&#40;state&#91;i&#93; == WBISHOP&#41; &#123;
			Board&#58;&#58;WB&#91;i&#93; = WBISHOP;
		&#125;
		else if&#40;state&#91;i&#93; == WROOK&#41; &#123;
			Board&#58;&#58;WR&#91;i&#93; = WROOK;
		&#125;
		else if&#40;state&#91;i&#93; == WQUEEN&#41; &#123;
			Board&#58;&#58;WQ&#91;i&#93; = WKING;
		&#125;
		else if&#40;state&#91;i&#93; == WKING&#41; &#123;
			Board&#58;&#58;WK&#91;i&#93; = WKING;
		&#125;
		else if&#40;state&#91;i&#93; == BPAWN&#41; &#123;
			Board&#58;&#58;BP&#91;i&#93; = BPAWN;
		&#125;
		else if&#40;state&#91;i&#93; == BKNIGHT&#41; &#123;
			Board&#58;&#58;BN&#91;i&#93; = BKNIGHT;
		&#125;
		else if&#40;state&#91;i&#93; == BBISHOP&#41; &#123;
			Board&#58;&#58;BB&#91;i&#93; = BBISHOP;
		&#125;
		else if&#40;state&#91;i&#93; == BROOK&#41; &#123;
			Board&#58;&#58;BR&#91;i&#93; = BROOK;
		&#125;
		else if&#40;state&#91;i&#93; == BQUEEN&#41; &#123;
			Board&#58;&#58;BQ&#91;i&#93; = BQUEEN;
		&#125;
		else if&#40;state&#91;i&#93; == BKING&#41; &#123;
			Board&#58;&#58;BK&#91;i&#93; = BKING;
		&#125;

		//Copy state to allBoard&#58;
		for &#40;short n = 0; i < 64; i++) &#123;
			Board&#58;&#58;allBoard&#91;i&#93; = state&#91;i&#93;; 
		&#125;

		//fill up W_Pieces and B_Pieces with White and Black pieces
		for&#40;short m = 0; m < 64; m++) &#123;
			if&#40;state&#91;m&#93; < BPAWN&#41; &#123; //if state&#91;m&#93; denotes a white piece.
								   //If you don't get me, pay attention on '<' sign. Think, think think!
				W_Pieces&#91;m&#93; = state&#91;m&#93;;
			&#125;
			else &#123;
				B_Pieces&#91;m&#93; = state&#91;m&#93;;
			&#125;
		&#125;
	&#125;
&#125;
void Board&#58;&#58;displayBoard&#40;) &#123;
	std&#58;&#58;cout << "*******************************";
	for&#40;short j = 0; j < 64; ++j&#41; &#123;
		if&#40;!&#40;j % 8&#41;) std&#58;&#58;cout << "\n";
		std&#58;&#58;cout << "| " << piece2char&#40;Board&#58;&#58;allBoard&#91;j&#93;) << " ";
	&#125;
	std&#58;&#58;cout << "\n";
	std&#58;&#58;cout << "*******************************" << std&#58;&#58;endl;
&#125;

inline char piece2char&#40;const short piece&#41; &#123;
	if&#40;piece == BLANK&#41; &#123;
		return ' ';
	&#125;
	else if&#40;piece == WPAWN&#41; &#123;
		return 'P';
	&#125;
	else if&#40;piece == WKNIGHT&#41; &#123;
		return 'N';
	&#125;
	else if&#40;piece == WBISHOP&#41; &#123;
		return 'B';
	&#125;
	else if&#40;piece == WROOK&#41; &#123;
		return 'R';
	&#125;
	else if&#40;piece == WQUEEN&#41; &#123;
		return 'Q';
	&#125;
	else if&#40;piece == WKING&#41; &#123;
		return 'K';
	&#125;
	else if&#40;piece == BPAWN&#41; &#123;
		return 'p';
	&#125;
	else if&#40;piece == BKNIGHT&#41; &#123;
		return 'n';
	&#125;
	else if&#40;piece == BBISHOP&#41; &#123;
		return 'b';
	&#125;
	else if&#40;piece == BROOK&#41; &#123;
		return 'r';
	&#125;
	else if&#40;piece == BQUEEN&#41; &#123;
		return 'q';
	&#125;
	else if&#40;piece == BKING&#41; &#123;
		return 'k';
	&#125;
	else return '!';
&#125;

void Board&#58;&#58;parseMove&#40;const char move&#91;&#93;) &#123;
	unsigned short file, rank, toFile, toRank;
	switch&#40;move&#91;0&#93;) &#123;
	case 'a'&#58;
		file = 1;
		break;
	case 'b'&#58;
		file = 2;
		break;
	case 'c'&#58;
		file = 3;
		break;
	case 'd'&#58;
		file = 4;
		break;
	case 'e'&#58;
		file = 5;
		break;
	case 'f'&#58;
		file = 6;
		break;
	case 'g'&#58;
		file = 7;
		break;
	case 'h'&#58;
		file = 8;
		break;
	&#125;

	rank = atoi&#40;&move&#91;1&#93;);

	switch&#40;move&#91;2&#93;) &#123;
	case 'a'&#58;
		toFile = 1;
		break;
	case 'b'&#58;
		toFile = 2;
		break;
	case 'c'&#58;
		toFile = 3;
		break;
	case 'd'&#58;
		toFile = 4;
		break;
	case 'e'&#58;
		toFile = 5;
		break;
	case 'f'&#58;
		toFile = 6;
		break;
	case 'g'&#58;
		toFile = 7;
		break;
	case 'h'&#58;
		toFile = 8;
		break;
	&#125;

	toRank = atoi&#40;&move&#91;3&#93;);

	unsigned short fromSq = toSquare&#40;file, rank&#41;;
	unsigned short toSq = toSquare&#40;toFile, toRank&#41;;
	Board&#58;&#58;doMove&#40;fromSq, toSq&#41;;
&#125;

inline void Board&#58;&#58;doMove&#40;const unsigned short &fromSq, const unsigned short &toSq&#41; &#123;
	short fsq = sq2comp&#40;fromSq&#41;, tsq = sq2comp&#40;toSq&#41;;
	Board&#58;&#58;allBoard&#91;tsq&#93; = Board&#58;&#58;allBoard&#91;fsq&#93;;
	Board&#58;&#58;allBoard&#91;fsq&#93; = BLANK;
	setPieces&#40;Board&#58;&#58;allBoard&#41;;
&#125;
As you can see, some (latter) methods of class Board are pretty incomplete, that's alright as programming my chess engine has just begin.
My questions:
1) Provide at least one code sample from my code where you use bitboards to access individual pieces like I do in a array.
2) Is my code 'creepy' or difficult to understand?
3) Is my code fast?
4) Give me some advice to improve this code, if you have...
Thanks in advance.[/code]
Aleks Peshkov
Posts: 892
Joined: Sun Nov 19, 2006 9:16 pm
Location: Russia

Re: How to implement bitboards?.. and some more questions

Post by Aleks Peshkov »

I suggest you to read a book about programming in general.
After that visit http://chessprogramming.wikispaces.com/
User avatar
vittyvirus
Posts: 646
Joined: Wed Jun 18, 2014 2:30 pm
Full name: Fahad Syed

Re: How to implement bitboards?.. and some more questions

Post by vittyvirus »

Aleks Peshkov wrote:I suggest you to read a book about programming in general.
After that visit http://chessprogramming.wikispaces.com/
I'm just behind half of C++ Primer, and I've read C++ The complete reference and Sams Teach yourself C++ in 1 hour a day.
What about the code?
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: How to implement bitboards?.. and some more questions

Post by ZirconiumX »

1) is pretty easy.

Code: Select all

int random = 123456789; // number to extract bit from
int bitnum = 7; // bit number &#40;note&#58; working from zero&#41;
int bit = random & &#40;1ULL << bitnum&#41;; // note that this keeps the bit in its original place, if you want to move it, you will have to shift it around.
Working serially in bitboards defeats the point of bitboards, though. You want to work in parallel as much as possible to achieve the greatest speed gain. (Amdahl's law - maximum speedup is limited by maximum amount of parallelisation)

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: How to implement bitboards?.. and some more questions

Post by ZirconiumX »

2) Is my code 'creepy' or difficult to understand?
Somewhat. Though the comments help a bit, WCCOOO is not going to be blindingly obvious what it does. WhiteCastlingQueenside is going to be obvious. Same with things like hmslcopm. Most people use FiftyMoveClock or something similar for that.
3) Is my code fast?
Probably not. You're using short way too much. Modern compilers work fastest in int. If you're trying to save memory, use char. There is no reason to use short here.
4) Give me some advice to improve this code, if you have...
Use macros or constants. It's a lot easier to read code if there is a section for constant meanings, instead of having to scroll back through the code to read what the value of 3 means in task.

Write defensively, using asserts and triple checking things. What happens if you input invalid FENs? By the looks of it, you'll segfault. If you want, I'll write you a list of FENs to check your reader.

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
User avatar
jsgroby
Posts: 83
Joined: Mon Mar 24, 2014 12:26 am
Location: Glen Carbon, IL USA

Re: How to implement bitboards?.. and some more questions

Post by jsgroby »

Definitely check out the chess programming wiki referenced in the above answers. I learned a ton from that. There a links from that wiki to engines with available source code you can take a look at and see how it works, etc. There are also programming examples and pseudo-code you can utilize. I wrote my engine in C, but learned just about all I needed to know from that wiki or from places it linked to. Then I started coming here to shore up peripheral details.

Just my .02...

jeff
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: How to implement bitboards?.. and some more questions

Post by Sven »

vittyvirus wrote:I want to use bitboard board representation system.

Code: Select all

class Board &#123;
public&#58;
    unsigned short WP&#91;64&#93;, WQ&#91;64&#93;, WK&#91;64&#93;, WN&#91;64&#93;, WB&#91;64&#93;, WR&#91;64&#93;;
    unsigned short BP&#91;64&#93;, BQ&#91;64&#93;, BK&#91;64&#93;, BN&#91;64&#93;, BB&#91;64&#93;, BR&#91;64&#93;;
    unsigned short allBoard&#91;64&#93;, W_Pieces&#91;64&#93;, B_Pieces&#91;64&#93;;
...
That's not bitboards. A bitboard in chess programming is a 64 bit number and represents a set of boolean properties, one for each square. When using bitboards for the board representation you might have something like:

Code: Select all

uint64 piece&#91;6&#93;;
uint64 color&#91;2&#93;;

void setPiece&#40;uint s, uint p, uint c&#41; &#123;
    assert&#40;s < 64&#41;;
    assert&#40;p < 6&#41;;
    assert&#40;c < 2&#41;;
    piece&#91;p&#93; |= &#40;1 << s&#41;;
    color&#91;c&#93; |= &#40;1 << s&#41;;
&#125;

void removePiece&#40;uint s, uint p, uint c&#41; &#123;
    assert&#40;s < 64&#41;;
    assert&#40;p < 6&#41;;
    assert&#40;c < 2&#41;;
    piece&#91;p&#93; &= ~&#40;1 << s&#41;;
    color&#91;c&#93; &= ~&#40;1 << s&#41;;
&#125;
Please have a look at the chess programming wiki which explains a lot about board representations and also about using bitboards for their implementation.

Another issue, code like the following ...

Code: Select all

switch&#40;move&#91;0&#93;) &#123;
    case 'a'&#58;
        file = 1;
        break;
    case 'b'&#58;
        file = 2;
        break;
    case 'c'&#58;
        file = 3;
        break;
    case 'd'&#58;
        file = 4;
        break;
    case 'e'&#58;
        file = 5;
        break;
    case 'f'&#58;
        file = 6;
        break;
    case 'g'&#58;
        file = 7;
        break;
    case 'h'&#58;
        file = 8;
        break;
    &#125;
&#125;
... is essentially equivalent to this much shorter form:

Code: Select all

file = move&#91;0&#93; + 1 - 'a';
if you can ensure that move[0] is not out of range.
vittyvirus wrote:My questions:
1) Provide at least one code sample from my code where you use bitboards to access individual pieces like I do in a array.
2) Is my code 'creepy' or difficult to understand?
3) Is my code fast?
4) Give me some advice to improve this code, if you have...
1) I do not understand your question, probably because it isn't a question ...
2) Yes + no.
3) No. You use about 15 arrays of 64 integers each, in total 2k (or 4k when using int instead of short, or 1k with char). And you are wasting a lot of instructions to copy redundant data around this way. Even for an array-based board representation you would only need something like 128 bytes plus a piece list.
4) See above ...

Sven
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: How to implement bitboards?.. and some more questions

Post by Ferdy »

This might be of help, apart from the maths that I learned from school, this is where I basically started learning what this bitboard is all about, after that cpw=chess programming wiki will carry you to wherever you want to go :).

http://www.mayothi.com/nagaskakichess6.html
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: How to implement bitboards?.. and some more questions

Post by Henk »

I don't understand why one should use bitboards for generating all moves. The engine can only apply one move at the time, so I need a separate bitboard for each move.

For captures it's a different story. For you only have one capture per direction.
User avatar
vittyvirus
Posts: 646
Joined: Wed Jun 18, 2014 2:30 pm
Full name: Fahad Syed

Re: How to implement bitboards?.. and some more questions

Post by vittyvirus »

To all of you:
Is

Code: Select all

square&#91;21&#93; = 1;
faster than

Code: Select all

square &= &#40;1ULL&#41; << 32;
?
Why is my code fast and slow?[/code]