more numerical integration implementations

This commit is contained in:
fredrik 2021-12-10 18:12:01 +01:00
parent 75df786325
commit e79a80340f
15 changed files with 679 additions and 34 deletions

View file

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2014-2015 Fredrik Johansson Copyright (C) 2014-2015, 2021 Fredrik Johansson
This file is part of Arb. This file is part of Arb.
@ -9,6 +9,7 @@
(at your option) any later version. See <http://www.gnu.org/licenses/>. (at your option) any later version. See <http://www.gnu.org/licenses/>.
*/ */
#include "arb_hypgeom.h"
#include "acb_hypgeom.h" #include "acb_hypgeom.h"
void void
@ -200,7 +201,7 @@ acb_hypgeom_bessel_i_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, s
} }
void void
acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, slong prec) acb_hypgeom_bessel_i_nointegration(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec)
{ {
mag_t zmag; mag_t zmag;
@ -209,27 +210,65 @@ acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, slong prec)
if (mag_cmp_2exp_si(zmag, 4) < 0 || if (mag_cmp_2exp_si(zmag, 4) < 0 ||
(mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec)) (mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec))
acb_hypgeom_bessel_i_0f1(res, nu, z, 0, prec); acb_hypgeom_bessel_i_0f1(res, nu, z, scaled, prec);
else else
acb_hypgeom_bessel_i_asymp(res, nu, z, 0, prec); acb_hypgeom_bessel_i_asymp(res, nu, z, scaled, prec);
mag_clear(zmag); mag_clear(zmag);
} }
void void
acb_hypgeom_bessel_i_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec) _acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec)
{ {
mag_t zmag; acb_t res2;
slong acc, max, t;
mag_init(zmag); acb_init(res2);
acb_get_mag(zmag, z);
if (mag_cmp_2exp_si(zmag, 4) < 0 || acb_hypgeom_bessel_i_nointegration(res2, nu, z, scaled, prec);
(mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec))
acb_hypgeom_bessel_i_0f1(res, nu, z, 1, prec);
else
acb_hypgeom_bessel_i_asymp(res, nu, z, 1, prec);
mag_clear(zmag); acc = acb_rel_accuracy_bits(res2);
if (acc < 0.5 * prec)
{
max = prec;
t = acb_rel_accuracy_bits(z);
max = FLINT_MIN(max, t);
t = acb_rel_accuracy_bits(nu);
max = FLINT_MIN(max, t);
if (max > 2 && acc < 0.5 * max)
{
if (acb_is_real(nu) && acb_is_real(z) && arf_cmp_2exp_si(arb_midref(acb_realref(nu)), -1) > 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_realref(nu)), 60) < 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0)
{
arb_hypgeom_bessel_i_integration(acb_realref(res),
acb_realref(nu), acb_realref(z), scaled, prec);
arb_zero(acb_imagref(res));
if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) ||
(acb_is_finite(res) && !acb_is_finite(res2)))
{
acb_swap(res, res2);
}
}
}
}
acb_swap(res, res2);
acb_clear(res2);
} }
void
acb_hypgeom_bessel_i(acb_t res, const acb_t nu, const acb_t z, slong prec)
{
_acb_hypgeom_bessel_i(res, nu, z, 0, prec);
}
void
acb_hypgeom_bessel_i_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec)
{
_acb_hypgeom_bessel_i(res, nu, z, 1, prec);
}

View file

