mirror of
https://github.com/vale981/arb
synced 2025-03-05 09:21:38 -05:00

This will allow us to not loose the julia session on error. See also https://github.com/wbhart/flint2/pull/243
289 lines
7 KiB
C
289 lines
7 KiB
C
/*
|
|
Copyright (C) 2016 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_hypgeom.h"
|
|
|
|
#define FAST_T 0
|
|
|
|
void acb_poly_reciprocal_majorant(arb_poly_t res, const acb_poly_t poly, slong prec);
|
|
|
|
static void
|
|
rsplit(acb_poly_t res, acb_poly_t term,
|
|
const acb_poly_struct * a, slong p,
|
|
const acb_poly_struct * b, slong q,
|
|
const acb_poly_t z, slong offset, slong n, slong len, slong prec)
|
|
{
|
|
acb_poly_struct * zpow;
|
|
acb_poly_t s, t, u;
|
|
slong i, j, k, m, tprec;
|
|
int is_real;
|
|
|
|
#if FAST_T
|
|
arb_poly_t B, C, D;
|
|
#else
|
|
acb_poly_t B, C, D;
|
|
#endif
|
|
|
|
if (n == 0)
|
|
{
|
|
acb_poly_zero(res);
|
|
acb_poly_one(term);
|
|
return;
|
|
}
|
|
|
|
if (n < 0)
|
|
flint_abort();
|
|
|
|
m = n_sqrt(n);
|
|
m = FLINT_MIN(m, 150);
|
|
|
|
acb_poly_init(s);
|
|
acb_poly_init(t);
|
|
acb_poly_init(u);
|
|
|
|
#if FAST_T
|
|
tprec = MAG_BITS;
|
|
|
|
arb_poly_init(B);
|
|
arb_poly_init(C);
|
|
arb_poly_init(D);
|
|
|
|
arb_poly_one(B);
|
|
arb_poly_one(D);
|
|
|
|
is_real = 1;
|
|
|
|
for (i = 0; i < p; i++)
|
|
for (j = 0; j < FLINT_MIN(acb_poly_length(a + i), len); j++)
|
|
is_real = is_real && acb_is_real((a + i)->coeffs + j);
|
|
|
|
for (i = 0; i < q; i++)
|
|
for (j = 0; j < FLINT_MIN(acb_poly_length(b + i), len); j++)
|
|
is_real = is_real && acb_is_real((b + i)->coeffs + j);
|
|
|
|
for (j = 0; j < FLINT_MIN(acb_poly_length(z), len); j++)
|
|
is_real = is_real && acb_is_real(z->coeffs + j);
|
|
#else
|
|
tprec = 2 * MAG_BITS;
|
|
is_real = 0; (void) is_real;
|
|
|
|
acb_poly_init(B);
|
|
acb_poly_init(C);
|
|
acb_poly_init(D);
|
|
|
|
acb_poly_one(B);
|
|
acb_poly_one(D);
|
|
#endif
|
|
|
|
zpow = flint_malloc(sizeof(acb_poly_struct) * (m + 1));
|
|
|
|
for (i = 0; i <= m; i++)
|
|
acb_poly_init(zpow + i);
|
|
|
|
for (i = 0; i <= m; i++)
|
|
{
|
|
if (i == 0)
|
|
acb_poly_one(zpow + i);
|
|
else if (i == 1)
|
|
acb_poly_set_round(zpow + i, z, prec);
|
|
else if (i % 2 == 0)
|
|
acb_poly_mullow(zpow + i, zpow + i / 2, zpow + i / 2, len, prec);
|
|
else
|
|
acb_poly_mullow(zpow + i, zpow + i - 1, zpow + 1, len, prec);
|
|
}
|
|
|
|
for (k = n; k >= 0; k--)
|
|
{
|
|
j = k % m;
|
|
|
|
if (k < n)
|
|
acb_poly_add(s, s, zpow + j, prec);
|
|
|
|
if (k > 0)
|
|
{
|
|
if (p > 0)
|
|
{
|
|
acb_poly_add_si(u, a, offset + k - 1, prec);
|
|
|
|
for (i = 1; i < p; i++)
|
|
{
|
|
acb_poly_add_si(t, a + i, offset + k - 1, prec);
|
|
acb_poly_mullow(u, u, t, len, prec);
|
|
}
|
|
|
|
if (k < n)
|
|
acb_poly_mullow(s, s, u, len, prec);
|
|
|
|
#if FAST_T
|
|
acb_poly_majorant(C, u, tprec);
|
|
arb_poly_mullow(B, B, C, len, tprec);
|
|
#else
|
|
acb_poly_set_round(C, u, tprec);
|
|
acb_poly_mullow(B, B, C, len, tprec);
|
|
|
|
#endif
|
|
}
|
|
|
|
if (q > 0)
|
|
{
|
|
acb_poly_add_si(u, b, offset + k - 1, prec);
|
|
|
|
for (i = 1; i < q; i++)
|
|
{
|
|
acb_poly_add_si(t, b + i, offset + k - 1, prec);
|
|
acb_poly_mullow(u, u, t, len, prec);
|
|
}
|
|
|
|
if (k < n)
|
|
acb_poly_div_series(s, s, u, len, prec);
|
|
|
|
#if FAST_T
|
|
acb_poly_reciprocal_majorant(C, u, tprec);
|
|
arb_poly_mullow(D, D, C, len, tprec);
|
|
#else
|
|
acb_poly_set_round(C, u, tprec);
|
|
acb_poly_mullow(D, D, C, len, tprec);
|
|
#endif
|
|
}
|
|
|
|
if (j == 0 && k < n)
|
|
{
|
|
acb_poly_mullow(s, s, zpow + m, len, prec);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if FAST_T
|
|
arb_poly_div_series(B, B, D, len, tprec);
|
|
acb_poly_majorant(C, z, tprec);
|
|
arb_poly_pow_ui_trunc_binexp(C, C, n, len, tprec);
|
|
arb_poly_mullow(C, B, C, len, tprec);
|
|
|
|
acb_poly_fit_length(term, arb_poly_length(C));
|
|
|
|
for (i = 0; i < arb_poly_length(C); i++)
|
|
{
|
|
arb_get_mag(arb_radref(acb_realref(term->coeffs + i)), C->coeffs + i);
|
|
arf_zero(arb_midref(acb_realref(term->coeffs + i)));
|
|
|
|
if (is_real)
|
|
arb_zero(acb_imagref(term->coeffs + i));
|
|
else
|
|
arb_set(acb_imagref(term->coeffs + i), acb_realref(term->coeffs + i));
|
|
}
|
|
|
|
_acb_poly_set_length(term, arb_poly_length(C));
|
|
_acb_poly_normalise(term);
|
|
|
|
#else
|
|
acb_poly_div_series(B, B, D, len, tprec);
|
|
acb_poly_set_round(C, z, tprec);
|
|
acb_poly_pow_ui_trunc_binexp(C, C, n, len, tprec);
|
|
acb_poly_mullow(term, B, C, len, tprec);
|
|
#endif
|
|
|
|
acb_poly_set(res, s);
|
|
|
|
#if FAST_T
|
|
arb_poly_clear(B);
|
|
arb_poly_clear(C);
|
|
arb_poly_clear(D);
|
|
#else
|
|
acb_poly_clear(B);
|
|
acb_poly_clear(C);
|
|
acb_poly_clear(D);
|
|
#endif
|
|
|
|
acb_poly_clear(s);
|
|
acb_poly_clear(t);
|
|
acb_poly_clear(u);
|
|
|
|
for (i = 0; i <= m; i++)
|
|
acb_poly_clear(zpow + i);
|
|
flint_free(zpow);
|
|
}
|
|
|
|
void
|
|
acb_hypgeom_pfq_series_sum_rs(acb_poly_t s, acb_poly_t t,
|
|
const acb_poly_struct * a, slong p,
|
|
const acb_poly_struct * b, slong q,
|
|
const acb_poly_t z, int regularized,
|
|
slong n, slong len, slong prec)
|
|
{
|
|
acb_poly_t u, v;
|
|
slong i, start;
|
|
|
|
if (n == 0)
|
|
{
|
|
acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z,
|
|
regularized, n, len, prec);
|
|
return;
|
|
}
|
|
|
|
start = 0;
|
|
|
|
if (regularized)
|
|
{
|
|
for (i = 0; i < q; i++)
|
|
{
|
|
if (acb_poly_is_zero(b + i))
|
|
{
|
|
start = FLINT_MAX(start, 1);
|
|
}
|
|
else
|
|
{
|
|
/* todo: use a fuzzier test? */
|
|
if (acb_contains_int((b + i)->coeffs) &&
|
|
!arb_is_positive(acb_realref((b + i)->coeffs)) &&
|
|
arf_cmpabs_2exp_si(arb_midref(acb_realref((b + i)->coeffs)),
|
|
FLINT_BITS - 2) < 0)
|
|
{
|
|
slong c = -arf_get_si(arb_midref(acb_realref((b + i)->coeffs)),
|
|
ARF_RND_NEAR);
|
|
|
|
/* if c >= n, terminates earlier, so no problem */
|
|
if (c < n)
|
|
{
|
|
start = FLINT_MAX(start, c + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* We should now have start <= n. */
|
|
if (start > n) flint_abort();
|
|
|
|
acb_hypgeom_pfq_series_sum_forward(s, t, a, p, b, q, z,
|
|
regularized, start, len, prec);
|
|
}
|
|
else
|
|
{
|
|
acb_poly_zero(s);
|
|
acb_poly_one(t);
|
|
}
|
|
|
|
if (start == n)
|
|
return;
|
|
|
|
acb_poly_init(u);
|
|
acb_poly_init(v);
|
|
|
|
rsplit(u, v, a, p, b, q, z, start, n - start, len, prec);
|
|
|
|
acb_poly_mullow(u, u, t, len, prec);
|
|
acb_poly_add(s, s, u, prec);
|
|
|
|
acb_poly_mullow(t, t, v, len, prec);
|
|
|
|
acb_poly_clear(u);
|
|
acb_poly_clear(v);
|
|
}
|
|
|