First One

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Jose Carlos
Posts: 151
Joined: Wed Mar 08, 2006 10:09 pm
Location: Murcia (Spain)

First One

Post by Jose Carlos »

Hi. Sorry if this has already been answered before.
I'm trying to compile an old engine of mine in 64 bits. I have some old asm code for FirstOne() (left and right, I mean, MSB and LSB) which won't compile for X64.
Is there some C code out there I can use for the tasks?
I don't care much for speed. I just want it to be problem-free.

Thanks in advance.
__________________________
José Carlos Martínez Galán
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: First One

Post by Sven »

José Carlos wrote:Hi. Sorry if this has already been answered before.
I'm trying to compile an old engine of mine in 64 bits. I have some old asm code for FirstOne() (left and right, I mean, MSB and LSB) which won't compile for X64.
Is there some C code out there I can use for the tasks?
I don't care much for speed. I just want it to be problem-free.

Thanks in advance.
Hi José,

have you already taken a look into the chess programming wiki? In case you haven't: go to the BitScan page and search for bitScanForward and bitScanReverse, there are several variants for both.

Sven
User avatar
Jim Ablett
Posts: 1383
Joined: Fri Jul 14, 2006 7:56 am
Location: London, England
Full name: Jim Ablett

Re: First One

Post by Jim Ablett »

I use these a lot >

Code: Select all

#include <assert.h>

const uint64_t magic = 0x03f79d71b4cb0a89;


const unsigned int magictable&#91;64&#93; =
    &#123;
    0,  1, 48,  2, 57, 49, 28,  3,
    61, 58, 50, 42, 38, 29, 17,  4,
    62, 55, 59, 36, 53, 51, 43, 22,
    45, 39, 33, 30, 24, 18, 12,  5,
    63, 47, 56, 27, 60, 41, 37, 16,
    54, 35, 52, 21, 44, 32, 23, 11,
    46, 26, 40, 15, 34, 20, 31, 10,
    25, 14, 19,  9, 13,  8,  7,  6,
    &#125;;


static int bitscan_forward&#40;uint64_t bb&#41; &#123;
assert &#40;bb != 0&#41;;
return magictable&#91;(&#40;bb&-bb&#41;*magic&#41; >> 58&#93;;
&#125;


static inline int bitscan_reverse&#40;uint64_t bb&#41; &#123;
    union &#123;
    double d;
    struct &#123;
    unsigned int mantissal &#58; 32;     
    unsigned int mantissah &#58; 20;     
    unsigned int exponent &#58; 11;     
    unsigned int sign &#58; 1;     
    &#125;;
    &#125; ud;
    ud.d = &#40;double&#41;&#40;uint64_t&#41;&#40;bb & ~&#40;bb >> 32&#41;);
    int idx = &#40;ud.exponent - 1023&#41; | &#40;63*ud.sign&#41;;
    return idx;
    &#125;


Jim.
Jose Carlos
Posts: 151
Joined: Wed Mar 08, 2006 10:09 pm
Location: Murcia (Spain)

Re: First One

Post by Jose Carlos »

Thanks a lot to both. Really useful :)
__________________________
José Carlos Martínez Galán
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: First One

Post by bob »

José Carlos wrote:Hi. Sorry if this has already been answered before.
I'm trying to compile an old engine of mine in 64 bits. I have some old asm code for FirstOne() (left and right, I mean, MSB and LSB) which won't compile for X64.
Is there some C code out there I can use for the tasks?
I don't care much for speed. I just want it to be problem-free.

Thanks in advance.
Look in the crafty source. You can find two inline functions for LSB and MSB, which will use the BSF/BSR instructions... Trivial piece of code...
jdart
Posts: 4366
Joined: Fri Mar 10, 2006 5:23 am
Location: http://www.arasanchess.org

Re: First One

Post by jdart »

There are intrinsics for this in most compilers.

Here is some code I have (returns InvalidSquare if 'data' is 0, the first bit otherwise, using intrinsics):

