int check_rref_form(slong * perm, nmod_mat_t A, slong rank) { slong i, j, k, prev_pivot; /* bottom should be zero */ for (i = rank; i < A->r; i++) for (j = 0; j < A->c; j++) if (nmod_mat_entry(A, i, j) != 0) return 0; prev_pivot = -1; for (i = 0; i < rank; i++) { for (j = 0; j < A->c; j++) { if (nmod_mat_entry(A, i, j) != 0) { /* pivot should have a higher column index than previous */ if (j <= prev_pivot) return 0; /* column should be 0 ... 0 1 0 ... 0 */ for (k = 0; k < rank; k++) if (nmod_mat_entry(A, k, j) != (i == k)) return 0; prev_pivot = j; break; } } } return 1; }
void nmod_mat_scalar_mul(nmod_mat_t B, const nmod_mat_t A, mp_limb_t c) { if (c == 0UL) { nmod_mat_zero(B); } else if (c == 1UL) { nmod_mat_set(B, A); } else if (c == A->mod.n - 1UL) { nmod_mat_neg(B, A); } else { long i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_mat_entry(B, i, j) = n_mulmod2_preinv( nmod_mat_entry(A, i, j), c, A->mod.n, A->mod.ninv); } }
void nmod_mat_solve_tril_classical(nmod_mat_t X, const nmod_mat_t L, const nmod_mat_t B, int unit) { int nlimbs; long i, j, n, m; nmod_t mod; mp_ptr inv, tmp; n = L->r; m = B->c; mod = L->mod; if (!unit) { inv = _nmod_vec_init(n); for (i = 0; i < n; i++) inv[i] = n_invmod(nmod_mat_entry(L, i, i), mod.n); } else inv = NULL; nlimbs = _nmod_vec_dot_bound_limbs(n, mod); tmp = _nmod_vec_init(n); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) tmp[j] = nmod_mat_entry(X, j, i); for (j = 0; j < n; j++) { mp_limb_t s; s = _nmod_vec_dot(L->rows[j], tmp, j, mod, nlimbs); s = nmod_sub(nmod_mat_entry(B, j, i), s, mod); if (!unit) s = n_mulmod2_preinv(s, inv[j], mod.n, mod.ninv); tmp[j] = s; } for (j = 0; j < n; j++) nmod_mat_entry(X, j, i) = tmp[j]; } _nmod_vec_clear(tmp); if (!unit) _nmod_vec_clear(inv); }
void fmpz_mat_CRT_ui(fmpz_mat_t res, const fmpz_mat_t mat1, const fmpz_t m1, const nmod_mat_t mat2, int sign) { long i, j; mp_limb_t c; mp_limb_t m2 = mat2->mod.n; mp_limb_t m2inv = mat2->mod.ninv; fmpz_t m1m2; c = fmpz_fdiv_ui(m1, m2); c = n_invmod(c, m2); if (c == 0) { printf("Exception in fmpz_mat_CRT_ui: m1 not invertible modulo m2!\n"); abort(); } fmpz_init(m1m2); fmpz_mul_ui(m1m2, m1, m2); for (i = 0; i < mat1->r; i++) { for (j = 0; j < mat1->c; j++) _fmpz_CRT_ui_precomp(fmpz_mat_entry(res, i, j), fmpz_mat_entry(mat1, i, j), m1, nmod_mat_entry(mat2, i, j), m2, m2inv, m1m2, c, sign); } fmpz_clear(m1m2); }
mp_limb_t _nmod_mat_det(nmod_mat_t A) { mp_limb_t det; long * P; long m = A->r; long rank; long i; P = flint_malloc(sizeof(long) * m); rank = nmod_mat_lu(P, A, 1); det = 0UL; if (rank == m) { det = 1UL; for (i = 0; i < m; i++) det = n_mulmod2_preinv(det, nmod_mat_entry(A, i, i), A->mod.n, A->mod.ninv); } if (_perm_parity(P, m) == 1) det = nmod_neg(det, A->mod); flint_free(P); return det; }
mp_limb_t nmod_mat_trace(const nmod_mat_t mat) { mp_limb_t t; slong i, n = nmod_mat_nrows(mat); if (n == 0) return 0; t = nmod_mat_entry(mat, 0, 0); for (i = 1; i < n; i++) t = nmod_add(t, nmod_mat_entry(mat, i, i), mat->mod); return t; }
void nmod_poly_mat_evaluate_nmod(nmod_mat_t B, const nmod_poly_mat_t A, mp_limb_t x) { slong i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) nmod_mat_entry(B, i, j) = nmod_poly_evaluate_nmod( nmod_poly_mat_entry(A, i, j), x); }
void fmpz_mat_scalar_addmul_nmod_mat_fmpz(fmpz_mat_t B, const nmod_mat_t A, const fmpz_t c) { long i, j; for (i = 0; i < A->r; i++) for (j = 0; j < A->c; j++) fmpz_addmul_ui(fmpz_mat_entry(B,i,j), c, nmod_mat_entry(A,i,j)); }
int nmod_mat_inv(nmod_mat_t B, const nmod_mat_t A) { nmod_mat_t I; long i, dim; int result; dim = A->r; switch (dim) { case 0: result = 1; break; case 1: if (nmod_mat_entry(A, 0, 0) == 0UL) { result = 0; } else { nmod_mat_entry(B, 0, 0) = n_invmod(nmod_mat_entry(A, 0, 0), B->mod.n); result = 1; } break; default: nmod_mat_init(I, dim, dim, B->mod.n); for (i = 0; i < dim; i++) nmod_mat_entry(I, i, i) = 1UL; result = nmod_mat_solve(B, A, I); nmod_mat_clear(I); } return result; }
mp_limb_t nmod_mat_det(const nmod_mat_t A) { nmod_mat_t tmp; mp_limb_t det; long dim = A->r; if (dim != A->c) { printf("nmod_mat_det: nonsquare matrix"); abort(); } if (dim == 0) return 1UL; if (dim == 1) return nmod_mat_entry(A, 0, 0); nmod_mat_init_set(tmp, A); det = _nmod_mat_det(tmp); nmod_mat_clear(tmp); return det; }
void fmpz_mat_multi_CRT_ui_precomp(fmpz_mat_t mat, nmod_mat_t * const residues, long nres, fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign) { long i, j, k; mp_ptr r; r = _nmod_vec_init(nres); for (i = 0; i < fmpz_mat_nrows(mat); i++) { for (j = 0; j < fmpz_mat_ncols(mat); j++) { for (k = 0; k < nres; k++) r[k] = nmod_mat_entry(residues[k], i, j); fmpz_multi_CRT_ui(fmpz_mat_entry(mat, i, j), r, comb, temp, sign); } } _nmod_vec_clear(r); }
int nmod_mat_randpermdiag(nmod_mat_t mat, flint_rand_t state, mp_srcptr diag, long n) { int parity; long i; long * rows; long * cols; rows = _perm_init(mat->r); cols = _perm_init(mat->c); parity = _perm_randtest(rows, mat->r, state); parity ^= _perm_randtest(cols, mat->c, state); nmod_mat_zero(mat); for (i = 0; i < n; i++) nmod_mat_entry(mat, rows[i], cols[i]) = diag[i]; _perm_clear(rows); _perm_clear(cols); return parity; }
int main(void) { slong i; FLINT_TEST_INIT(state); flint_printf("rref...."); fflush(stdout); for (i = 0; i < 1000 * flint_test_multiplier(); i++) { nmod_mat_t A, B, C, D; mp_limb_t mod; slong j, k, m, n, rank1, rank2; slong *perm; int equal; mp_limb_t c; mod = n_randtest_prime(state, 0); m = n_randint(state, 20); n = n_randint(state, 20); perm = _perm_init(2*m); nmod_mat_init(A, m, n, mod); nmod_mat_init(D, 2*m, n, mod); nmod_mat_randtest(A, state); nmod_mat_init_set(B, A); nmod_mat_init_set(C, A); rank1 = nmod_mat_rref(B); if (!check_rref_form(perm, B, rank1)) { flint_printf("FAIL (malformed rref)\n"); nmod_mat_print_pretty(A); flint_printf("\n\n"); nmod_mat_print_pretty(B); flint_printf("\n\n"); abort(); } /* Concatenate the original matrix with the rref, scramble the rows, and check that the rref is the same */ _perm_randtest(perm, 2 * m, state); for (j = 0; j < m; j++) { do { c = n_randint(state, mod); } while (c == 0); for (k = 0; k < n; k++) nmod_mat_entry(D, perm[j], k) = nmod_mul(nmod_mat_entry(A, j, k), c, A->mod); } for (j = 0; j < m; j++) { do { c = n_randint(state, mod); } while (c == 0); for (k = 0; k < n; k++) nmod_mat_entry(D, perm[m + j], k) = nmod_mul(nmod_mat_entry(B, j, k), c, A->mod); } rank2 = nmod_mat_rref(D); equal = (rank1 == rank2); if (equal) { for (j = 0; j < rank2; j++) for (k = 0; k < n; k++) equal = equal && (nmod_mat_entry(B, j, k) == nmod_mat_entry(D, j, k)); for (j = rank2; j < 2 * rank2; j++) for (k = 0; k < n; k++) equal = equal && (nmod_mat_entry(D, j, k) == 0); } if (!equal) { flint_printf("FAIL (rank1 = %wd, rank2 = %wd)!\n", rank1, rank2); nmod_mat_print_pretty(A); flint_printf("\n\n"); nmod_mat_print_pretty(B); flint_printf("\n\n"); nmod_mat_print_pretty(D); flint_printf("\n\n"); abort(); } _perm_clear(perm); nmod_mat_clear(A); nmod_mat_clear(B); nmod_mat_clear(C); nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }