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; }
void _nmod_poly_taylor_shift_convolution(mp_ptr p, mp_limb_t c, slong len, nmod_t mod) { slong i, n = len - 1; mp_limb_t f, d; mp_ptr t, u; if (c == 0 || len <= 1) return; t = _nmod_vec_init(len); u = _nmod_vec_init(len); f = 1; for (i = 2; i <= n; i++) { f = n_mulmod2_preinv(f, i, mod.n, mod.ninv); p[i] = n_mulmod2_preinv(p[i], f, mod.n, mod.ninv); } _nmod_poly_reverse(p, p, len, len); t[n] = 1; for (i = n; i > 0; i--) t[i - 1] = n_mulmod2_preinv(t[i], i, mod.n, mod.ninv); if (c == mod.n - 1) { for (i = 1; i <= n; i += 2) t[i] = nmod_neg(t[i], mod); } else if (c != 1) { d = c; for (i = 1; i <= n; i++) { t[i] = n_mulmod2_preinv(t[i], d, mod.n, mod.ninv); d = n_mulmod2_preinv(d, c, mod.n, mod.ninv); } } _nmod_poly_mullow(u, p, len, t, len, len, mod); f = n_mulmod2_preinv(f, f, mod.n, mod.ninv); f = n_invmod(f, mod.n); for (i = n; i >= 0; i--) { p[i] = n_mulmod2_preinv(u[n - i], f, mod.n, mod.ninv); f = n_mulmod2_preinv(f, (i == 0) ? 1 : i, mod.n, mod.ninv); } _nmod_vec_clear(t); _nmod_vec_clear(u); }
void _nmod_poly_product_roots_nmod_vec(mp_ptr poly, mp_srcptr xs, slong n, nmod_t mod) { if (n == 0) { poly[0] = UWORD(1); } else if (n < 20) { slong i, j; poly[n] = UWORD(1); poly[n - 1] = nmod_neg(xs[0], mod); for (i = 1; i < n; i++) { poly[n-i-1] = nmod_neg(n_mulmod2_preinv(poly[n-i], xs[i], mod.n, mod.ninv), mod); for (j = 0; j < i - 1; j++) { poly[n-i+j] = nmod_sub(poly[n-i+j], n_mulmod2_preinv(poly[n-i+j+1], xs[i], mod.n, mod.ninv), mod); } poly[n-1] = nmod_sub(poly[n-1], xs[i], mod); } } else { const slong m = (n + 1) / 2; mp_ptr tmp; tmp = _nmod_vec_init(n + 2); _nmod_poly_product_roots_nmod_vec(tmp, xs, m, mod); _nmod_poly_product_roots_nmod_vec(tmp + m + 1, xs + m, n - m, mod); _nmod_poly_mul(poly, tmp, m + 1, tmp + m + 1, n - m + 1, mod); _nmod_vec_clear(tmp); } }
long hmod_mat_lu_classical(long * P, hmod_mat_t A, int rank_check) { hlimb_t d, e, **a; nmod_t mod; long i, m, n, rank, length, row, col; m = A->r; n = A->c; a = A->rows; mod = A->mod; rank = row = col = 0; for (i = 0; i < m; i++) P[i] = i; while (row < m && col < n) { if (hmod_mat_pivot(A, P, row, col) == 0) { if (rank_check) return 0; col++; continue; } rank++; d = a[row][col]; d = n_invmod(d, mod.n); length = n - col - 1; for (i = row + 1; i < m; i++) { e = n_mulmod2_preinv(a[i][col], d, mod.n, mod.ninv); if (length != 0) _hmod_vec_scalar_addmul_hmod(a[i] + col + 1, a[row] + col + 1, length, nmod_neg(e, mod), mod); a[i][col] = 0; a[i][rank - 1] = e; } row++; col++; } return rank; }