void _fmpz_vec_lcm(fmpz_t res, const fmpz * vec, long len) { long i; fmpz_one(res); for (i = 0; i < len && !fmpz_is_zero(res); i++) fmpz_lcm(res, res, vec + i); fmpz_abs(res, res); }
void _fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_struct ** num, fmpz * den, const fmpq_mat_struct ** mat, slong n) { fmpz_t t, lcm; slong i, j, k; if (fmpq_mat_is_empty(mat[0])) return; fmpz_init(t); fmpz_init(lcm); for (i = 0; i < mat[0]->r; i++) { /* Compute common denominator of row */ fmpz_set(lcm, fmpq_mat_entry_den(mat[0], i, 0)); for (k = 0; k < n; k++) for (j = (k == 0); j < mat[k]->c; j++) fmpz_lcm(lcm, lcm, fmpq_mat_entry_den(mat[k], i, j)); if (den != NULL) fmpz_set(den + i, lcm); for (k = 0; k < n; k++) { /* Rescale numerators in row */ if (fmpz_is_one(lcm)) { for (j = 0; j < mat[k]->c; j++) fmpz_set(fmpz_mat_entry(num[k], i, j), fmpq_mat_entry_num(mat[k], i, j)); } else { for (j = 0; j < mat[k]->c; j++) { fmpz_divexact(t, lcm, fmpq_mat_entry_den(mat[k], i, j)); fmpz_mul(fmpz_mat_entry(num[k], i, j), fmpq_mat_entry_num(mat[k], i, j), t); } } } } fmpz_clear(t); fmpz_clear(lcm); }
static void _set_vec(fmpz * rnum, fmpz_t den, const fmpz * xnum, const fmpz * xden, slong len) { slong j; fmpz_t t; fmpz_init(t); fmpz_one(den); for (j = 0; j < len; j++) fmpz_lcm(den, den, xden + j); for (j = 0; j < len; j++) { fmpz_divexact(t, den, xden + j); fmpz_mul(rnum + j, xnum + j, t); } fmpz_clear(t); }
void fmpz_holonomic_get_nth_fmpq(fmpq_t res, const fmpz_holonomic_t op, const fmpq * initial, long n0, long n) { long r = fmpz_holonomic_order(op); if (r == 0) { fmpq_zero(res); return; } else if (n < n0) { printf("not implemented\n"); abort(); } else if (n - n0 < r) { fmpq_set(res, initial + n - n0); return; } else { fmpz_mat_t M; long i; fmpz_t Q; fmpz_mat_init(M, r, r); fmpz_init(Q); fmpz_holonomic_forward_fmpz_mat(M, Q, op, n0, n - n0 - r + 1); { fmpz_t g, t; fmpz_init(g); fmpz_init(t); fmpz_one(g); for (i = 0; i < r; i++) fmpz_lcm(g, g, fmpq_denref(initial + i)); fmpz_divexact(t, g, fmpq_denref(initial + 0)); fmpz_mul(t, t, fmpq_numref(initial + 0)); fmpz_mul(fmpz_mat_entry(M, r - 1, 0), fmpz_mat_entry(M, r - 1, 0), t); for (i = 1; i < r; i++) { fmpz_divexact(t, g, fmpq_denref(initial + i)); fmpz_mul(t, t, fmpq_numref(initial + i)); fmpz_addmul(fmpz_mat_entry(M, r - 1, 0), fmpz_mat_entry(M, r - 1, i), t); } fmpz_set(fmpq_numref(res), fmpz_mat_entry(M, r - 1, 0)); fmpz_mul(fmpq_denref(res), Q, g); fmpq_canonicalise(res); fmpz_clear(g); fmpz_clear(t); } fmpz_mat_clear(M); fmpz_clear(Q); } }
void nf_elem_rep_mat_fmpz_mat_den(fmpz_mat_t res, fmpz_t den, const nf_elem_t a, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz_set(fmpz_mat_entry(res, 0, 0), LNF_ELEM_NUMREF(a)); fmpz_set(den, LNF_ELEM_DENREF(a)); } else if (nf->flag & NF_QUADRATIC) { nf_elem_t t; const fmpz * const anum = QNF_ELEM_NUMREF(a); const fmpz * const aden = QNF_ELEM_DENREF(a); fmpz * const tnum = QNF_ELEM_NUMREF(t); fmpz * const tden = QNF_ELEM_DENREF(t); nf_elem_init(t, nf); nf_elem_mul_gen(t, a, nf); if (fmpz_equal(tden, aden)) { fmpz_set(fmpz_mat_entry(res, 0, 0), anum); fmpz_set(fmpz_mat_entry(res, 0, 1), anum + 1); fmpz_set(fmpz_mat_entry(res, 1, 0), tnum); fmpz_set(fmpz_mat_entry(res, 1, 1), tnum + 1); fmpz_set(den, tden); } else { fmpz_lcm(den, tden, aden); fmpz_divexact(fmpz_mat_entry(res, 0, 0), den, aden); fmpz_mul(fmpz_mat_entry(res, 0, 1), anum + 1, fmpz_mat_entry(res, 0, 0)); fmpz_mul(fmpz_mat_entry(res, 0, 0), anum, fmpz_mat_entry(res, 0, 0)); fmpz_divexact(fmpz_mat_entry(res, 1, 0), den, tden); fmpz_mul(fmpz_mat_entry(res, 1, 1), tnum + 1, fmpz_mat_entry(res, 1, 0)); fmpz_mul(fmpz_mat_entry(res, 1, 0), tnum, fmpz_mat_entry(res, 1, 0)); } nf_elem_clear(t, nf); } else { slong i, j; nf_elem_t t; slong d = fmpq_poly_degree(nf->pol); nf_elem_init(t, nf); nf_elem_set(t, a, nf); if (NF_ELEM(a)->length == 0) { fmpz_mat_zero(res); fmpz_one(den); } else if (NF_ELEM(a)->length == 1) { fmpz_mat_zero(res); for (i = 0; i <= d - 1; i++) { fmpz_set(fmpz_mat_entry(res, i, i), fmpq_poly_numref(NF_ELEM(a))); } fmpz_set(den, fmpq_poly_denref(NF_ELEM(a))); } else { /* Special case if defining polynomial is monic and integral and the element also has trivial denominator */ if (nf->flag & NF_MONIC && fmpz_is_one(fmpq_poly_denref(nf->pol)) && fmpz_is_one(fmpq_poly_denref(NF_ELEM(a)))) { fmpz_one(den); for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, 0, i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, 0, i)); for (j = 1; j <= d - NF_ELEM(a)->length; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i < j; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, j, j + i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = j + NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); } for (j = d - NF_ELEM(a)->length + 1; j <= d - 1; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i <= d - 1; i++) fmpz_set(fmpz_mat_entry(res, j, i), fmpq_poly_numref(NF_ELEM(t)) + i); } } else { /* Now the general case. For 0 <= j < d - 2 we store the * denominator for row j at res[d - 1, j]. At the end we * divide the lcm of all of them by the corresponding * denominator of the row to get the correct multiplier for * row. */ for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, 0, i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, 0, i)); fmpz_set(fmpz_mat_entry(res, d - 1, 0), fmpq_poly_denref(NF_ELEM(a))); for (j = 1; j <= d - NF_ELEM(a)->length; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i < j; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); for (i = 0; i <= NF_ELEM(a)->length - 1; i++) fmpz_set(fmpz_mat_entry(res, j, j + i), fmpq_poly_numref(NF_ELEM(a)) + i); for (i = j + NF_ELEM(a)->length; i <= d - 1; i++) fmpz_zero(fmpz_mat_entry(res, j, i)); fmpz_set(fmpz_mat_entry(res, d - 1, j), fmpq_poly_denref(NF_ELEM(a))); } for (j = d - NF_ELEM(a)->length + 1; j <= d - 2; j++) { nf_elem_mul_gen(t, t, nf); for (i = 0; i <= d - 1; i++) fmpz_set(fmpz_mat_entry(res, j, i), fmpq_poly_numref(NF_ELEM(t)) + i); fmpz_set(fmpz_mat_entry(res, d - 1, j), fmpq_poly_denref(NF_ELEM(t))); } nf_elem_mul_gen(t, t, nf); /* Now compute the correct denominator */ fmpz_set(fmpz_mat_entry(res, d - 1, d - 1), fmpq_poly_denref(NF_ELEM(t))); fmpz_set(den, fmpq_poly_denref(NF_ELEM(t))); for (j = 0; j <= d - 2; j++) fmpz_lcm(den, den, fmpz_mat_entry(res, d - 1, j)); for (j = 0; j <= d - 2; j++) { if (!fmpz_equal(den, fmpz_mat_entry(res, d - 1, j))) { fmpz_divexact(fmpz_mat_entry(res, d - 1, j), den, fmpz_mat_entry(res, d - 1, j)); for (i = 0; i <= d - 1; i++) fmpz_mul(fmpz_mat_entry(res, j, i), fmpz_mat_entry(res, j, i), fmpz_mat_entry(res, d - 1, j)); } } if (fmpz_equal(den, fmpz_mat_entry(res, d - 1, d - 1))) { for (i = 0; i < d; i++) fmpz_set(fmpz_mat_entry(res, d - 1, i), fmpq_poly_numref(NF_ELEM(t)) + i); } else { fmpz_divexact(fmpz_mat_entry(res, d - 1, d - 1), den, fmpq_poly_denref(NF_ELEM(t))); for (i = 0; i < d; i++) fmpz_mul(fmpz_mat_entry(res, d - 1, i), fmpq_poly_numref(NF_ELEM(t)) + i, fmpz_mat_entry(res, d - 1, d - 1)); } } } nf_elem_clear(t, nf); } }