about pst

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Flipping squares

Post by bob »

AlvaroBegue wrote:
bob wrote:
sje wrote:

Code: Select all

flipsq = Flip[sq];
is slower than

Code: Select all

flipsq = sq ^ 0x38;
For those that use 0-63 of course. :)

There are still a few mailboxers around.
It's `sq ^ 0x70' for mailboxers.
ONLY if you use 0x88. Cray Blitz didn't, for example.
User avatar
hgm
Posts: 27790
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: about pst

Post by hgm »

hgm wrote:In my new engine Simple I even store the eg and op values in the same table (pst[7][64]) of 32-bit integers, as (op-eg/3)*N + eg, where N is the constant 2^16. I have a game phase that runs from 0 (eg) to 24 (op). In the evaluation I then calculate (8*N+gamePhase)*pstEval>>19. Some algebra shows that this is equal to

({N*N*8*(op-eg)/3} + N*(gamePhase*(op-eg)/3 + 8*eg) + gamePhase*eg) >> 19

The part in braces contains a factor 2^32, and is thus clipped off the 32-bit result by overflow. Shifting right by 16 bits pushes the term gamePhase*eg (which is smaller than 2^16, eg running only upto 4000 or so even if the piece ase value is included in the PST) out of the int, and undoes the multiplication by N on the remaining term, so that it would leave you with

gamePhase/3 * (op-eg) + 8*eg

(give or take some rounding), where gamePhase/3 runs from 0 to 8 (so let us call that 8*phi). The result is then

8*(phi*op + (1-phi)*eg)

which is 8 times the sought interpolated result. Currently the factor 8 is also removed by right-shifting 3 bits extra (19 instead of 16) ...
It occurred to me that I could limit the rounding error in (op-eg)/3 by not clipping it to an integer, but allow 3 bits of fraction to it. In the PST store

(8*(op-eg)/3)*N/8 + eg

When this is multipled by 8*N+gamePhase the term

(8*(op-eg)/3)*N/8 * 8*N

still contains a factor N*N (as the division by 8 was exact and thus cancels the factor 8 in 8*N, N being 2^16), and is thus pushed out of the 32-bit int by overflow. What remains is

N*(8*eg + (8*(op-eg)/3)/8 * gamePhase) + gamePhase*eg

The rightmost term gets negligible (and rounded away) after division by N (right-shift by 16), so that we are left with

8*eg + (8*(op-eg)/3)/8 * gamePhase

The difference with the previous result (which did not have the 8* and /8 on the (op-eg)/3 factor) is that the rounding error in the (integer) division by 3 is divided by 8 afterwards. When no rounding is taking place (i.e. when op-eg happens to be a multiple of 3) the result remains the same, namely

8*(eg + (op-eg)*gamePhase/24)