@ -9,6 +9,7 @@
(at your option) any later version. See <http://www.gnu.org/licenses/>. (at your option) any later version. See <http://www.gnu.org/licenses/>.
*/ */
#include "arb_hypgeom.h"
#include "acb_hypgeom.h" #include "acb_hypgeom.h"
void void
@ -206,7 +207,7 @@ acb_hypgeom_bessel_k_0f1(acb_t res, const acb_t nu, const acb_t z, int scaled, s
} }
void void
acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, slong prec) acb_hypgeom_bessel_k_nointegration(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec)
{ {
mag_t zmag; mag_t zmag;
@ -215,27 +216,65 @@ acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, slong prec)
if (mag_cmp_2exp_si(zmag, 4) < 0 || if (mag_cmp_2exp_si(zmag, 4) < 0 ||
(mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec)) (mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec))
acb_hypgeom_bessel_k_0f1(res, nu, z, 0, prec); acb_hypgeom_bessel_k_0f1(res, nu, z, scaled, prec);
else else
acb_hypgeom_bessel_k_asymp(res, nu, z, 0, prec); acb_hypgeom_bessel_k_asymp(res, nu, z, scaled, prec);
mag_clear(zmag); mag_clear(zmag);
} }
void void
acb_hypgeom_bessel_k_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec) _acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, int scaled, slong prec)
{ {
mag_t zmag; acb_t res2;
slong acc, max, t;
mag_init(zmag); acb_init(res2);
acb_get_mag(zmag, z);
if (mag_cmp_2exp_si(zmag, 4) < 0 || acb_hypgeom_bessel_k_nointegration(res2, nu, z, scaled, prec);
(mag_cmp_2exp_si(zmag, 64) < 0 && 2 * mag_get_d(zmag) < prec))
acb_hypgeom_bessel_k_0f1(res, nu, z, 1, prec);
else
acb_hypgeom_bessel_k_asymp(res, nu, z, 1, prec);
mag_clear(zmag); acc = acb_rel_accuracy_bits(res2);
if (acc < 0.5 * prec)
{
max = prec;
t = acb_rel_accuracy_bits(z);
max = FLINT_MIN(max, t);
t = acb_rel_accuracy_bits(nu);
max = FLINT_MIN(max, t);
if (max > 2 && acc < 0.5 * max)
{
if (acb_is_real(nu) && acb_is_real(z) && arf_cmp_d(arb_midref(acb_realref(nu)), -0.5) > 0 &&
arf_cmp_2exp_si(arb_midref(acb_realref(z)), -16) > 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_realref(nu)), 60) < 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0)
{
arb_hypgeom_bessel_k_integration(acb_realref(res),
acb_realref(nu), acb_realref(z), scaled, prec);
arb_zero(acb_imagref(res));
if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) ||
(acb_is_finite(res) && !acb_is_finite(res2)))
{
acb_swap(res, res2);
}
}
}
}
acb_swap(res, res2);
acb_clear(res2);
} }
void
acb_hypgeom_bessel_k(acb_t res, const acb_t nu, const acb_t z, slong prec)
{
_acb_hypgeom_bessel_k(res, nu, z, 0, prec);
}
void
acb_hypgeom_bessel_k_scaled(acb_t res, const acb_t nu, const acb_t z, slong prec)
{
_acb_hypgeom_bessel_k(res, nu, z, 1, prec);
}

View file

@ -9,6 +9,7 @@
(at your option) any later version. See <http://www.gnu.org/licenses/>. (at your option) any later version. See <http://www.gnu.org/licenses/>.
*/ */
#include "arb_hypgeom.h"
#include "acb_hypgeom.h" #include "acb_hypgeom.h"
int int
@ -390,7 +391,7 @@ _acb_is_nonnegative_real(const acb_t z)
} }
void void
acb_hypgeom_gamma_upper(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec) acb_hypgeom_gamma_upper_nointegration(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec)
{ {
if (!acb_is_finite(s) || !acb_is_finite(z)) if (!acb_is_finite(s) || !acb_is_finite(z))
{ {
@ -525,3 +526,46 @@ acb_hypgeom_gamma_upper(acb_t res, const acb_t s, const acb_t z, int regularized
} }
} }
void
acb_hypgeom_gamma_upper(acb_t res, const acb_t s, const acb_t z, int regularized, slong prec)
{
acb_t res2;
slong acc, max, t;
acb_init(res2);
acb_hypgeom_gamma_upper_nointegration(res2, s, z, regularized, prec);
acc = acb_rel_accuracy_bits(res2);
if (acc < 0.5 * prec)
{
max = prec;
t = acb_rel_accuracy_bits(z);
max = FLINT_MIN(max, t);
t = acb_rel_accuracy_bits(s);
max = FLINT_MIN(max, t);
if (max > 2 && acc < 0.5 * max)
{
if (acb_is_real(s) && acb_is_real(z) &&
arf_cmp_2exp_si(arb_midref(acb_realref(z)), -16) > 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_realref(s)), 60) < 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), 60) < 0)
{
arb_hypgeom_gamma_upper_integration(acb_realref(res),
acb_realref(s), acb_realref(z), regularized, prec);
arb_zero(acb_imagref(res));
if (acb_rel_accuracy_bits(res) > acb_rel_accuracy_bits(res2) ||
(acb_is_finite(res) && !acb_is_finite(res2)))
{
acb_swap(res, res2);
}
}
}
}
acb_swap(res, res2);
acb_clear(res2);
}

