mirror of
https://github.com/vale981/arb
synced 2025-03-04 17:01:40 -05:00
114 lines
2.6 KiB
C
114 lines
2.6 KiB
C
/*
|
|
Copyright (C) 2021 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 "arb_hypgeom.h"
|
|
#include "acb_hypgeom.h"
|
|
|
|
void
|
|
acb_hypgeom_rising_ui_rs(acb_t res, const acb_t x, ulong n, ulong m, slong prec)
|
|
{
|
|
slong i, k, l, m0, climbs, climbs_max, wp;
|
|
acb_ptr xpow;
|
|
acb_t t, u;
|
|
mp_ptr c;
|
|
TMP_INIT;
|
|
|
|
if (n <= 1)
|
|
{
|
|
if (n == 0)
|
|
acb_one(res);
|
|
else
|
|
acb_set_round(res, x, prec);
|
|
return;
|
|
}
|
|
|
|
TMP_START;
|
|
|
|
if (m == 0 || m == -1)
|
|
{
|
|
if (n <= 6)
|
|
m = 2;
|
|
else if (n <= 16)
|
|
m = 4;
|
|
else if (n <= 40)
|
|
m = 6;
|
|
else
|
|
{
|
|
m0 = n_sqrt(n);
|
|
m = 8 + 0.27 * pow(1.5 * FLINT_MAX(0, prec - 1024), 0.4);
|
|
m = FLINT_MIN(m, m0);
|
|
m = FLINT_MIN(m, 64);
|
|
}
|
|
}
|
|
|
|
wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n));
|
|
|
|
climbs_max = FLINT_BIT_COUNT(n - 1) * m;
|
|
c = TMP_ALLOC(sizeof(mp_limb_t) * climbs_max * m);
|
|
|
|
xpow = _acb_vec_init(m + 1);
|
|
_acb_vec_set_powers(xpow, x, m + 1, wp);
|
|
acb_init(t);
|
|
acb_init(u);
|
|
|
|
for (k = 0; k < n; k += m)
|
|
{
|
|
l = FLINT_MIN(m, n - k);
|
|
climbs = FLINT_BIT_COUNT(k + l - 1) * l;
|
|
climbs = (climbs + FLINT_BITS - 1) / FLINT_BITS;
|
|
|
|
/* assumes l >= 2 */
|
|
if (l == 1)
|
|
{
|
|
acb_add_ui(u, x, k, wp);
|
|
}
|
|
else
|
|
{
|
|
if (climbs == 1)
|
|
{
|
|
_arb_hypgeom_rising_coeffs_1(c, k, l);
|
|
acb_dot_ui(u, xpow + l, 0, xpow, 1, c, 1, l, wp);
|
|
}
|
|
else if (climbs == 2)
|
|
{
|
|
_arb_hypgeom_rising_coeffs_2(c, k, l);
|
|
acb_dot_uiui(u, xpow + l, 0, xpow, 1, c, 1, l, wp);
|
|
}
|
|
else
|
|
{
|
|
fmpz * f = (fmpz *) c;
|
|
|
|
for (i = 0; i < l; i++)
|
|
fmpz_init(f + i);
|
|
|
|
_arb_hypgeom_rising_coeffs_fmpz(f, k, l);
|
|
|
|
acb_dot_fmpz(u, xpow + l, 0, xpow, 1, f, 1, l, wp);
|
|
|
|
for (i = 0; i < l; i++)
|
|
fmpz_clear(f + i);
|
|
}
|
|
}
|
|
|
|
if (k == 0)
|
|
acb_swap(t, u);
|
|
else
|
|
acb_mul(t, t, u, wp);
|
|
}
|
|
|
|
acb_set_round(res, t, prec);
|
|
|
|
acb_clear(t);
|
|
acb_clear(u);
|
|
_acb_vec_clear(xpow, m + 1);
|
|
TMP_END;
|
|
}
|
|
|