[fpc-devel] Question to developers

J. Gareth Moreton gareth at moreton-family.com
Fri Sep 17 17:55:05 CEST 2021


Hi everyone,

I have a question for third-party developers, especially mathematical, 
scientific and games programmers...

How often would you use a construct akin to "case x mod n of", where n 
is a constant and not a power of 2?  I ask because while I wait for my 
"(x mod n) = 0" optimisation to be approved, I've discovered that it 
could be extended to cover remainders other than 0.  For example, 
starting with (x mod 3) = 0 (unsigned 32-bit using Intel notation):

MOV EAX, x
IMUL EAX, $AAAAAAAB
CMP EAX, $55555555
JBE @Remainder0

For (x mod 3) = 1:

MOV EAX, x
IMUL EAX, $AAAAAAAB
SUB EAX, $AAAAAAAB
CMP EAX, $55555554
JBE @Remainder1

Which in this case, can be simplified to:

MOV EAX, x
IMUL EAX, $AAAAAAAB
CMP EAX, $AAAAAAAB
JAE @Remainder1

To keep with the simple case of n and 2^32 being relatively prime (i.e. 
n is odd), this is due to the fact that for a given divisor n, you can 
calculate its multiplicative inverse r such that nr = 1 (mod 2^32).  
Then if x is a multiple of n, it can be written as kn for some integer 
k, and (kn)r = k (mod 2^32), and because n and 2^32 are relatively 
prime, the domain has an exact one-to-one mapping onto the range, so the 
output k cannot be produced by any other input after being multiplied by 
r, and k falls in the range 0 to floor(2^32 / n), which is 0 to 
$55555555 for n = 3.

For remainder 1, x has the form kn + 1, and when multipled by r, the 
result is congruent to k + r (mod 2^32).  Because of the 1-to-1 mapping, 
the ranges of k and k + r will not overlap, and in the case for a 
divisor of 3 and a remainder of 1, maps onto the linear range $AAAAAAAB 
(k = 0) to $FFFFFFFF (k = $55555554).  For completion, for divisor 3 and 
a remainder of 2, the range is $55555556 to $AAAAAAAA (note that 2r = 
$55555556 (mod 2^32)).

I still got a couple of nuances to figure out, such as what to do with 
even values of n and the exact length of each range (for n = 3, k can 
range from 0 to $55555555 for remainder 0, but only 0 to $55555554 for 
remainders 1 and 2... this is because $FFFFFFFF is an exact multiple of 3).

So long story short, would optimisations for "(x mod n) = c" and "case 
(x mod n) of" be welcome, or is it overkill and "(x mod n) = 0" more 
than enough?

Gareth aka. Kit


-- 
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus



More information about the fpc-devel mailing list