14 double integrate_1d(
const function_type &
fcn,
const double &min,
const double &max, gsl_integration_workspace *ws =
nullptr) {
15 gsl_integration_workspace *w = (ws ==
nullptr) ? gsl_integration_workspace_alloc(1000) : ws;
20 if constexpr(is_functor<function_type, double(
const double &)>::value) {
21 F.function = [](
double x,
void *p) ->
double {
return (*
static_cast<function_type *
>(p))(x); };
22 }
else if constexpr(is_functor<function_type, double(
const std::array<double, 1> &)>::value) {
23 F.function = [](
double x,
void *p) ->
double {
return (*
static_cast<function_type *
>(p))(std::array<double, 1>{x}); };
25 static_assert(
true,
"function matches no signature!");
27 F.params =
const_cast<function_type *
>(&
fcn);
28 gsl_integration_qags(&F, min, max, 0, 1e-5, 1000, w, &result, &error);
29 if(ws ==
nullptr) gsl_integration_workspace_free(w);
32 template <
typename function_type>
double integrate_1d_inf(
const function_type &
fcn, gsl_integration_workspace *ws =
nullptr) {
33 gsl_integration_workspace *w = (ws ==
nullptr) ? gsl_integration_workspace_alloc(1000) : ws;
37 F.function = [](
double x,
void *p) ->
double {
return (*
static_cast<function_type *
>(p))(x); };
38 F.params =
const_cast<function_type *
>(&
fcn);
39 gsl_integration_qagi(&F, 0, 1e-5, 1000, w, &result, &error);
40 if(ws ==
nullptr) gsl_integration_workspace_free(w);
46 double integrate_1d_cauchy(
const function_type &
fcn,
const double &x0,
const double &min,
const double &max, gsl_integration_workspace *ws =
nullptr) {
47 gsl_integration_workspace *w = (ws ==
nullptr) ? gsl_integration_workspace_alloc(1000) : ws;
51 F.function = [](
double x,
void *p) ->
double {
return (*
static_cast<function_type *
>(p))(x); };
52 F.params =
const_cast<function_type *
>(&
fcn);
53 gsl_integration_qawc(&F, min, max, x0, 0, 1e-8, 1000, w, &result, &error);
54 if(ws ==
nullptr) gsl_integration_workspace_free(w);
75 template <
unsigned dim,
typename fcn>
double integrate(
const fcn &F,
const std::array<double, dim> xmin,
const std::array<double, dim> &xmax) {
87 if constexpr(dim == 1) {
88 if constexpr(is_functor<
fcn, double(
const double &)>::value) {
90 }
else if constexpr(is_functor<
fcn, double(
const std::array<double, 1> &)>::value) {
91 return integrate_1d([&F](
const double &x) {
return F(std::array<double, 1>{x}); }, xmin[0], xmax[0]);
93 static_assert(
true,
"1D function doesn't have recognised signature");
96 double epsrel = 1e-10;
105 unsigned int ifncls = 0;
110 constexpr unsigned irlcls = get_power<2, dim>::value + 2 * dim * (dim + 1) + 1;
111 constexpr unsigned minpts = get_power<2, dim>::value + 2 * dim * (dim + 1) + 1;
112 constexpr unsigned maxpts = 1000000;
114 std::array<integral<dim>, (1 + maxpts / irlcls) / 2> partial_integrals;
118 for(
unsigned j = 0; j < dim; j++) {
119 current_integral->a[j] = (xmax[j] + xmin[j]) * 0.5;
120 current_integral->b[j] = (xmax[j] - xmin[j]) * 0.5;
123 unsigned int idvax0 = 0;
127 auto [rgnval, rgnerr, idvaxn] =
integrate_fp<dim>(F, current_integral->a, current_integral->b);
132 double aresult = std::abs(result);
136 tmp.
a = current_integral->a;
137 tmp.
b = current_integral->b;
143 if(isbtmp > isbrgs)
break;
144 if(isbtmp < isbrgs && partial_integrals[isbtmp].var < partial_integrals[isbtmp + 1].var) isbtmp++;
145 if(rgnerr >= partial_integrals[isbtmp].var)
break;
146 partial_integrals[isbrgn] = partial_integrals[isbtmp];
153 if(isbtmp >= 1 && rgnerr > partial_integrals[isbtmp].var) {
154 partial_integrals[isbrgn] = partial_integrals[isbtmp];
157 }
while(isbtmp >= 1 && rgnerr > partial_integrals[isbtmp].var);
160 partial_integrals[isbrgn] = tmp;
163 current_integral = &(partial_integrals[isbrgn]);
166 partial_integrals[isbrgn].a = current_integral->a;
167 partial_integrals[isbrgn].b = current_integral->b;
168 partial_integrals[isbrgn].a[idvax0] += 2 * current_integral->b[idvax0];
169 current_integral = &(partial_integrals[isbrgn]);
173 relerr = std::abs(result) == 0 ? abserr : abserr / std::abs(result);
174 if((relerr < epsrel && aresult < epsabs) or ((relerr < epsrel || abserr < epsabs) && ifncls > minpts)) {
178 if((isbrgs >= partial_integrals.size() - 1) or (ifncls + 2 * irlcls > maxpts)) {
185 current_integral = &(partial_integrals[isbrgn]);
187 abserr -= current_integral->var;
188 result -= current_integral->value;
189 idvax0 = current_integral->index;
191 current_integral->b[idvax0] *= 0.5;
192 current_integral->a[idvax0] -= current_integral->b[idvax0];
193 }
while(status == 3);
std::tuple< double, double, unsigned > integrate_fp(const fcn &F, const std::array< double, dim > &ctr, const std::array< double, dim > &wth)
std::tuple< double, double, unsigned > integrate_fp_scalar(const fcn &F, const std::array< double, dim > &ctr, const std::array< double, dim > &wth)