Skip to content

Commit 0d94c8b

Browse files
authored
Merge pull request #181 from sumiya11/64bit_mod_crt_windows
Issue with 64 bit integers in CRT for Windows
2 parents 31c1be0 + 393eac3 commit 0d94c8b

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

src/reconstruction/crt.jl

+43-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,44 @@
33
###
44
# CRT
55

6+
# Auxiliary functions allowing to avoid overflow
7+
# on Windows for numbers between 32 and 64 bits
8+
function my_set_ui!(a::BigInt, b::UInt64)
9+
@static if Culong == UInt64
10+
Base.GMP.MPZ.set_ui!(a, b)
11+
else
12+
if b < 2^32
13+
Base.GMP.MPZ.set_ui!(a, b)
14+
else
15+
Base.GMP.MPZ.set!(a, BigInt(b))
16+
end
17+
end
18+
end
19+
20+
function my_mul_ui!(a::BigInt, b::BigInt, c::UInt64)
21+
@static if Culong == UInt64
22+
Base.GMP.MPZ.mul_ui!(a, b, c)
23+
else
24+
if c < 2^32
25+
Base.GMP.MPZ.mul_ui!(a, b, c)
26+
else
27+
Base.GMP.MPZ.mul!(a, b, BigInt(c))
28+
end
29+
end
30+
end
31+
32+
function my_mul_ui!(a::BigInt, b::UInt64)
33+
@static if Culong == UInt64
34+
Base.GMP.MPZ.mul_ui!(a, b)
35+
else
36+
if b < 2^32
37+
Base.GMP.MPZ.mul_ui!(a, b)
38+
else
39+
Base.GMP.MPZ.mul!(a, BigInt(b))
40+
end
41+
end
42+
end
43+
644
"""
745
crt!
846
@@ -23,9 +61,9 @@ Then, `x` is obtained as `x = ∑ ci[i] ai[i] mod M`.
2361
function crt!(M::BigInt, buf::BigInt, n1::BigInt, n2::BigInt, ai::Vector{UInt}, ci::Vector{BigInt})
2462
@invariant length(ai) == length(ci)
2563

26-
Base.GMP.MPZ.set_ui!(n1, UInt(0))
64+
my_set_ui!(n1, UInt(0))
2765
for i in 1:length(ai)
28-
Base.GMP.MPZ.mul_ui!(n2, ci[i], ai[i])
66+
my_mul_ui!(n2, ci[i], ai[i])
2967
Base.GMP.MPZ.add!(n1, n2)
3068
end
3169

@@ -52,13 +90,13 @@ function crt_precompute!(
5290
@invariant length(ci) == length(moduli)
5391

5492
n3, n4 = BigInt(), BigInt()
55-
@inbounds Base.GMP.MPZ.set_ui!(M, moduli[1])
93+
@inbounds my_set_ui!(M, moduli[1])
5694
@inbounds for i in 2:length(moduli)
57-
Base.GMP.MPZ.mul_ui!(M, moduli[i])
95+
my_mul_ui!(M, moduli[i])
5896
end
5997

6098
@inbounds for i in 1:length(moduli)
61-
Base.GMP.MPZ.set_ui!(n2, moduli[i])
99+
my_set_ui!(n2, moduli[i])
62100
Base.GMP.MPZ.tdiv_q!(ci[i], M, n2)
63101
Base.GMP.MPZ.gcdext!(n2, n3, n4, ci[i], n2)
64102
Base.GMP.MPZ.mul!(ci[i], n3)

test/crt.jl

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
@testset "CRT" begin
2+
cases = []
3+
4+
push!(
5+
cases,
6+
Dict(
7+
:moduli => Vector{UInt64}([1099511627791, 3518437208889]),
8+
:ai => Vector{UInt64}([8590035092, 8589936485])
9+
),
10+
Dict(
11+
:moduli => Vector{UInt64}([1099511627791, 17, 3518437208889]),
12+
:ai => Vector{UInt64}([8590035092, 3, 8589936485])
13+
),
14+
Dict(
15+
:moduli => Vector{UInt64}([1099511627791, 2^30 + 3, 3518437208889]),
16+
:ai => Vector{UInt64}([8590035092, 42, 0])
17+
),
18+
Dict(
19+
:moduli => Vector{UInt64}([1099511627791, 2^30 + 3, 3518437208889]),
20+
:ai => Vector{UInt64}([0, 0, 0])
21+
)
22+
)
23+
24+
for c in cases
25+
ai = c[:ai]
26+
moduli = c[:moduli]
27+
M = prod(Vector{BigInt}(moduli))
28+
ci = Vector{BigInt}([0 for _ in moduli])
29+
n1, n2 = BigInt(0), BigInt(0)
30+
Groebner.crt_precompute!(M, n1, n2, ci, moduli)
31+
for i in 1:length(ci)
32+
pii = div(M, moduli[i])
33+
@test ci[i] % pii == 0
34+
@test (ci[i] - 1) % moduli[i] == 0
35+
end
36+
buf = BigInt(0)
37+
Groebner.crt!(M, buf, n1, n2, ai, ci)
38+
@test 0 <= buf < M
39+
for i in 1:length(ci)
40+
@test (buf - ai[i]) % moduli[i] == 0
41+
end
42+
end
43+
end

test/runtests.jl

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ end
3535

3636
@time @testset "All tests" verbose = true begin
3737
@time include("arithmetic.jl")
38+
@time include("crt.jl")
3839

3940
# Different implementations of a monomial
4041
@time include("monoms/exponentvector.jl")

0 commit comments

Comments
 (0)