Skip to content

Commit

Permalink
Fix ZZMatrix modular reduction (issue #2947) (#1564)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnAAbbott authored Oct 27, 2023
1 parent 89b14ca commit 978dd47
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/flint/FlintTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5449,8 +5449,31 @@ mutable struct ZZModMatrix <: MatElem{ZZModRingElem}
end
return z
end

function ZZModMatrix(n::UInt, b::ZZMatrix)
return ZZModMatrix(ZZ(n), b)
end

function ZZModMatrix(n::Int, b::ZZMatrix)
return ZZModMatrix(ZZ(n), b)
end

function ZZModMatrix(n::ZZRingElem, b::ZZMatrix)
(n < 2) && error("Modulus must be >= 2")
z = new()
ccall((:fmpz_mod_mat_init, libflint), Nothing,
(Ref{ZZModMatrix}, Int, Int, Ref{ZZRingElem}), z, b.r, b.c, n)
finalizer(_fmpz_mod_mat_clear_fn, z)
for i = 1:b.r
for j = 1:b.c
setindex_raw!(z, mod(ZZRingElem(b[i,j]), n), i, j)
end
end
return z
end
end


function _fmpz_mod_mat_clear_fn(mat::ZZModMatrix)
ccall((:fmpz_mod_mat_clear, libflint), Nothing, (Ref{ZZModMatrix}, ), mat)
end
Expand Down
7 changes: 7 additions & 0 deletions src/flint/fmpz_mod_mat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,13 @@ function (a::ZZModMatrixSpace)(arr::AbstractVector{ZZModRingElem})
return z
end

function (a::ZZModMatrixSpace)(b::ZZMatrix)
(ncols(a) != b.c || nrows(a) != b.r) && error("Dimensions do not fit")
z = ZZModMatrix(modulus(base_ring(a)), b)
z.base_ring = a.base_ring
return z
end

###############################################################################
#
# Matrix constructor
Expand Down
23 changes: 23 additions & 0 deletions test/generic/Matrix-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,29 @@ end
@test floor(ZZMatrix, M) == ZZMatrix(map(x->floor(Int,x), M))
end

@testset "Modular reduction of ZZMatrix" begin
S0 = matrix_space(ZZ,2,2)
M0 = S0(1)
M0[1,2] = 99
M0[2,1] = 199
M0[2,2] = -499
# First call the ZZModMatrix constructor directly: (3 cases)
ignore = ZZModMatrix(UInt(81), M0)
ignore = ZZModMatrix(Int(81), M0)
ignore = ZZModMatrix(ZZ(81), M0)
# Now check conversion via matrix_space: first use a modulus of type Int/UInt
m = 81
ZZmodm = residue_ring(ZZ,m)
S81 = matrix_space(ZZmodm,2,2)
M81 = S81(M0)
@test M81[1,1] == 1 && M81[1,2] == 18 && M81[2,1] == 37 && M81[2,2] == -13;
# Now use matrix_space with modulus of type ZZRingElem (see GitHub issue #2947)
ZZmodM = residue_ring(ZZ,ZZ(m))
SZZ81 = matrix_space(ZZmodM,2,2)
MZZ81 = SZZ81(M0)
@test MZZ81[1,1] == 1 && MZZ81[1,2] == 18 && MZZ81[2,1] == 37 && MZZ81[2,2] == -13;
end

#=
TODO: Add tests for the following when there are rings that are not fields
that have delayed reduction
Expand Down

0 comments on commit 978dd47

Please sign in to comment.