mirror of
https://github.com/vale981/arb
synced 2025-03-04 17:01:40 -05:00
192 lines
4.8 KiB
C
192 lines
4.8 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_sum_fmpq_arb_forward(arb_t res, const fmpq * a, slong alen, const fmpq * b, slong blen, const arb_t z, int reciprocal, slong N, slong prec)
|
|
{
|
|
arb_t t, u, sden;
|
|
slong i, k, num_max_bits, den_max_bits, bits1, bits2, Nbits, den_prec;
|
|
|
|
if (N <= 1)
|
|
{
|
|
if (N == 1)
|
|
arb_one(res);
|
|
else
|
|
arb_zero(res);
|
|
return;
|
|
}
|
|
|
|
arb_init(t);
|
|
arb_init(u);
|
|
arb_init(sden);
|
|
|
|
Nbits = FLINT_BIT_COUNT(N);
|
|
num_max_bits = 0;
|
|
for (i = 0; i < alen; i++)
|
|
{
|
|
bits1 = fmpz_bits(fmpq_numref(a + i));
|
|
bits2 = fmpz_bits(fmpq_denref(a + i)) + Nbits;
|
|
num_max_bits += FLINT_MAX(bits1, bits2) + 1;
|
|
}
|
|
|
|
den_max_bits = 0;
|
|
for (i = 0; i < blen; i++)
|
|
{
|
|
bits1 = fmpz_bits(fmpq_numref(b + i));
|
|
bits2 = fmpz_bits(fmpq_denref(b + i)) + Nbits;
|
|
den_max_bits += FLINT_MAX(bits1, bits2) + 1;
|
|
}
|
|
|
|
den_prec = FLINT_MAX(128, prec + 2 * Nbits);
|
|
|
|
if (num_max_bits <= FLINT_BITS - 1 && den_max_bits <= FLINT_BITS - 1)
|
|
{
|
|
slong num, den;
|
|
|
|
den = 1;
|
|
num = 1;
|
|
for (i = 0; i < alen; i++)
|
|
den *= *fmpq_denref(a + i);
|
|
for (i = 0; i < blen; i++)
|
|
num *= *fmpq_denref(b + i);
|
|
|
|
if (reciprocal)
|
|
{
|
|
arb_mul_si(u, z, den, prec);
|
|
arb_set_si(t, num);
|
|
arb_div(u, t, u, prec);
|
|
}
|
|
else
|
|
{
|
|
arb_mul_si(u, z, num, prec);
|
|
arb_div_si(u, u, den, prec);
|
|
}
|
|
|
|
arb_one(res);
|
|
arb_one(t);
|
|
arb_one(sden);
|
|
|
|
for (k = 1; k < N && !arb_is_zero(t); k++)
|
|
{
|
|
arb_mul(t, t, u, prec);
|
|
|
|
if (alen != 0)
|
|
{
|
|
num = *fmpq_denref(a + 0) * (k - 1) + *fmpq_numref(a + 0);
|
|
|
|
for (i = 1; i < alen; i++)
|
|
num *= (*fmpq_denref(a + i) * (k - 1) + *fmpq_numref(a + i));
|
|
|
|
arb_mul_si(t, t, num, prec);
|
|
}
|
|
|
|
if (blen != 0)
|
|
{
|
|
den = *fmpq_denref(b + 0) * (k - 1) + *fmpq_numref(b + 0);
|
|
|
|
for (i = 1; i < blen; i++)
|
|
den *= (*fmpq_denref(b + i) * (k - 1) + *fmpq_numref(b + i));
|
|
|
|
arb_fma_si(res, res, den, t, prec);
|
|
arb_mul_si(sden, sden, den, den_prec);
|
|
}
|
|
else
|
|
{
|
|
arb_add(res, res, t, prec);
|
|
}
|
|
}
|
|
|
|
arb_div(res, res, sden, prec);
|
|
}
|
|
else
|
|
{
|
|
fmpz_t num, den, c;
|
|
|
|
fmpz_init(num);
|
|
fmpz_init(den);
|
|
fmpz_init(c);
|
|
|
|
fmpz_one(den);
|
|
fmpz_one(num);
|
|
for (i = 0; i < alen; i++)
|
|
fmpz_mul(den, den, fmpq_denref(a + i));
|
|
for (i = 0; i < blen; i++)
|
|
fmpz_mul(num, num, fmpq_denref(b + i));
|
|
|
|
if (reciprocal)
|
|
{
|
|
arb_mul_fmpz(u, z, den, prec);
|
|
arb_set_fmpz(t, num);
|
|
arb_div(u, t, u, prec);
|
|
}
|
|
else
|
|
{
|
|
arb_mul_fmpz(u, z, num, prec);
|
|
arb_div_fmpz(u, u, den, prec);
|
|
}
|
|
|
|
arb_one(res);
|
|
arb_one(t);
|
|
arb_one(sden);
|
|
|
|
for (k = 1; k < N && !arb_is_zero(t); k++)
|
|
{
|
|
arb_mul(t, t, u, prec);
|
|
|
|
if (alen != 0)
|
|
{
|
|
fmpz_mul_ui(num, fmpq_denref(a + 0), k - 1);
|
|
fmpz_add(num, num, fmpq_numref(a + 0));
|
|
|
|
for (i = 1; i < alen; i++)
|
|
{
|
|
fmpz_mul_ui(c, fmpq_denref(a + i), k - 1);
|
|
fmpz_add(c, c, fmpq_numref(a + i));
|
|
fmpz_mul(num, num, c);
|
|
}
|
|
|
|
arb_mul_fmpz(t, t, num, prec);
|
|
}
|
|
|
|
if (blen != 0)
|
|
{
|
|
fmpz_mul_ui(den, fmpq_denref(b + 0), k - 1);
|
|
fmpz_add(den, den, fmpq_numref(b + 0));
|
|
|
|
for (i = 1; i < blen; i++)
|
|
{
|
|
fmpz_mul_ui(c, fmpq_denref(b + i), k - 1);
|
|
fmpz_add(c, c, fmpq_numref(b + i));
|
|
fmpz_mul(den, den, c);
|
|
}
|
|
|
|
arb_fma_fmpz(res, res, den, t, prec);
|
|
arb_mul_fmpz(sden, sden, den, den_prec);
|
|
}
|
|
else
|
|
{
|
|
arb_add(res, res, t, prec);
|
|
}
|
|
}
|
|
|
|
arb_div(res, res, sden, prec);
|
|
|
|
fmpz_clear(num);
|
|
fmpz_clear(den);
|
|
fmpz_clear(c);
|
|
}
|
|
|
|
arb_clear(t);
|
|
arb_clear(u);
|
|
arb_clear(sden);
|
|
}
|