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); depth_limit = FLINT_MAX(depth_limit, 1);
if (eval_limit <= 0) if (eval_limit <= 0)
eval_limit = 1000 * prec; eval_limit = 1000 * prec + prec * prec;
eval_limit = FLINT_MAX(eval_limit, 1); eval_limit = FLINT_MAX(eval_limit, 1);
goal = FLINT_MAX(goal, 0); 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. */ /* We know that the result is real. */
real_error = acb_is_finite(t) && acb_is_real(t); 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); bs + depth - 1, new_tol, deg_limit, flags, prec);
eval += feval; eval += feval;
@ -138,12 +138,12 @@ acb_calc_integrate(acb_t res, acb_calc_func_t f, void * param,
if (feval > 0) if (feval > 0)
{ {
if (real_error) 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. */ /* 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_mul_2exp_si(tmpm, tmpm, -goal);
mag_max(new_tol, new_tol, tmpm); 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. coefficients in *out* to non-finite values otherwise.
For algorithms that do not rely on derivatives, *func* will always For algorithms that do not rely on derivatives, *func* will always
get called with *order* = 0, in which case the user only needs to get called with *order* = 0 or *order* = 1, in which case the user
implement evaluation of the single function value `f(z)`. only needs to implement evaluation of the direct function value `f(z)`
In the special case *order* = 1, the user only needs to implement (without derivatives). With *order* = 1, *func* must verify
evaluation of `f(z)` (without derivatives), but must verify
holomorphicity (unlike the *order* = 0 case). holomorphicity (unlike the *order* = 0 case).
If *f* is built from field operations and meromorphic functions, then If *f* is built from field operations and meromorphic functions, then
@ -189,7 +188,7 @@ Integration
- *eval_limit* - maximum number of function evaluations. - *eval_limit* - maximum number of function evaluations.
If a zero or negative value is provided, the limit is set to a default 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 This is the main parameter used to limit the amount of work before
aborting due to possible slow convergence or non-convergence. 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; 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 */ /* Main test program */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#define NUM_INTEGRALS 13 #define NUM_INTEGRALS 15
const char * descr[NUM_INTEGRALS] = const char * descr[NUM_INTEGRALS] =
{ {
"int_0^100 sin(x) dx", "int_0^100 sin(x) dx",
"4 int_0^1 1/(1+x^2) 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^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^100 floor(x) dx",
"int_0^1 |x^4+10x^3+19x^2-6x-6| exp(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)", "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_1^{1+1000i} gamma(x) dx",
"int_{-10}^{10} sin(x) + exp(-200-x^2) dx", "int_{-10}^{10} sin(x) + exp(-200-x^2) dx",
"int_{-1020}^{-1000} exp(x) dx (use -tol 0 for relative error)", "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[]) int main(int argc, char *argv[])
@ -415,11 +457,12 @@ int main(int argc, char *argv[])
break; break;
case 2: case 2:
acb_set_d(a, 1); acb_set_d(a, 0);
acb_set_ui(b, 10); acb_one(b);
acb_pow_ui(b, b, 100, prec); 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_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; break;
case 3: 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); acb_calc_integrate(s, f_exp, NULL, a, b, goal, tol, deg_limit, eval_limit, depth_limit, flags, prec);
break; 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: default:
abort(); abort();
} }