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