diff --git a/src/flint/fmpz_mod_mat.jl b/src/flint/fmpz_mod_mat.jl index cc0df32dbe..5452d267bb 100644 --- a/src/flint/fmpz_mod_mat.jl +++ b/src/flint/fmpz_mod_mat.jl @@ -916,3 +916,38 @@ function matrix_space(R::ZZModRing, r::Int, c::Int; cached::Bool = true) ZZModMatrixSpace(R, r, c) end +################################################################################ +# +# Kernel +# +################################################################################ + +function AbstractAlgebra.Solve.kernel(M::ZZModMatrix; side::Symbol = :right) + AbstractAlgebra.Solve.check_option(side, [:right, :left], "side") + + if side === :left + K = AbstractAlgebra.Solve.kernel(transpose(M), side = :right) + return transpose(K) + end + + R = base_ring(M) + N = hcat(transpose(M), identity_matrix(R, ncols(M))) + if nrows(N) < ncols(N) + N = vcat(N, zero_matrix(R, ncols(N) - nrows(N), ncols(N))) + end + howell_form!(N) + H = N + nr = 1 + while nr <= nrows(H) && !is_zero_row(H, nr) + nr += 1 + end + nr -= 1 + h = view(H, 1:nr, 1:nrows(M)) + for i = 1:nrows(h) + if is_zero_row(h, i) + k = view(H, i:nrows(h), nrows(M) + 1:ncols(H)) + return transpose(k) + end + end + return zero_matrix(R, ncols(M), 0) +end diff --git a/src/flint/gfp_mat.jl b/src/flint/gfp_mat.jl index 1dc3503069..a393f0dfe3 100644 --- a/src/flint/gfp_mat.jl +++ b/src/flint/gfp_mat.jl @@ -508,3 +508,22 @@ function matrix_space(R::fpField, r::Int, c::Int; cached::Bool = true) # TODO/FIXME: `cached` is ignored and only exists for backwards compatibility fpMatrixSpace(R, r, c) end + +################################################################################ +# +# Kernel +# +################################################################################ + +function AbstractAlgebra.Solve.kernel(A::fpMatrix; side::Symbol = :right) + AbstractAlgebra.Solve.check_option(side, [:right, :left], "side") + + if side === :left + K = AbstractAlgebra.Solve.kernel(transpose(A), side = :right) + return transpose(K) + end + + K = zero_matrix(base_ring(A), ncols(A), max(nrows(A), ncols(A))) + n = ccall((:nmod_mat_nullspace, libflint), Int, (Ref{fpMatrix}, Ref{fpMatrix}), K, A) + return view(K, 1:nrows(K), 1:n) +end diff --git a/src/flint/nmod_mat.jl b/src/flint/nmod_mat.jl index 569fda855e..5b3bf83592 100644 --- a/src/flint/nmod_mat.jl +++ b/src/flint/nmod_mat.jl @@ -919,3 +919,43 @@ function matrix_space(R::zzModRing, r::Int, c::Int; cached::Bool = true) zzModMatrixSpace(R, r, c) end +################################################################################ +# +# Kernel +# +################################################################################ + +function AbstractAlgebra.Solve.kernel(M::zzModMatrix; side::Symbol = :right) + AbstractAlgebra.Solve.check_option(side, [:right, :left], "side") + + if side === :left + K = AbstractAlgebra.Solve.kernel(transpose(M), side = :right) + return transpose(K) + end + + R = base_ring(M) + if is_prime(modulus(R)) + k = zero_matrix(R, ncols(M), ncols(M)) + n = ccall((:nmod_mat_nullspace, libflint), Int, (Ref{zzModMatrix}, Ref{zzModMatrix}), k, M) + return view(k, 1:nrows(k), 1:n) + end + + H = hcat(transpose(M), identity_matrix(R, ncols(M))) + if nrows(H) < ncols(H) + H = vcat(H, zero_matrix(R, ncols(H) - nrows(H), ncols(H))) + end + howell_form!(H) + nr = 1 + while nr <= nrows(H) && !is_zero_row(H, nr) + nr += 1 + end + nr -= 1 + h = view(H, 1:nr, 1:nrows(M)) + for i = 1:nrows(h) + if is_zero_row(h, i) + k = view(H, i:nrows(h), nrows(M) + 1:ncols(H)) + return transpose(k) + end + end + return zero_matrix(R, ncols(M), 0) +end