void fmprb_mul_main_naive(fmprb_t z, const fmprb_t x, const fmprb_t y, slong prec) { if (fmpr_is_pos_inf(fmprb_radref(x)) || fmpr_is_pos_inf(fmprb_radref(y))) { fmpr_mul(fmprb_midref(z), fmprb_midref(x), fmprb_midref(y), prec, FMPR_RND_DOWN); fmpr_pos_inf(fmprb_radref(z)); } else { fmpr_t t, u; slong r; fmpr_init(t); fmpr_init(u); /* (x+a)*(y+b) = x*y + x*b + y*a + a*b*/ fmpr_mul(t, fmprb_midref(x), fmprb_radref(y), FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_abs(t, t); fmpr_mul(u, fmprb_midref(y), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_abs(u, u); fmpr_add(t, t, u, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_addmul(t, fmprb_radref(x), fmprb_radref(y), FMPRB_RAD_PREC, FMPR_RND_UP); r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), fmprb_midref(y), prec, FMPR_RND_DOWN); fmpr_add_error_result(fmprb_radref(z), t, fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_clear(t); fmpr_clear(u); } }
void fmprb_mul_fmpr_naive(fmprb_t z, const fmprb_t x, const fmpr_t y, slong prec) { /* (x+a) * y = x*y + y*a */ if (fmpr_is_pos_inf(fmprb_radref(x))) { fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN); fmpr_pos_inf(fmprb_radref(z)); } else if (fmpr_is_zero(fmprb_radref(x))) { slong r; r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN); fmpr_set_error_result(fmprb_radref(z), fmprb_midref(z), r); } else { slong r; fmpr_mul(fmprb_radref(z), fmprb_radref(x), y, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_abs(fmprb_radref(z), fmprb_radref(z)); r = fmpr_mul(fmprb_midref(z), fmprb_midref(x), y, prec, FMPR_RND_DOWN); fmpr_add_error_result(fmprb_radref(z), fmprb_radref(z), fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP); } }
void fmprb_sqrt(fmprb_t z, const fmprb_t x, slong prec) { slong r; if (fmprb_contains_negative(x)) { fmpr_nan(fmprb_midref(z)); fmpr_pos_inf(fmprb_radref(z)); return; } if (fmprb_is_exact(x)) { r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN); fmpr_set_error_result(fmprb_radref(z), fmprb_midref(z), r); } else { fmpr_t err; fmpr_init(err); fmpr_sub(err, fmprb_midref(x), fmprb_radref(x), FMPRB_RAD_PREC, FMPR_RND_DOWN); fmpr_rsqrt(err, err, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul(err, fmprb_radref(x), err, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul_2exp_si(err, err, -1); r = fmpr_sqrt(fmprb_midref(z), fmprb_midref(x), prec, FMPR_RND_DOWN); fmpr_add_error_result(fmprb_radref(z), err, fmprb_midref(z), r, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_clear(err); } fmprb_adjust(z); }
void gamma_taylor_bound_remainder(fmpr_t err, const fmpr_t z, long n) { fmpr_t t, u; gamma_taylor_bound_extend_cache(n + 1); fmpr_init(t); fmpr_init(u); /* denominator: 1 - r(n+1) * z, rounded down */ fmpr_mul(t, gamma_taylor_bound_ratio_cache + n + 1, z, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_one(u); fmpr_sub(u, u, t, FMPRB_RAD_PREC, FMPR_RND_DOWN); if (fmpr_sgn(u) <= 0) { fmpr_pos_inf(err); } else { fmpr_pow_sloppy_ui(t, z, n, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul_2exp_si(t, t, gamma_taylor_bound_mag_cache[n + 1]); fmpr_div(err, t, u, FMPRB_RAD_PREC, FMPR_RND_UP); } fmpr_clear(t); fmpr_clear(u); }
static __inline__ void fmpcb_inv_mid(fmpcb_t z, const fmpcb_t x, long prec) { fmpr_t t; fmpr_init(t); #define a fmprb_midref(fmpcb_realref(x)) #define b fmprb_midref(fmpcb_imagref(x)) #define e fmprb_midref(fmpcb_realref(z)) #define f fmprb_midref(fmpcb_imagref(z)) fmpr_mul(t, a, a, prec, FMPR_RND_DOWN); fmpr_addmul(t, b, b, prec, FMPR_RND_DOWN); fmpr_div(e, a, t, prec, FMPR_RND_DOWN); fmpr_div(f, b, t, prec, FMPR_RND_DOWN); fmpr_neg(f, f); #undef a #undef b #undef e #undef f fmpr_clear(t); }
void fmpr_pow_sloppy_fmpz(fmpr_t y, const fmpr_t b, const fmpz_t e, long prec, fmpr_rnd_t rnd) { long i, wp, bits; if (fmpz_is_zero(e)) { fmpr_set_ui(y, 1UL); return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); fmpr_pow_sloppy_fmpz(y, b, f, prec + 2, (rnd == FMPR_RND_FLOOR || rnd == FMPR_RND_DOWN) ? FMPR_RND_UP : FMPR_RND_DOWN); fmpr_ui_div(y, 1UL, y, prec, rnd); fmpz_clear(f); } if (y == b) { fmpr_t t; fmpr_init(t); fmpr_set(t, b); fmpr_pow_sloppy_fmpz(y, t, e, prec, rnd); fmpr_clear(t); return; } fmpr_set(y, b); bits = fmpz_bits(e); wp = FMPR_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { fmpr_mul(y, y, y, wp, rnd); if (fmpz_tstbit(e, i)) fmpr_mul(y, y, b, wp, rnd); } }
static slong fmpr_mul_si_naive(fmpr_t z, const fmpr_t x, slong y, slong prec, fmpr_rnd_t rnd) { fmpr_t t; slong r; fmpr_init(t); fmpr_set_si(t, y); r = fmpr_mul(z, x, t, prec, rnd); fmpr_clear(t); return r; }
slong fmpr_submul(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd) { fmpr_t t; slong r; fmpr_init(t); fmpr_mul(t, x, y, FMPR_PREC_EXACT, FMPR_RND_DOWN); r = fmpr_sub(z, z, t, prec, rnd); fmpr_clear(t); return r; }
/* Absolute value of rising factorial (could speed up once complex gamma is available). */ void fmpcb_rfac_abs_ubound2(fmpr_t bound, const fmpcb_t s, ulong n, long prec) { fmpr_t term, t; ulong k; /* M(k) = (a+k)^2 + b^2 M(0) = a^2 + b^2 M(k+1) = M(k) + 2*a + (2*k+1) */ fmpr_init(t); fmpr_init(term); fmpr_one(bound); /* M(0) = a^2 + b^2 */ fmprb_get_abs_ubound_fmpr(t, fmpcb_realref(s), prec); fmpr_mul(term, t, t, prec, FMPR_RND_UP); fmprb_get_abs_ubound_fmpr(t, fmpcb_imagref(s), prec); fmpr_mul(t, t, t, prec, FMPR_RND_UP); fmpr_add(term, term, t, prec, FMPR_RND_UP); /* we add t = 2*a to each term. note that this can be signed; we always want the most positive value */ fmpr_add(t, fmprb_midref(fmpcb_realref(s)), fmprb_radref(fmpcb_realref(s)), prec, FMPR_RND_CEIL); fmpr_mul_2exp_si(t, t, 1); for (k = 0; k < n; k++) { fmpr_mul(bound, bound, term, prec, FMPR_RND_UP); fmpr_add_ui(term, term, 2 * k + 1, prec, FMPR_RND_UP); fmpr_add(term, term, t, prec, FMPR_RND_UP); } fmpr_sqrt(bound, bound, prec, FMPR_RND_UP); fmpr_clear(t); fmpr_clear(term); }
static __inline__ void fmpcb_mul_mid(fmpcb_t z, const fmpcb_t x, const fmpcb_t y, long prec) { #define a fmprb_midref(fmpcb_realref(x)) #define b fmprb_midref(fmpcb_imagref(x)) #define c fmprb_midref(fmpcb_realref(y)) #define d fmprb_midref(fmpcb_imagref(y)) #define e fmprb_midref(fmpcb_realref(z)) #define f fmprb_midref(fmpcb_imagref(z)) fmpr_t t, u, v; fmpr_init(t); fmpr_init(u); fmpr_init(v); fmpr_add(t, a, b, prec, FMPR_RND_DOWN); fmpr_add(u, c, d, prec, FMPR_RND_DOWN); fmpr_mul(v, t, u, prec, FMPR_RND_DOWN); fmpr_mul(t, a, c, prec, FMPR_RND_DOWN); fmpr_mul(u, b, d, prec, FMPR_RND_DOWN); fmpr_sub(e, t, u, prec, FMPR_RND_DOWN); fmpr_sub(f, v, t, prec, FMPR_RND_DOWN); fmpr_sub(f, f, u, prec, FMPR_RND_DOWN); fmpr_clear(t); fmpr_clear(u); fmpr_clear(v); #undef a #undef b #undef c #undef d #undef e #undef f }
void fmprb_hypgeom_infsum(fmprb_t P, fmprb_t Q, hypgeom_t hyp, long target_prec, long prec) { mag_t err, z; long n; mag_init(err); mag_init(z); mag_set_fmpz(z, hyp->P->coeffs + hyp->P->length - 1); mag_div_fmpz(z, z, hyp->Q->coeffs + hyp->Q->length - 1); if (!hyp->have_precomputed) { hypgeom_precompute(hyp); hyp->have_precomputed = 1; } n = hypgeom_bound(err, hyp->r, hyp->boundC, hyp->boundD, hyp->boundK, hyp->MK, z, target_prec); fmprb_hypgeom_sum(P, Q, hyp, n, prec); if (fmpr_sgn(fmprb_midref(Q)) < 0) { fmprb_neg(P, P); fmprb_neg(Q, Q); } /* We have p/q = s + err i.e. (p + q*err)/q = s */ { fmpr_t u, v; fmpr_init(u); fmpr_init(v); mag_get_fmpr(v, err); fmpr_add(u, fmprb_midref(Q), fmprb_radref(Q), FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul(u, u, v, FMPRB_RAD_PREC, FMPR_RND_UP); fmprb_add_error_fmpr(P, u); fmpr_clear(u); fmpr_clear(v); } mag_clear(z); mag_clear(err); }
void fmprb_mat_det_inplace(fmprb_t det, fmprb_mat_t A, long prec) { long i, n, sign, rank; n = fmprb_mat_nrows(A); rank = fmprb_mat_gauss_partial(A, prec); sign = (rank < 0) ? -1 : 1; rank = FLINT_ABS(rank); fmprb_set_si(det, sign); for (i = 0; i < rank; i++) fmprb_mul(det, det, fmprb_mat_entry(A, i, i), prec); /* bound unreduced part using Hadamard's inequality */ if (rank < n) { fmpr_t t; fmprb_t d; fmpr_init(t); fmprb_init(d); fmpr_one(fmprb_radref(d)); for (i = rank; i < n; i++) { fmprb_vec_get_fmpr_2norm_squared_bound(t, A->rows[i] + rank, n - rank, FMPRB_RAD_PREC); fmpr_mul(fmprb_radref(d), fmprb_radref(d), t, FMPRB_RAD_PREC, FMPR_RND_UP); } fmpr_sqrt(fmprb_radref(d), fmprb_radref(d), FMPRB_RAD_PREC, FMPR_RND_UP); fmprb_mul(det, det, d, prec); fmprb_clear(d); fmpr_clear(t); } }
void _fmprb_poly_mullow_ztrunc(fmprb_ptr C, fmprb_srcptr A, long lenA, fmprb_srcptr B, long lenB, long n, long prec) { fmpz * Acoeffs, * Bcoeffs, * Ccoeffs; fmpz_t Aexp, Bexp, Cexp; fmpr_t Aerr, Berr, Anorm, Bnorm, err; long i; int squaring; lenA = FLINT_MIN(lenA, n); lenB = FLINT_MIN(lenB, n); squaring = (A == B) && (lenA == lenB); /* TODO: make the code below work correctly with out this workaround */ if (_fmprb_vec_rad_has_inf_nan(A, lenA) || (!squaring && _fmprb_vec_rad_has_inf_nan(B, lenB))) { _fmprb_vec_indeterminate(C, n); return; } fmpz_init(Aexp); fmpz_init(Bexp); fmpz_init(Cexp); Acoeffs = _fmpz_vec_init(lenA); Bcoeffs = _fmpz_vec_init(lenB); Ccoeffs = _fmpz_vec_init(n); fmpr_init(Aerr); fmpr_init(Berr); fmpr_init(Anorm); fmpr_init(Bnorm); fmpr_init(err); _fmprb_poly_get_fmpz_poly_2exp(Aerr, Aexp, Acoeffs, A, lenA, prec); if (squaring) { _fmpz_poly_sqrlow(Ccoeffs, Acoeffs, lenA, n); fmpz_add(Cexp, Aexp, Aexp); /* cross-multiply error bounds: (A+r)(B+s) = A^2 + 2Ar + r^2 */ _fmpr_fmpz_vec_max_norm(Anorm, Acoeffs, lenA, FMPRB_RAD_PREC); fmpr_mul_2exp_fmpz(Anorm, Anorm, Aexp); fmpr_mul(err, Anorm, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_mul_2exp_si(err, err, 1); fmpr_addmul(err, Aerr, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP); } else { _fmprb_poly_get_fmpz_poly_2exp(Berr, Bexp, Bcoeffs, B, lenB, prec); /* main multiplication */ if (lenA >= lenB) _fmpz_poly_mullow(Ccoeffs, Acoeffs, lenA, Bcoeffs, lenB, n); else _fmpz_poly_mullow(Ccoeffs, Bcoeffs, lenB, Acoeffs, lenA, n); fmpz_add(Cexp, Aexp, Bexp); /* cross-multiply error bounds: (A+r)(B+s) = AB + As + Br + rs */ _fmpr_fmpz_vec_max_norm(Anorm, Acoeffs, lenA, FMPRB_RAD_PREC); fmpr_mul_2exp_fmpz(Anorm, Anorm, Aexp); _fmpr_fmpz_vec_max_norm(Bnorm, Bcoeffs, lenB, FMPRB_RAD_PREC); fmpr_mul_2exp_fmpz(Bnorm, Bnorm, Bexp); fmpr_mul(err, Aerr, Berr, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_addmul(err, Anorm, Berr, FMPRB_RAD_PREC, FMPR_RND_UP); fmpr_addmul(err, Bnorm, Aerr, FMPRB_RAD_PREC, FMPR_RND_UP); } for (i = 0; i < n; i++) { fmprb_set_round_fmpz_2exp(C + i, Ccoeffs + i, Cexp, prec); /* there are at most (i+1) error terms for coefficient i */ /* TODO: make this tight */ fmpr_addmul_ui(fmprb_radref(C + i), err, i + 1, FMPRB_RAD_PREC, FMPR_RND_UP); } fmpr_clear(Aerr); fmpr_clear(Berr); fmpr_clear(Anorm); fmpr_clear(Bnorm); fmpr_clear(err); _fmpz_vec_clear(Acoeffs, lenA); _fmpz_vec_clear(Bcoeffs, lenB); _fmpz_vec_clear(Ccoeffs, n); fmpz_clear(Aexp); fmpz_clear(Bexp); fmpz_clear(Cexp); }
int main() { long iter, iter2; flint_rand_t state; printf("mul...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000; iter++) { fmpr_t x, y, z, v; long prec, r1, r2; fmpr_rnd_t rnd; fmpr_init(x); fmpr_init(y); fmpr_init(z); fmpr_init(v); for (iter2 = 0; iter2 < 100; iter2++) { fmpr_randtest_special(x, state, 2000, 200); fmpr_randtest_special(y, state, 2000, 200); prec = 2 + n_randint(state, 2000); switch (n_randint(state, 4)) { case 0: rnd = FMPR_RND_DOWN; break; case 1: rnd = FMPR_RND_UP; break; case 2: rnd = FMPR_RND_FLOOR; break; default: rnd = FMPR_RND_CEIL; break; } switch (n_randint(state, 5)) { case 0: r1 = fmpr_mul(z, x, y, prec, rnd); r2 = fmpr_mul_naive(v, x, y, prec, rnd); if (!fmpr_equal(z, v) || r1 != r2 || !fmpr_check_ulp(z, r1, prec)) { printf("FAIL!\n"); printf("x = "); fmpr_print(x); printf("\n\n"); printf("y = "); fmpr_print(y); printf("\n\n"); printf("z = "); fmpr_print(z); printf("\n\n"); printf("v = "); fmpr_print(v); printf("\n\n"); printf("r1 = %ld, r2 = %ld\n", r1, r2); abort(); } break; case 1: r1 = fmpr_mul(z, x, x, prec, rnd); r2 = fmpr_mul_naive(v, x, x, prec, rnd); if (!fmpr_equal(z, v) || r1 != r2 || !fmpr_check_ulp(z, r1, prec)) { printf("FAIL (aliasing 1)!\n"); printf("x = "); fmpr_print(x); printf("\n\n"); printf("z = "); fmpr_print(z); printf("\n\n"); printf("v = "); fmpr_print(v); printf("\n\n"); printf("r1 = %ld, r2 = %ld\n", r1, r2); abort(); } break; case 2: r2 = fmpr_mul_naive(v, x, x, prec, rnd); r1 = fmpr_mul(x, x, x, prec, rnd); if (!fmpr_equal(v, x) || r1 != r2 || !fmpr_check_ulp(x, r1, prec)) { printf("FAIL (aliasing 2)!\n"); printf("x = "); fmpr_print(x); printf("\n\n"); printf("z = "); fmpr_print(z); printf("\n\n"); printf("v = "); fmpr_print(v); printf("\n\n"); printf("r1 = %ld, r2 = %ld\n", r1, r2); abort(); } break; case 3: r2 = fmpr_mul_naive(v, x, y, prec, rnd); r1 = fmpr_mul(x, x, y, prec, rnd); if (!fmpr_equal(x, v) || r1 != r2 || !fmpr_check_ulp(x, r1, prec)) { printf("FAIL (aliasing 3)!\n"); printf("x = "); fmpr_print(x); printf("\n\n"); printf("y = "); fmpr_print(y); printf("\n\n"); printf("v = "); fmpr_print(v); printf("\n\n"); printf("r1 = %ld, r2 = %ld\n", r1, r2); abort(); } break; default: r2 = fmpr_mul_naive(v, x, y, prec, rnd); r1 = fmpr_mul(x, y, x, prec, rnd); if (!fmpr_equal(x, v) || r1 != r2 || !fmpr_check_ulp(x, r1, prec)) { printf("FAIL (aliasing 4)!\n"); printf("x = "); fmpr_print(x); printf("\n\n"); printf("y = "); fmpr_print(y); printf("\n\n"); printf("v = "); fmpr_print(v); printf("\n\n"); printf("r1 = %ld, r2 = %ld\n", r1, r2); abort(); } break; } } fmpr_clear(x); fmpr_clear(y); fmpr_clear(z); fmpr_clear(v); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
int main() { slong iter; flint_rand_t state; flint_printf("root...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { slong bits; ulong k; fmpr_t x, z, w; mpfr_t X, Z; bits = 2 + n_randint(state, 200); k = 1 + n_randint(state, 20); fmpr_init(x); fmpr_init(z); fmpr_init(w); mpfr_init2(X, k * (bits + 100)); mpfr_init2(Z, bits); fmpr_randtest_special(x, state, bits + n_randint(state, 100), 10); fmpr_abs(x, x); fmpr_randtest_special(z, state, bits + n_randint(state, 100), 10); /* occasionally produce perfect powers */ if (n_randint(state, 4) == 0) fmpr_mul(x, x, x, k * bits, FMPR_RND_DOWN); fmpr_get_mpfr(X, x, MPFR_RNDN); switch (n_randint(state, 4)) { case 0: mpfr_root(Z, X, k, MPFR_RNDZ); fmpr_root(z, x, k, bits, FMPR_RND_DOWN); break; case 1: mpfr_root(Z, X, k, MPFR_RNDA); fmpr_root(z, x, k, bits, FMPR_RND_UP); break; case 2: mpfr_root(Z, X, k, MPFR_RNDD); fmpr_root(z, x, k, bits, FMPR_RND_FLOOR); break; case 3: mpfr_root(Z, X, k, MPFR_RNDU); fmpr_root(z, x, k, bits, FMPR_RND_CEIL); break; } fmpr_set_mpfr(w, Z); if (!fmpr_equal(z, w)) { flint_printf("FAIL\n\n"); flint_printf("bits = %wd, k = %wu\n", bits, k); flint_printf("x = "); fmpr_print(x); flint_printf("\n\n"); flint_printf("z = "); fmpr_print(z); flint_printf("\n\n"); flint_printf("w = "); fmpr_print(w); flint_printf("\n\n"); abort(); } fmpr_clear(x); fmpr_clear(z); fmpr_clear(w); mpfr_clear(X); mpfr_clear(Z); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }