Skip to content

Commit 40a3e22

Browse files
guitargeekanigamova
authored andcommitted
Make it possible to build combine without VDT via CMake
This makes it possible to build combine in environments where VDT is not available. Nothing is changed for the default code, e.g. the case where `COMBINE_NO_VDT` is not defined. The GBRMath header was also generalized to a meta-header for math includes plus some preprocessor checks and defines dpeneding on VDT is requested or not.
1 parent 374e622 commit 40a3e22

File tree

8 files changed

+141
-79
lines changed

8 files changed

+141
-79
lines changed

CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ project(HiggsAnalysisCombinedLimit VERSION 0.0.1)
44

55
option( MODIFY_ROOTMAP "Modify generated Rootmap to take out classes already bundled in StatAnalysis" FALSE )
66
option( INSTALL_PYTHON "Install the Python library and scripts" TRUE )
7+
option( USE_VDT "Use VDT (fast and vectorisable mathematical functions)" TRUE )
78

89
# Can build with CMake after e.g. setting up StatAnalysis release like this:
910
# export ATLAS_LOCAL_ROOT_BASE=/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase
@@ -41,7 +42,13 @@ ROOT_GENERATE_DICTIONARY(G__${LIBNAME} HiggsAnalysis/CombinedLimit/src/classes.h
4142
OPTIONS ${ROOTCLING_OPTIONS})
4243
add_library(${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx)
4344
set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}")
44-
target_link_libraries (${LIBNAME} Eigen3::Eigen ${ROOT_LIBRARIES} ${Boost_LIBRARIES} VDT::VDT)
45+
target_link_libraries (${LIBNAME} Eigen3::Eigen ${ROOT_LIBRARIES} ${Boost_LIBRARIES})
46+
47+
if(NOT USE_VDT)
48+
target_compile_definitions(${LIBNAME} PUBLIC COMBINE_NO_VDT)
49+
else()
50+
target_link_libraries (${LIBNAME} VDT::VDT)
51+
endif()
4552

4653
add_executable(combine bin/combine.cpp)
4754
target_link_libraries(combine PUBLIC ${LIBNAME})

interface/GBRMath.h

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/GBRMath.cc

Lines changed: 0 additions & 2 deletions
This file was deleted.

src/MathHeaders.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef MathHeaders_h
2+
#define MathHeaders_h
3+
4+
#ifndef COMBINE_NO_VDT
5+
#include "vdt/vdtMath.h"
6+
#endif
7+
8+
#include <cmath>
9+
10+
#ifdef COMBINE_NO_VDT
11+
12+
#define my_exp std::exp
13+
#define my_log std::log
14+
inline double my_inv(double x) { return 1. / x; }
15+
16+
#else
17+
18+
#define my_exp vdt::fast_exp
19+
#define my_log vdt::fast_log
20+
#define my_inv vdt::fast_inv
21+
22+
#endif
23+
24+
namespace gbrmath {
25+
26+
inline double fast_pow(double base, double exponent) {
27+
if (base == 0. && exponent > 0.)
28+
return 0.;
29+
#ifdef COMBINE_NO_VDT
30+
else if (base > 0.)
31+
return std::exp(exponent * std::log(base));
32+
#else
33+
else if (base > 0.)
34+
return vdt::fast_exp(exponent * vdt::fast_log(base));
35+
#endif
36+
else
37+
return std::nan("");
38+
}
39+
40+
// inline float fast_powf(float base, float exponent) {
41+
// if (base==0. && exponent>0.) return 0.;
42+
// else if (base>0.) return vdt::fast_expf(exponent*vdt::fast_logf(base));
43+
// else return std::nanf("");
44+
// }
45+
46+
} // namespace gbrmath
47+
48+
#endif

src/RooDoubleCBFast.cc

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22
#include <math.h>
33
#include "TMath.h"
44

5-
//#include "../interface/RooDoubleCBFast.h"
6-
//#include "../interface/RooFermi.h"
7-
//#include "../interface/RooRelBW.h"
85
#include "../interface/RooDoubleCBFast.h"
96
#include "RooRealVar.h"
107
#include "RooRealConstant.h"
11-
#include "../interface/GBRMath.h"
8+
#include "./MathHeaders.h"
129

1310
using namespace RooFit;
1411

@@ -52,21 +49,21 @@ using namespace RooFit;
5249

