Expand/Shrink

remainder / mod

Definition: atom res = remainder(atom x, y)
-- or --
atom res = rmdr(atom x, y)
-- or --
atom res = mod(atom x, y)
Description: Compute the remainder after dividing x by y, using floored division in the case of mod().

An error occurs when y is zero, otherwise the magnitude of the result is less than that of y, ie abs(res) < abs(y).
When the two operands have the same sign, mod() returns the same result as remainder().
When the signs are different mod() rounds away from zero whereas remainder() rounds towards zero.
The result of mod() has the same sign as y, whereas that of remainder() has the same sign as x.
rmdr() is just a simple alias of remainder() and thus always behaves identically, ditto sq_rmdr() and sq_remainder().
There is no infix % operator, instead you must use rmdr()/mod() and that way explicitly choose the desired behaviour.

Should you be confident that x and y always have the same sign, stick to remainder/rmdr, since that is faster.
pwa/p2js: Supported.
Comments: These functions may be applied to an atom or sq_rmdr(), sq_mod() to all elements of a sequence.
The rules for sequence operations apply.

The Phix implementation of mod() tries to yield the same results as plain C, however (I wasn’t expecting this, either!) a quick glance at https://en.wikipedia.org/wiki/Modulo_operation#In_programming_languages reveals the modulus operation is just about as far from a standard thing as anything could ever be.

As of 1.0.2, the odd(x) and even(x) builtins outperform use of remainder|mod(x,2).
(There is, incidentally, no performance difference between odd/even and and_bits(x,1), just so you know.)
Also note that remainder(x,2) yields -1, not +1, for negative odd integers, which may very well [sometimes be desired and] sometimes be a latent bug, as in unnoticed or automatically fixed/introduced by switching to odd()/even().

NB modular arithmetic is brainache personified. While I have tried my level best here to explain the differences between remainder() and mod(), in practice when one doesn’t work I simply just try the other, and there will doubtless be instances within this very documentation where I have inadvertently mixed them up. The intellectual concept of zero is probably much more recent than you might imagine, in fact the mathematician Fibonacci is credited with introducing zero to Europe around 1200 AD!. I suppose akin to that the very idea of negative remainders is much more than just a little bit academic, abstract, unreal, and tbh meaningless. (But when you need ’em, you need ’em.)
Examples:
               x,y: -9,-4  -9,+4  +9,-4  +9,+4
    remainder(x,y):    -1     -1     +1     +1
          mod(x,y):    -1     +3     -3     +1      -- (matches the C % operator)

?sq_rmdr({81,-3.5,-9,5.5}, {8,-1.7,2,-4})   -- {1,-0.1,-1,1.5}
?sq_mod( {81,-3.5,-9,5.5}, {8,-1.7,2,-4})   -- {1,-0.1,1,-2.5}
?sq_rmdr({17,12,34}, 16)                    -- {1,12,2} -- (ditto mod)
?sq_rmdr(16, {2,3,5})                       -- {0,1,1}  -- (ditto mod)
Implementation: remainder(): via :%opRmdr in builtins\VM\pRmdr.e (an autoinclude)
mod(): see builtins\pmaths.e (an autoinclude) for details of the actual implementation.
See Also: floor, powmod, mulmod