int fmpz_mat_solve_cramer(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { long i, dim = fmpz_mat_nrows(A); if (dim == 0) { fmpz_one(den); return 1; } else if (dim == 1) { fmpz_set(den, fmpz_mat_entry(A, 0, 0)); if (fmpz_is_zero(den)) return 0; if (!fmpz_mat_is_empty(B)) _fmpz_vec_set(X->rows[0], B->rows[0], fmpz_mat_ncols(B)); return 1; } else if (dim == 2) { fmpz_t t, u; _fmpz_mat_det_cofactor_2x2(den, A->rows); if (fmpz_is_zero(den)) return 0; fmpz_init(t); fmpz_init(u); for (i = 0; i < fmpz_mat_ncols(B); i++) { fmpz_mul (t, fmpz_mat_entry(A, 1, 1), fmpz_mat_entry(B, 0, i)); fmpz_submul(t, fmpz_mat_entry(A, 0, 1), fmpz_mat_entry(B, 1, i)); fmpz_mul (u, fmpz_mat_entry(A, 0, 0), fmpz_mat_entry(B, 1, i)); fmpz_submul(u, fmpz_mat_entry(A, 1, 0), fmpz_mat_entry(B, 0, i)); fmpz_swap(fmpz_mat_entry(X, 0, i), t); fmpz_swap(fmpz_mat_entry(X, 1, i), u); } fmpz_clear(t); fmpz_clear(u); return 1; } else if (dim == 3) { return _fmpz_mat_solve_cramer_3x3(X, den, A, B); } else { printf("Exception: fmpz_mat_solve_cramer: dim > 3 not implemented"); abort(); } }
void _fmpz_mat_solve_cramer_2x2(fmpz * x, fmpz_t d, fmpz ** const a, const fmpz * b) { fmpz_mul (&x[0], &a[1][1], &b[0]); fmpz_submul(&x[0], &a[0][1], &b[1]); fmpz_mul (&x[1], &a[0][0], &b[1]); fmpz_submul(&x[1], &a[1][0], &b[0]); _fmpz_mat_det_cofactor_2x2(d, a); }
void _fmpz_poly_newton_to_monomial(fmpz * poly, const fmpz * roots, slong n) { slong i, j; for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) fmpz_submul(poly + j, poly + j + 1, roots + i); }
void _fmpz_ramanujan_tau(fmpz_t res, fmpz_factor_t factors) { fmpz_poly_t poly; fmpz_t tau_p, p_11, next, this, prev; long k, r; ulong max_prime; max_prime = 1UL; for (k = 0; k < factors->length; k++) { /* TODO: handle overflow properly */ max_prime = FLINT_MAX(max_prime, fmpz_get_ui(factors->p + k)); } fmpz_poly_init(poly); fmpz_poly_ramanujan_tau(poly, max_prime + 1); fmpz_set_ui(res, 1); fmpz_init(tau_p); fmpz_init(p_11); fmpz_init(next); fmpz_init(this); fmpz_init(prev); for (k = 0; k < factors->length; k++) { ulong p = fmpz_get_ui(factors->p + k); fmpz_set(tau_p, poly->coeffs + p); fmpz_set_ui(p_11, p); fmpz_pow_ui(p_11, p_11, 11); fmpz_set_ui(prev, 1); fmpz_set(this, tau_p); for (r = 1; r < fmpz_get_ui(factors->exp + k); r++) { fmpz_mul(next, tau_p, this); fmpz_submul(next, p_11, prev); fmpz_set(prev, this); fmpz_set(this, next); } fmpz_mul(res, res, this); } fmpz_clear(tau_p); fmpz_clear(p_11); fmpz_clear(next); fmpz_clear(this); fmpz_clear(prev); fmpz_poly_clear(poly); }
void _fmpz_mat_solve_cramer_3x3(fmpz * x, fmpz_t d, fmpz ** const a, const fmpz * b) { fmpz_t t12, t13, t14, t15, t16, t17; fmpz_init(t12); fmpz_init(t13); fmpz_init(t14); fmpz_init(t15); fmpz_init(t16); fmpz_init(t17); fmpz_mul(t17, &a[1][0], &a[2][1]); fmpz_submul(t17, &a[1][1], &a[2][0]); fmpz_mul(t16, &a[1][2], &a[2][0]); fmpz_submul(t16, &a[1][0], &a[2][2]); fmpz_mul(t15, &a[1][1], &a[2][2]); fmpz_submul(t15, &a[1][2], &a[2][1]); fmpz_mul(t14, &a[2][0], &b[1]); fmpz_submul(t14, &a[1][0], &b[2]); fmpz_mul(t13, &a[2][1], &b[1]); fmpz_submul(t13, &a[1][1], &b[2]); fmpz_mul(t12, &a[2][2], &b[1]); fmpz_submul(t12, &a[1][2], &b[2]); fmpz_mul (&x[0], t15, &b[0]); fmpz_addmul(&x[0], t13, &a[0][2]); fmpz_submul(&x[0], t12, &a[0][1]); fmpz_mul (&x[1], t16, &b[0]); fmpz_addmul(&x[1], t12, &a[0][0]); fmpz_submul(&x[1], t14, &a[0][2]); fmpz_mul (&x[2], t17, &b[0]); fmpz_addmul(&x[2], t14, &a[0][1]); fmpz_submul(&x[2], t13, &a[0][0]); fmpz_mul (d, t15, &a[0][0]); fmpz_addmul(d, t16, &a[0][1]); fmpz_addmul(d, t17, &a[0][2]); fmpz_clear(t12); fmpz_clear(t13); fmpz_clear(t14); fmpz_clear(t15); fmpz_clear(t16); fmpz_clear(t17); }
void acb_quadratic_roots_fmpz(acb_t r1, acb_t r2, const fmpz_t a, const fmpz_t b, const fmpz_t c, slong prec) { fmpz_t d; fmpz_init(d); /* d = b^2 - 4ac */ fmpz_mul(d, a, c); fmpz_mul_2exp(d, d, 2); fmpz_submul(d, b, b); fmpz_neg(d, d); /* +/- sqrt(d) */ acb_zero(r1); if (fmpz_sgn(d) >= 0) { arb_sqrt_fmpz(acb_realref(r1), d, prec + fmpz_bits(d) + 4); } else { fmpz_neg(d, d); arb_sqrt_fmpz(acb_imagref(r1), d, prec + fmpz_bits(d) + 4); } acb_neg(r2, r1); /* -b */ acb_sub_fmpz(r1, r1, b, prec + 4); acb_sub_fmpz(r2, r2, b, prec + 4); /* divide by 2a */ fmpz_mul_2exp(d, a, 1); acb_div_fmpz(r1, r1, d, prec); acb_div_fmpz(r2, r2, d, prec); fmpz_clear(d); return; }
void _fmpz_vec_scalar_submul_fmpz(fmpz * vec1, const fmpz * vec2, slong len2, const fmpz_t x) { fmpz c = *x; if (!COEFF_IS_MPZ(c)) { if (c == 0) return; else if (c == 1) _fmpz_vec_sub(vec1, vec1, vec2, len2); else if (c == -1) _fmpz_vec_add(vec1, vec1, vec2, len2); else _fmpz_vec_scalar_submul_si(vec1, vec2, len2, c); } else { slong i; for (i = 0; i < len2; i++) fmpz_submul(vec1 + i, vec2 + i, x); } }
int _fmpz_mat_solve_cramer_3x3(fmpz_mat_t X, fmpz_t den, const fmpz_mat_t A, const fmpz_mat_t B) { fmpz_t t15, t16, t17; int success; fmpz_init(t15); fmpz_init(t16); fmpz_init(t17); fmpz_mul(t17, AA(1,0), AA(2,1)); fmpz_submul(t17, AA(1,1), AA(2,0)); fmpz_mul(t16, AA(1,2), AA(2,0)); fmpz_submul(t16, AA(1,0), AA(2,2)); fmpz_mul(t15, AA(1,1), AA(2,2)); fmpz_submul(t15, AA(1,2), AA(2,1)); fmpz_mul (den, t15, AA(0,0)); fmpz_addmul(den, t16, AA(0,1)); fmpz_addmul(den, t17, AA(0,2)); success = !fmpz_is_zero(den); if (success) { fmpz_t t12, t13, t14, x0, x1, x2; long i, n = fmpz_mat_ncols(B); fmpz_init(t12); fmpz_init(t13); fmpz_init(t14); fmpz_init(x0); fmpz_init(x1); fmpz_init(x2); for (i = 0; i < n; i++) { fmpz_mul(t14, AA(2,0), BB(1,i)); fmpz_submul(t14, AA(1,0), BB(2,i)); fmpz_mul(t13, AA(2,1), BB(1,i)); fmpz_submul(t13, AA(1,1), BB(2,i)); fmpz_mul(t12, AA(2,2), BB(1,i)); fmpz_submul(t12, AA(1,2), BB(2,i)); fmpz_mul (x0, t15, BB(0,i)); fmpz_addmul(x0, t13, AA(0,2)); fmpz_submul(x0, t12, AA(0,1)); fmpz_mul (x1, t16, BB(0,i)); fmpz_addmul(x1, t12, AA(0,0)); fmpz_submul(x1, t14, AA(0,2)); fmpz_mul (x2, t17, BB(0,i)); fmpz_addmul(x2, t14, AA(0,1)); fmpz_submul(x2, t13, AA(0,0)); fmpz_swap(XX(0,i), x0); fmpz_swap(XX(1,i), x1); fmpz_swap(XX(2,i), x2); } fmpz_clear(t12); fmpz_clear(t13); fmpz_clear(t14); fmpz_clear(x0); fmpz_clear(x1); fmpz_clear(x2); } fmpz_clear(t15); fmpz_clear(t16); fmpz_clear(t17); return success; }
static void __ramanujan_even_common_denom(fmpz * num, fmpz * den, long start, long n) { fmpz_t t, c, d, cden; long j, k, m, mcase; int prodsize; if (start >= n) return; fmpz_init(t); fmpz_init(c); fmpz_init(d); fmpz_init(cden); /* Common denominator */ fmpz_primorial(cden, n + 1); start += start % 2; /* Convert initial values to common denominator */ for (k = 0; k < start; k += 2) { fmpz_divexact(t, cden, den + k); fmpz_mul(num + k, num + k, t); } /* Ramanujan's recursive formula */ for (m = start; m < n; m += 2) { mcase = m % 6; fmpz_mul_ui(num + m, cden, m + 3UL); fmpz_divexact_ui(num + m, num + m, 3UL); if (mcase == 4) { fmpz_neg(num + m, num + m); fmpz_divexact_ui(num + m, num + m, 2UL); } /* All factors are strictly smaller than m + 4; choose prodsize such that (m + 4)^prodsize fits in a signed long. */ { #if FLINT64 if (m < 1444L) prodsize = 6; else if (m < 2097148L) prodsize = 3; else if (m < 3037000495L) prodsize = 2; /* not very likely... */ else abort(); #else if (m < 32L) prodsize = 6; else if (m < 1286L) prodsize = 3; else if (m < 46336L) prodsize = 2; else abort(); #endif } /* c = t = binomial(m+3, m) */ fmpz_set_ui(t, m + 1UL); fmpz_mul_ui(t, t, m + 2UL); fmpz_mul_ui(t, t, m + 3UL); fmpz_divexact_ui(t, t, 6UL); fmpz_set(c, t); for (j = 6; j <= m; j += 6) { long r = m - j; /* c = binomial(m+3, m-j); */ switch (prodsize) { case 2: fmpz_mul_ui(c, c, (r+6)*(r+5)); fmpz_mul_ui(c, c, (r+4)*(r+3)); fmpz_mul_ui(c, c, (r+2)*(r+1)); fmpz_set_ui(d, (j+0)*(j+3)); fmpz_mul_ui(d, d, (j-2)*(j+2)); fmpz_mul_ui(d, d, (j-1)*(j+1)); fmpz_divexact(c, c, d); break; case 3: fmpz_mul_ui(c, c, (r+6)*(r+5)*(r+4)); fmpz_mul_ui(c, c, (r+3)*(r+2)*(r+1)); fmpz_set_ui(d, (j+0)*(j+3)*(j-2)); fmpz_mul_ui(d, d, (j+2)*(j-1)*(j+1)); fmpz_divexact(c, c, d); break; case 6: fmpz_mul_ui(c, c, (r+6)*(r+5)*(r+4)*(r+3)*(r+2)*(r+1)); fmpz_divexact_ui(c, c, (j+0)*(j+3)*(j-2)*(j+2)*(j-1)*(j+1)); break; } fmpz_submul(num + m, c, num + (m - j)); } fmpz_divexact(num + m, num + m, t); } /* Convert to separate denominators */ for (k = 0; k < n; k += 2) { bernoulli_number_denom(den + k, k); fmpz_divexact(t, cden, den + k); fmpz_divexact(num + k, num + k, t); } fmpz_clear(t); fmpz_clear(c); fmpz_clear(d); fmpz_clear(cden); }
static void _fmpz_mod_mat_det(fmpz_t rop, const fmpz *M, slong n, const fmpz_t pN) { fmpz *F; fmpz *a; fmpz *A; fmpz_t s; slong t, i, j, p, k; F = _fmpz_vec_init(n); a = _fmpz_vec_init((n-1) * n); A = _fmpz_vec_init(n); fmpz_init(s); fmpz_neg(F + 0, M + 0*n + 0); for (t = 1; t < n; t++) { for (i = 0; i <= t; i++) fmpz_set(a + 0*n + i, M + i*n + t); fmpz_set(A + 0, M + t*n + t); for (p = 1; p < t; p++) { for (i = 0; i <= t; i++) { fmpz_zero(s); for (j = 0; j <= t; j++) fmpz_addmul(s, M + i*n + j, a + (p-1)*n + j); fmpz_mod(a + p*n + i, s, pN); } fmpz_set(A + p, a + p*n + t); } fmpz_zero(s); for (j = 0; j <= t; j++) fmpz_addmul(s, M + t*n + j, a + (t-1)*n + j); fmpz_mod(A + t, s, pN); for (p = 0; p <= t; p++) { fmpz_sub(F + p, F + p, A + p); for (k = 0; k < p; k++) fmpz_submul(F + p, A + k, F + (p-k-1)); fmpz_mod(F + p, F + p, pN); } } /* Now [F{n-1}, F{n-2}, ..., F{0}, 1] is the characteristic polynomial of the matrix M. */ if (n % WORD(2) == 0) { fmpz_set(rop, F + (n-1)); } else { fmpz_neg(rop, F + (n-1)); fmpz_mod(rop, rop, pN); } _fmpz_vec_clear(F, n); _fmpz_vec_clear(a, (n-1)*n); _fmpz_vec_clear(A, n); fmpz_clear(s); }
void _nf_elem_sub_qf(nf_elem_t a, const nf_elem_t b, const nf_elem_t c, const nf_t nf, int can) { fmpz_t d; const fmpz * const bnum = QNF_ELEM_NUMREF(b); const fmpz * const bden = QNF_ELEM_DENREF(b); const fmpz * const cnum = QNF_ELEM_NUMREF(c); const fmpz * const cden = QNF_ELEM_DENREF(c); fmpz * const anum = QNF_ELEM_NUMREF(a); fmpz * const aden = QNF_ELEM_DENREF(a); fmpz_init(d); fmpz_one(d); if (fmpz_equal(bden, cden)) { fmpz_sub(anum, bnum, cnum); fmpz_sub(anum + 1, bnum + 1, cnum + 1); fmpz_sub(anum + 2, bnum + 2, cnum + 2); fmpz_set(aden, bden); if (can && !fmpz_is_one(aden)) { fmpz_gcd(d, anum, anum + 1); fmpz_gcd(d, d, anum + 2); if (!fmpz_is_one(d)) { fmpz_gcd(d, d, aden); if (!fmpz_is_one(d)) { fmpz_divexact(anum, anum, d); fmpz_divexact(anum + 1, anum + 1, d); fmpz_divexact(anum + 2, anum + 2, d); fmpz_divexact(aden, aden, d); } } } fmpz_clear(d); return; } if (!fmpz_is_one(bden) && !fmpz_is_one(cden)) fmpz_gcd(d, bden, cden); if (fmpz_is_one(d)) { fmpz_mul(anum, bnum, cden); fmpz_mul(anum + 1, bnum + 1, cden); fmpz_mul(anum + 2, bnum + 2, cden); fmpz_submul(anum, cnum, bden); fmpz_submul(anum + 1, cnum + 1, bden); fmpz_submul(anum + 2, cnum + 2, bden); fmpz_mul(aden, bden, cden); } else { fmpz_t bden1; fmpz_t cden1; fmpz_init(bden1); fmpz_init(cden1); fmpz_divexact(bden1, bden, d); fmpz_divexact(cden1, cden, d); fmpz_mul(anum, bnum, cden1); fmpz_mul(anum + 1, bnum + 1, cden1); fmpz_mul(anum + 2, bnum + 2, cden1); fmpz_submul(anum, cnum, bden1); fmpz_submul(anum + 1, cnum + 1, bden1); fmpz_submul(anum + 2, cnum + 2, bden1); if (fmpz_is_zero(anum) && fmpz_is_zero(anum + 1) && fmpz_is_zero(anum + 2)) fmpz_one(aden); else { if (can) { fmpz_t e; fmpz_init(e); fmpz_gcd(e, anum, anum + 1); fmpz_gcd(e, e, anum + 2); if (!fmpz_is_one(e)) fmpz_gcd(e, e, d); if (fmpz_is_one(e)) fmpz_mul(aden, bden, cden1); else { fmpz_divexact(anum, anum, e); fmpz_divexact(anum + 1, anum + 1, e); fmpz_divexact(anum + 2, anum + 2, e); fmpz_divexact(bden1, bden, e); fmpz_mul(aden, bden1, cden1); } fmpz_clear(e); } else fmpz_mul(aden, bden, cden1); } fmpz_clear(bden1); fmpz_clear(cden1); } fmpz_clear(d); }
void _fmpq_poly_interpolate_fmpz_vec(fmpz * poly, fmpz_t den, const fmpz * xs, const fmpz * ys, long n) { fmpz *P, *Q, *w; fmpz_t t; long i, j; /* Constant */ if (n == 1) { fmpz_set(poly, ys); fmpz_one(den); return; } /* Linear */ if (n == 2) { fmpz_sub(den, xs, xs + 1); fmpz_sub(poly + 1, ys, ys + 1); fmpz_mul(poly, xs, ys + 1); fmpz_submul(poly, xs + 1, ys); return; } fmpz_init(t); P = _fmpz_vec_init(n + 1); Q = _fmpz_vec_init(n); w = _fmpz_vec_init(n); /* P = (x-x[0])*(x-x[1])*...*(x-x[n-1]) */ _fmpz_poly_product_roots_fmpz_vec(P, xs, n); /* Weights */ for (i = 0; i < n; i++) { fmpz_one(w + i); for (j = 0; j < n; j++) { if (i != j) { fmpz_sub(t, xs + i, xs + j); fmpz_mul(w + i, w + i, t); } } } _fmpz_vec_zero(poly, n); _fmpz_vec_lcm(den, w, n); for (i = 0; i < n; i++) { /* Q = P / (x - x[i]) */ _fmpz_poly_div_root(Q, P, n + 1, xs + i); /* result += Q * weight(i) */ fmpz_divexact(t, den, w + i); fmpz_mul(t, t, ys + i); _fmpz_vec_scalar_addmul_fmpz(poly, Q, n, t); } _fmpz_vec_clear(P, n + 1); _fmpz_vec_clear(Q, n); _fmpz_vec_clear(w, n); fmpz_clear(t); }
int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, long len) { long i, m; int result; /* the degree must be even */ if (len % 2 == 0) return 0; /* valuation must be even, and then can be reduced to 0 */ while (fmpz_is_zero(poly)) { if (!fmpz_is_zero(poly + 1)) return 0; fmpz_zero(res); poly += 2; len -= 2; res++; } /* check whether a square root exists modulo 2 */ for (i = 1; i < len; i += 2) if (!fmpz_is_even(poly + i)) return 0; /* check endpoints */ if (!fmpz_is_square(poly) || (len > 1 && !fmpz_is_square(poly + len - 1))) return 0; /* square root of leading coefficient */ m = (len + 1) / 2; fmpz_sqrt(res + m - 1, poly + len - 1); result = 1; /* do long divison style 'square root with remainder' from top to bottom */ if (len > 1) { fmpz_t t, u; fmpz * r; fmpz_init(t); fmpz_init(u); r = _fmpz_vec_init(len); _fmpz_vec_set(r, poly, len); fmpz_mul_ui(u, res + m - 1, 2); for (i = 1; i < m; i++) { fmpz_fdiv_qr(res + m - i - 1, t, r + len - i - 1, u); if (!fmpz_is_zero(t)) { result = 0; break; } fmpz_mul_si(t, res + m - i - 1, -2); _fmpz_vec_scalar_addmul_fmpz(r + len - 2*i, res + m - i, i - 1, t); fmpz_submul(r + len - 2*i - 1, res + m - i - 1, res + m - i - 1); } for (i = m; i < len && result; i++) if (!fmpz_is_zero(r + len - 1 - i)) result = 0; _fmpz_vec_clear(r, len); fmpz_clear(t); fmpz_clear(u); } return result; }
void acb_modular_transform(acb_t w, const psl2z_t g, const acb_t z, slong prec) { #define a (&g->a) #define b (&g->b) #define c (&g->c) #define d (&g->d) #define x acb_realref(z) #define y acb_imagref(z) if (fmpz_is_zero(c)) { /* (az+b)/d, where we must have a = d = 1 */ acb_add_fmpz(w, z, b, prec); } else if (fmpz_is_zero(a)) { /* b/(cz+d), where -bc = 1, c = 1 => -1/(z+d) */ acb_add_fmpz(w, z, d, prec); acb_inv(w, w, prec); acb_neg(w, w); } else if (0) { acb_t t, u; acb_init(t); acb_init(u); acb_set_fmpz(t, b); acb_addmul_fmpz(t, z, a, prec); acb_set_fmpz(u, d); acb_addmul_fmpz(u, z, c, prec); acb_div(w, t, u, prec); acb_clear(t); acb_clear(u); } else { /* (az+b)/(cz+d) = (re+im*i)/den where re = bd + (bc+ad)x + ac(x^2+y^2) im = (ad-bc)y den = c^2(x^2+y^2) + 2cdx + d^2 */ fmpz_t t; arb_t re, im, den; arb_init(re); arb_init(im); arb_init(den); fmpz_init(t); arb_mul(im, x, x, prec); arb_addmul(im, y, y, prec); fmpz_mul(t, b, d); arb_set_fmpz(re, t); fmpz_mul(t, b, c); fmpz_addmul(t, a, d); arb_addmul_fmpz(re, x, t, prec); fmpz_mul(t, a, c); arb_addmul_fmpz(re, im, t, prec); fmpz_mul(t, d, d); arb_set_fmpz(den, t); fmpz_mul(t, c, d); fmpz_mul_2exp(t, t, 1); arb_addmul_fmpz(den, x, t, prec); fmpz_mul(t, c, c); arb_addmul_fmpz(den, im, t, prec); fmpz_mul(t, a, d); fmpz_submul(t, b, c); arb_mul_fmpz(im, y, t, prec); arb_div(acb_realref(w), re, den, prec); arb_div(acb_imagref(w), im, den, prec); arb_clear(re); arb_clear(im); arb_clear(den); fmpz_clear(t); } #undef a #undef b #undef c #undef d #undef x #undef y }