Understanding first rank attack state generation
Moderators: hgm, Rebel, chrisw
-
- Posts: 2566
- Joined: Fri Nov 26, 2010 2:00 pm
- Location: Czech Republic
- Full name: Martin Sedlak
Re: Understanding first rank attack state generation
My guess is because masking by 2*63 already gives you a value that's already multiplied by two, masking out the LSBit
-
- Posts: 9
- Joined: Sun May 12, 2019 1:41 pm
- Full name: Kalyankumar Ramaseshan
Re: Understanding first rank attack state generation
May be correct ("May be!"). But the following argument makes me think otherwise:
When you generate rank attacks (generate_rank_attacks() - see my post earler for the code) it is invoked as:
Ideally every square is multiplied by 2 (the multiplication by 2 is needed since the edge bits should be masked and only 6 bits should be considered) and passed as occupancy to generate_rank_attacks() which then works it way through the file bits stopping at the blocker bit in either directions to generate rank attacks. This is when initializing the rank attacks. But what happens when looking up for the rank attacks when you actually get an rank occupancy bitboard is what is shown in the code below:
What I am still not convinced with my understanding and reasoning is this:
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.
When you generate rank attacks (generate_rank_attacks() - see my post earler for the code) it is invoked as:
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;
}
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
Thanks,
Kalyan
Kalyan
-
- Posts: 2250
- Joined: Wed Mar 08, 2006 8:47 pm
- Location: Hattingen, Germany
Re: Understanding first rank attack state generation
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
-
- Posts: 9
- Joined: Sun May 12, 2019 1:41 pm
- Full name: Kalyankumar Ramaseshan
Re: Understanding first rank attack state generation
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 ...
While looking up the rankattacks array the computation if index uses occupancy multipled by 4 instead of 8, why?
Code: Select all
4*occ + file
Thanks,
Kalyan
Kalyan
-
- Posts: 2250
- Joined: Wed Mar 08, 2006 8:47 pm
- Location: Hattingen, Germany
Re: Understanding first rank attack state generation
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;
}
-
- Posts: 9
- Joined: Sun May 12, 2019 1:41 pm
- Full name: Kalyankumar Ramaseshan
Re: Understanding first rank attack state generation
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; }
Thanks,
Kalyan
Kalyan