Computer Chess Club Archives


Search

Terms

Messages

Subject: Another hacky method for bitboard bit extraction

Author: Walter Faxon

Date: 15:49:27 11/17/02

Go up one level in this thread


Hi, Joel.

Here's my hack to find, remove and report the low-order bit in a bitboard.
I find it a little faster than Gerd's generic solution, but you should
experiment.  Also, strangely, coding either method as a macro rather than
as an inline function can sometimes improve speed, depending on the compiler.

-- Walter

Code follows:
// ---------------------------------------------------------------------------

typedef unsigned long long  u64;    // nonstandard
typedef unsigned long       u32;
typedef unsigned char       u8;

extern const u8 LSB_64_table[154];              // bit number table
#define LSB_64_adj  -51                         // offset to table base
#define LSB_64_magic  ( (u32)0x01C5FC81 )       // magic constant

// ---------------------------------------------------------------------------
// LSB_64() -- find, remove, report least-significant bit of 64.
// Argument 'bb' must be non-null.  Method:  fold then table lookup.
// Written by Walter Faxon, June 2002.  No copyright.  No warranty.
//
inline                  // inline declaration may differ by compiler
u8 LSB_64( u64* bb )
    {
    u64 t64;
    u32 t32;
    t64 = *bb - 1;
    *bb &= t64;         // omit this line to retain current LSB
    t64 ^= *bb;
    t32 = (u32)t64 ^ (u32)(t64 >> 32);
    t32 ^= LSB_64_magic;
    t32 += t32 >> 16;
    t32 -= t32 >> 8;
    return LSB_64_table [LSB_64_adj + (u8)t32];
    }

// ---------------------------------------------------------------------------
// Table reports number of low-order bit as 0, high-order as 63.
// (Numbering can be reversed by changing this table.)
// Important:  arrange storage so that this table is kept in the cache.
const u8 LSB_64_table[154] =
    {
#define __  0
    23,__,__,__,31,__,__,39,19,__, 17,16,18,__,47,10,20, 9, 8,11,
     1, 0, 2,57,56,58, 3,12,__,59, __,__,21,__, 4,__,__,60,__,__,
    __,__,__,13,__,__,__,__,__,__,  5,__,__,61,__,__,__,__,__,__,
    __,__,__,__,22,__,__,__,30,__, __,38,__,__,__,14,__,__,46,__,
    __,__, 6,__,__,62,__,__,__,54, __,__,__,__,__,__,__,__,__,__,
    29,__,__,37,__,__,__,__,__,__, 45,__,__,__,__,__,28,__,__,36,
    __,53,__,__,27,__,44,35,26,24, 25,34,32,33,43,40,41,52,42,15,
    __,50,48,49,__,51, 7,__,__,63, __,__,__,55
#undef __
    };

//eof
===============================================================================
On November 17, 2002 at 16:00:35, Gerd Isenberg wrote:

>Hi Anthony,
>
>i havn't compared it in an simple loop running n times and mesured the time.
>The effect in my chess program is rather significant, a few percent if i
>remember well. To traverse bitboards, i use this version, which resets the found
>bit as well:
>
>__forceinline UINT BitSearchAndReset(BitBoard &bb)
>{
>#ifdef	_M_IX86
>#ifdef FASTEST_AND_SAFEST
>	__asm
>	{
>		xor		edx, edx
>		mov		ebx, [bb]
>		mov		eax, edx
>		inc		edx
>		bsf		ecx, [ebx]
>		jnz		found
>		bsf		ecx, [ebx + 4]
>		lea		ebx, [ebx + 4]
>		xor		eax, 32
>	found:
>		shl		edx, cl
>		xor		eax, ecx
>		xor		[ebx], edx
>	}
>#else
>	__asm
>	{
>		mov		edx, [bb]
>		bsf		eax, [edx+4]
>		xor		eax, 32
>		bsf		eax, [edx]
>		btr		[edx],eax
>	}
>#endif
>
>#else	// _M_IX86
>	BitBoard lsbb = bb & (-(__int64)bb);
>	bb ^= lsbb;
>	UINT32 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
>}



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.