Zach Wegner wrote:Hello Gerd and everyone else,Gerd Isenberg wrote:

- Code: Select all
`u64 rayBB = occupiedBB & rayMask[sq];`

u32 fold = (u32)(rayBB) | (u32)(rayBB>>32);

u32 occ64 = (fold * 0x02020202) >> (32-6);

...

Problem are the vertical files, where all masked occupied bits reside on the same file.

I was playing with these ideas, and I found, using a modified version of Walter Faxon's/Tony's magic finder, how to do a 32-bit folded lookup with one multiply:

- Code: Select all
`u64 rayBB = occupiedBB & fileMask[sq];`

u32 fold = (u32)(rayBB) | (u32)(rayBB>>29);

u32 occ64 = (fold * 0x01041041) >> (32-6);

All magics with the same lower 25 bits give the same result, and you can probably change with the 29. It's an interesting magic because each of the bits are 6 away from each other == the number of bits in the index.

Regards,

Zach

Hi Zach,

well, i have some problems with your 5-bit factor to map masked six inner occupied file bits to some occupied64 state 32-bit wise! I think that problem is solved so far, as demonstrated in the posted 64/32-bit source.

Some further explanation on the file-flipping, to make things clear:

Assume a1,b1,...,h8 == 0,1,...,,63 square-bitindex-mapping. For h1,a8 == 0,63 mapping, simply mirror the files a-h,b-g etc.. The six inner bits of the a-file, a2..a7 are masked, all other bits zero. 64-bit arithmetic first, to get the index in the six upper bits (before >> 58): We need to map a2->c8, a3->d8, .a7->h8, thus we need to shift left six bits by different amounts:

- Code: Select all
`a2->c8 8->58 <<50`

a3->d8 16->59 <<43

a4->e8 24->60 <<36

a5->f8 32->61 <<29

a6->g8 40->62 <<22

a7->h8 48->63 <<15

Since our fileBB contains set bit only in an eight-bit distance, and all six shifts have a delta of seven, each shift containts disjoint sets of bits, ....

- Code: Select all
`( fileBB << 50 )`

| ( fileBB << 43 )

| ( fileBB << 36 )

| ( fileBB << 29 )

| ( fileBB << 22 )

| ( fileBB << 15 )

- Code: Select all
`( fileBB << 50 )`

+ ( fileBB << 43 )

+ ( fileBB << 36 )

+ ( fileBB << 29 )

+ ( fileBB << 22 )

+ ( fileBB << 15 )

... and finally replace the whole shift,add expression by 64-bit multiplication with the h2-c7 antidiagonal:

- Code: Select all
`fileBB * 0x0004081020408000`

- Code: Select all
`occ64 = (fileBB * 0x0004081020408000) >> (64-6);`

That only works for the masked a-file so far, with the masked b-file we need to shift one less each. And so on with other files

- Code: Select all
`A-fileBB * 0x0004081020408000`

B-fileBB * 0x0002040810204000

C-fileBB * 0x0001020408102000

D-fileBB * 0x0000810204081000

E-fileBB * 0x0000408102040800

F-fileBB * 0x0000204081020400

G-fileBB * 0x0000102040810200

H-fileBB * 0x0000081020408100

or

- Code: Select all
`maskedFileBB * (0x0004081020408000 >> file);`

Instead of masking the file and to shift the factor right, i prefere to safe the filemask memory access but shifting right the occupied bitboard, to mask the a-File by constant:

- Code: Select all
`((occupied >> file) & 0x0101010101010101) * 0x0004081020408000`

The proplem i had, to map the first rank attacks to the h-file was the bit-distance inside the factors. Here a 7-bit distance, antidiagonal factor resulted in overflows, since shifted rank attacks would overlap by one bit. Thus the need for the nine bit distance factor, the a1-h8 diagonal, 0x8040201008040201, and to consider the reversed result with the reversed occupied index factor 0x0080402010080400, the c2-h7 diagonal.

For 32-bit there are some options to fold both halfs to get disjoint multiplication as well. I prefere symmetrical 4-bit distance which also works for mapping all eight bits, see my fileAttacks 32-bit code. All my file-rank mapping factors are either diagonals or antidiagonals, while your 32-bit factor seems to have a strange square pattern. at least with my mapping a1,a4,c3,e2,g1?

Did i miss something?

Cheers,

Gerd