AmpGen 2.1
Loading...
Searching...
No Matches
integrate_fp.h
Go to the documentation of this file.
1#ifndef AMPGEN_INTEGRATE_FP
2#define AMPGEN_INTEGRATE_FP 1
3
4#include <tuple>
5#include "AmpGen/simd/utils.h"
6#include "AmpGen/MetaUtils.h"
7
8namespace AmpGen {
10 static const double xl2 = 0.358568582800318073; // lambda_2
11 static const double xl4 = 0.948683298050513796; // lambda_4
12 static const double xl5 = 0.688247201611685289; // lambda_5
13 static const double w2 = 980. / 6561; // weights/2^n
14 static const double w4 = 200. / 19683;
15 static const double wp2 = 245. / 486; // error weights/2^n
16 static const double wp4 = 25. / 729;
17
18 static const double wn1[14] = {-0.193872885230909911, -0.555606360818980835, -0.876695625666819078, -1.15714067977442459, -1.39694152314179743,
19 -1.59609815576893754, -1.75461057765584494, -1.87247878880251983, -1.94970278920896201, -1.98628257887517146,
20 -1.98221815780114818, -1.93750952598689219, -1.85215668343240347, -1.72615963013768225};
21
22 static const double wn3[14] = {0.0518213686937966768, 0.0314992633236803330, 0.0111771579535639891, -0.00914494741655235473, -0.0294670527866686986,
23 -0.0497891581567850424, -0.0701112635269013768, -0.0904333688970177241, -0.110755474267134071, -0.131077579637250419,
24 -0.151399685007366752, -0.171721790377483099, -0.192043895747599447, -0.212366001117715794};
25
26 static const double wn5[14]
27 = {0.871183254585174982e-01, 0.435591627292587508e-01, 0.217795813646293754e-01, 0.108897906823146873e-01, 0.544489534115734364e-02,
28 0.272244767057867193e-02, 0.136122383528933596e-02, 0.680611917644667955e-03, 0.340305958822333977e-03, 0.170152979411166995e-03,
29 0.850764897055834977e-04, 0.425382448527917472e-04, 0.212691224263958736e-04, 0.106345612131979372e-04};
30
31 static const double wpn1[14] = {-1.33196159122085045, -2.29218106995884763, -3.11522633744855959, -3.80109739368998611, -4.34979423868312742,
32 -4.76131687242798352, -5.03566529492455417, -5.17283950617283939, -5.17283950617283939, -5.03566529492455417,
33 -4.76131687242798352, -4.34979423868312742, -3.80109739368998611, -3.11522633744855959};
34
35 static const double wpn3[14] = {0.0445816186556927292, -0.0240054869684499309, -0.0925925925925925875, -0.161179698216735251, -0.229766803840877915,
36 -0.298353909465020564, -0.366941015089163228, -0.435528120713305891, -0.504115226337448555, -0.572702331961591218,
37 -0.641289437585733882, -0.709876543209876532, -0.778463648834019195, -0.847050754458161859};
38 }
39#if INSTRUCTION_SET == INSTRUCTION_SET_AVX2d
40 template <unsigned dim, unsigned width, typename fcn>
41 std::tuple<double, double, unsigned> integrate_fp(const fcn &F, const std::array<double, dim> &ctr, const std::array<double, dim> &wth) {
42 using namespace integrate_fp_constants;
43 auto eval = [&F](auto z, const auto &p, const unsigned &ind) {
44 z[ind] += p;
45 return F(z);
46 };
47 auto eval_2 = [&F](auto z, const auto &p, const unsigned &ind, const auto &p2, const unsigned int &ind2) {
48 z[ind] += p;
49 z[ind2] += p2;
50 return F(z);
51 };
52 unsigned idvaxn = 0;
53 std::array<real_v, dim> z;
54 double rgnvol = get_power<2, dim>::value;
55 for(unsigned j = 0; j < dim; j++) {
56 z[j] = ctr[j];
57 rgnvol *= wth[j]; // region volume
58 }
59 double sum1{0}, sum2{0}, sum3{0}, sum4{0}, sum5{0};
60 sum1 = F(z).at(0);
61 double difmax = 0;
62 const real_v xl(-xl4, -xl2, +xl2, +xl4);
63 const real_v dxp(-xl4, +xl4, -xl4, +xl4);
64 const real_v dxp2(-xl4, -xl4, +xl4, +xl4);
65
66 // loop over coordinates
67 for(unsigned j = 0; j != dim; j++) {
68 auto fb = eval(z, xl * wth[j], j).to_array();
69 auto f2 = fb[1] + fb[2];
70 auto f3 = fb[0] + fb[3];
71 sum2 += f2;
72 sum3 += f3;
73 double dif = std::abs(7 * f2 - f3 - 12 * sum1);
74 idvaxn = dif >= difmax ? j : idvaxn;
75 difmax = dif >= difmax ? dif : difmax;
76 for(unsigned k = j + 1; k < dim; ++k) sum4 += utils::sum_elements(eval_2(z, dxp * wth[j], j, dxp2 * wth[k], k));
77 }
78 for(int j = 0; j < get_power<2, dim>::value; j += 4) {
79 // auto loop_mask =
80 for(int k = 0; k != dim; ++k)
81 z[k] = real_v(ctr[k] + (0x1 & ((j + 0) >> k) ? +1 : -1) * xl5 * wth[k], ctr[k] + (0x1 & ((j + 1) >> k) ? +1 : -1) * xl5 * wth[k],
82 ctr[k] + (0x1 & ((j + 2) >> k) ? +1 : -1) * xl5 * wth[k], ctr[k] + (0x1 & ((j + 3) >> k) ? +1 : -1) * xl5 * wth[k]);
83 sum5 += utils::sum_elements(F(z));
84 }
85
86 auto rgncmp = rgnvol * (wpn1[dim - 2] * sum1 + wp2 * sum2 + wpn3[dim - 2] * sum3 + wp4 * sum4);
87 auto rgnval = rgnvol * (wn1[dim - 2] * sum1 + w2 * sum2 + wn3[dim - 2] * sum3 + w4 * sum4 + wn5[dim - 2] * sum5);
88 auto rgnerr = std::abs(rgnval - rgncmp); // compares estim error with expected error
89 return {rgnval, rgnerr, idvaxn};
90 }
91#endif
92 template <unsigned dim, typename fcn>
93 std::tuple<double, double, unsigned> integrate_fp_scalar(const fcn &F, const std::array<double, dim> &ctr, const std::array<double, dim> &wth) {
94 using namespace integrate_fp_constants;
95 auto eval = [&F](auto &z, const auto &p, const unsigned &ind) {
96 auto zt = z[ind];
97 z[ind] += p;
98 auto v = F(z);
99 z[ind] = zt;
100 return v;
101 };
102 auto eval_2 = [&F](auto &z, const auto &p, const unsigned &ind, const auto &p2, const unsigned int &ind2) {
103 auto zt = z[ind];
104 auto zt2 = z[ind2];
105 z[ind] += p;
106 z[ind2] += p2;
107 auto v = F(z);
108 z[ind] = zt;
109 z[ind2] = zt2;
110 return v;
111 };
112
113 unsigned idvaxn = 0;
114 std::array<double, dim> z = ctr;
115 double rgnvol = get_power<2, dim>::value;
116 for(unsigned j = 0; j < dim; j++) rgnvol *= wth[j]; // region volume
117 double sum1 = F(z);
118 double sum2 = 0;
119 double sum3 = 0;
120 double sum4 = 0;
121 double sum5 = 0;
122
123 double difmax = 0;
124
125 // loop over coordinates
126 for(unsigned j = 0; j != dim; j++) {
127 auto f2 = eval(z, -xl2 * wth[j], j) + eval(z, +xl2 * wth[j], j);
128 auto f3 = eval(z, -xl4 * wth[j], j) + eval(z, +xl4 * wth[j], j);
129
130 sum2 += f2; // sum func eval with different weights separately
131 sum3 += f3;
132 double dif = std::abs(7 * f2 - f3 - 12 * sum1);
133 idvaxn = dif >= difmax ? j : idvaxn;
134 difmax = dif >= difmax ? dif : difmax;
135 for(unsigned k = j + 1; k < dim; ++k) {
136 sum4 += eval_2(z, xl4 * wth[j], j, xl4 * wth[k], k);
137 sum4 += eval_2(z, xl4 * wth[j], j, -xl4 * wth[k], k);
138 sum4 += eval_2(z, -xl4 * wth[j], j, xl4 * wth[k], k);
139 sum4 += eval_2(z, -xl4 * wth[j], j, -xl4 * wth[k], k);
140 }
141 }
142 for(int j = 0; j != get_power<2, dim>::value; ++j) {
143 for(int k = 0; k != dim; ++k) z[k] = ctr[k] + (0x1 & (j >> k) ? +1 : -1) * xl5 * wth[k];
144 sum5 += F(z);
145 }
146
147 auto rgncmp = rgnvol * (wpn1[dim - 2] * sum1 + wp2 * sum2 + wpn3[dim - 2] * sum3 + wp4 * sum4);
148 auto rgnval = rgnvol * (wn1[dim - 2] * sum1 + w2 * sum2 + wn3[dim - 2] * sum3 + w4 * sum4 + wn5[dim - 2] * sum5);
149 auto rgnerr = std::abs(rgnval - rgncmp); // compares estim error with expected error
150 return {rgnval, rgnerr, idvaxn};
151 }
152
153}
154
155#endif
static const double wn3[14]
static const double wpn1[14]
static const double wpn3[14]
static const double wn1[14]
static const double wn5[14]
auto sum_elements(const simd_type &obj)
Definition utils.h:87
AVX::real_v real_v
Definition utils.h:47
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)