Code: Select all

#elif defined&#40;_WIN64&#41; && defined&#40;_MSC_VER&#41; && defined&#40;USE_INTRINSICS&#41;
      DWORD index;
      if (_BitScanForward64&#40;&index,data&#41;)
        return &#40;Square&#41;index;
      else 
        return InvalidSquare;
#elif defined&#40;USE_INTRINSICS&#41; && defined&#40;__INTEL_COMPILER&#41;
      if &#40;lovalue&#40;)) &#123;
         return _bit_scan_forward&#40;lovalue&#40;));
      else if &#40;hivalue&#40;)) &#123;
         return _bit_scan_forward&#40;hivalue&#40;))+32;
      &#125; else &#123;
         return InvalidSquare;
      &#125;  
#elif defined&#40;USE_INTRINSICS&#41; && defined&#40;__GNUC__)
      int tmp = __builtin_ffsll&#40;data&#41;;
      if &#40;tmp == 0&#41; return InvalidSquare;
      else return tmp-1;
Ron Murawski
Posts: 397
Joined: Sun Oct 29, 2006 4:38 am
Location: Schenectady, NY

Re: First One

Post by Ron Murawski »

jdart wrote:There are intrinsics for this in most compilers.

Here is some code I have (returns InvalidSquare if 'data' is 0, the first bit otherwise, using intrinsics):

Code: Select all

#elif defined&#40;_WIN64&#41; && defined&#40;_MSC_VER&#41; && defined&#40;USE_INTRINSICS&#41;
      DWORD index;
      if (_BitScanForward64&#40;&index,data&#41;)
        return &#40;Square&#41;index;
      else 
        return InvalidSquare;
#elif defined&#40;USE_INTRINSICS&#41; && defined&#40;__INTEL_COMPILER&#41;
      if &#40;lovalue&#40;)) &#123;
         return _bit_scan_forward&#40;lovalue&#40;));
      else if &#40;hivalue&#40;)) &#123;
         return _bit_scan_forward&#40;hivalue&#40;))+32;
      &#125; else &#123;
         return InvalidSquare;
      &#125;  
#elif defined&#40;USE_INTRINSICS&#41; && defined&#40;__GNUC__)
      int tmp = __builtin_ffsll&#40;data&#41;;
      if &#40;tmp == 0&#41; return InvalidSquare;
      else return tmp-1;
Hi Jon,

for GCC you can use this instead:

Code: Select all

#elif defined&#40;USE_INTRINSICS&#41; && defined&#40;__GNUC__)
      int tmp = __builtin_ctzll&#40;data&#41;;
      if &#40;tmp == 0&#41; return InvalidSquare;
      else return tmp;
it will save you the subtraction
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: First One

Post by lucasart »

José Carlos wrote:Hi. Sorry if this has already been answered before.
I'm trying to compile an old engine of mine in 64 bits. I have some old asm code for FirstOne() (left and right, I mean, MSB and LSB) which won't compile for X64.
Is there some C code out there I can use for the tasks?
I don't care much for speed. I just want it to be problem-free.

Thanks in advance.
From Stockfish. fast and portable

Code: Select all

static const unsigned BitTable&#91;NB_SQUARE&#93; = &#123;
	0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 34, 20, 40, 5, 17, 26, 38, 15,
	46, 29, 48, 10, 31, 35, 54, 21, 50, 41, 57, 63, 6, 12, 18, 24, 27, 33, 39,
	16, 37, 45, 47, 30, 53, 49, 56, 62, 11, 23, 32, 36, 44, 52, 55, 61, 22, 43,
	51, 60, 42, 59, 58
&#125;;

unsigned first_bit&#40;uint64_t b&#41;
/* From Stockfish */
&#123;
	return BitTable&#91;(&#40;b & -b&#41; * 0x218a392cd3d5dbfULL&#41; >> 58&#93;;
&#125;