Re: Understanding first rank attack state generation
Posted: Wed Oct 09, 2019 8:53 pm
My guess is because masking by 2*63 already gives you a value that's already multiplied by two, masking out the LSBit
Computer Chess Club
https://talkchess.com/
Code: Select all
generate_rank_attacks(2 * sq, file);
Code: Select all
BYTE arrFirstRankAttacks64x8[64*8]; // 512 Bytes = 1/2KByte
U64 rankAttacks(U64 occ, enumSquare sq) {
unsigned int file = sq & 7;
unsigned int rkx8 = sq & 56; // rank * 8
occ = (occ >> rkx8) & 2*63;
U64 attacks = arrFirstRankAttacks64x8[4*occ + file];
return attacks << rkx8;
}
Code: Select all
4*occ + file
Sorry for the confusion. I will comment the routine a little bit more ...kalyan4code wrote: ↑Thu Oct 10, 2019 5:21 amWhat I am still not convinced with my understanding and reasoning is this:Code: Select all
BYTE arrFirstRankAttacks64x8[64*8]; // 512 Bytes = 1/2KByte U64 rankAttacks(U64 occ, enumSquare sq) { unsigned int file = sq & 7; unsigned int rkx8 = sq & 56; // rank * 8 occ = (occ >> rkx8) & 2*63; U64 attacks = arrFirstRankAttacks64x8[4*occ + file]; return attacks << rkx8; }
When looking up given the rank occupancy bit board after masking it through right shift rank multiplier (rank * 8 - this gets the rank occupancy to LSBits) and masking off LSBits (2 * 63 = 126 = 0b01111110 - take only 6 bits) the calculation of the index using the formula as shown below is still not very clear and I'm not understanding what's written in CPW page regarding scaling by 4 instead of 8. I think this in first place requires a clarification and second the wiki page should be corrected to read the statement properly so that layman like me can understand much better.Code: Select all
4*occ + file
Code: Select all
unsigned int rankOccX2 = (occ >> rkx8) & 2*63; // 2 times the inner six bit rank occupancy used as index
U64 attacks = arrFirstRankAttacks64x8[4*rankOccX2 + file]; // 8 * rank occupancy
Thanks Gerd. That was clear to me already. But still my question remains unanswered:Sorry for the confusion. I will comment the routine a little bit more ...
Code: Select all
4*occ + file
Code: Select all
BYTE arrFirstRankAttacks64x8[64][8]; // 512 Bytes = 1/2KByte
U64 rankAttacks(U64 occ, enumSquare sq) {
unsigned int file = sq & 7;
unsigned int rkx8 = sq & 56; // rank * 8
occ = ((occ >> rkx8) >> 1) & 63; // occ = (occ >> (rkx8+1)) & 63;
U64 attacks = arrFirstRankAttacks64x8[occ][file]; // aka 8*occ + file
return attacks << rkx8;
}
Thanks Gerd. Appreciate this level of clarity described in this CPW page/section.Gerd Isenberg wrote: ↑Thu Oct 10, 2019 11:38 am Because of the inner six bit mask with 01111110b, which would usually require an additional shift right 1 for a 0..63 range, is already implicitly multiplied by two (0,2,4,....126). With a two-dimensional array it takes one additional instruction
Code: Select all
BYTE arrFirstRankAttacks64x8[64][8]; // 512 Bytes = 1/2KByte U64 rankAttacks(U64 occ, enumSquare sq) { unsigned int file = sq & 7; unsigned int rkx8 = sq & 56; // rank * 8 occ = ((occ >> rkx8) >> 1) & 63; // occ = (occ >> (rkx8+1)) & 63; U64 attacks = arrFirstRankAttacks64x8[occ][file]; // aka 8*occ + file return attacks << rkx8; }