5350
double RooDoubleCBFast::evaluate() const
5451
{
55-
double t = (x-mean)*vdt::fast_inv(width);
52+
double t = (x-mean)*my_inv(width);
5653
double val = -99.;
5754
if(t>-alpha1 && t<alpha2){
58-
val = vdt::fast_exp(-0.5*t*t);
55+
val = my_exp(-0.5*t*t);
5956
}else if(t<=-alpha1){
60-
double alpha1invn1 = alpha1*vdt::fast_inv(n1);
61-
val = vdt::fast_exp(-0.5*alpha1*alpha1)*gbrmath::fast_pow(1. - alpha1invn1*(alpha1+t), -n1);
57+
double alpha1invn1 = alpha1*my_inv(n1);
58+
val = my_exp(-0.5*alpha1*alpha1)*gbrmath::fast_pow(1. - alpha1invn1*(alpha1+t), -n1);
6259

6360
// double n1invalpha1 = n1*vdt::fast_inv(fabs(alpha1));
6461
// double A1 = gbrmath::fast_pow(n1invalpha1,n1)*vdt::fast_exp(-alpha1*alpha1/2.);
6562
// double B1 = n1invalpha1-fabs(alpha1);
6663
// val = A1*gbrmath::fast_pow(B1-t,-n1);
6764
}else if(t>=alpha2){
68-
double alpha2invn2 = alpha2*vdt::fast_inv(n2);
69-
val = vdt::fast_exp(-0.5*alpha2*alpha2)*gbrmath::fast_pow(1. - alpha2invn2*(alpha2-t), -n2);
65+
double alpha2invn2 = alpha2*my_inv(n2);
66+
val = my_exp(-0.5*alpha2*alpha2)*gbrmath::fast_pow(1. - alpha2invn2*(alpha2-t), -n2);
7067

7168
// double n2invalpha2 = n2*vdt::fast_inv(fabs(alpha2));
7269
// double A2 = gbrmath::fast_pow(n2invalpha2,n2)*vdt::fast_exp(-alpha2*alpha2/2.);
@@ -111,7 +108,7 @@ using namespace RooFit;
111108
static const double rootPiBy2 = sqrt(atan2(0.0,-1.0)/2.0);
112109
static const double invRoot2 = 1.0/sqrt(2);
113110

114-
double invwidth = vdt::fast_inv(width);
111+
double invwidth = my_inv(width);
115112

116113
double tmin = (xmin-mean)*invwidth;
117114
double tmax = (xmax-mean)*invwidth;
@@ -129,7 +126,7 @@ using namespace RooFit;
129126
}
130127
//compute left tail;
131128
if (isfullrange && (n1-1.0)>1.e-5) {
132-
left = width*vdt::fast_exp(-0.5*alpha1*alpha1)*n1*vdt::fast_inv(alpha1*(n1-1.));
129+
left = width*my_exp(-0.5*alpha1*alpha1)*n1*my_inv(alpha1*(n1-1.));
133130
}
134131
else {
135132

@@ -138,11 +135,11 @@ using namespace RooFit;
138135
double thigh = (left_high-mean)*invwidth;
139136

140137
if(left_low < left_high){ //is the left tail in range?
141-
double n1invalpha1 = n1*vdt::fast_inv(fabs(alpha1));
138+
double n1invalpha1 = n1*my_inv(fabs(alpha1));
142139
if(fabs(n1-1.0)>1.e-5) {
143-
double invn1m1 = vdt::fast_inv(n1-1.);
140+
double invn1m1 = my_inv(n1-1.);
144141
double leftpow = gbrmath::fast_pow(n1invalpha1,-n1*invn1m1);
145-
double left0 = width*vdt::fast_exp(-0.5*alpha1*alpha1)*invn1m1;
142+
double left0 = width*my_exp(-0.5*alpha1*alpha1)*invn1m1;
146143
double left1, left2;
147144

148145
if (xmax>(mean-alpha1*width)) left1 = n1invalpha1;
@@ -158,28 +155,28 @@ using namespace RooFit;
158155
//left = A1*vdt::fast_inv(-n1+1.0)*width*(gbrmath::fast_pow(B1-(left_low-mean)*invwidth,-n1+1.)-gbrmath::fast_pow(B1-(left_high-mean)*invwidth,-n1+1.));
159156
}
160157
else {
161-
double A1 = gbrmath::fast_pow(n1invalpha1,n1)*vdt::fast_exp(-0.5*alpha1*alpha1);
158+
double A1 = gbrmath::fast_pow(n1invalpha1,n1)*my_exp(-0.5*alpha1*alpha1);
162159
double B1 = n1invalpha1-fabs(alpha1);
163-
left = A1*width*(vdt::fast_log(B1-(left_low-mean)*invwidth) - vdt::fast_log(B1-(left_high-mean)*invwidth) );
160+
left = A1*width*(my_log(B1-(left_low-mean)*invwidth) - my_log(B1-(left_high-mean)*invwidth) );
164161
}
165162
}
166163
}
167164

168165
//compute right tail;
169166
if (isfullrange && (n2-1.0)>1.e-5) {
170-
right = width*vdt::fast_exp(-0.5*alpha2*alpha2)*n2*vdt::fast_inv(alpha2*(n2-1.));
167+
right = width*my_exp(-0.5*alpha2*alpha2)*n2*my_inv(alpha2*(n2-1.));
171168
}
172169
else {
173170
double right_low=std::max(xmin,mean + alpha2*width);
174171
double right_high=xmax;
175172
double tlow = (right_low - mean)*invwidth;
176173

177174
if(right_low < right_high){ //is the right tail in range?
178-
double n2invalpha2 = n2*vdt::fast_inv(fabs(alpha2));
175+
double n2invalpha2 = n2*my_inv(fabs(alpha2));
179176
if(fabs(n2-1.0)>1.e-5) {
180-
double invn2m2 = vdt::fast_inv(n2-1.);
177+
double invn2m2 = my_inv(n2-1.);
181178
double rightpow = gbrmath::fast_pow(n2invalpha2,-n2*invn2m2);
182-
double right0 = width*vdt::fast_exp(-0.5*alpha2*alpha2)*invn2m2;
179+
double right0 = width*my_exp(-0.5*alpha2*alpha2)*invn2m2;
183180
double right1, right2;
184181

185182
if (xmin<(mean+alpha2*width)) right1 = n2invalpha2;
@@ -193,9 +190,9 @@ using namespace RooFit;
193190
//right = A2*vdt::fast_inv(-n2+1.0)*width*(gbrmath::fast_pow(B2+(right_high-mean)*invwidth,-n2+1.)-gbrmath::fast_pow(B2+(right_low-mean)*invwidth,-n2+1.));
194191
}
195192
else {
196-
double A2 = gbrmath::fast_pow(n2invalpha2,n2)*vdt::fast_exp(-0.5*alpha2*alpha2);
193+
double A2 = gbrmath::fast_pow(n2invalpha2,n2)*my_exp(-0.5*alpha2*alpha2);
197194
double B2 = n2invalpha2-fabs(alpha2);
198-
right = A2*width*(vdt::fast_log(B2+(right_high-mean)*invwidth) - vdt::fast_log(B2+(right_low-mean)*invwidth) );
195+
right = A2*width*(my_log(B2+(right_high-mean)*invwidth) - my_log(B2+(right_low-mean)*invwidth) );
199196
}
200197
}
201198
}

src/VectorizedCB.cc

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../interface/ProfilingTools.h"
55
#include <RooRealVar.h>
66
#include <stdexcept>
7+
#include "./MathHeaders.h"
78

89
VectorizedCBShape::VectorizedCBShape(const RooCBShape &gaus, const RooAbsData &data, bool includeZeroWeights)
910
{
@@ -125,9 +126,9 @@ void VectorizedCBShape::fill(std::vector<Double_t> &out) const {
125126
} else {
126127
for (unsigned int i = 0; i < n; ++i) {
127128
if(work1_[i]>-alpha1){
128-
out[i] = norm * vdt::fast_exp(-0.5*work1_[i]*work1_[i]);
129+
out[i] = norm * my_exp(-0.5*work1_[i]*work1_[i]);
129130
} else {
130-
out[i] = norm2 * vdt::fast_exp(-n1 * vdt::fast_log(1. - alpha1invn1*(alpha1+work1_[i])));
131+
out[i] = norm2 * my_exp(-n1 * my_log(1. - alpha1invn1*(alpha1+work1_[i])));
131132
}
132133
}
133134
}
@@ -171,17 +172,17 @@ double VectorizedCBShape::getIntegral() const {
171172

172173
//compute left tail;
173174
if (isfullrange && (n1-1.0)>1.e-5) {
174-
left = width*std::exp(-0.5*alpha1*alpha1)*n1*vdt::inv(alpha1*(n1-1.));
175+
left = width*std::exp(-0.5*alpha1*alpha1)*n1*(1./(alpha1*(n1-1.)));
175176
} else {
176177

177178
double left_low=xmin;
178179
double left_high=std::min(xmax,mean - alpha1*width);
179180
double thigh = (left_high-mean)*invwidth;
180181

181182
if(left_low < left_high){ //is the left tail in range?
182-
double n1invalpha1 = n1*vdt::inv(fabs(alpha1));
183+
double n1invalpha1 = n1 / std::abs(alpha1);
183184
if(fabs(n1-1.0)>1.e-5) {
184-
double invn1m1 = vdt::inv(n1-1.);
185+
double invn1m1 = 1. / (n1-1.);
185186
double leftpow = std::pow(n1invalpha1,-n1*invn1m1);
186187
double left0 = width*std::exp(-0.5*alpha1*alpha1)*invn1m1;
187188
double left1, left2;
@@ -210,42 +211,55 @@ double VectorizedCBShape::getIntegral() const {
210211
}
211212

212213
void VectorizedCBShape::cbGauss(double* __restrict__ t, unsigned int n, double norm, double* __restrict__ out, double* __restrict__ work2) const {
214+
// The fast code code path is only available when VDT is available
215+
#ifndef COMBINE_NO_VDT
216+
if (!hasFast()) {
217+
#endif
218+
for (unsigned int i = 0; i < n; ++i) {
219+
out[i] = std::exp(-0.5 * t[i] * t[i]) * norm;
220+
}
221+
#ifndef COMBINE_NO_VDT
222+
return;
223+
}
213224
for (unsigned int i = 0; i < n; ++i) {
214225
work2[i] = -0.5*t[i]*t[i];
215226
}
216-
if (hasFast()) {
217-
vdt::fast_expv(n, work2, t);
218-
} else {
219-
vdt::expv(n, work2, t);
220-
}
227+
vdt::fast_expv(n, work2, t);
221228
for (unsigned int i = 0; i < n; ++i) {
222229
out[i] = t[i]*norm;
223230
}
231+
#endif
224232
}
233+
225234
void VectorizedCBShape::cbCB(double* __restrict__ t, unsigned int n, double norm, double* __restrict__ out, double* __restrict__ work2) const {
226235
// val = norm * std::exp(-0.5*alpha1*alpha1) * pow(1. - alpha1/n1 * (alpha1+t), -n1);
227236
double alpha1 = alpha_->getVal();
228-
double n1 = n_->getVal(), notn1 = -n1;
237+
double n1 = n_->getVal();
238+
double notn1 = -n1;
229239
double alpha1invn1 = alpha1/n1;
230240
double prefactor = norm*std::exp(-0.5*std::pow(alpha1, 2));
231241

242+
// The fast code code path is only available when VDT is available
243+
#ifndef COMBINE_NO_VDT
244+
if (!hasFast()) {
245+
#endif
246+
for (unsigned int i = 0; i < n; ++i) {
247+
out[i] = prefactor * std::exp(notn1 * std::log(1. - alpha1invn1*(alpha1+t[i])));
248+
}
249+
#ifndef COMBINE_NO_VDT
250+
return;
251+
}
252+
232253
for (unsigned int i = 0; i < n; ++i) {
233254
work2[i] = 1 - alpha1invn1*(alpha1+t[i]);
234255
}
235-
if (hasFast()) {
236-
vdt::fast_logv(n, work2, t);
237-
} else {
238-
vdt::logv(n, work2, t);
239-
}
256+
vdt::fast_logv(n, work2, t);
240257
for (unsigned int i = 0; i < n; ++i) {
241258
t[i] *= notn1;
242259
}
243-
if (hasFast()) {
244-
vdt::fast_expv(n, t, work2);
245-
} else {
246-
vdt::expv(n, t, work2);
247-
}
260+
vdt::fast_expv(n, t, work2);
248261
for (unsigned int i = 0; i < n; ++i) {
249262
out[i] = prefactor*work2[i];
250263
}
264+
#endif
251265
}

0 commit comments

Comments
 (0)