diff --git a/src/flint/flintlib/types/fmpz_mod_mat_compat.pxd b/src/flint/flintlib/types/fmpz_mod_mat_compat.pxd index eadcc6a2..916845b9 100644 --- a/src/flint/flintlib/types/fmpz_mod_mat_compat.pxd +++ b/src/flint/flintlib/types/fmpz_mod_mat_compat.pxd @@ -3,6 +3,9 @@ from flint.flintlib.types.fmpz_mod cimport fmpz_mod_ctx_t, fmpz_mod_mat_t, fmpz_ cdef extern from *: """ + #include + #include + /* * fmpz_mod_mat function signatures were changed in FLINT 3.1.0 */ @@ -28,6 +31,7 @@ cdef extern from *: #define compat_fmpz_mod_mat_transpose(B, A, ctx) fmpz_mod_mat_transpose(B, A, ctx) #define compat_fmpz_mod_mat_solve(X, A, B, ctx) fmpz_mod_mat_solve(X, A, B, ctx) #define compat_fmpz_mod_mat_rref(mat, ctx) fmpz_mod_mat_rref(mat, mat, ctx) + #define compat_fmpz_mod_mat_det(res, mat, ctx) fmpz_mod_mat_det(res, mat, ctx) #define compat_fmpz_mod_mat_charpoly(p, M, ctx) fmpz_mod_mat_charpoly(p, M, ctx) #define compat_fmpz_mod_mat_minpoly(p, M, ctx) fmpz_mod_mat_minpoly(p, M, ctx) @@ -53,9 +57,26 @@ cdef extern from *: #define compat_fmpz_mod_mat_transpose(B, A, ctx) fmpz_mod_mat_transpose(B, A) #define compat_fmpz_mod_mat_solve(X, A, B, ctx) fmpz_mod_mat_solve(X, A, B) #define compat_fmpz_mod_mat_rref(mat, ctx) fmpz_mod_mat_rref(NULL, mat) + #define compat_fmpz_mod_mat_det(res, mat, ctx) compat_fmpz_mod_mat_det_fallback(res, mat, ctx) #define compat_fmpz_mod_mat_charpoly(p, M, ctx) fmpz_mod_mat_charpoly(p, M, ctx) #define compat_fmpz_mod_mat_minpoly(p, M, ctx) fmpz_mod_mat_minpoly(p, M, ctx) + /* fmpz_mod_mat_det was added in FLINT 3.1.0 */ + static inline void + compat_fmpz_mod_mat_det_fallback(fmpz_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) + { + fmpz_mod_poly_t p; + + fmpz_mod_poly_init(p, ctx); + fmpz_mod_mat_charpoly(p, mat, ctx); + fmpz_mod_poly_get_coeff_fmpz(res, p, 0, ctx); + + if (fmpz_mod_mat_nrows(mat) % 2) + fmpz_mod_neg(res, res, ctx); + + fmpz_mod_poly_clear(p, ctx); + } + #endif """ @@ -81,6 +102,7 @@ cdef extern from "flint/fmpz_mod_mat.h": void compat_fmpz_mod_mat_transpose(fmpz_mod_mat_t B, const fmpz_mod_mat_t A, const fmpz_mod_ctx_t ctx) int compat_fmpz_mod_mat_solve(fmpz_mod_mat_t X, const fmpz_mod_mat_t A, const fmpz_mod_mat_t B, const fmpz_mod_ctx_t ctx) slong compat_fmpz_mod_mat_rref(fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) + void compat_fmpz_mod_mat_det(fmpz_t res, const fmpz_mod_mat_t mat, const fmpz_mod_ctx_t ctx) void compat_fmpz_mod_mat_charpoly(fmpz_mod_poly_t p, const fmpz_mod_mat_t M, const fmpz_mod_ctx_t ctx) void compat_fmpz_mod_mat_minpoly(fmpz_mod_poly_t p, const fmpz_mod_mat_t M, const fmpz_mod_ctx_t ctx) # diff --git a/src/flint/types/fmpz_mod_mat.pyx b/src/flint/types/fmpz_mod_mat.pyx index 91d7839f..3e4f824c 100644 --- a/src/flint/types/fmpz_mod_mat.pyx +++ b/src/flint/types/fmpz_mod_mat.pyx @@ -28,6 +28,7 @@ from flint.flintlib.types.fmpz_mod_mat_compat cimport ( compat_fmpz_mod_mat_transpose, compat_fmpz_mod_mat_solve, compat_fmpz_mod_mat_rref, + compat_fmpz_mod_mat_det, compat_fmpz_mod_mat_charpoly, compat_fmpz_mod_mat_minpoly, ) @@ -501,12 +502,13 @@ cdef class fmpz_mod_mat(flint_mat): fmpz_mod(5, 7) """ - # XXX: No fmpz_mod_mat_det function... - p = self.charpoly() - p0 = p[0] - if self.nrows() % 2: - p0 = -p0 - return p0 + cdef fmpz_mod d + if self.nrows() != self.ncols(): + raise ValueError("fmpz_mod_mat det: matrix must be square") + d = fmpz_mod.__new__(fmpz_mod) + d.ctx = self.ctx + compat_fmpz_mod_mat_det(d.val, self.val, self.ctx.val) + return d def charpoly(self): """Return the characteristic polynomial of a matrix.