mirror of
https://github.com/vale981/arb
synced 2025-03-04 17:01:40 -05:00
181 lines
4.3 KiB
C
181 lines
4.3 KiB
C
/*
|
|
Copyright (C) 2017 Fredrik Johansson
|
|
|
|
This file is part of Arb.
|
|
|
|
Arb is free software: you can redistribute it and/or modify it under
|
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
|
by the Free Software Foundation; either version 2.1 of the License, or
|
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "acb_dirichlet.h"
|
|
|
|
/*
|
|
f(s) = (f(s+hi) + f(s-hi))/2 + err0
|
|
f'(s) = (f(s+hi) - f(s-hi))/(2hi) + err1
|
|
|
|
|err0| <= |f(s +/- R)| (1/R)^2 h^2 / (1 - h/R)
|
|
|err1| <= |f(s +/- R)| (1/R)^3 h^2 / (1 - h/R)
|
|
|
|
assuming h/R < 1
|
|
*/
|
|
static void
|
|
acb_dirichlet_zeta_jet_rs_mid(acb_ptr res, const acb_t s, slong prec)
|
|
{
|
|
acb_t t, u;
|
|
arb_t hh;
|
|
mag_t h, R, err0, err1, tmp;
|
|
slong hexp;
|
|
|
|
acb_init(t);
|
|
acb_init(u);
|
|
arb_init(hh);
|
|
mag_init(h);
|
|
mag_init(R);
|
|
mag_init(err0);
|
|
mag_init(err1);
|
|
mag_init(tmp);
|
|
|
|
hexp = -(prec / 2) - 10;
|
|
mag_set_ui_2exp_si(h, 1, hexp);
|
|
mag_set_ui_2exp_si(R, 1, -5);
|
|
|
|
acb_set(t, s);
|
|
mag_add(arb_radref(acb_realref(t)), arb_radref(acb_realref(t)), R);
|
|
mag_add(arb_radref(acb_imagref(t)), arb_radref(acb_imagref(t)), R);
|
|
/* tmp = |f(s +/- R)| */
|
|
acb_dirichlet_zeta_bound(tmp, t);
|
|
|
|
/* err0 = (1/R)^2 h^2 / (1 - h/R) */
|
|
mag_div(err0, h, R);
|
|
mag_geom_series(err0, err0, 2);
|
|
/* err0 *= tmp */
|
|
mag_mul(err0, err0, tmp);
|
|
/* err1 = err0 / R */
|
|
mag_div(err1, err0, R);
|
|
|
|
/* hh = h as an arb_t */
|
|
arb_one(hh);
|
|
arb_mul_2exp_si(hh, hh, hexp);
|
|
|
|
acb_set(t, s);
|
|
acb_set(u, s);
|
|
arb_add(acb_imagref(t), acb_imagref(t), hh, 10 * prec);
|
|
arb_sub(acb_imagref(u), acb_imagref(u), hh, 10 * prec);
|
|
|
|
/* zeta(mid(s)+ih) */
|
|
acb_dirichlet_zeta_rs(res, t, 0, 1.5 * prec + 10);
|
|
/* zeta(mid(s)-ih) */
|
|
acb_dirichlet_zeta_rs(res + 1, u, 0, 1.5 * prec + 10);
|
|
|
|
acb_sub(t, res, res + 1, prec);
|
|
acb_add(res, res, res + 1, prec);
|
|
acb_swap(res + 1, t);
|
|
|
|
acb_mul_2exp_si(res, res, -1);
|
|
acb_mul_2exp_si(res + 1, res + 1, -1);
|
|
acb_mul_2exp_si(res + 1, res + 1, -hexp);
|
|
acb_div_onei(res + 1, res + 1);
|
|
|
|
acb_add_error_mag(res, err0);
|
|
acb_add_error_mag(res + 1, err1);
|
|
|
|
acb_clear(t);
|
|
acb_clear(u);
|
|
arb_clear(hh);
|
|
mag_clear(h);
|
|
mag_clear(R);
|
|
mag_clear(err0);
|
|
mag_clear(err1);
|
|
mag_clear(tmp);
|
|
}
|
|
|
|
void
|
|
acb_dirichlet_zeta_jet_rs(acb_ptr res, const acb_t s, slong len, slong prec)
|
|
{
|
|
if (len > 2)
|
|
{
|
|
flint_printf("acb_dirichlet_zeta_jet_rs: len > 2 not implemented\n");
|
|
flint_abort();
|
|
}
|
|
|
|
if (len <= 0)
|
|
return;
|
|
|
|
if (len == 1)
|
|
{
|
|
acb_dirichlet_zeta_rs(res, s, 0, prec);
|
|
}
|
|
else if (acb_is_exact(s))
|
|
{
|
|
acb_dirichlet_zeta_jet_rs_mid(res, s, prec);
|
|
}
|
|
else
|
|
{
|
|
acb_t t;
|
|
mag_t r, err0, err1, der1, der2, M;
|
|
|
|
/*
|
|
slong acc;
|
|
|
|
acc = acb_rel_accuracy_bits(s);
|
|
acc = FLINT_MAX(acc, 0);
|
|
acc = FLINT_MIN(acc, prec);
|
|
prec = FLINT_MIN(prec, acc + 20);
|
|
*/
|
|
|
|
/*
|
|
assume s = m +/- r
|
|
|
|
f(s) = f(m) + err0
|
|
f'(s) = f'(m) + err1
|
|
|
|
|err1| <= |f''(s)| r
|
|
|err0| <= min(|f'(s)| r, |f'(m)| r + 0.5 |f''(s)| r^2)
|
|
= r min(|f'(s)|, |f'(m)| + 0.5 |f''(s)| r)
|
|
*/
|
|
|
|
acb_init(t);
|
|
mag_init(r);
|
|
mag_init(err0);
|
|
mag_init(err1);
|
|
mag_init(der1);
|
|
mag_init(der2);
|
|
mag_init(M);
|
|
|
|
/* r = rad(s) */
|
|
mag_hypot(r, arb_radref(acb_realref(s)), arb_radref(acb_imagref(s)));
|
|
|
|
/* Bound zeta'(s), zeta''(s) */
|
|
acb_dirichlet_zeta_deriv_bound(der1, der2, s);
|
|
|
|
/* f(m), f'(m) */
|
|
acb_get_mid(t, s);
|
|
acb_dirichlet_zeta_jet_rs_mid(res, t, prec);
|
|
|
|
/* err1 = |f''(s)| r */
|
|
mag_mul(err1, der2, r);
|
|
|
|
/* err0 = |f'(m)| + 0.5 |f''(s)| r */
|
|
acb_get_mag(M, res + 1);
|
|
mag_mul_2exp_si(err0, err1, -1);
|
|
mag_add(err0, err0, M);
|
|
/* err0 = min(err0, |f'(s)| */
|
|
mag_min(err0, err0, der1);
|
|
/* err0 = err0 * r */
|
|
mag_mul(err0, err0, r);
|
|
|
|
acb_add_error_mag(res, err0);
|
|
acb_add_error_mag(res + 1, err1);
|
|
|
|
acb_clear(t);
|
|
mag_clear(r);
|
|
mag_clear(err0);
|
|
mag_clear(err1);
|
|
mag_clear(der1);
|
|
mag_clear(der2);
|
|
mag_clear(M);
|
|
}
|
|
}
|
|
|