24 #ifndef O2SCL_GSL_INTE_QAWO_H
25 #define O2SCL_GSL_INTE_QAWO_H
32 #include <o2scl/inte.h>
33 #include <o2scl/inte_qawc_gsl.h>
35 #ifndef DOXYGEN_NO_O2NS
80 virtual int integ_err(func_t &func,
double a,
double b,
81 double &res,
double &err) {
83 otable=gsl_integration_qawo_table_alloc
87 this->
w,this->
otable,&res,&err);
89 gsl_integration_qawo_table_free(
otable);
94 #ifndef DOXYGEN_INTERNAL
105 int qawo(func_t &func,
const double a,
const double epsabs,
107 gsl_integration_qawo_table *wf,
double *result,
double *abserr) {
110 double res_ext, err_ext;
111 double result0=0.0, abserr0=0.0, resabs0=0.0, resasc0=0.0;
115 double error_over_large_intervals = 0;
116 double reseps = 0, abseps = 0, correc = 0;
118 int roundoff_type1 = 0, roundoff_type2 = 0, roundoff_type3 = 0;
119 int error_type = 0, error_type2 = 0;
121 size_t iteration = 0;
123 int positive_integrand = 0;
126 int disallow_extrapolation = 0;
130 double b = a + wf->L ;
131 double abs_omega = fabs (wf->omega) ;
140 size_t limit=this->
w->
limit;
144 double dbl_eps=std::numeric_limits<double>::epsilon();
146 if (epsabs <= 0 && (epsrel < 50 * dbl_eps || epsrel < 0.5e-28)) {
148 std::string estr=
"Tolerance cannot be achieved with given ";
149 estr+=
"value of tol_abs, "+
dtos(epsabs)+
", and tol_rel, "+
150 dtos(epsrel)+
", in inte_qawo_gsl_sin::qawo().";
156 this->
qc25f(func, a, b, wf, 0,
157 &result0, &abserr0, &resabs0, &resasc0);
161 tolerance = GSL_MAX_DBL (epsabs, epsrel * fabs (result0));
164 std::cout <<
"inte_qawo_gsl Iter: " << 1;
165 std::cout.setf(std::ios::showpos);
166 std::cout <<
" Res: " << result0;
167 std::cout.unsetf(std::ios::showpos);
168 std::cout <<
" Err: " << abserr0
169 <<
" Tol: " << tolerance << std::endl;
172 std::cout <<
"Press a key and type enter to continue. " ;
177 if (abserr0 <= 100 * GSL_DBL_EPSILON * resabs0 &&
178 abserr0 > tolerance) {
183 std::string estr=
"Cannot reach tolerance because of roundoff error ";
184 estr+=
"on first attempt in inte_qawo_gsl_sin::qawo().";
186 }
else if ((abserr0 <= tolerance && abserr0 != resasc0) ||
193 }
else if (limit == 1) {
198 std::string estr=
"A maximum of 1 iteration was insufficient ";
199 estr+=
"in inte_qawo_gsl_sin::qawo().";
207 if (0.5 * abs_omega * fabs(b - a) <= 2) {
216 err_ext = GSL_DBL_MAX;
224 size_t current_level;
225 double a1, b1, a2, b2;
226 double a_i, b_i, r_i, e_i;
227 double area1 = 0, area2 = 0, area12 = 0;
228 double error1 = 0, error2 = 0, error12 = 0;
229 double resasc1=0.0, resasc2=0.0;
230 double resabs1=0.0, resabs2=0.0;
235 loc_w->
retrieve (&a_i, &b_i, &r_i, &e_i);
237 current_level = loc_w->
level[loc_w->
i] + 1;
239 if (current_level >= wf->n) {
245 b1 = 0.5 * (a_i + b_i);
251 qc25f(func, a1, b1, wf, current_level,
252 &area1, &error1, &resabs1, &resasc1);
253 qc25f(func, a2, b2, wf, current_level,
254 &area2, &error2, &resabs2, &resasc2);
256 area12 = area1 + area2;
257 error12 = error1 + error2;
267 errsum = errsum + error12 - e_i;
268 area = area + area12 - r_i;
270 tolerance = GSL_MAX_DBL (epsabs, epsrel * fabs (area));
273 std::cout <<
"inte_qawo_gsl Iter: " << iteration;
274 std::cout.setf(std::ios::showpos);
275 std::cout <<
" Res: " << area;
276 std::cout.unsetf(std::ios::showpos);
277 std::cout <<
" Err: " << errsum
278 <<
" Tol: " << tolerance << std::endl;
281 std::cout <<
"Press a key and type enter to continue. " ;
286 if (resasc1 != error1 && resasc2 != error2) {
288 double delta = r_i - area12;
290 if (fabs (delta) <= 1.0e-5 * fabs (area12) &&
291 error12 >= 0.99 * e_i) {
300 if (iteration > 10 && error12 > e_i) {
307 if (roundoff_type1 + roundoff_type2 >= 10 || roundoff_type3 >= 20) {
311 if (roundoff_type2 >= 5) {
324 loc_w->
update (a1, b1, area1, error1, a2, b2, area2, error2);
326 if (errsum <= tolerance) {
334 if (iteration >= limit - 1) {
341 if (iteration == 2 && extall) {
342 error_over_large_intervals = errsum;
348 if (disallow_extrapolation) {
353 error_over_large_intervals += -last_e_i;
355 if (current_level < loc_w->maximum_level)
357 error_over_large_intervals += error12;
376 double width = loc_w->
blist[i] - loc_w->
alist[i];
378 if (0.25 * fabs(width) * abs_omega > 2) {
383 error_over_large_intervals = errsum;
390 if (!error_type2 && error_over_large_intervals > ertest) {
403 error_over_large_intervals = errsum;
407 this->
qelg (&table, &reseps, &abseps);
411 if (ktmin > 5 && err_ext < 0.001 * errsum) {
415 if (abseps < err_ext) {
419 correc = error_over_large_intervals;
420 ertest = GSL_MAX_DBL (epsabs, epsrel * fabs (reseps));
421 if (err_ext <= ertest) {
429 disallow_extrapolation = 1;
432 if (error_type == 5) {
440 error_over_large_intervals = errsum;
442 }
while (iteration < limit);
447 if (err_ext == GSL_DBL_MAX)
450 if (error_type || error_type2) {
459 if (result != 0 && area != 0) {
460 if (err_ext / fabs (res_ext) > errsum / fabs (area)) {
463 }
else if (err_ext > errsum) {
465 }
else if (area == 0.0) {
473 double max_area = GSL_MAX_DBL (fabs (res_ext), fabs (area));
475 if (!positive_integrand && max_area < 0.01 * resabs0) {
481 double ratio = res_ext / area;
483 if (ratio < 0.01 || ratio > 100 || errsum > fabs (area)) {
497 if (error_type > 2) {
503 if (error_type == 0) {
505 }
else if (error_type == 1) {
506 std::string estr=
"Number of iterations was insufficient ";
507 estr+=
" in inte_qawo_gsl_sin::qawo().";
509 }
else if (error_type == 2) {
510 std::string estr=
"Roundoff error prevents tolerance ";
511 estr+=
"from being achieved in inte_qawo_gsl_sin::qawo().";
513 }
else if (error_type == 3) {
514 std::string estr=
"Bad integrand behavior ";
515 estr+=
" in inte_qawo_gsl_sin::qawo().";
517 }
else if (error_type == 4) {
518 std::string estr=
"Roundoff error detected in extrapolation table ";
519 estr+=
"in inte_qawo_gsl_sin::qawo().";
521 }
else if (error_type == 5) {
522 std::string estr=
"Integral is divergent or slowly convergent ";
523 estr+=
"in inte_qawo_gsl_sin::qawo().";
525 }
else if (error_type == -1) {
526 std::string estr=
"Exceeded limit of trigonometric table ";
527 estr+=
"inte_qawo_gsl_sin::qawo()";
530 std::string estr=
"Could not integrate function in inte_qawo_gsl";
531 estr+=
"::qawo() (it may have returned a non-finite result).";
538 void qc25f(func_t &func,
double a,
double b,
539 gsl_integration_qawo_table *wf,
size_t level,
540 double *result,
double *abserr,
double *resabs,
543 const double center = 0.5 * (a + b);
544 const double half_length = 0.5 * (b - a);
546 const double par =
omega * half_length;
548 if (fabs (par) < 2) {
557 double cheb12[13], cheb24[25];
558 double result_abs, res12_cos, res12_sin, res24_cos, res24_sin;
559 double est_cos, est_sin;
565 if (level >= wf->n) {
567 O2SCL_ERR(
"Table overflow in inte_qawo_gsl::qc25f().",
574 moment = wf->chebmo + 25 * level;
576 res12_cos = cheb12[12] * moment[12];
579 for (i = 0; i < 6; i++) {
580 size_t k = 10 - 2 * i;
581 res12_cos += cheb12[k] * moment[k];
582 res12_sin += cheb12[k + 1] * moment[k + 1];
585 res24_cos = cheb24[24] * moment[24];
588 result_abs = fabs(cheb24[24]) ;
590 for (i = 0; i < 12; i++) {
591 size_t k = 22 - 2 * i;
592 res24_cos += cheb24[k] * moment[k];
593 res24_sin += cheb24[k + 1] * moment[k + 1];
594 result_abs += fabs(cheb24[k]) + fabs(cheb24[k+1]);
597 est_cos = fabs(res24_cos - res12_cos);
598 est_sin = fabs(res24_sin - res12_sin);
600 c = half_length * cos(center *
omega);
601 s = half_length * sin(center * omega);
603 if (wf->sine == GSL_INTEG_SINE) {
604 *result = c * res24_sin + s * res24_cos;
605 *abserr = fabs(c * est_sin) + fabs(s * est_cos);
607 *result = c * res24_cos - s * res24_sin;
608 *abserr = fabs(c * est_cos) + fabs(s * est_sin);
611 *resabs = result_abs * half_length;
612 *resasc = GSL_DBL_MAX;
620 return func(t)*sin(this->
omega*t);
626 const char *
type() {
return "inte_qawo_gsl_sin"; }
656 double &res,
double &err) {
658 this->
otable=gsl_integration_qawo_table_alloc
662 this->
w,this->
otable,&res,&err);
664 gsl_integration_qawo_table_free(this->
otable);
669 #ifndef DOXYGEN_INTERNAL
675 return func(t)*cos(this->
omega*t);
681 const char *
type() {
return "inte_qawo_gsl_cos"; }
685 #ifndef DOXYGEN_NO_O2NS
const char * type()
Return string denoting type ("inte_qawo_gsl_cos")
virtual int integ_err(func_t &func, double a, double b, double &res, double &err)
Integrate function func from a to b and place the result in res and the error in err.
Integration workspace for the GSL integrators.
int qawo(func_t &func, const double a, const double epsabs, const double epsrel, inte_workspace_gsl *loc_w, gsl_integration_qawo_table *wf, double *result, double *abserr)
The full GSL integration routine called by integ_err()
void initialise_table(struct extrapolation_table *table)
Initialize the table.
#define O2SCL_CONV_RET(d, n, b)
Set a "convergence" error and return the error value.
double * alist
Left endpoints of subintervals.
void inte_cheb_series(func2_t &f, double a, double b, double *cheb12, double *cheb24)
Compute Chebyshev series expansion using a FFT method.
double * blist
Right endpoints of subintervals.
double omega
The user-specified frequency (default 1.0)
sanity check failed - shouldn't happen
size_t * level
Numbers of subdivisions made.
void append_table(struct extrapolation_table *table, double y)
Append a result to the table.
apparent singularity detected
exceeded max number of iterations
int large_interval(inte_workspace_gsl *workspace)
Determine if an interval is large.
size_t last_iter
The most recent number of iterations taken.
bool err_nonconv
If true, call the error handler if the routine does not converge or reach the desired tolerance (defa...
table table limit exceeded
int update(double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
Determine which new subinterval to add to the workspace stack and perform update. ...
size_t n_levels
The number of bisection levels (default 10)
size_t i
Index of current subinterval.
virtual int integ_err(func_t &func, double a, double b, double &res, double &err)
Integrate function func from a to b and place the result in res and the error in err.
Chebyshev integration base class (GSL)
int subinterval_too_small(double a1, double a2, double b2)
Test whether the proposed subdivision falls before floating-point precision.
double tol_abs
The maximum absolute uncertainty in the value of the integral (default )
int test_positivity(double result, double resabs)
Test if the integrand satisfies .
int initialise(double a, double b)
Initialize the workspace for an integration with limits a and b.
int set_initial_result(double result, double error)
Update the workspace with the result and error from the first integration.
const char * type()
Return string denoting type ("inte_qawo_gsl_sin")
std::string dtos(double x, int prec=6, bool auto_prec=false)
Convert a double to a string.
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
virtual double transform(double t, func_t &func)
Add the oscillating part to the integrand.
int retrieve(double *a, double *b, double *r, double *e) const
Retrieve the ith result from the workspace stack.
size_t nrmax
Counter for extrapolation routine.
void qelg(struct extrapolation_table *table, double *result, double *abserr)
Determines the limit of a given sequence of approximations.
inte_workspace_gsl * w
The integration workspace.
double sum_results()
Add up all of the contributions to construct the final result.
double tol_rel
The maximum relative uncertainty in the value of the integral (default )
virtual double transform(double t, func_t &func)
Add the oscillating part to the integrand.
void reset_nrmax(inte_workspace_gsl *workspace)
Reset workspace to work on the interval with the largest error.
int increase_nrmax(inte_workspace_gsl *workspace)
Increase workspace.
Adaptive integration a function with finite limits of integration (GSL)
size_t limit
Maximum number of subintervals allocated.
user specified an invalid tolerance
Adaptive integration for oscillatory integrals (GSL)
void qc25f(func_t &func, double a, double b, gsl_integration_qawo_table *wf, size_t level, double *result, double *abserr, double *resabs, double *resasc)
25-point quadrature for oscillating functions
gsl_integration_qawo_table * otable
The integration workspace.
failed because of roundoff error
integral or series is divergent