tweaks to integration

This commit is contained in:
Fredrik Johansson 2017-11-12 17:14:25 +01:00
parent ed24c04d0c
commit c2745a17a1
3 changed files with 75 additions and 17 deletions

View file

@ -75,7 +75,7 @@ acb_calc_integrate(acb_t res, acb_calc_func_t f, void * param,
depth_limit = FLINT_MAX(depth_limit, 1);
if (eval_limit <= 0)
eval_limit = 1000 * prec;
eval_limit = 1000 * prec + prec * prec;
eval_limit = FLINT_MAX(eval_limit, 1);
goal = FLINT_MAX(goal, 0);
@ -130,7 +130,7 @@ acb_calc_integrate(acb_t res, acb_calc_func_t f, void * param,
/* We know that the result is real. */
real_error = acb_is_finite(t) && acb_is_real(t);
feval = acb_calc_integrate_gl_auto_deg(t, f, param, as + depth - 1,
feval = acb_calc_integrate_gl_auto_deg(u, f, param, as + depth - 1,
bs + depth - 1, new_tol, deg_limit, flags, prec);
eval += feval;
@ -138,12 +138,12 @@ acb_calc_integrate(acb_t res, acb_calc_func_t f, void * param,
if (feval > 0)
{
if (real_error)
arb_zero(acb_imagref(t));
arb_zero(acb_imagref(u));
acb_add(s, s, t, prec);
acb_add(s, s, u, prec);
/* Adjust absolute tolerance based on new information. */
acb_get_mag_lower(tmpm, t);
acb_get_mag_lower(tmpm, u);
mag_mul_2exp_si(tmpm, tmpm, -goal);
mag_max(new_tol, new_tol, tmpm);

View file

@ -35,10 +35,9 @@ Types, macros and constants
coefficients in *out* to non-finite values otherwise.
For algorithms that do not rely on derivatives, *func* will always
get called with *order* = 0, in which case the user only needs to
implement evaluation of the single function value `f(z)`.
In the special case *order* = 1, the user only needs to implement
evaluation of `f(z)` (without derivatives), but must verify
get called with *order* = 0 or *order* = 1, in which case the user
only needs to implement evaluation of the direct function value `f(z)`
(without derivatives). With *order* = 1, *func* must verify
holomorphicity (unlike the *order* = 0 case).
If *f* is built from field operations and meromorphic functions, then
@ -189,7 +188,7 @@ Integration
- *eval_limit* - maximum number of function evaluations.
If a zero or negative value is provided, the limit is set to a default
value which currently equals `1000 \cdot \text{prec}`.
value which currently equals `1000 \cdot \text{prec} + \text{prec}^2`.
This is the main parameter used to limit the amount of work before
aborting due to possible slow convergence or non-convergence.

View file

@ -285,19 +285,59 @@ f_exp(acb_ptr res, const acb_t z, void * param, slong order, slong prec)
return 0;
}
/* f(z) = exp(-z^2) */
int
f_gaussian(acb_ptr res, const acb_t z, void * param, slong order, slong prec)
{
if (order > 1)
flint_abort(); /* Would be needed for Taylor method. */
acb_mul(res, z, z, prec);
acb_neg(res, res);
acb_exp(res, res, prec);
return 0;
}
int
f_monster(acb_ptr res, const acb_t z, void * param, slong order, slong prec)
{
acb_t t;
if (order > 1)
flint_abort(); /* Would be needed for Taylor method. */
acb_init(t);
acb_exp(t, z, prec);
acb_holomorphic_floor(res, t, order != 0, prec);
if (acb_is_finite(res))
{
acb_sub(res, t, res, prec);
acb_add(t, t, z, prec);
acb_sin(t, t, prec);
acb_mul(res, res, t, prec);
}
acb_clear(t);
return 0;
}
/* ------------------------------------------------------------------------- */
/* Main test program */
/* ------------------------------------------------------------------------- */
#define NUM_INTEGRALS 13
#define NUM_INTEGRALS 15
const char * descr[NUM_INTEGRALS] =
{
"int_0^100 sin(x) dx",
"4 int_0^1 1/(1+x^2) dx",
"4 int_1^{10^100} 1/(1+x^2) dx",
"2 int_0^{inf} 1/(1+x^2) dx (using domain truncation)",
"4 int_0^1 sqrt(1-x^2) dx",
"4 int_0^8 sin(x+exp(x)) dx",
"int_0^8 sin(x+exp(x)) dx",
"int_0^100 floor(x) dx",
"int_0^1 |x^4+10x^3+19x^2-6x-6| exp(x) dx",
"1/(2 pi i) int zeta(s) ds (closed path around s = 1)",
@ -306,6 +346,8 @@ const char * descr[NUM_INTEGRALS] =
"int_1^{1+1000i} gamma(x) dx",
"int_{-10}^{10} sin(x) + exp(-200-x^2) dx",
"int_{-1020}^{-1000} exp(x) dx (use -tol 0 for relative error)",
"int_0^{inf} exp(-x^2) dx (using domain truncation)",
"int_0^8 (exp(x)-floor(exp(x))) sin(x+exp(x)) dx (use higher -eval)",
};
int main(int argc, char *argv[])
@ -415,11 +457,12 @@ int main(int argc, char *argv[])
break;
case 2:
acb_set_d(a, 1);
acb_set_ui(b, 10);
acb_pow_ui(b, b, 100, prec);
acb_set_d(a, 0);
acb_one(b);
acb_mul_2exp_si(b, b, goal);
acb_calc_integrate(s, f_atanderiv, NULL, a, b, goal, tol, deg_limit, eval_limit, depth_limit, flags, prec);
acb_mul_2exp_si(s, s, 2);
arb_add_error_2exp_si(acb_realref(s), -goal);
acb_mul_2exp_si(s, s, 1);
break;
case 3:
@ -506,6 +549,22 @@ int main(int argc, char *argv[])
acb_calc_integrate(s, f_exp, NULL, a, b, goal, tol, deg_limit, eval_limit, depth_limit, flags, prec);
break;
case 13:
acb_set_d(a, 0);
acb_set_d(b, ceil(sqrt(goal * 0.693147181) + 1.0));
acb_calc_integrate(s, f_gaussian, NULL, a, b, goal, tol, deg_limit, eval_limit, depth_limit, flags, prec);
acb_mul(b, b, b, prec);
acb_neg(b, b);
acb_exp(b, b, prec);
arb_add_error(acb_realref(s), acb_realref(b));
break;
case 14:
acb_set_d(a, 0.0);
acb_set_d(b, 8.0);
acb_calc_integrate(s, f_monster, NULL, a, b, goal, tol, deg_limit, eval_limit, depth_limit, flags, prec);
break;
default:
abort();
}