mirror of
https://github.com/vale981/arb
synced 2025-03-05 09:21:38 -05:00
131 lines
3.2 KiB
C
131 lines
3.2 KiB
C
/*
|
|
Copyright (C) 2014 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_poly.h"
|
|
#include "bernoulli.h"
|
|
|
|
static void
|
|
bsplit(acb_ptr P, acb_ptr T, const acb_t s, const acb_t Na,
|
|
slong a, slong b, int cont, slong len, slong prec)
|
|
{
|
|
slong plen = FLINT_MIN(2 * (b - a) + 1, len);
|
|
|
|
if (b - a == 1)
|
|
{
|
|
slong j = a;
|
|
|
|
fmpz_t t;
|
|
fmpz_init(t);
|
|
|
|
if (j == 0)
|
|
{
|
|
acb_set(P, s);
|
|
if (len > 1) acb_one(P + 1);
|
|
if (len > 2) acb_zero(P + 2);
|
|
}
|
|
else
|
|
{
|
|
/* P = ((s+x)+2j-1)(s+x)+2j) */
|
|
|
|
/* constant term = s^2 + (4j-1)s + (4j^2-2j)*/
|
|
acb_mul(P, s, s, prec);
|
|
acb_addmul_ui(P, s, 4*j-1, prec);
|
|
fmpz_set_ui(t, 2*j);
|
|
fmpz_mul_ui(t, t, 2*j-1);
|
|
acb_add_fmpz(P, P, t, prec);
|
|
|
|
/* x term = (2s+4j-1) */
|
|
if (len > 1)
|
|
{
|
|
acb_mul_ui(P + 1, s, 2, prec);
|
|
acb_add_ui(P + 1, P + 1, 4*j-1, prec);
|
|
}
|
|
|
|
/* x^2 term = 1 */
|
|
if (len > 2)
|
|
acb_one(P + 2);
|
|
|
|
}
|
|
|
|
/* P = P / ((2j+1)*(2j+2)) */
|
|
fmpz_set_ui(t, 2*j+1);
|
|
fmpz_mul_ui(t, t, 2*j+2);
|
|
_acb_vec_scalar_div_fmpz(P, P, plen, t, prec);
|
|
|
|
/* P = P / Na or P / Na^2 */
|
|
if (j == 0)
|
|
acb_set(T, Na);
|
|
else
|
|
acb_mul(T, Na, Na, prec);
|
|
_acb_vec_scalar_div(P, P, plen, T, prec);
|
|
|
|
/* T = P * B_{2j+2} */
|
|
_acb_vec_scalar_mul_fmpz(T, P, plen, fmpq_numref(bernoulli_cache + 2 * j + 2), prec);
|
|
_acb_vec_scalar_div_fmpz(T, T, plen, fmpq_denref(bernoulli_cache + 2 * j + 2), prec);
|
|
|
|
fmpz_clear(t);
|
|
}
|
|
else
|
|
{
|
|
slong m, len1, len2, alloc;
|
|
acb_ptr P1, T1, P2, T2;
|
|
|
|
m = a + (b - a) / 2;
|
|
|
|
len1 = FLINT_MIN(2 * (m - a) + 1, len);
|
|
len2 = FLINT_MIN(2 * (b - m) + 1, len);
|
|
|
|
alloc = 2 * len1 + 2 * len2;
|
|
|
|
P1 = _acb_vec_init(alloc);
|
|
T1 = P1 + len1;
|
|
P2 = T1 + len1;
|
|
T2 = P2 + len2;
|
|
|
|
bsplit(P1, T1, s, Na, a, m, 1, len, prec);
|
|
bsplit(P2, T2, s, Na, m, b, 1, len, prec);
|
|
|
|
/* P = P1 * P2 */
|
|
if (cont)
|
|
_acb_poly_mullow(P, P2, len2, P1, len1, plen, prec);
|
|
|
|
/* T = T1 + P1 * T2 */
|
|
_acb_poly_mullow(T, T2, len2, P1, len1, plen, prec);
|
|
_acb_vec_add(T, T, T1, len1, prec);
|
|
|
|
_acb_vec_clear(P1, alloc);
|
|
}
|
|
}
|
|
|
|
void
|
|
_acb_poly_zeta_em_tail_bsplit(acb_ptr z, const acb_t s, const acb_t Na, acb_srcptr Nasx, slong M, slong len, slong prec)
|
|
{
|
|
acb_ptr P, T;
|
|
|
|
if (M < 1)
|
|
{
|
|
_acb_vec_zero(z, len);
|
|
return;
|
|
}
|
|
|
|
BERNOULLI_ENSURE_CACHED(2 * M);
|
|
|
|
P = _acb_vec_init(len);
|
|
T = _acb_vec_init(len);
|
|
|
|
bsplit(P, T, s, Na, 0, M, 0, len, prec);
|
|
|
|
_acb_poly_mullow(z, T, len, Nasx, len, len, prec);
|
|
|
|
_acb_vec_clear(P, len);
|
|
_acb_vec_clear(T, len);
|
|
}
|
|
|