View file

@ -36,9 +36,16 @@ int main()
prec = 2 + n_randint(state, 500); prec = 2 + n_randint(state, 500);
scaled = n_randint(state, 2); scaled = n_randint(state, 2);
acb_randtest_param(nu, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 10)); acb_randtest_param(nu, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 20));
acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100)); acb_randtest(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));
if (n_randint(state, 2) && prec <= 200)
{
arb_zero(acb_imagref(nu));
arb_zero(acb_imagref(z));
arb_abs(acb_realref(nu), acb_realref(nu));
}
switch (n_randint(state, 3)) switch (n_randint(state, 3))
{ {
case 0: case 0:

View file

@ -51,6 +51,13 @@ int main()
if (n_randint(state, 4) == 0) if (n_randint(state, 4) == 0)
arb_zero(acb_imagref(z)); arb_zero(acb_imagref(z));
if (n_randint(state, 2) && prec0 <= 200 && prec1 <= 200 && prec2 <= 200)
{
arb_zero(acb_imagref(nu0));
arb_zero(acb_imagref(z));
arb_abs(acb_realref(nu0), acb_realref(nu0));
}
acb_sub_ui(nu1, nu0, 1, prec0); acb_sub_ui(nu1, nu0, 1, prec0);
acb_sub_ui(nu2, nu0, 2, prec0); acb_sub_ui(nu2, nu0, 2, prec0);

View file

@ -129,6 +129,9 @@ void arb_hypgeom_bessel_k(arb_t res, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_bessel_i_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_i_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_bessel_k_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec); void arb_hypgeom_bessel_k_scaled(arb_t res, const arb_t nu, const arb_t z, slong prec);
void arb_hypgeom_bessel_i_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec);
void arb_hypgeom_bessel_k_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec);
void arb_hypgeom_airy(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const arb_t z, slong prec); void arb_hypgeom_airy(arb_t ai, arb_t aip, arb_t bi, arb_t bip, const arb_t z, slong prec);
void arb_hypgeom_airy_jet(arb_ptr ai, arb_ptr bi, const arb_t z, slong len, slong prec); void arb_hypgeom_airy_jet(arb_ptr ai, arb_ptr bi, const arb_t z, slong len, slong prec);
void arb_hypgeom_airy_series(arb_poly_t ai, arb_poly_t ai_prime, void arb_hypgeom_airy_series(arb_poly_t ai, arb_poly_t ai_prime,
@ -153,6 +156,8 @@ void arb_hypgeom_gamma_upper(arb_t res, const arb_t s, const arb_t z, int regula
void _arb_hypgeom_gamma_upper_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec); void _arb_hypgeom_gamma_upper_series(arb_ptr g, const arb_t s, arb_srcptr h, slong hlen, int regularized, slong n, slong prec);
void arb_hypgeom_gamma_upper_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec); void arb_hypgeom_gamma_upper_series(arb_poly_t g, const arb_t s, const arb_poly_t h, int regularized, slong n, slong prec);
void arb_hypgeom_gamma_upper_integration(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec);
void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t c, const arb_t z, int regularized, slong prec); void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t c, const arb_t z, int regularized, slong prec);
void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, slong len, slong prec); void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, slong len, slong prec);
void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, slong zlen, int regularized, slong len, slong prec); void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, slong zlen, int regularized, slong len, slong prec);

