Gerd Isenberg wrote:Michael Sherwin wrote:- Code: Select all
u08 hiBishopShifts[] = {
35, 37, 38, 32, 32, 33, 33, 33,
35, 35, 37, 38, 33, 33, 33, 33,
33, 33, 33, 33, 33, 33, 33, 33,
33, 33, 33, 33, 33, 33, 33, 33,
33, 33, 33, 33, 33, 33, 35, 37,
33, 33, 33, 33, 33, 33, 33, 37,
33, 33, 33, 33, 33, 35, 33, 37,
33, 33, 33, 33, 33, 33, 35, 35};
uo8 loBishopShifts[] = {
16, 17, 19, 19, 17, 17, 18, 16,
16, 16, 16, 17, 18, 18, 16, 17,
17, 17, 17, 17, 17, 17, 17, 17,
16, 16, 16, 16, 16, 16, 18, 18,
17, 17, 17, 17, 16, 16, 17, 21,
17, 17, 15, 17, 17, 17, 19, 17,
18, 20, 20, 20, 17, 16, 16, 17,
16, 17, 16, 16, 16, 17, 16, 16};
u64 BishopAttacks(u64 occ, u32 sq) {
u32 loc;
u32 hoc;
occ &= bishopBits[sq];
hoc = (u32)(occ >> hiBishopShifts[sq]);
loc = ((u32)occ | hoc);
loc = (loc & 0xffff) | (loc >> loBishopShifts[sq]);
return bishopAttackSet[bishopOffsets[64] + loc];
}
This is the fastest expression of the code, however, it requires an enormous lookup table--many megabytes. Memory is cheap and speed is well, speed! I believe that modern computers will run fastest with the code as is. It is a starting place. An obvious memory saving modification is to split the 11 - 15 bit index loc into two eight bit indexs. Then on 32 bit machines retrive two index fragments and by oring them together form an index into the bishop attack set table. On 64 bit machines just retrieve two possible attack sets and by anding them together the correct attack set is formed!
This folding down seems an interesting parallel prefix alternative to the mul/shift right approach and reminds me on Walter Faxon's bitscan. May be it is better to use "add" or "sub" instead of "or" - and to eventually provide a final "and" for the index.
- Code: Select all
occ &= bishopBits[sq];
hoc = (u32)(occ >> hiBishopShifts[sq]);
loc = (u32)occ + hoc;
loc = (loc + (loc >> loBishopShifts[sq])) & maskFinalBishopIndex[sq];
Gerd
Hi Gerd,
I think that I understand your suggestion now!
1. Use '+' when possible to not over burden the logical engine of the processor and adding
may just be faster anyway!?
2. Do a final masking to get rid of any spurious bits!?
I could be wrong, but, I did select the shift values carefully to avoid any spurious bits. I
will double check my logic to see if that is true.
Here anyway, is the rook attack set getter and a new bishop ... getter that is designed after
the rook ... getter.
I will add the data to drive them and an explaination when I get a chance.
- Code: Select all
u64 RookAttacks(u64 occ, u32 sq) {
u32 index;
occ &= rookBits[sq];
index = (u32)((occ & rankMask[sq]) >> rankShifts[sq]);
index += (u32)((occ & hiFileMask[sq]) >> hiFileShifts[sq]);
index += ((u32) ooc & loFileMask[sq]);
index += ((index & 0xffff0000) >> loFileShifts[sq]);
return (rookAttacks[rookOffsets[sq] + index]);
}
u64 BishopAttacks(u64 occ, u32 sq) {
u32 index;
occ &= bishopBits[sq];
index = (u32)(occ) + (u32)(occ >> hiBishopShifts[sq])
+ ((u32)occ & 0xffff0000) >> loBishopShifts[sq]);
return (bishopAttacks[bishopOffsets[sq] + index]);
}
Hi all,
These are baseline functions to be used as a starting point. All indexs generated are
contained in 16 bits or less, however, they still require huge amounts of ram for the attack
tables. Memory compression techniques will have to be added if you want to minimise memory
usage. I have thought of at least a dozen ways to greatly reduce memory usage with only a
very slight slowdown of the algorithm. I did not want to cloud the basic algorithm by including
any compression methods in the code. However, I have mentioned several already in this
thread--some of wich may actually work. I hope that programmers will like what I have already
done and want to contribute some good compression ideas. Of course, if I am deluded and my
code is crap, I am sure that someone will let me know--I welcome that!
Thanks,
Mike