42 #ifndef GSL_INTE_QAWS_H
43 #define GSL_INTE_QAWS_H
49 #include <o2scl/inte_qawc_gsl.h>
51 #ifndef DOXYGEN_NO_O2NS
84 #ifndef DOXYGEN_INTERNAL
110 const double alpha_p1 = this->alpha + 1.0;
111 const double beta_p1 = this->beta + 1.0;
113 const double alpha_p2 = this->alpha + 2.0;
114 const double beta_p2 = this->beta + 2.0;
116 const double r_alpha = pow (2.0, alpha_p1);
117 const double r_beta = pow (2.0,beta_p1);
123 this->ri[0] = r_alpha / alpha_p1;
124 this->ri[1] = this->ri[0] * this->alpha / alpha_p2;
129 for (i = 2; i < 25; i++) {
130 this->ri[i] = -(r_alpha + an * (an - alpha_p2) * this->ri[i - 1])
131 / (anm1 * (an + alpha_p1));
136 rj[0] = r_beta / beta_p1;
137 rj[1] = rj[0] * this->beta / beta_p2;
142 for (i = 2; i < 25; i++) {
143 rj[i] = (-(r_beta + an * (an - beta_p2) * rj[i - 1])
144 / (anm1 * (an + beta_p1)));
149 this->rg[0] = -this->ri[0] / alpha_p1;
150 this->rg[1] = -this->rg[0] - 2.0 * r_alpha / (alpha_p2 * alpha_p2);
155 for (i = 2; i < 25; i++) {
156 this->rg[i] = (-(an * (an - alpha_p2) *
157 this->rg[i - 1] - an * this->ri[i - 1]
158 + anm1 * this->ri[i])
159 / (anm1 * (an + alpha_p1)));
164 this->rh[0] = -this->rj[0] / beta_p1;
165 this->rh[1] = -this->rh[0] - 2.0 * r_beta / (beta_p2 * beta_p2);
170 for (i = 2; i < 25; i++) {
171 this->rh[i] = (-(an * (an - beta_p2) *
172 this->rh[i - 1] - an * this->rj[i - 1]
173 + anm1 * this->rj[i])
174 / (anm1 * (an + beta_p1)));
179 for (i = 1; i < 25; i += 2) {
207 double factor = 1.0,y;
227 return func(t)*factor;
234 void qc25s(func_t &func,
double a,
double b,
double a1,
double b1,
235 double &result,
double &abserr,
int &err_reliable) {
239 std::bind(std::mem_fn<
double(
double,func_t &)>
241 this,std::placeholders::_1,func);
246 if (a1 == a && (this->alpha != 0.0 || this->mu != 0)) {
248 double cheb12[13], cheb24[25];
250 double factor = pow(0.5 * (b1 - a1),this->alpha + 1.0);
259 double res12 = 0,res24 = 0;
265 abserr = fabs(u * (res24 - res12));
269 double res12a = 0,res24a = 0;
270 double res12b = 0,res24b = 0;
272 double u = factor * log(b1 - a1);
278 result = u * res24a + v * res24b;
279 abserr = fabs(u*(res24a - res12a)) + fabs(v*(res24b - res12b));
285 }
else if (b1 == b && (this->beta != 0.0 || this->nu != 0)) {
287 double cheb12[13], cheb24[25];
288 double factor = pow(0.5 * (b1 - a1), this->beta + 1.0);
298 double res12 = 0, res24 = 0;
304 abserr = fabs(u * (res24 - res12));
308 double res12a = 0, res24a = 0;
309 double res12b = 0, res24b = 0;
311 double u = factor * log(b1 - a1);
317 result = u * res24a + v * res24b;
318 abserr = fabs(u*(res24a - res12a)) + fabs(v*(res24b - res12b));
326 double resabs, resasc;
332 this->
gauss_kronrod(func,a1,b1,&result,&abserr,&resabs,&resasc);
334 if (abserr == resasc) {
348 double &result12,
double &result24) {
354 for (i = 0; i < 13; i++) {
355 result12 += r[i] * cheb12[i];
358 for (i = 0; i < 25; i++) {
359 result24 += r[i] * cheb24[i];
394 int set_weight(
double u_alpha,
double u_beta,
int u_mu,
int u_nu) {
396 if (u_alpha < -1.0) {
397 std::string estr=((std::string)
"Variable alpha must be ")+
398 "greater than -1.0 in inte_qaws_gsl().";
402 std::string estr=((std::string)
"Variable beta must be ")+
403 "greater than -1.0 in inte_qaws_gsl().";
406 if (u_mu != 0 && u_mu != 1) {
407 std::string estr=((std::string)
"Variable mu must be 0 or 1 ")+
408 "in inte_qaws_gsl().";
411 if (u_nu != 0 && u_nu != 1) {
412 std::string estr=((std::string)
"Variable nu must be 0 or 1 ")+
413 "in inte_qaws_gsl().";
417 this->alpha = u_alpha;
429 void get_weight(
double &u_alpha,
double &u_beta,
int &u_mu,
int &u_nu) {
430 u_alpha = this->alpha;
440 double &result,
double &abserr) {
443 double result0, abserr0;
446 int roundoff_type1 = 0, roundoff_type2 = 0, error_type = 0;
455 size_t limit=this->
w->
limit;
458 std::string estr=
"Integration limits, a="+
dtos(a);
459 estr+=
" and b="+
dtos(b)+
", must satisfy a < b";
460 estr+=
" in inte_qaws_gsl::gsl_qaws().";
464 double dbl_eps=std::numeric_limits<double>::epsilon();
469 std::string estr=
"Tolerance cannot be achieved with given ";
470 estr+=
"value of tol_abs, "+
dtos(this->
tol_abs)+
", and tol_rel, "+
471 dtos(this->
tol_rel)+
", in inte_qaws_gsl::integ_err().";
479 double error1, error2;
480 int err_reliable1, err_reliable2;
482 double b1 = 0.5 * (a + b);
486 this->
qc25s(func, a, b, a1, b1, area1, error1, err_reliable1);
487 this->
qc25s(func, a, b, a2, b2, area2, error2, err_reliable2);
491 if (error1 > error2) {
499 result0 = area1 + area2;
500 abserr0 = error1 + error2;
505 tolerance = GSL_MAX_DBL (this->
tol_abs, this->
tol_rel * fabs (result0));
510 if (abserr0 < tolerance && abserr0 < 0.01 * fabs(result0)) {
514 }
else if (limit == 1) {
518 std::string estr =
"A maximum of 1 iteration was insufficient ";
519 estr +=
"in inte_qaws_gsl::gsl_qaws().";
527 double a1, b1, a2, b2;
528 double a_i, b_i, r_i, e_i;
529 double area1 = 0, area2 = 0, area12 = 0;
530 double error1 = 0, error2 = 0, error12 = 0;
531 int err_reliable1, err_reliable2;
537 b1 = 0.5 * (a_i + b_i);
541 qc25s(func, a, b, a1, b1, area1, error1, err_reliable1);
542 qc25s(func, a, b, a2, b2, area2, error2, err_reliable2);
544 area12 = area1 + area2;
545 error12 = error1 + error2;
547 errsum += (error12 - e_i);
548 area += area12 - r_i;
550 if (err_reliable1 && err_reliable2) {
552 double delta = r_i - area12;
554 if (fabs(delta) <= 1.0e-5 * fabs (area12)
555 && error12 >= 0.99 * e_i) {
558 if (this->
last_iter >= 10 && error12 > e_i) {
563 tolerance = GSL_MAX_DBL (this->
tol_abs, this->
tol_rel * fabs (area));
565 if (errsum > tolerance) {
566 if (roundoff_type1 >= 6 || roundoff_type2 >= 20) {
578 this->
w->
update(a1, b1, area1, error1, a2, b2, area2, error2);
582 }
while (this->last_iter < this->
w->
limit
583 && !error_type && errsum > tolerance);
589 if (errsum <= tolerance) {
591 }
else if (error_type == 2) {
592 std::string estr=
"Round-off error prevents tolerance ";
593 estr+=
"from being achieved in inte_qaws_gsl::gsl_qaws().";
595 }
else if (error_type == 3) {
596 std::string estr=
"Bad integrand behavior ";
597 estr+=
" in inte_qaws_gsl::gsl_qaws().";
600 std::string estr=
"Maximum number of subdivisions ("+
itos(limit);
601 estr+=
") reached in inte_qaws_gsl::gsl_qaws().";
604 std::string estr=
"Could not integrate function in ";
605 estr+=
"inte_qaws_gsl::gsl_qaws().";
614 const char *
type() {
return "inte_qaws_gsl"; }
618 #ifndef DOXYGEN_NO_O2NS
virtual int integ_err(func_t &func, double a, double b, double &result, double &abserr)
Integrate the function func on the interval (a, b) returning the result and error estimate abserr...
bool fn_qaws_L
True if algebraic-logarithmic singularity is present at the left endpoint in the definition f_trans...
bool fn_qaws_R
True if algebraic-logarithmic singularity is present at the right endpoint in the definition f_trans...
void get_weight(double &u_alpha, double &u_beta, int &u_mu, int &u_nu)
Returns the current values (via reference) of the weight-function's parameters.
#define O2SCL_CONV_RET(d, n, b)
Set a "convergence" error and return the error value.
std::function< double(double)> funct11
One-dimensional function typedef.
double left_endpoint
Left endpoint in definition of f_trans.
void inte_cheb_series(func2_t &f, double a, double b, double *cheb12, double *cheb24)
Compute Chebyshev series expansion using a FFT method.
invalid argument supplied by user
apparent singularity detected
exceeded max number of iterations
Adaptive integration with with algebraic-logarithmic singularities at the end-points (GSL) ...
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...
double right_endpoint
Right endpoint in definition of f_trans.
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. ...
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 set_weight(double u_alpha, double u_beta, int u_mu, int u_nu)
Sets the exponents of singularites of the weight function.
int initialise(double a, double b)
Initialize the workspace for an integration with limits a and b.
std::string dtos(double x, int prec=6, bool auto_prec=false)
Convert a double to a string.
inte_qaws_gsl()
Initialize the adptive workspace as with the constructor inte_qag_gsl::inte_qag_gsl.
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
virtual double transform(double t, func_t &func)
Weighted integrand.
void compute_result(double *r, double *cheb12, double *cheb24, double &result12, double &result24)
Compute the 13-point and 25-point approximations from the Chebyshev moments and coefficients.
double interror
The uncertainty for the last integration computation.
int retrieve(double *a, double *b, double *r, double *e) const
Retrieve the ith result from the workspace stack.
void append_interval(double a1, double b1, double area1, double error1)
Push a new interval to the workspace stack.
inte_workspace_gsl * w
The integration workspace.
double sum_results()
Add up all of the contributions to construct the final result.
void qc25s(func_t &func, double a, double b, double a1, double b1, double &result, double &abserr, int &err_reliable)
Clenshaw-Curtis 25-point integration and error estimator for functions with an algebraic-logarithmic ...
double tol_rel
The maximum relative uncertainty in the value of the integral (default )
size_t limit
Maximum number of subintervals allocated.
const char * type()
Return string denoting type ("inte_qaws_gsl")
std::string itos(int x)
Convert an integer to a string.
user specified an invalid tolerance
failed because of roundoff error
void initialise_qaws_table()
Set the array values ri, rj, rg, rh from the current values alpha and beta.