View file

@ -0,0 +1,68 @@
/*
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_bessel_i_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec)
{
arb_t t, a, b, w;
arb_init(t);
arb_init(a);
arb_init(b);
arb_init(w);
arb_one(a);
arb_mul_2exp_si(a, a, -1);
arb_add(a, a, nu, prec);
arb_mul_2exp_si(b, nu, 1);
arb_add_ui(b, b, 1, prec);
arb_mul_2exp_si(w, z, 1);
arb_hypgeom_1f1_integration(t, a, b, w, 0, prec);
if (arb_is_finite(t))
{
if (!scaled)
{
arb_neg(a, z);
arb_exp(a, a, prec);
arb_mul(t, t, a, prec);
}
else
{
arb_neg(a, z);
arb_mul_2exp_si(a, a, 1);
arb_exp(a, a, prec);
arb_mul(t, t, a, prec);
}
arb_mul_2exp_si(w, z, -1);
arb_pow(w, w, nu, prec);
arb_mul(t, t, w, prec);
arb_add_ui(w, nu, 1, prec);
arb_rgamma(w, w, prec);
arb_mul(res, t, w, prec);
}
else
{
arb_indeterminate(res);
}
arb_clear(t);
arb_clear(a);
arb_clear(b);
arb_clear(w);
}

View file

@ -0,0 +1,60 @@
/*
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_bessel_k_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec)
{
arb_t t, a, b, w;
arb_init(t);
arb_init(a);
arb_init(b);
arb_init(w);
arb_one(a);
arb_mul_2exp_si(a, a, -1);
arb_add(a, a, nu, prec);
arb_mul_2exp_si(b, nu, 1);
arb_add_ui(b, b, 1, prec);
arb_mul_2exp_si(w, z, 1);
arb_hypgeom_u_integration(t, a, b, w, prec);
if (arb_is_finite(t))
{
if (!scaled)
{
arb_neg(a, z);
arb_exp(a, a, prec);
arb_mul(t, t, a, prec);
}
arb_mul_2exp_si(w, z, 1);
arb_pow(w, w, nu, prec);
arb_mul(res, t, w, prec);
arb_const_sqrt_pi(w, prec);
arb_mul(res, res, w, prec);
}
else
{
arb_indeterminate(res);
}
arb_clear(t);
arb_clear(a);
arb_clear(b);
arb_clear(w);
}

View file

@ -0,0 +1,53 @@
/*
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_gamma_upper_integration(arb_t res, const arb_t s,
const arb_t z, int regularized, slong prec)
{
arb_t t, u;
arb_init(t);
arb_init(u);
arb_one(t);
arb_add_ui(u, s, 1, prec);
arb_hypgeom_u_integration(u, t, u, z, prec);
if (arb_is_finite(u))
{
if (regularized != 2)
{
arb_pow(t, z, s, prec);
arb_mul(u, u, t, prec);
if (regularized == 1)
{
arb_rgamma(t, s, prec);
arb_mul(u, u, t, prec);
}
}
arb_neg(t, z);
arb_exp(t, t, prec);
arb_mul(res, t, u, prec);
}
else
{
arb_indeterminate(res);
}
arb_clear(t);
arb_clear(u);
}

View file

@ -0,0 +1,82 @@
/*
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"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("bessel_i_integration....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 100 * arb_test_multiplier(); iter++)
{
arb_t a, z, r1, r2;
slong prec1, prec2;
int scaled;
prec1 = 2 + n_randint(state, 80);
prec2 = 2 + n_randint(state, 150);
arb_init(a);
arb_init(z);
arb_init(r1);
arb_init(r2);
scaled = n_randint(state, 2);
arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8));
arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8));
arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5));
arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5));
arb_add_ui(a, a, n_randint(state, 100), prec1 + 100);
arb_add_ui(z, z, n_randint(state, 100), prec1 + 100);
arb_hypgeom_bessel_i_integration(r1, a, z, scaled, prec1);
if (arb_is_finite(r1))
{
if (n_randint(state, 2))
arb_hypgeom_bessel_i_integration(r2, a, z, scaled, prec2);
else
{
if (scaled)
arb_hypgeom_bessel_i_scaled(r2, a, z, prec2);
else
arb_hypgeom_bessel_i(r2, a, z, prec2);
}
if (!arb_overlaps(r1, r2))
{
flint_printf("FAIL: overlap\n\n");
flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n");
flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n");
flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n");
flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n");
flint_abort();
}
}
arb_clear(a);
arb_clear(z);
arb_clear(r1);
arb_clear(r2);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,82 @@
/*
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"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("bessel_k_integration....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 100 * arb_test_multiplier(); iter++)
{
arb_t a, z, r1, r2;
slong prec1, prec2;
int scaled;
prec1 = 2 + n_randint(state, 80);
prec2 = 2 + n_randint(state, 150);
arb_init(a);
arb_init(z);
arb_init(r1);
arb_init(r2);
scaled = n_randint(state, 2);
arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8));
arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8));
arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5));
arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5));
arb_add_ui(a, a, n_randint(state, 100), prec1 + 100);
arb_add_ui(z, z, n_randint(state, 100), prec1 + 100);
arb_hypgeom_bessel_k_integration(r1, a, z, scaled, prec1);
if (arb_is_finite(r1))
{
if (n_randint(state, 2))
arb_hypgeom_bessel_k_integration(r2, a, z, scaled, prec2);
else
{
if (scaled)
arb_hypgeom_bessel_k_scaled(r2, a, z, prec2);
else
arb_hypgeom_bessel_k(r2, a, z, prec2);
}
if (!arb_overlaps(r1, r2))
{
flint_printf("FAIL: overlap\n\n");
flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n");
flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n");
flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n");
flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n");
flint_abort();
}
}
arb_clear(a);
arb_clear(z);
arb_clear(r1);
arb_clear(r2);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,111 @@
/*
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"
int main()
{
slong iter;
flint_rand_t state;
flint_printf("gamma_upper_integration....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 100 * arb_test_multiplier(); iter++)
{
arb_t a, z, r1, r2;
slong prec1, prec2;
int regularized;
prec1 = 2 + n_randint(state, 80);
prec2 = 2 + n_randint(state, 150);
arb_init(a);
arb_init(z);
arb_init(r1);
arb_init(r2);
regularized = n_randint(state, 3);
arb_randtest_precise(a, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8));
arb_randtest_precise(z, state, 1 + n_randint(state, 200), 1 + n_randint(state, 8));
arb_randtest(r1, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5));
arb_randtest(r2, state, 1 + n_randint(state, 200), 1 + n_randint(state, 5));
arb_add_ui(a, a, n_randint(state, 100), prec1 + 100);
arb_add_ui(z, z, n_randint(state, 100), prec1 + 100);
arb_hypgeom_gamma_upper_integration(r1, a, z, regularized, prec1);
if (arb_is_finite(r1))
{
if (n_randint(state, 2))
arb_hypgeom_gamma_upper_integration(r2, a, z, regularized, prec2);
else
arb_hypgeom_gamma_upper(r2, a, z, regularized, prec2);
if (!arb_overlaps(r1, r2))
{
flint_printf("FAIL: overlap\n\n");
flint_printf("a = "); arb_printd(a, 30); flint_printf("\n\n");
flint_printf("z = "); arb_printd(z, 30); flint_printf("\n\n");
flint_printf("r1 = "); arb_printd(r1, 30); flint_printf("\n\n");
flint_printf("r2 = "); arb_printd(r2, 30); flint_printf("\n\n");
flint_abort();
}
}
if (iter == 0)
{
prec1 = 333;
arb_set_str(a, "5.25", prec1);
arb_set_str(z, "1.125", prec1);
arb_hypgeom_gamma_upper_integration(r1, a, z, 0, prec1);
arb_set_str(r2, "35.072486673952527119466762267780775062420879980812938235868074922070540736636294202721367124421387 +/- 5.01e-97", prec1);
if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10)
{
flint_printf("FAIL: overlap (1)\n\n");
flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n");
flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n");
flint_abort();
}
arb_set_str(a, "-23515.25", prec1);
arb_set_str(z, "5118.125", prec1);
arb_hypgeom_gamma_upper_integration(r1, a, z, 0, prec1);
arb_set_str(r2, "1.2585189324946269645868452847608400602717904014578585865177198314407671242201776909963228597279e-89448 +/- 8.86e-89543", prec1);
if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10)
{
flint_printf("FAIL: overlap (1)\n\n");
flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n");
flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n");
flint_abort();
}
}
arb_clear(a);
arb_clear(z);
arb_clear(r1);
arb_clear(r2);
}
flint_randclear(state);
flint_cleanup();
flint_printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -86,6 +86,21 @@ int main()
flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n"); flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n");
flint_abort(); flint_abort();
} }
arb_set_str(a, "1.0", prec1);
arb_set_str(b, "1351.25", prec1);
arb_set_str(z, "5118.125", prec1);
arb_hypgeom_u_integration(r1, a, b, z, prec1);
arb_set_str(r2, "0.0002653059837025369361090415756761601958818507141969057844945316037867908521084665825645386229229474 +/- 5.74e-101", prec1);
if (!arb_overlaps(r1, r2) || arb_rel_accuracy_bits(r1) < arb_rel_accuracy_bits(r2) - 10)
{
flint_printf("FAIL: overlap (2)\n\n");
flint_printf("r1 = "); arb_printd(r1, 100); flint_printf("\n\n");
flint_printf("r2 = "); arb_printd(r2, 100); flint_printf("\n\n");
flint_abort();
}
} }
arb_clear(a); arb_clear(a);

View file

@ -31,7 +31,12 @@ di_integrand_edge(di_t u, di_t v, di_t a1, di_t ba1, di_t z)
di_t X, Y, Z; di_t X, Y, Z;
X = di_neg(di_fast_mul(z, u)); X = di_neg(di_fast_mul(z, u));
Y = di_fast_mul(a1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(u), di_fast_sqr(v))));
if (a1.a == 0.0 && a1.b == 0.0)
Y = di_interval(0.0, 0.0);
else
Y = di_fast_mul(a1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(u), di_fast_sqr(v))));
Z = di_fast_mul(ba1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(di_fast_add_d(u, 1.0)), di_fast_sqr(v)))); Z = di_fast_mul(ba1, di_fast_log_nonnegative(di_fast_add(di_fast_sqr(di_fast_add_d(u, 1.0)), di_fast_sqr(v))));
return di_fast_add(X, di_fast_mul_d(di_fast_add(Y, Z), 0.5)); return di_fast_add(X, di_fast_mul_d(di_fast_add(Y, Z), 0.5));
@ -46,7 +51,11 @@ di_integrand_edge_diff(di_t u, di_t v, di_t a1, di_t ba1, di_t z, int which)
{ {
di_t Y, Z; di_t Y, Z;
Y = di_fast_div(a1, di_fast_add(di_fast_sqr(u), di_fast_sqr(v))); if (a1.a == 0.0 && a1.b == 0.0)
Y = di_interval(0.0, 0.0);
else
Y = di_fast_div(a1, di_fast_add(di_fast_sqr(u), di_fast_sqr(v)));
Z = di_fast_div(ba1, di_fast_add(di_fast_sqr(di_fast_add_d(u, 1.0)), di_fast_sqr(v))); Z = di_fast_div(ba1, di_fast_add(di_fast_sqr(di_fast_add_d(u, 1.0)), di_fast_sqr(v)));
if (which == 0) if (which == 0)
@ -206,7 +215,8 @@ integrand(acb_ptr out, const acb_t t, void * param, slong order, slong prec)
if (order == 1) if (order == 1)
{ {
if (!arb_is_positive(acb_realref(t))) if (!(arb_is_positive(acb_realref(t)) || arb_is_zero(a1)) ||
!arb_is_positive(acb_realref(v)))
acb_indeterminate(out); acb_indeterminate(out);
else else
integrand_wide_bound5(out, t, a1, ba1, z, prec); integrand_wide_bound5(out, t, a1, ba1, z, prec);
@ -222,6 +232,7 @@ integrand(acb_ptr out, const acb_t t, void * param, slong order, slong prec)
/* t^(a-1) */ /* t^(a-1) */
acb_my_pow_arb(u, t, a1, prec); acb_my_pow_arb(u, t, a1, prec);
/* (1+t)^(b-a-1) */ /* (1+t)^(b-a-1) */
acb_pow_arb(v, v, ba1, prec); acb_pow_arb(v, v, ba1, prec);
@ -234,8 +245,15 @@ integrand(acb_ptr out, const acb_t t, void * param, slong order, slong prec)
acb_neg(s, s); acb_neg(s, s);
/* t^(a-1) */ /* t^(a-1) */
acb_log(u, t, prec); if (arb_is_zero(a1))
acb_mul_arb(u, u, a1, prec); {
acb_zero(u);
}
else
{
acb_log(u, t, prec);
acb_mul_arb(u, u, a1, prec);
}
/* (1+t)^(b-a-1) */ /* (1+t)^(b-a-1) */
acb_log(v, v, prec); acb_log(v, v, prec);
@ -278,6 +296,10 @@ estimate_magnitude(mag_t res, const arb_t ra, const arb_t rb, const arb_t rz)
t2 = 1e-8; t2 = 1e-8;
} }
/* todo: better estimate when peak is at 0 */
t1 = FLINT_MAX(t1, 1e-8);
t2 = FLINT_MAX(t2, 1e-8);
m = -1e300; m = -1e300;
if (t1 > 0.0) if (t1 > 0.0)

