BubbaTough wrote:
1. multiplication / division is not truly supported (they might define functions that fake it, but they just extract the values, do operations, and reinsert making it slower than keeping things in two different variables).
Multiplication is supported and safe (as long as you do not cause an overflow). Division does not work.
BubbaTough wrote:
2. negative values...I am not sure if these are gracefully handled during addition/subtraction. It seems maybe not? If not there is great risk for causing problems (such as calculating the net gain / loss of a PST entry from a move).
Addition/subtraction handles signed arithmetic correctly. Negative values are overflow-corrected when extracting individual (eg/mg) values.
rvida wrote:Addition/subtraction handles signed arithmetic correctly. Negative values are overflow-corrected when extracting individual (eg/mg) values.
Set score1 as (mg=6000, eg=7000) and score2 as (mg=25000, eg=26000). Calculate score1+score2 and extract the MG part, is it 31000?
I know that such high values usually do not occur in the evaluation of centipawn-based engines but shouldn't the system be safe for the whole range of 16 bit?
rvida wrote:Addition/subtraction handles signed arithmetic correctly. Negative values are overflow-corrected when extracting individual (eg/mg) values.
Set score1 as (mg=6000, eg=7000) and score2 as (mg=25000, eg=26000). Calculate score1+score2 and extract the MG part, is it 31000?
I know that such high values usually do not occur in the evaluation of centipawn-based engines but shouldn't the system be safe for the whole range of 16 bit?
Sven
Sevn , as long as I understand 26000 + 7000 = 33000 and here you have an overflow (signed 16 bit number overflows at 32768).
BTW it is true that multiplication is natively supported, but we considered that the risk of overflow is very high, so we purposely only declared the multiply operator:
/// Only declared but not defined. We don't want to multiply two scores due to
/// a very high risk of overflow. So user should explicitly convert to integer.
inline Score operator*(Score s1, Score s2);
This does not mean that we have a specialized operator for multiply, actually it means exactly the opposite ! We have forbid it.
rvida wrote:Addition/subtraction handles signed arithmetic correctly. Negative values are overflow-corrected when extracting individual (eg/mg) values.
Set score1 as (mg=6000, eg=7000) and score2 as (mg=25000, eg=26000). Calculate score1+score2 and extract the MG part, is it 31000?
I know that such high values usually do not occur in the evaluation of centipawn-based engines but shouldn't the system be safe for the whole range of 16 bit?
Sven
Sven , as long as I understand 26000 + 7000 = 33000 and here you have an overflow (signed 16 bit number overflows at 32768).
Ok, so the mechanism does exclude adding two score pairs where adding the two EG parts results in an overflow. Even though this is simple to understand, one has to be aware of it, and using terms like "overflow-corrected" and "handles signed arithmetic correctly" can be misleading even though they were in fact used correctly. The inherent restriction of using signed 16 bit scores is not only the range of -32768 .. +32767 for the scores itself but also that adding (or subtracting) two such scores must not result in an overflow.
Of course this is also the case for any other implementation of score pairs, including the "struct" solution For this reason, at least those engines using a higher resolution than centipawns should probably not use 16 bit scores, whether packed or not.
rvida wrote:Addition/subtraction handles signed arithmetic correctly. Negative values are overflow-corrected when extracting individual (eg/mg) values.
Set score1 as (mg=6000, eg=7000) and score2 as (mg=25000, eg=26000). Calculate score1+score2 and extract the MG part, is it 31000?
I know that such high values usually do not occur in the evaluation of centipawn-based engines but shouldn't the system be safe for the whole range of 16 bit?
Sven
Sven , as long as I understand 26000 + 7000 = 33000 and here you have an overflow (signed 16 bit number overflows at 32768).
Ok, so the mechanism does exclude adding two score pairs where adding the two EG parts results in an overflow. Even though this is simple to understand, one has to be aware of it, and using terms like "overflow-corrected" and "handles signed arithmetic correctly" can be misleading even though they were in fact used correctly. The inherent restriction of using signed 16 bit scores is not only the range of -32768 .. +32767 for the scores itself but also that adding (or subtracting) two such scores must not result in an overflow.
Of course this is also the case for any other implementation of score pairs, including the "struct" solution For this reason, at least those engines using a higher resolution than centipawns should probably not use 16 bit scores, whether packed or not.
Sven
I'm not sure what you're complaining about the overflow for. The same is true of 16-bit signed types, which you presumably store in your TT entries, right?
If you want to do intermediate calculations with more precision, you have to unpack the ScorePair, sure. I can't imagine any reason to need to do that though--since you have to end up with a score that fits in 16 bits anyway, extra intermediate precision doesn't seem like it buys you much.
To put it another way: Where in your eval do you calculate part of a score or weight etc. that takes more than 16 bits to represent?