2016-04-26 17:20:05 +02:00
|
|
|
/*
|
2012-12-19 14:04:00 +01:00
|
|
|
Copyright (C) 2012 Fredrik Johansson
|
|
|
|
|
2016-04-26 17:20:05 +02:00
|
|
|
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/>.
|
|
|
|
*/
|
2012-12-19 14:04:00 +01:00
|
|
|
|
|
|
|
#include "bernoulli.h"
|
|
|
|
|
|
|
|
void
|
|
|
|
bernoulli_rev_init(bernoulli_rev_t iter, ulong nmax)
|
|
|
|
{
|
2015-11-05 18:01:09 +00:00
|
|
|
slong j;
|
2012-12-19 14:04:00 +01:00
|
|
|
fmpz_t t;
|
2014-06-14 23:23:55 +02:00
|
|
|
arb_t x;
|
|
|
|
arf_t u;
|
2012-12-19 14:04:00 +01:00
|
|
|
int round1, round2;
|
2015-11-05 18:01:09 +00:00
|
|
|
slong wp;
|
2012-12-19 14:04:00 +01:00
|
|
|
|
|
|
|
nmax -= (nmax % 2);
|
|
|
|
iter->n = nmax;
|
|
|
|
|
|
|
|
iter->alloc = 0;
|
2013-02-13 07:56:56 +01:00
|
|
|
if (nmax < BERNOULLI_REV_MIN)
|
2012-12-19 14:04:00 +01:00
|
|
|
return;
|
|
|
|
|
2014-11-11 03:01:57 +01:00
|
|
|
iter->prec = wp = bernoulli_global_prec(nmax);
|
2012-12-19 14:04:00 +01:00
|
|
|
|
2014-11-11 03:01:57 +01:00
|
|
|
iter->max_power = bernoulli_zeta_terms(nmax, iter->prec);
|
2012-12-19 14:04:00 +01:00
|
|
|
iter->alloc = iter->max_power + 1;
|
|
|
|
iter->powers = _fmpz_vec_init(iter->alloc);
|
|
|
|
fmpz_init(iter->pow_error);
|
2014-06-14 23:23:55 +02:00
|
|
|
arb_init(iter->prefactor);
|
|
|
|
arb_init(iter->two_pi_squared);
|
2012-12-19 14:04:00 +01:00
|
|
|
|
2014-06-14 23:23:55 +02:00
|
|
|
arb_init(x);
|
2012-12-19 14:04:00 +01:00
|
|
|
fmpz_init(t);
|
2014-06-14 23:23:55 +02:00
|
|
|
arf_init(u);
|
2012-12-19 14:04:00 +01:00
|
|
|
|
|
|
|
/* precompute powers */
|
|
|
|
for (j = 3; j <= iter->max_power; j += 2)
|
|
|
|
{
|
2014-11-11 03:01:57 +01:00
|
|
|
arb_ui_pow_ui(x, j, nmax, bernoulli_power_prec(j, nmax, wp));
|
|
|
|
arb_inv(x, x, bernoulli_power_prec(j, nmax, wp));
|
2014-06-14 23:23:55 +02:00
|
|
|
round1 = arf_get_fmpz_fixed_si(t, arb_midref(x), -wp);
|
2012-12-19 14:04:00 +01:00
|
|
|
fmpz_set(iter->powers + j, t);
|
|
|
|
|
|
|
|
/* error: the radius, plus two roundings */
|
2014-06-14 23:23:55 +02:00
|
|
|
arf_set_mag(u, arb_radref(x));
|
|
|
|
round2 = arf_get_fmpz_fixed_si(t, u, -wp);
|
2012-12-19 14:04:00 +01:00
|
|
|
fmpz_add_ui(t, t, (round1 != 0) + (round2 != 0));
|
|
|
|
if (fmpz_cmp(iter->pow_error, t) < 0)
|
|
|
|
fmpz_set(iter->pow_error, t);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* precompute (2pi)^2 and 2*(n!)/(2pi)^n */
|
2014-06-14 23:23:55 +02:00
|
|
|
arb_fac_ui(iter->prefactor, nmax, wp);
|
|
|
|
arb_mul_2exp_si(iter->prefactor, iter->prefactor, 1);
|
2012-12-19 14:04:00 +01:00
|
|
|
|
2014-06-14 23:23:55 +02:00
|
|
|
arb_const_pi(x, wp);
|
|
|
|
arb_mul_2exp_si(x, x, 1);
|
|
|
|
arb_mul(iter->two_pi_squared, x, x, wp);
|
2012-12-19 14:04:00 +01:00
|
|
|
|
2014-06-14 23:23:55 +02:00
|
|
|
arb_pow_ui(x, iter->two_pi_squared, nmax / 2, wp);
|
|
|
|
arb_div(iter->prefactor, iter->prefactor, x, wp);
|
2012-12-19 14:04:00 +01:00
|
|
|
|
|
|
|
fmpz_clear(t);
|
2014-06-14 23:23:55 +02:00
|
|
|
arb_clear(x);
|
|
|
|
arf_clear(u);
|
2012-12-19 14:04:00 +01:00
|
|
|
}
|
|
|
|
|