`div`/`mod` behaviour
The behaviour of div and mod is currently inconsistent with the respective operators for ints. For example:
import bigints
func divmod(a, b: int): tuple[q, r: int] =
(q: a div b, r: a mod b)
echo "int:"
echo " divmod(1, 2): ", divmod(1, 2)
echo " divmod(1, -2): ", divmod(1, -2)
echo " divmod(-1, 2): ", divmod(-1, 2)
echo " divmod(-1, -2): ", divmod(-1, -2)
echo "BigInt:"
echo " divmod(1, 2): ", divmod(1'bi, 2'bi)
echo " divmod(1, -2): ", divmod(1'bi, -2'bi)
echo " divmod(-1, 2): ", divmod(-1'bi, 2'bi)
echo " divmod(-1, -2): ", divmod(-1'bi, -2'bi)
prints the following:
int:
divmod(1, 2): (q: 0, r: 1)
divmod(1, -2): (q: 0, r: 1)
divmod(-1, 2): (q: 0, r: -1)
divmod(-1, -2): (q: 0, r: -1)
BigInt:
divmod(1, 2): (q: 0, r: 1)
divmod(1, -2): (q: -1, r: -1)
divmod(-1, 2): (q: -1, r: 1)
divmod(-1, -2): (q: 0, r: -1)
For ints, division rounds towards 0 and the sign of a mod b is the sign of a. Meanwhile, for BigInts, division rounds towards negative infinity and the sign of a mod b is the sign of b.
I suggest we change the behavior of BigInts to match that of ints.
@def- since you implemented this, did you have a specific reason for implementing it this way?
I think that generaly the motivation to implement it this way is that it doesn't break modular arithmetic. Meaning that if M divides (a-b) then a mod M == b mod M. If one does any sort of math with the integers, the other way (which is usually called remainder) gets in the way.
I think that it is really unfortunate that mod for ints means remainder rather than modulus, but that is to stay.
The ideal state would be there where two operators: rem implementing a remainder and mod implementing a modulo. For both ints and BigInts.
@MichalMarsalek if that’s the case, then shouldn’t the modulo always be positive? After all, $$\mathbb Zn+r = \mathbb Z(-n)+r$$