scheinerman/Mods.jl

Missing correctness of arithmetic operations

Closed this issue · 7 comments

For + the calculations not always correct if mod >= typemax(T) ÷ 2.
For * the calculations are not always correct if mod^2 >= typemax(T).

Test cases:

julia> p = typemax(T) ÷ 4 * 3
6917529027641081853
julia> Mod(-1, p) + Mod(-2, p) == Mod(-3, p)
false

julia> p = Int(ceil(sqrt(typemax(T)))) + 1
3037000501
julia> Mod(-1, p) * Mod(-1, p) == Mod(1, p)
false

julia> a = Mod(UInt32(p-1), p) 
Mod(999998,999999)

julia> a * a
Mod(590895,999999)

julia> p = UInt32(999999)
0x000f423f
julia> a = Mod(UInt32(p-1), p)
Mod(999998,999999)
julia> a * a == Mod(UInt32(1), p)
false

That is due to unhandled arithmetic overflow in the bits integer + and * operations.

We have the same issue with ordinary integers. For example:

julia> a = typemax(Int)-2
9223372036854775805

julia> a*a > a
false

A fix could be made but that might result in a performance hit. I think the better option for folks working with very large integers is to create Mod values based on BigInt values.

julia> p = typemax(Int) ÷ 4 * 3
6917529027641081853

julia> p = big(p)
6917529027641081853

julia> Mod(-1,p) + Mod(-2,p) == Mod(-3,p)
true

We have the same issue with ordinary integers

true, but everybody knows, that for example Int64 performs arithmetic operations modulo 2^64.
There are Int64 and Int32 operators with overflow available, which would allow to fix that without much performance penalty. For example multiplication:

    prod, ovf = Base.mul_with_overflow(a, b)
    ovf  || return prod % mod
    oftype(mod, widemul(a, b) % mod) # double precision product only in case of overflow

or addition:

    sum = a + b
    0 <= sum < mod ? sum : sum - mod # assuming 0 <= a, b < mod

Hmmm... OK, I'll think on this :-)

I think I've got it fixed.

I see, the operations are correct now. I you could add the corresponding test cases ...

btw, I am an undiscrete mathematician :-)

Yes ... I should do that ...

OK. Tests added. And as a discrete mathematician, I need continuous improvement :-).