View file

@ -286,6 +286,11 @@ Incomplete gamma and beta functions
intended for internal use; :func:`arb_hypgeom_expint` is the intended intended for internal use; :func:`arb_hypgeom_expint` is the intended
interface for computing the exponential integral). interface for computing the exponential integral).
.. function:: void arb_hypgeom_gamma_upper_integration(arb_t res, const arb_t s, const arb_t z, int regularized, slong prec)
Computes the upper incomplete gamma function using numerical
integration.
.. function:: void _arb_hypgeom_gamma_upper_series(arb_ptr res, const arb_t s, arb_srcptr z, slong zlen, int regularized, slong n, slong prec) .. function:: void _arb_hypgeom_gamma_upper_series(arb_ptr res, const arb_t s, arb_srcptr z, slong zlen, int regularized, slong n, slong prec)
void arb_hypgeom_gamma_upper_series(arb_poly_t res, const arb_t s, const arb_poly_t z, int regularized, slong n, slong prec) void arb_hypgeom_gamma_upper_series(arb_poly_t res, const arb_t s, const arb_poly_t z, int regularized, slong n, slong prec)
@ -329,6 +334,7 @@ Incomplete gamma and beta functions
The underscore method requires positive lengths and does not support The underscore method requires positive lengths and does not support
aliasing. aliasing.
Internal evaluation functions Internal evaluation functions
................................................................................ ................................................................................
@ -495,6 +501,11 @@ Bessel functions
Computes the function `e^{z} K_{\nu}(z)`. Computes the function `e^{z} K_{\nu}(z)`.
.. function:: void arb_hypgeom_bessel_i_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec)
void arb_hypgeom_bessel_k_integration(arb_t res, const arb_t nu, const arb_t z, int scaled, slong prec)
Computes the modified Bessel functions using numerical integration.
Airy functions Airy functions
------------------------------------------------------------------------------- -------------------------------------------------------------------------------