static void _interpolate_newton(arb_ptr ys, arb_srcptr xs, long n, long prec) { arb_t p, q, t; long i, j; arb_init(p); arb_init(q); arb_init(t); for (i = 1; i < n; i++) { arb_set(t, ys + i - 1); for (j = i; j < n; j++) { arb_sub(p, ys + j, t, prec); arb_sub(q, xs + j, xs + j - i, prec); arb_set(t, ys + j); arb_div(ys + j, p, q, prec); } } arb_clear(p); arb_clear(q); arb_clear(t); }
int acb_cmp_pretty(const acb_t a, const acb_t b) { arb_t t, u, v; int res; arb_init(t); arb_init(u); arb_init(v); arb_abs(u, acb_imagref(a)); arb_abs(v, acb_imagref(b)); arb_sub(t, u, v, MAG_BITS); res = 0; if (arb_contains_zero(t)) { arb_sub(t, acb_realref(a), acb_realref(b), MAG_BITS); res = arb_is_positive(t) ? 1 : -1; } else { res = arb_is_positive(t) ? 1 : -1; } arb_clear(t); arb_clear(u); arb_clear(v); return res; }
static void _newton_to_monomial(arb_ptr ys, arb_srcptr xs, long n, long prec) { arb_t t, u; long i, j; arb_init(t); arb_init(u); for (i = n - 2; i >= 0; i--) { arb_set(t, ys + i); arb_set(ys + i, ys + i + 1); for (j = i + 1; j < n - 1; j++) { arb_mul(u, ys + j, xs + i, prec); arb_sub(ys + j, ys + j + 1, u, prec); } arb_mul(u, ys + n - 1, xs + i, prec); arb_sub(ys + n - 1, t, u, prec); } _arb_poly_reverse(ys, ys, n, n); arb_clear(t); arb_clear(u); }
void acb_real_min(acb_t res, const acb_t x, const acb_t y, int analytic, slong prec) { arb_t t; if (!acb_is_finite(x) || !acb_is_finite(y)) { acb_indeterminate(res); return; } arb_init(t); arb_sub(t, acb_realref(x), acb_realref(y), prec); if (arb_is_positive(t)) acb_set_round(res, y, prec); else if (arb_is_negative(t)) acb_set_round(res, x, prec); else if (!analytic) acb_union(res, x, y, prec); else acb_indeterminate(res); arb_clear(t); }
static void arb_sqrt1pm1_tiny(arb_t r, const arb_t z, slong prec) { mag_t b, c; arb_t t; mag_init(b); mag_init(c); arb_init(t); /* if |z| < 1, then |(sqrt(1+z)-1) - (z/2-z^2/8)| <= |z|^3/(1-|z|)/16 */ arb_get_mag(b, z); mag_one(c); mag_sub_lower(c, c, b); mag_pow_ui(b, b, 3); mag_div(b, b, c); mag_mul_2exp_si(b, b, -4); arb_mul(t, z, z, prec); arb_mul_2exp_si(t, t, -2); arb_sub(r, z, t, prec); arb_mul_2exp_si(r, r, -1); if (mag_is_finite(b)) arb_add_error_mag(r, b); else arb_indeterminate(r); mag_clear(b); mag_clear(c); arb_clear(t); }
void arb_submul_naive(arb_t z, const arb_t x, const arb_t y, slong prec) { arb_t t; arb_init(t); arb_mul(t, x, y, ARF_PREC_EXACT); arb_sub(z, z, t, prec); arb_clear(t); }
void arb_twobytwo_diag(arb_t u1, arb_t u2, const arb_t a, const arb_t b, const arb_t d, slong prec) { // Compute the orthogonal matrix that diagonalizes // // A = [a b] // [b d] // // This matrix will have the form // // U = [cos x , -sin x] // [sin x, cos x] // // where the diagonal matrix is U^t A U. // We set u1 = cos x, u2 = -sin x. if(arb_contains_zero(b)) { // this is not quite right (doesn't set error intervals) arb_set_ui(u1, 1); arb_set_ui(u2, 0); return; } arb_t x; arb_init(x); arb_mul(u1, b, b, prec); // u1 = b^2 arb_sub(u2, a, d, prec); // u2 = a - d arb_mul_2exp_si(u2, u2, -1); // u2 = (a - d)/2 arb_mul(u2, u2, u2, prec); // u2 = ( (a - d)/2 )^2 arb_add(u1, u1, u2, prec); // u1 = b^2 + ( (a-d)/2 )^2 arb_sqrt(u1, u1, prec); // u1 = sqrt(above) arb_mul_2exp_si(u1, u1, 1); // u1 = 2 (sqrt (above) ) arb_add(u1, u1, d, prec); // u1 += d arb_sub(u1, u1, a, prec); // u1 -= a arb_mul_2exp_si(u1, u1, -1); // u1 = (d - a)/2 + sqrt(b^2 + ( (a-d)/2 )^2) arb_mul(x, u1, u1, prec); arb_addmul(x, b, b, prec); // x = u1^2 + b^2 arb_sqrt(x, x, prec); // x = sqrt(u1^2 + b^2) arb_div(u2, u1, x, prec); arb_div(u1, b, x, prec); arb_neg(u1, u1); arb_clear(x); }
void arb_mat_sub(arb_mat_t res, const arb_mat_t mat1, const arb_mat_t mat2, slong prec) { slong i, j; for (i = 0; i < arb_mat_nrows(mat1); i++) for (j = 0; j < arb_mat_ncols(mat1); j++) arb_sub(arb_mat_entry(res, i, j), arb_mat_entry(mat1, i, j), arb_mat_entry(mat2, i, j), prec); }
/* This gives some speedup for small lengths. */ static __inline__ void _arb_poly_rem_2(arb_ptr r, arb_srcptr a, long al, arb_srcptr b, long bl, long prec) { if (al == 2) { arb_mul(r + 0, a + 1, b + 0, prec); arb_sub(r + 0, a + 0, r + 0, prec); } else { _arb_poly_rem(r, a, al, b, bl, prec); } }
int arb_calc_newton_step(arb_t xnew, arb_calc_func_t func, void * param, const arb_t x, const arb_t conv_region, const arf_t conv_factor, slong prec) { mag_t err, v; arb_t t; arb_struct u[2]; int result; mag_init(err); mag_init(v); arb_init(t); arb_init(u + 0); arb_init(u + 1); mag_mul(err, arb_radref(x), arb_radref(x)); arf_get_mag(v, conv_factor); mag_mul(err, err, v); arf_set(arb_midref(t), arb_midref(x)); mag_zero(arb_radref(t)); func(u, t, param, 2, prec); arb_div(u, u, u + 1, prec); arb_sub(u, t, u, prec); mag_add(arb_radref(u), arb_radref(u), err); if (arb_contains(conv_region, u) && (mag_cmp(arb_radref(u), arb_radref(x)) < 0)) { arb_swap(xnew, u); result = ARB_CALC_SUCCESS; } else { arb_set(xnew, x); result = ARB_CALC_NO_CONVERGENCE; } arb_clear(t); arb_clear(u); arb_clear(u + 1); mag_clear(err); mag_clear(v); return result; }
int _arb_poly_newton_step(arb_t xnew, arb_srcptr poly, long len, const arb_t x, const arb_t convergence_interval, const arf_t convergence_factor, long prec) { arf_t err; arb_t t, u, v; int result; arf_init(err); arb_init(t); arb_init(u); arb_init(v); arf_set_mag(err, arb_radref(x)); arf_mul(err, err, err, MAG_BITS, ARF_RND_UP); arf_mul(err, err, convergence_factor, MAG_BITS, ARF_RND_UP); arf_set(arb_midref(t), arb_midref(x)); mag_zero(arb_radref(t)); _arb_poly_evaluate2(u, v, poly, len, t, prec); arb_div(u, u, v, prec); arb_sub(u, t, u, prec); arb_add_error_arf(u, err); if (arb_contains(convergence_interval, u) && (mag_cmp(arb_radref(u), arb_radref(x)) < 0)) { arb_swap(xnew, u); result = 1; } else { arb_set(xnew, x); result = 0; } arb_clear(t); arb_clear(u); arb_clear(v); arf_clear(err); return result; }
static void _acb_hypgeom_li_offset(acb_t res, const acb_t z, long prec) { if (acb_is_int(z) && arf_cmp_2exp_si(arb_midref(acb_realref(z)), 1) == 0) { acb_zero(res); } else { arb_t t; arb_init(t); _acb_hypgeom_const_li2(t, prec); _acb_hypgeom_li(res, z, prec); arb_sub(acb_realref(res), acb_realref(res), t, prec); arb_clear(t); } }
static void _stirling_number_1_vec_next(arb_ptr row, arb_srcptr prev, slong n, slong klen, slong prec) { slong k; if (klen > n) arb_one(row + n); if (n != 0 && klen != 0) arb_zero(row); for (k = FLINT_MIN(n, klen) - 1; k >= 1; k--) { arb_mul_ui(row + k, prev + k, n - 1, prec); arb_sub(row + k, prev + k - 1, row + k, prec); } for (k = n + 1; k < klen; k++) arb_zero(row + k); }
void arb_zeta_ui_borwein_bsplit(arb_t x, ulong s, slong prec) { zeta_bsplit_t sum; mag_t err; slong wp, n; /* zeta(0) = -1/2 */ if (s == 0) { arb_set_si(x, -1); arb_mul_2exp_si(x, x, -1); return; } if (s == 1) { flint_printf("zeta_ui_borwein_bsplit: zeta(1)"); abort(); } n = prec / ERROR_B + 2; wp = prec + 30; zeta_bsplit_init(sum); zeta_bsplit(sum, 0, n + 1, n, s, 0, wp); /* A/Q3 - B/Q3 / (C/Q1) = (A*C - B*Q1) / (Q3*C) */ arb_mul(sum->A, sum->A, sum->C, wp); arb_mul(sum->B, sum->B, sum->Q1, wp); arb_sub(sum->A, sum->A, sum->B, wp); arb_mul(sum->Q3, sum->Q3, sum->C, wp); arb_div(sum->C, sum->A, sum->Q3, wp); mag_init(err); mag_borwein_error(err, n); mag_add(arb_radref(sum->C), arb_radref(sum->C), err); mag_clear(err); /* convert from eta(s) to zeta(s) */ arb_div_2expm1_ui(x, sum->C, s - 1, wp); arb_mul_2exp_si(x, x, s - 1); zeta_bsplit_clear(sum); }
int acb_modular_is_in_fundamental_domain(const acb_t z, const arf_t tol, long prec) { arb_t t; arb_init(t); /* require re(w) + 1/2 >= 0 */ arb_set_ui(t, 1); arb_mul_2exp_si(t, t, -1); arb_add(t, t, acb_realref(z), prec); arb_add_arf(t, t, tol, prec); if (!arb_is_nonnegative(t)) { arb_clear(t); return 0; } /* require re(w) - 1/2 <= 0 */ arb_set_ui(t, 1); arb_mul_2exp_si(t, t, -1); arb_sub(t, acb_realref(z), t, prec); arb_sub_arf(t, t, tol, prec); if (!arb_is_nonpositive(t)) { arb_clear(t); return 0; } /* require |w| >= 1 - tol, i.e. |w| - 1 + tol >= 0 */ acb_abs(t, z, prec); arb_sub_ui(t, t, 1, prec); arb_add_arf(t, t, tol, prec); if (!arb_is_nonnegative(t)) { arb_clear(t); return 0; } arb_clear(t); return 1; }
int main() { long p = 1000; long d = 53; arb_t a, b, x, t; arb_init(a); arb_init(b); arb_init(x); arb_init(t); // a = 1 + 2 ^ -76 arb_set_str(a, "2", p); arb_set_str(t, "-76", p); arb_pow(a, a, t, p); arb_set_str(t, "1", p); arb_add(a, t, a, p); printf("a = "); arb_printd(a, d); printf("\n"); // b = 4 ^ 38 + 0.5 arb_set_str(b, "0.5", p); arb_ui_pow_ui(t, 4, 38, p); arb_add(b, t, b, p); printf("b = "); arb_printd(b, d); printf("\n"); // x = a ^ b arb_pow(x, a, b, p); printf("x = "); arb_printd(x, d); printf("\n"); arb_const_e(t, p); printf("e = "); arb_printd(t, d); printf("\n"); arb_sub(t, x, t, p); printf("x-e = "); arb_printd(t, d); printf("\n"); printf("Computed with arb-%s\n", arb_version); arb_clear(a); arb_clear(b); arb_clear(x); arb_clear(t); }
void _arb_poly_div_series(arb_ptr Q, arb_srcptr A, long Alen, arb_srcptr B, long Blen, long n, long prec) { Alen = FLINT_MIN(Alen, n); Blen = FLINT_MIN(Blen, n); if (Blen == 1) { _arb_vec_scalar_div(Q, A, Alen, B, prec); _arb_vec_zero(Q + Alen, n - Alen); } else if (n == 2) { if (Alen == 1) { arb_div(Q, A, B, prec); arb_div(Q + 1, Q, B, prec); arb_mul(Q + 1, Q + 1, B + 1, prec); arb_neg(Q + 1, Q + 1); } else { arb_div(Q, A, B, prec); arb_mul(Q + 1, Q, B + 1, prec); arb_sub(Q + 1, A + 1, Q + 1, prec); arb_div(Q + 1, Q + 1, B, prec); } } else { arb_ptr Binv; Binv = _arb_vec_init(n); _arb_poly_inv_series(Binv, B, Blen, n, prec); _arb_poly_mullow(Q, Binv, n, A, Alen, n, prec); _arb_vec_clear(Binv, n); } }
void _arb_poly_taylor_shift_horner(arb_ptr poly, const arb_t c, slong n, slong prec) { slong i, j; if (arb_is_one(c)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) arb_add(poly + j, poly + j, poly + j + 1, prec); } else if (arb_equal_si(c, -1)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) arb_sub(poly + j, poly + j, poly + j + 1, prec); } else if (!arb_is_zero(c)) { for (i = n - 2; i >= 0; i--) for (j = i; j < n - 1; j++) arb_addmul(poly + j, poly + j + 1, c, prec); } }
int main() { slong iter; flint_rand_t state; flint_printf("sub_si...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 10000; iter++) { arb_t a, b, c, d; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_init(d); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_sub_si(c, a, x, prec); arb_sub(d, a, b, prec); if (!arb_equal(c, d)) { flint_printf("FAIL\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); flint_printf("d = "); arb_print(d); flint_printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); arb_clear(d); } /* aliasing */ for (iter = 0; iter < 10000; iter++) { arb_t a, b, c; slong x; slong prec; arb_init(a); arb_init(b); arb_init(c); arb_randtest_special(a, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(b, state, 1 + n_randint(state, 2000), 100); arb_randtest_special(c, state, 1 + n_randint(state, 2000), 100); x = z_randtest(state); prec = 2 + n_randint(state, 2000); arb_set_si(b, x); arb_sub_si(c, a, x, prec); arb_sub_si(a, a, x, prec); if (!arb_equal(a, c)) { flint_printf("FAIL (aliasing)\n\n"); flint_printf("a = "); arb_print(a); flint_printf("\n\n"); flint_printf("b = "); arb_print(b); flint_printf("\n\n"); flint_printf("c = "); arb_print(c); flint_printf("\n\n"); abort(); } arb_clear(a); arb_clear(b); arb_clear(c); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void acb_hypgeom_ci_asymp(acb_t res, const acb_t z, slong prec) { acb_t t, u, w, v, one; acb_init(t); acb_init(u); acb_init(w); acb_init(v); acb_init(one); acb_one(one); acb_mul_onei(w, z); /* u = U(1,1,iz) */ acb_hypgeom_u_asymp(u, one, one, w, -1, prec); /* v = e^(-iz) */ acb_neg(v, w); acb_exp(v, v, prec); acb_mul(t, u, v, prec); if (acb_is_real(z)) { arb_div(acb_realref(t), acb_imagref(t), acb_realref(z), prec); arb_zero(acb_imagref(t)); acb_neg(t, t); } else { /* u = U(1,1,-iz) */ acb_neg(w, w); acb_hypgeom_u_asymp(u, one, one, w, -1, prec); acb_inv(v, v, prec); acb_submul(t, u, v, prec); acb_div(t, t, w, prec); acb_mul_2exp_si(t, t, -1); } if (arb_is_zero(acb_realref(z))) { if (arb_is_positive(acb_imagref(z))) { arb_const_pi(acb_imagref(t), prec); arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1); } else if (arb_is_negative(acb_imagref(z))) { arb_const_pi(acb_imagref(t), prec); arb_mul_2exp_si(acb_imagref(t), acb_imagref(t), -1); arb_neg(acb_imagref(t), acb_imagref(t)); } else { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_zero(acb_imagref(t)); arb_add_error(acb_imagref(t), acb_realref(u)); } } else { /* 0 if positive or positive imaginary pi if upper left quadrant (including negative real axis) -pi if lower left quadrant (including negative imaginary axis) */ if (arb_is_positive(acb_realref(z))) { /* do nothing */ } else if (arb_is_negative(acb_realref(z)) && arb_is_nonnegative(acb_imagref(z))) { acb_const_pi(u, prec); arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else if (arb_is_nonpositive(acb_realref(z)) && arb_is_negative(acb_imagref(z))) { acb_const_pi(u, prec); arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else { /* add [-pi,pi] */ acb_const_pi(u, prec); arb_add_error(acb_imagref(t), acb_realref(u)); } } acb_swap(res, t); acb_clear(t); acb_clear(u); acb_clear(w); acb_clear(v); acb_clear(one); }
void keiper_li_series(arb_ptr z, slong len, slong prec) { arb_ptr t, u, v; t = _arb_vec_init(len); u = _arb_vec_init(len); v = _arb_vec_init(len); /* -zeta(s) */ flint_printf("zeta: "); TIMEIT_ONCE_START arb_zero(t + 0); arb_one(t + 1); arb_one(u); _arb_poly_zeta_series(v, t, 2, u, 0, len, prec); _arb_vec_neg(v, v, len); TIMEIT_ONCE_STOP SHOW_MEMORY_USAGE /* logarithm */ flint_printf("log: "); TIMEIT_ONCE_START _arb_poly_log_series(t, v, len, len, prec); TIMEIT_ONCE_STOP /* add log(gamma(1+s/2)) */ flint_printf("gamma: "); TIMEIT_ONCE_START arb_one(u); arb_one(u + 1); arb_mul_2exp_si(u + 1, u + 1, -1); _arb_poly_lgamma_series(v, u, 2, len, prec); _arb_vec_add(t, t, v, len, prec); TIMEIT_ONCE_STOP /* subtract 0.5 s log(pi) */ arb_const_pi(u, prec); arb_log(u, u, prec); arb_mul_2exp_si(u, u, -1); arb_sub(t + 1, t + 1, u, prec); /* add log(1-s) */ arb_one(u); arb_set_si(u + 1, -1); _arb_poly_log_series(v, u, 2, len, prec); _arb_vec_add(t, t, v, len, prec); /* binomial transform */ flint_printf("binomial transform: "); TIMEIT_ONCE_START arb_set(z, t); _arb_vec_neg(t + 1, t + 1, len - 1); _arb_poly_binomial_transform(z + 1, t + 1, len - 1, len - 1, prec); TIMEIT_ONCE_STOP _arb_vec_clear(t, len); _arb_vec_clear(u, len); _arb_vec_clear(v, len); }
void _arb_bell_sum_taylor(arb_t res, const fmpz_t n, const fmpz_t a, const fmpz_t b, const fmpz_t mmag, long tol) { fmpz_t m, r, R, tmp; mag_t B, C, D, bound; arb_t t, u; long wp, k, N; if (_fmpz_sub_small(b, a) < 5) { arb_bell_sum_bsplit(res, n, a, b, mmag, tol); return; } fmpz_init(m); fmpz_init(r); fmpz_init(R); fmpz_init(tmp); /* r = max(m - a, b - m) */ /* m = a + (b - a) / 2 */ fmpz_sub(r, b, a); fmpz_cdiv_q_2exp(r, r, 1); fmpz_add(m, a, r); fmpz_mul_2exp(R, r, RADIUS_BITS); mag_init(B); mag_init(C); mag_init(D); mag_init(bound); arb_init(t); arb_init(u); if (fmpz_cmp(R, m) >= 0) { mag_inf(C); mag_inf(D); } else { /* C = exp(R * |F'(m)| + (1/2) R^2 * (n/(m-R)^2 + 1/(m-R))) */ /* C = exp(R * (|F'(m)| + (1/2) R * (n/(m-R) + 1)/(m-R))) */ /* D = (1/2) R * (n/(m-R) + 1)/(m-R) */ fmpz_sub(tmp, m, R); mag_set_fmpz(D, n); mag_div_fmpz(D, D, tmp); mag_one(C); mag_add(D, D, C); mag_div_fmpz(D, D, tmp); mag_mul_fmpz(D, D, R); mag_mul_2exp_si(D, D, -1); /* C = |F'(m)| */ wp = 20 + 1.05 * fmpz_bits(n); arb_set_fmpz(t, n); arb_div_fmpz(t, t, m, wp); fmpz_add_ui(tmp, m, 1); arb_set_fmpz(u, tmp); arb_digamma(u, u, wp); arb_sub(t, t, u, wp); arb_get_mag(C, t); /* C = exp(R * (C + D)) */ mag_add(C, C, D); mag_mul_fmpz(C, C, R); mag_exp(C, C); } if (mag_cmp_2exp_si(C, tol / 4 + 2) > 0) { _arb_bell_sum_taylor(res, n, a, m, mmag, tol); _arb_bell_sum_taylor(t, n, m, b, mmag, tol); arb_add(res, res, t, 2 * tol); } else { arb_ptr mx, ser1, ser2, ser3; /* D = T(m) */ wp = 20 + 1.05 * fmpz_bits(n); arb_set_fmpz(t, m); arb_pow_fmpz(t, t, n, wp); fmpz_add_ui(tmp, m, 1); arb_gamma_fmpz(u, tmp, wp); arb_div(t, t, u, wp); arb_get_mag(D, t); /* error bound: (b-a) * C * D * B^N / (1 - B), B = r/R */ /* ((b-a) * C * D * 2) * 2^(-N*RADIUS_BITS) */ /* ((b-a) * C * D * 2) */ mag_mul(bound, C, D); mag_mul_2exp_si(bound, bound, 1); fmpz_sub(tmp, b, a); mag_mul_fmpz(bound, bound, tmp); /* N = (tol + log2((b-a)*C*D*2) - mmag) / RADIUS_BITS */ if (mmag == NULL) { /* estimate D ~= 2^mmag */ fmpz_add_ui(tmp, MAG_EXPREF(C), tol); fmpz_cdiv_q_ui(tmp, tmp, RADIUS_BITS); } else { fmpz_sub(tmp, MAG_EXPREF(bound), mmag); fmpz_add_ui(tmp, tmp, tol); fmpz_cdiv_q_ui(tmp, tmp, RADIUS_BITS); } if (fmpz_cmp_ui(tmp, 5 * tol / 4) > 0) N = 5 * tol / 4; else if (fmpz_cmp_ui(tmp, 2) < 0) N = 2; else N = fmpz_get_ui(tmp); /* multiply by 2^(-N*RADIUS_BITS) */ mag_mul_2exp_si(bound, bound, -N * RADIUS_BITS); mx = _arb_vec_init(2); ser1 = _arb_vec_init(N); ser2 = _arb_vec_init(N); ser3 = _arb_vec_init(N); /* estimate (this should work for moderate n and tol) */ wp = 1.1 * tol + 1.05 * fmpz_bits(n) + 5; /* increase precision until convergence */ while (1) { /* (m+x)^n / gamma(m+1+x) */ arb_set_fmpz(mx, m); arb_one(mx + 1); _arb_poly_log_series(ser1, mx, 2, N, wp); for (k = 0; k < N; k++) arb_mul_fmpz(ser1 + k, ser1 + k, n, wp); arb_add_ui(mx, mx, 1, wp); _arb_poly_lgamma_series(ser2, mx, 2, N, wp); _arb_vec_sub(ser1, ser1, ser2, N, wp); _arb_poly_exp_series(ser3, ser1, N, N, wp); /* t = a - m, u = b - m */ arb_set_fmpz(t, a); arb_sub_fmpz(t, t, m, wp); arb_set_fmpz(u, b); arb_sub_fmpz(u, u, m, wp); arb_power_sum_vec(ser1, t, u, N, wp); arb_zero(res); for (k = 0; k < N; k++) arb_addmul(res, ser3 + k, ser1 + k, wp); if (mmag != NULL) { if (_fmpz_sub_small(MAG_EXPREF(arb_radref(res)), mmag) <= -tol) break; } else { if (arb_rel_accuracy_bits(res) >= tol) break; } wp = 2 * wp; } /* add the series truncation bound */ arb_add_error_mag(res, bound); _arb_vec_clear(mx, 2); _arb_vec_clear(ser1, N); _arb_vec_clear(ser2, N); _arb_vec_clear(ser3, N); } mag_clear(B); mag_clear(C); mag_clear(D); mag_clear(bound); arb_clear(t); arb_clear(u); fmpz_clear(m); fmpz_clear(r); fmpz_clear(R); fmpz_clear(tmp); }
void Lib_Arb_Sub(ArbPtr f, ArbPtr g, ArbPtr h, int32_t prec) { arb_sub( (arb_ptr) f, (arb_ptr) g, (arb_ptr) h, prec); }
void acb_sqrt(acb_t y, const acb_t x, slong prec) { arb_t r, t, u; slong wp; #define a acb_realref(x) #define b acb_imagref(x) #define c acb_realref(y) #define d acb_imagref(y) if (arb_is_zero(b)) { if (arb_is_nonnegative(a)) { arb_sqrt(c, a, prec); arb_zero(d); return; } else if (arb_is_nonpositive(a)) { arb_neg(d, a); arb_sqrt(d, d, prec); arb_zero(c); return; } } if (arb_is_zero(a)) { if (arb_is_nonnegative(b)) { arb_mul_2exp_si(c, b, -1); arb_sqrt(c, c, prec); arb_set(d, c); return; } else if (arb_is_nonpositive(b)) { arb_mul_2exp_si(c, b, -1); arb_neg(c, c); arb_sqrt(c, c, prec); arb_neg(d, c); return; } } wp = prec + 4; arb_init(r); arb_init(t); arb_init(u); acb_abs(r, x, wp); arb_add(t, r, a, wp); if (arb_rel_accuracy_bits(t) > 8) { /* sqrt(a+bi) = sqrt((r+a)/2) + b/sqrt(2*(r+a))*i, r = |a+bi| */ arb_mul_2exp_si(u, t, 1); arb_sqrt(u, u, wp); arb_div(d, b, u, prec); arb_set_round(c, u, prec); arb_mul_2exp_si(c, c, -1); } else { /* sqrt(a+bi) = sqrt((r+a)/2) + (b/|b|)*sqrt((r-a)/2)*i (sign) */ arb_mul_2exp_si(t, t, -1); arb_sub(u, r, a, wp); arb_mul_2exp_si(u, u, -1); arb_sqrtpos(c, t, prec); if (arb_is_nonnegative(b)) { arb_sqrtpos(d, u, prec); } else if (arb_is_nonpositive(b)) { arb_sqrtpos(d, u, prec); arb_neg(d, d); } else { arb_sqrtpos(t, u, wp); arb_neg(u, t); arb_union(d, t, u, prec); } } arb_clear(r); arb_clear(t); arb_clear(u); #undef a #undef b #undef c #undef d }
int renf_elem_cmp_fmpq(renf_elem_t a, const fmpq_t b, renf_t nf) { int s; slong prec, cond; arb_t diffball; renf_elem_t diffnf; if (fmpq_is_zero(b)) return renf_elem_sgn(a, nf); if (nf_elem_is_rational(a->elem, nf->nf)) { if (nf->nf->flag & NF_LINEAR) return _fmpq_cmp(LNF_ELEM_NUMREF(a->elem), LNF_ELEM_DENREF(a->elem), fmpq_numref(b), fmpq_denref(b)); else if (nf->nf->flag & NF_QUADRATIC) return _fmpq_cmp(QNF_ELEM_NUMREF(a->elem), QNF_ELEM_DENREF(a->elem), fmpq_numref(b), fmpq_denref(b)); else return _fmpq_cmp(NF_ELEM_NUMREF(a->elem), NF_ELEM_DENREF(a->elem), fmpq_numref(b), fmpq_denref(b)); } arb_init(diffball); arb_set_fmpq(diffball, b, nf->prec); arb_sub(diffball, a->emb, diffball, nf->prec); if (!arb_contains_zero(diffball)) { s = arf_sgn(arb_midref(diffball)); arb_clear(diffball); return s; } renf_elem_relative_condition_number_2exp(&cond, a, nf); prec = FLINT_MAX(nf->prec, arb_rel_accuracy_bits(nf->emb)); renf_elem_set_evaluation(a, nf, prec + cond); arb_set_fmpq(diffball, b, prec); arb_sub(diffball, a->emb, diffball, prec); if (!arb_contains_zero(diffball)) { s = arf_sgn(arb_midref(diffball)); arb_clear(diffball); return s; } arb_clear(diffball); renf_elem_init(diffnf, nf); renf_elem_set(diffnf, a, nf); renf_elem_sub_fmpq(diffnf, diffnf, b, nf); s = renf_elem_sgn(diffnf, nf); renf_elem_clear(diffnf, nf); return s; }
void acb_calc_cauchy_bound(arb_t bound, acb_calc_func_t func, void * param, const acb_t x, const arb_t radius, slong maxdepth, slong prec) { slong i, n, depth, wp; arb_t pi, theta, v, s1, c1, s2, c2, st, ct; acb_t t, u; arb_t b; arb_init(pi); arb_init(theta); arb_init(v); arb_init(s1); arb_init(c1); arb_init(s2); arb_init(c2); arb_init(st); arb_init(ct); acb_init(t); acb_init(u); arb_init(b); wp = prec + 20; arb_const_pi(pi, wp); arb_zero_pm_inf(b); for (depth = 0, n = 16; depth < maxdepth; n *= 2, depth++) { arb_zero(b); /* theta = 2 pi / n */ arb_div_ui(theta, pi, n, wp); arb_mul_2exp_si(theta, theta, 1); /* sine and cosine of i*theta and (i+1)*theta */ arb_zero(s1); arb_one(c1); arb_sin_cos(st, ct, theta, wp); arb_set(s2, st); arb_set(c2, ct); for (i = 0; i < n; i++) { /* sine and cosine of 2 pi ([i,i+1]/n) */ /* since we use power of two subdivision points, the sine and cosine are monotone on each subinterval */ arb_union(acb_realref(t), c1, c2, wp); arb_union(acb_imagref(t), s1, s2, wp); acb_mul_arb(t, t, radius, wp); acb_add(t, t, x, prec); /* next angle */ arb_mul(v, c2, ct, wp); arb_mul(c1, s2, st, wp); arb_sub(c1, v, c1, wp); arb_mul(v, c2, st, wp); arb_mul(s1, s2, ct, wp); arb_add(s1, v, s1, wp); arb_swap(c1, c2); arb_swap(s1, s2); func(u, t, param, 1, prec); acb_abs(v, u, prec); arb_add(b, b, v, prec); } arb_div_ui(b, b, n, prec); if (arb_is_positive(b)) break; } arb_set(bound, b); arb_clear(pi); arb_clear(theta); arb_clear(v); acb_clear(t); acb_clear(u); arb_clear(b); arb_clear(s1); arb_clear(c1); arb_clear(s2); arb_clear(c2); arb_clear(st); arb_clear(ct); }
int arb_mat_jacobi(arb_mat_t D, arb_mat_t P, const arb_mat_t A, slong prec) { // // Given a d x d real symmetric matrix A, compute an orthogonal matrix // P and a diagonal D such that A = P D P^t = P D P^(-1). // // D should have already been initialized as a d x 1 matrix, and Pp // should have already been initialized as a d x d matrix. // // If the eigenvalues can be certified as unique, then a nonzero int is // returned, and the eigenvectors should have reasonable error bounds. If // the eigenvalues cannot be certified as unique, then some of the // eigenvectors will have infinite error radius. #define B(i,j) arb_mat_entry(B, i, j) #define D(i) arb_mat_entry(D, i, 0) #define P(i,j) arb_mat_entry(P, i, j) int dim = arb_mat_nrows(A); if(dim == 1) { arb_mat_set(D, A); arb_mat_one(P); return 0; } arb_mat_t B; arb_mat_init(B, dim, dim); arf_t * B1 = (arf_t*)malloc(dim * sizeof(arf_t)); arf_t * B2 = (arf_t*)malloc(dim * sizeof(arf_t)); arf_t * row_max = (arf_t*)malloc((dim - 1) * sizeof(arf_t)); int * row_max_indices = (int*)malloc((dim - 1) * sizeof(int)); for(int k = 0; k < dim; k++) { arf_init(B1[k]); arf_init(B2[k]); } for(int k = 0; k < dim - 1; k++) { arf_init(row_max[k]); } arf_t x1, x2; arf_init(x1); arf_init(x2); arf_t Gii, Gij, Gji, Gjj; arf_init(Gii); arf_init(Gij); arf_init(Gji); arf_init(Gjj); arb_mat_set(B, A); arb_mat_one(P); for(int i = 0; i < dim - 1; i++) { for(int j = i + 1; j < dim; j++) { arf_abs(x1, arb_midref(B(i,j))); if(arf_cmp(row_max[i], x1) < 0) { arf_set(row_max[i], x1); row_max_indices[i] = j; } } } int finished = 0; while(!finished) { arf_zero(x1); int i = 0; int j = 0; for(int k = 0; k < dim - 1; k++) { if(arf_cmp(x1, row_max[k]) < 0) { arf_set(x1, row_max[k]); i = k; } } j = row_max_indices[i]; slong bound = arf_abs_bound_lt_2exp_si(x1); if(bound < -prec * .9) { finished = 1; break; } else { //printf("%ld\n", arf_abs_bound_lt_2exp_si(x1)); //arb_mat_printd(B, 10); //printf("\n"); } arf_twobytwo_diag(Gii, Gij, arb_midref(B(i,i)), arb_midref(B(i,j)), arb_midref(B(j,j)), 2*prec); arf_neg(Gji, Gij); arf_set(Gjj, Gii); //printf("%d %d\n", i, j); //arf_printd(Gii, 100); //printf(" "); //arf_printd(Gij, 100); //printf("\n"); if(arf_is_zero(Gij)) { // If this happens, we're finished = 1; // not going to do any better break; // without increasing the precision. } for(int k = 0; k < dim; k++) { arf_mul(B1[k], Gii, arb_midref(B(i,k)), prec, ARF_RND_NEAR); arf_addmul(B1[k], Gji, arb_midref(B(j,k)), prec, ARF_RND_NEAR); arf_mul(B2[k], Gij, arb_midref(B(i,k)), prec, ARF_RND_NEAR); arf_addmul(B2[k], Gjj, arb_midref(B(j,k)), prec, ARF_RND_NEAR); } for(int k = 0; k < dim; k++) { arf_set(arb_midref(B(i,k)), B1[k]); arf_set(arb_midref(B(j,k)), B2[k]); } for(int k = 0; k < dim; k++) { arf_mul(B1[k], Gii, arb_midref(B(k,i)), prec, ARF_RND_NEAR); arf_addmul(B1[k], Gji, arb_midref(B(k,j)), prec, ARF_RND_NEAR); arf_mul(B2[k], Gij, arb_midref(B(k,i)), prec, ARF_RND_NEAR); arf_addmul(B2[k], Gjj, arb_midref(B(k,j)), prec, ARF_RND_NEAR); } for(int k = 0; k < dim; k++) { arf_set(arb_midref(B(k,i)), B1[k]); arf_set(arb_midref(B(k,j)), B2[k]); } for(int k = 0; k < dim; k++) { arf_mul(B1[k], Gii, arb_midref(P(k,i)), prec, ARF_RND_NEAR); arf_addmul(B1[k], Gji, arb_midref(P(k,j)), prec, ARF_RND_NEAR); arf_mul(B2[k], Gij, arb_midref(P(k,i)), prec, ARF_RND_NEAR); arf_addmul(B2[k], Gjj, arb_midref(P(k,j)), prec, ARF_RND_NEAR); } for(int k = 0; k < dim; k++) { arf_set(arb_midref(P(k,i)), B1[k]); arf_set(arb_midref(P(k,j)), B2[k]); } if(i < dim - 1) arf_set_ui(row_max[i], 0); if(j < dim - 1) arf_set_ui(row_max[j], 0); // Update the max in any row where the maximum // was in a column that changed. for(int k = 0; k < dim - 1; k++) { if(row_max_indices[k] == j || row_max_indices[k] == i) { arf_abs(row_max[k], arb_midref(B(k,k+1))); row_max_indices[k] = k+1; for(int l = k+2; l < dim; l++) { arf_abs(x1, arb_midref(B(k,l))); if(arf_cmp(row_max[k], x1) < 0) { arf_set(row_max[k], x1); row_max_indices[k] = l; } } } } // Update the max in the ith row. for(int k = i + 1; k < dim; k++) { arf_abs(x1, arb_midref(B(i, k))); if(arf_cmp(row_max[i], x1) < 0) { arf_set(row_max[i], x1); row_max_indices[i] = k; } } // Update the max in the jth row. for(int k = j + 1; k < dim; k++) { arf_abs(x1, arb_midref(B(j, k))); if(arf_cmp(row_max[j], x1) < 0) { arf_set(row_max[j], x1); row_max_indices[j] = k; } } // Go through column i to see if any of // the new entries are larger than the // max of their row. for(int k = 0; k < i; k++) { if(k == dim) continue; arf_abs(x1, arb_midref(B(k, i))); if(arf_cmp(row_max[k], x1) < 0) { arf_set(row_max[k], x1); row_max_indices[k] = i; } } // And then column j. for(int k = 0; k < j; k++) { if(k == dim) continue; arf_abs(x1, arb_midref(B(k, j))); if(arf_cmp(row_max[k], x1) < 0) { arf_set(row_max[k], x1); row_max_indices[k] = j; } } } for(int k = 0; k < dim; k++) { arb_set(D(k), B(k,k)); arb_set_exact(D(k)); } // At this point we've done that diagonalization and all that remains is // to certify the correctness and compute error bounds. arb_mat_t e; arb_t error_norms[dim]; for(int k = 0; k < dim; k++) arb_init(error_norms[k]); arb_mat_init(e, dim, 1); arb_t z1, z2; arb_init(z1); arb_init(z2); for(int j = 0; j < dim; j++) { arb_mat_set(B, A); for(int k = 0; k < dim; k++) { arb_sub(B(k, k), B(k, k), D(j), prec); } for(int k = 0; k < dim; k++) { arb_set(arb_mat_entry(e, k, 0), P(k, j)); } arb_mat_L2norm(z2, e, prec); arb_mat_mul(e, B, e, prec); arb_mat_L2norm(error_norms[j], e, prec); arb_div(z2, error_norms[j], z2, prec); // and now z1 is an upper bound for the // error in the eigenvalue arb_add_error(D(j), z2); } int unique_eigenvalues = 1; for(int j = 0; j < dim; j++) { if(j == 0) { arb_sub(z1, D(j), D(1), prec); } else { arb_sub(z1, D(j), D(0), prec); } arb_get_abs_lbound_arf(x1, z1, prec); for(int k = 1; k < dim; k++) { if(k == j) continue; arb_sub(z1, D(j), D(k), prec); arb_get_abs_lbound_arf(x2, z1, prec); if(arf_cmp(x2, x1) < 0) { arf_set(x1, x2); } } if(arf_is_zero(x1)) { unique_eigenvalues = 0; } arb_div_arf(z1, error_norms[j], x1, prec); for(int k = 0; k < dim; k++) { arb_add_error(P(k, j), z1); } } arb_mat_clear(e); arb_clear(z1); arb_clear(z2); for(int k = 0; k < dim; k++) arb_clear(error_norms[k]); arf_clear(x1); arf_clear(x2); arb_mat_clear(B); for(int k = 0; k < dim; k++) { arf_clear(B1[k]); arf_clear(B2[k]); } for(int k = 0; k < dim - 1; k++) { arf_clear(row_max[k]); } arf_clear(Gii); arf_clear(Gij); arf_clear(Gji); arf_clear(Gjj); free(B1); free(B2); free(row_max); free(row_max_indices); if(unique_eigenvalues) return 0; else return 1; #undef B #undef D #undef P }
int main() { slong iter; flint_rand_t state; flint_printf("get_mpn_fixed_mod_pi4...."); fflush(stdout); flint_randinit(state); /* _flint_rand_init_gmp(state); */ for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { arf_t x; int octant; fmpz_t q; mp_ptr w; arb_t wb, t, u; mp_size_t wn; slong prec, prec2; int success; mp_limb_t error; prec = 2 + n_randint(state, 10000); wn = 1 + n_randint(state, 200); prec2 = FLINT_MAX(prec, wn * FLINT_BITS) + 100; arf_init(x); arb_init(wb); arb_init(t); arb_init(u); fmpz_init(q); w = flint_malloc(sizeof(mp_limb_t) * wn); arf_randtest(x, state, prec, 14); /* this should generate numbers close to multiples of pi/4 */ if (n_randint(state, 4) == 0) { arb_const_pi(t, prec); arb_mul_2exp_si(t, t, -2); fmpz_randtest(q, state, 200); arb_mul_fmpz(t, t, q, prec); arf_add(x, x, arb_midref(t), prec, ARF_RND_DOWN); } arf_abs(x, x); success = _arb_get_mpn_fixed_mod_pi4(w, q, &octant, &error, x, wn); if (success) { /* could round differently */ if (fmpz_fdiv_ui(q, 8) != octant) { flint_printf("bad octant\n"); abort(); } _arf_set_mpn_fixed(arb_midref(wb), w, wn, wn, 0, FLINT_BITS * wn, ARB_RND); mag_set_ui_2exp_si(arb_radref(wb), error, -FLINT_BITS * wn); arb_const_pi(u, prec2); arb_mul_2exp_si(u, u, -2); arb_set(t, wb); if (octant % 2 == 1) arb_sub(t, u, t, prec2); arb_addmul_fmpz(t, u, q, prec2); if (!arb_contains_arf(t, x)) { flint_printf("FAIL (containment)\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("q = "); fmpz_print(q); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); flint_printf("t = "); arb_printd(t, 50); flint_printf("\n\n"); abort(); } arb_const_pi(t, prec2); arb_mul_2exp_si(t, t, -2); if (arf_sgn(arb_midref(wb)) < 0 || arf_cmp(arb_midref(wb), arb_midref(t)) >= 0) { flint_printf("FAIL (expected 0 <= w < pi/4)\n"); flint_printf("x = "); arf_printd(x, 50); flint_printf("\n\n"); flint_printf("w = "); arb_printd(wb, 50); flint_printf("\n\n"); abort(); } } flint_free(w); fmpz_clear(q); arf_clear(x); arb_clear(wb); arb_clear(t); arb_clear(u); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
void acb_hypgeom_chi_asymp(acb_t res, const acb_t z, slong prec) { acb_t t, u, v, one; acb_init(t); acb_init(u); acb_init(v); acb_init(one); acb_one(one); /* u = U(1,1,z) */ acb_hypgeom_u_asymp(u, one, one, z, -1, prec); /* v = e^(-z) */ acb_neg(v, z); acb_exp(v, v, prec); acb_mul(t, u, v, prec); if (arb_is_zero(acb_realref(z))) { arb_div(acb_realref(t), acb_imagref(t), acb_imagref(z), prec); arb_zero(acb_imagref(t)); acb_neg(t, t); } else { /* u = U(1,1,-z) */ acb_neg(u, z); acb_hypgeom_u_asymp(u, one, one, u, -1, prec); acb_inv(v, v, prec); acb_submul(t, u, v, prec); acb_div(t, t, z, prec); acb_mul_2exp_si(t, t, -1); acb_neg(t, t); } if (acb_is_real(z)) { if (arb_is_positive(acb_realref(z))) { arb_zero(acb_imagref(t)); } else if (arb_is_negative(acb_realref(z))) { arb_const_pi(acb_imagref(t), prec); } else { /* add [-pi,pi]/2 i */ acb_const_pi(u, prec); arb_zero(acb_imagref(t)); arb_add_error(acb_imagref(t), acb_realref(u)); } } else { /* -pi/2 if positive real or in lower half plane pi/2 if negative real or in upper half plane */ if (arb_is_negative(acb_imagref(z))) { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_sub(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else if (arb_is_positive(acb_imagref(z))) { acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_add(acb_imagref(t), acb_imagref(t), acb_realref(u), prec); } else { /* add [-pi,pi]/2 i */ acb_const_pi(u, prec); acb_mul_2exp_si(u, u, -1); arb_add_error(acb_imagref(t), acb_realref(u)); } } acb_swap(res, t); acb_clear(t); acb_clear(u); acb_clear(v); acb_clear(one); }
void acb_gamma_stirling_eval(acb_t s, const acb_t z, long nterms, int digamma, long prec) { acb_t t, logz, zinv, zinv2; arb_t b; mag_t err; long k, term_prec; double z_mag, term_mag; acb_init(t); acb_init(logz); acb_init(zinv); acb_init(zinv2); arb_init(b); acb_log(logz, z, prec); acb_inv(zinv, z, prec); nterms = FLINT_MAX(nterms, 1); acb_zero(s); if (nterms > 1) { acb_mul(zinv2, zinv, zinv, prec); z_mag = arf_get_d(arb_midref(acb_realref(logz)), ARF_RND_UP) * 1.44269504088896; for (k = nterms - 1; k >= 1; k--) { term_mag = bernoulli_bound_2exp_si(2 * k); term_mag -= (2 * k - 1) * z_mag; term_prec = prec + term_mag; term_prec = FLINT_MIN(term_prec, prec); term_prec = FLINT_MAX(term_prec, 10); arb_gamma_stirling_coeff(b, k, digamma, term_prec); if (prec > 2000) { acb_set_round(t, zinv2, term_prec); acb_mul(s, s, t, term_prec); } else acb_mul(s, s, zinv2, term_prec); arb_add(acb_realref(s), acb_realref(s), b, term_prec); } if (digamma) acb_mul(s, s, zinv2, prec); else acb_mul(s, s, zinv, prec); } /* remainder bound */ mag_init(err); acb_gamma_stirling_bound(err, z, digamma ? 1 : 0, 1, nterms); mag_add(arb_radref(acb_realref(s)), arb_radref(acb_realref(s)), err); mag_add(arb_radref(acb_imagref(s)), arb_radref(acb_imagref(s)), err); mag_clear(err); if (digamma) { acb_neg(s, s); acb_mul_2exp_si(zinv, zinv, -1); acb_sub(s, s, zinv, prec); acb_add(s, s, logz, prec); } else { /* (z-0.5)*log(z) - z + log(2*pi)/2 */ arb_one(b); arb_mul_2exp_si(b, b, -1); arb_set(acb_imagref(t), acb_imagref(z)); arb_sub(acb_realref(t), acb_realref(z), b, prec); acb_mul(t, logz, t, prec); acb_add(s, s, t, prec); acb_sub(s, s, z, prec); arb_const_log_sqrt2pi(b, prec); arb_add(acb_realref(s), acb_realref(s), b, prec); } acb_clear(t); acb_clear(logz); acb_clear(zinv); acb_clear(zinv2); arb_clear(b); }