diff --git a/src/flint/FlintTypes.jl b/src/flint/FlintTypes.jl index eb236fd58..bb6b01550 100644 --- a/src/flint/FlintTypes.jl +++ b/src/flint/FlintTypes.jl @@ -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 diff --git a/src/flint/fmpz_mod_mat.jl b/src/flint/fmpz_mod_mat.jl index 68160c0db..9b87e53bd 100644 --- a/src/flint/fmpz_mod_mat.jl +++ b/src/flint/fmpz_mod_mat.jl @@ -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 diff --git a/test/generic/Matrix-test.jl b/test/generic/Matrix-test.jl index d505567fb..36759f176 100644 --- a/test/generic/Matrix-test.jl +++ b/test/generic/Matrix-test.jl @@ -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