9 #ifdef PORTABLE_LAR_SHAPE
10 #define SINCOSPOLY_USE_EIGEN 1
13 #ifndef SINCOSPOLY_USE_EIGEN
17 #include "TMatrixDLazy.h"
18 #include "TDecompLU.h"
19 #include "TDecompSVD.h"
24 #include "Eigen/Dense"
25 typedef Eigen::VectorXd
VECTOR;
26 typedef Eigen::MatrixXd
MATRIX;
29 #define Double_t double
39 #include "GeoModelKernel/Units.h"
40 using namespace GeoModelKernelUnits;
42 #ifndef SINCOSPOLY_USE_EIGEN
43 template<
typename T,
typename Q>
44 std::ostream &
operator << (std::ostream & ostr,
const TVectorT<T> &
v)
46 std::ios_base::fmtflags save_flags(ostr.flags());
48 ostr << std::scientific;
50 ostr <<
v[
idx] <<
", ";
52 ostr <<
v[
v.GetUpb()];
54 ostr.flags(save_flags);
60 static VECTOR findLinearApproximation(
61 const Int_t dataLen,
const Int_t nBasisFuntions,
64 #ifndef SINCOSPOLY_USE_EIGEN
71 for(Int_t j = 0; j < nBasisFuntions; ++ j){
72 for(Int_t
k = 0;
k < nBasisFuntions; ++
k){
74 for(Int_t
i = 0;
i < dataLen; ++
i){
75 Ajk += bf(j,
i) * bf(
k,
i);
81 for(Int_t
k = 0;
k < nBasisFuntions; ++
k){
83 for(Int_t
i = 0;
i < dataLen; ++
i){
88 #ifndef SINCOSPOLY_USE_EIGEN
93 return A.inverse()*vY;
97 using namespace CLHEP;
104 struct sincos_params {
105 std::array<double, nBasisFunctions>
sin{};
106 std::array<double, nBasisFunctions>
cos{};
114 const Double_t Rstep = 1.*
mm;
115 const Int_t nrPoints = (Rmax -
Rmin) * (1./Rstep);
116 const Int_t dataLen = nrPoints + 1;
117 #ifndef SINCOSPOLY_USE_EIGEN
121 MATRIX bf(nBasisFunctions, dataLen);
128 for(Int_t
i = 0;
i < dataLen; ++
i){
129 const Double_t
a =
Rmin +
i * Rstep;
132 ysin[
i] = scalpha.sn;
133 ycos[
i] = scalpha.cs;
134 for(Int_t
n = 0;
n < nBasisFunctions; ++
n) {
140 findLinearApproximation(dataLen, nBasisFunctions, ysin, bf);
142 findLinearApproximation(dataLen, nBasisFunctions, ycos, bf);
144 for(Int_t
i = 0;
i < nBasisFunctions; ++
i){
145 p.sin[
i] = params_sin[
i];
146 p.cos[
i] = params_cos[
i];
154 std::cout <<
"sin params:" << params_sin << std::endl;
155 std::cout <<
"cos params:" << params_cos << std::endl;
157 double dsinr = 0., dcosr = 0.;
160 double dsin = 0., dcos = 0.;
162 for(
double r =
Rmin + 40.;
r < Rmax - 40.;
r += Rstep / 10.){
165 double sin_a_v, cos_a_v;
166 lwc.parameterized_sincos(
r, sin_a, cos_a);
167 lwc.m_vsincos_par.eval(
r, sin_a_v, cos_a_v);
168 std::streamsize
ss = std::cout.precision();
169 std::cout.precision(16);
170 std::cout <<
"def: " <<
r <<
" " << sin_a <<
" " << cos_a << std::endl;
171 std::cout <<
"vec: " <<
r <<
" " << sin_a_v <<
" " << cos_a_v << std::endl;
172 std::cout <<
"dif: " <<
r <<
" " << (sin_a - sin_a_v) / sin_a <<
" " << (cos_a - cos_a_v) / cos_a << std::endl;
173 std::cout.precision(
ss);
174 double ds = fabs(scalpha.sn - sin_a);
179 double dc = fabs(scalpha.cs - cos_a);
184 double dt = fabs(sin_a*sin_a + cos_a*cos_a - 1.);
191 std::cout <<
"Max. difference: " << std::endl
192 <<
"\tsin: " << dsin <<
" at " << dsinr << std::endl
193 <<
"\tcos: " << dcos <<
" at " << dcosr << std::endl
194 <<
"\tsin^2+cos^2: " << dtrig <<
" at " << dtrigr << std::endl;
198 TVectorD y_test(dataLen);
199 const Int_t nIter=10000;
200 std::cout <<
"Perfomance test started, " << nIter <<
" iterations" << std::endl;
202 double y_testsin[dataLen] ={};
203 double y_testcos[dataLen] ={};
204 struct timeval tvsincos_start, tvsincos_stop;
205 gettimeofday(&tvsincos_start, 0);
206 for(Int_t iIter=0;iIter<nIter;iIter++) {
207 for(Int_t
i=0;
i<dataLen;
i++) {
208 sincos(parameterized_slant_angle(
x[
i]), &y_testsin[
i], &y_testcos[
i]);
211 gettimeofday(&tvsincos_stop, 0);
212 double timeSinCos=(tvsincos_stop.tv_sec-tvsincos_start.tv_sec + 1
E-6*(tvsincos_stop.tv_usec-tvsincos_start.tv_usec))/nIter;
214 std::cout.unsetf ( std::ios::fixed | std::ios::scientific );
215 std::cout <<
"Time to fill 2x" << dataLen <<
" elements using sincos function: " << timeSinCos << std::endl;
217 struct timeval tvpoly_start, tvpoly_stop;
218 gettimeofday(&tvpoly_start, 0);
219 for(Int_t iIter=0;iIter<nIter;iIter++) {
220 for(Int_t
i=0;
i<dataLen;
i++) {
221 lwc.parameterized_sincos(
x[
i], y_testsin[
i], y_testcos[
i]);
224 gettimeofday(&tvpoly_stop, 0);
225 double timePoly=(tvpoly_stop.tv_sec - tvpoly_start.tv_sec + 1
E-6*(tvpoly_stop.tv_usec - tvpoly_start.tv_usec))/nIter;
226 std::cout <<
"Time to fill 2x" << dataLen <<
" elements using approximation sin&cos: " << timePoly << std::endl;
227 std::cout.unsetf ( std::ios::fixed | std::ios::scientific );
228 std::cout <<
"Approximation is " << timeSinCos/timePoly <<
" faster " << std::endl;
236 static const sincos_params
p = calc_params(
lwc, 250.*
mm, 750.*
mm);
242 static const sincos_params
p = calc_params(
lwc, 560.*
mm, 2090.*
mm);
251 const sincos_params&
p = m_isInner ? inner_params(*
this) : outer_params(*
this);
254 m_sin_parametrization =
p.sin;
255 m_cos_parametrization =
p.cos;
262 m_vsincos_par.param_0[0] = m_sin_parametrization[4];
263 m_vsincos_par.param_0[1] = m_sin_parametrization[5];
264 m_vsincos_par.param_0[2] = m_cos_parametrization[4];
265 m_vsincos_par.param_0[3] = m_cos_parametrization[5];
266 m_vsincos_par.param_1[0] = m_sin_parametrization[2];
267 m_vsincos_par.param_1[1] = m_sin_parametrization[3];
268 m_vsincos_par.param_1[2] = m_cos_parametrization[2];
269 m_vsincos_par.param_1[3] = m_cos_parametrization[3];
270 m_vsincos_par.param_2[0] = m_sin_parametrization[0];
271 m_vsincos_par.param_2[1] = m_sin_parametrization[1];
272 m_vsincos_par.param_2[2] = m_cos_parametrization[0];
273 m_vsincos_par.param_2[3] = m_cos_parametrization[1];