On Fri, 7 Aug 2020, Joern Wolfgang Rennecke wrote:


On 07/08/20 19:21, Marc Glisse wrote:

If we are going to handle the wrapping case, we shouldn't limit to the non-wrapping meaning of multiplicity. 3*X==5 should become X==1431655767 (for a 32 bit type), etc.

Do we have an extended gcd somewhere in gcc, to help compute 1431655767?
I don't quite see yet how this relates to gcd,

https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm is the most common way to compute the modular multiplicative inverse of a number. For 3 and 2^32, it could tell us that 2863311531*3-2*2^32=1, so modulo 2^32 2863311531*3==1, and 3*X==5 is the same as 2863311531*3*X==2863311531*5, i.e. X==1431655767.

However, there are cases were the second division will not be possible without rest.
Consider : 7*X == 3
3/7 is 0 rest 3.
0x100000000 / 7 is 0x24924924 rest 4
Since 3 cannot be represented as an integer multiple of -4, we can conclude that the predicate
is always false.

613566757*7-2^32==3

Also: 14*X == 28
has a non-zero power of two in the constant factor, so we have to factor out the power of two (if the right hand side has a lower power of two, the predicate is always false) and consider in modulo arithmetic with a number of bits less by the factored out power of two, i.e. 31 bit here:
7*X == 14
which is solved as above - but in 32 bit arithmetic - to
X == 2
and to convert back to 32 bit arithmetic, we get:
X & 0x7fffffff == 2
or
2*x == 4

Yes, we can reduce the size of the numbers a bit, but the gains won't be as nice for even numbers. I think the always-false case is already handled by CCP, tracking which bits can be 0 (I didn't check).

--
Marc Glisse

Reply via email to