mirror of
https://github.com/vale981/arb
synced 2025-03-05 09:21:38 -05:00
159 lines
4 KiB
C
159 lines
4 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"
|
|
|
|
void
|
|
arb_hypgeom_rising_ui_jet_powsum(arb_ptr res, const arb_t x, ulong n, slong len, slong prec)
|
|
{
|
|
slong i, j, k, wp;
|
|
arb_ptr xpow;
|
|
TMP_INIT;
|
|
|
|
if (len == 0)
|
|
return;
|
|
|
|
if (len > n + 1)
|
|
{
|
|
_arb_vec_zero(res + n + 1, len - n - 1);
|
|
len = n + 1;
|
|
}
|
|
|
|
if (len == n + 1)
|
|
{
|
|
arb_one(res + n);
|
|
len = n;
|
|
}
|
|
|
|
if (n <= 1)
|
|
{
|
|
if (n == 1)
|
|
arb_set_round(res, x, prec);
|
|
return;
|
|
}
|
|
|
|
if (len == 1)
|
|
{
|
|
arb_hypgeom_rising_ui_rs(res, x, n, 0, prec);
|
|
return;
|
|
}
|
|
|
|
if (n == 2)
|
|
{
|
|
arb_mul_2exp_si(res + 1, x, 1);
|
|
arb_add_ui(res + 1, res + 1, 1, prec);
|
|
arb_mul(res, x, x, prec + 4);
|
|
arb_add(res, res, x, prec);
|
|
return;
|
|
}
|
|
|
|
if (n <= 12 || (FLINT_BITS == 64 && n <= 20))
|
|
{
|
|
mp_ptr c;
|
|
TMP_START;
|
|
|
|
wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n));
|
|
c = TMP_ALLOC(sizeof(mp_limb_t) * (n + 1) * len);
|
|
|
|
_nmod_vec_zero(c, (n + 1) * len);
|
|
|
|
c[0] = 0;
|
|
c[1] = 1;
|
|
c[(n + 1) + 0] = 1;
|
|
|
|
for (i = 2; i <= n; i++)
|
|
{
|
|
for (j = FLINT_MIN(len - 1, i); j >= 0; j--)
|
|
{
|
|
slong ln, pos;
|
|
|
|
ln = i + 1 - j;
|
|
pos = (n + 1) * j;
|
|
if (i == j)
|
|
{
|
|
c[pos] = 1;
|
|
}
|
|
else
|
|
{
|
|
c[pos + ln - 1] = c[pos + ln - 2];
|
|
for (k = ln - 2; k >= 1; k--)
|
|
c[pos + k] = c[pos + k] * (i - 1) + c[pos + k - 1];
|
|
c[pos + 0] *= (i - 1);
|
|
if (j != 0)
|
|
for (k = ln - 1; k >= 0; k--)
|
|
c[pos + k] += c[pos - (n + 1) + k];
|
|
}
|
|
}
|
|
}
|
|
|
|
xpow = _arb_vec_init(n + 1);
|
|
_arb_vec_set_powers(xpow, x, n + 1, wp);
|
|
|
|
arb_dot_ui(res, NULL, 0, xpow + 1, 1, c + 1, 1, n, prec);
|
|
|
|
for (i = 1; i < len; i++)
|
|
arb_dot_ui(res + i, NULL, 0, xpow, 1, c + (n + 1) * i, 1, n + 1 - i, prec);
|
|
|
|
_arb_vec_clear(xpow, n + 1);
|
|
TMP_END;
|
|
}
|
|
else
|
|
{
|
|
fmpz * c;
|
|
|
|
wp = ARF_PREC_ADD(prec, FLINT_BIT_COUNT(n));
|
|
c = _fmpz_vec_init((n + 1) * len);
|
|
|
|
fmpz_one(c + 1);
|
|
fmpz_one(c + (n + 1) + 0);
|
|
|
|
for (i = 2; i <= n; i++)
|
|
{
|
|
for (j = FLINT_MIN(len - 1, i); j >= 0; j--)
|
|
{
|
|
slong ln, pos;
|
|
|
|
ln = i + 1 - j;
|
|
pos = (n + 1) * j;
|
|
if (i == j)
|
|
{
|
|
fmpz_one(c + pos);
|
|
}
|
|
else
|
|
{
|
|
fmpz_set(c + pos + ln - 1, c + pos + ln - 2);
|
|
for (k = ln - 2; k >= 1; k--)
|
|
{
|
|
fmpz_mul_ui(c + pos + k, c + pos + k, i - 1);
|
|
fmpz_add(c + pos + k, c + pos + k, c + pos + k - 1);
|
|
}
|
|
|
|
fmpz_mul_ui(c + pos + 0, c + pos + 0, i - 1);
|
|
if (j != 0)
|
|
for (k = ln - 1; k >= 0; k--)
|
|
fmpz_add(c + pos + k, c + pos + k, c + pos - (n + 1) + k);
|
|
}
|
|
}
|
|
}
|
|
|
|
xpow = _arb_vec_init(n + 1);
|
|
_arb_vec_set_powers(xpow, x, n + 1, wp);
|
|
|
|
arb_dot_fmpz(res, NULL, 0, xpow + 1, 1, c + 1, 1, n, prec);
|
|
|
|
for (i = 1; i < len; i++)
|
|
arb_dot_fmpz(res + i, NULL, 0, xpow, 1, c + (n + 1) * i, 1, n + 1 - i, prec);
|
|
|
|
_arb_vec_clear(xpow, n + 1);
|
|
_fmpz_vec_clear(c, (n + 1) * len);
|
|
}
|
|
}
|
|
|