Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooBifurGauss.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2  * Project: RooFit *
3  * Package: RooFitModels *
4  * @(#)root/roofit:$Id$
5  * Authors: *
6  * Abi Soffer, Colorado State University, abi@slac.stanford.edu *
7  * *
8  * Copyright (c) 2000-2005, Regents of the University of California, *
9  * Colorado State University *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 #include "RooFit.h"
17 
18 /** \class RooBifurGauss
19  \ingroup Roofit
20 
21 Bifurcated Gaussian p.d.f with different widths on left and right
22 side of maximum value
23 **/
24 
25 #include "RooBifurGauss.h"
26 
27 #include "RooAbsReal.h"
28 #include "RooMath.h"
29 #include "BatchHelpers.h"
30 #include "RooVDTHeaders.h"
31 
32 #include "TMath.h"
33 
34 #include <cmath>
35 
36 using namespace std;
37 
38 ClassImp(RooBifurGauss);
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 
42 RooBifurGauss::RooBifurGauss(const char *name, const char *title,
43  RooAbsReal& _x, RooAbsReal& _mean,
44  RooAbsReal& _sigmaL, RooAbsReal& _sigmaR) :
45  RooAbsPdf(name, title),
46  x ("x" , "Dependent" , this, _x),
47  mean ("mean" , "Mean" , this, _mean),
48  sigmaL("sigmaL", "Left Sigma" , this, _sigmaL),
49  sigmaR("sigmaR", "Right Sigma", this, _sigmaR)
50 
51 {
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 
56 RooBifurGauss::RooBifurGauss(const RooBifurGauss& other, const char* name) :
57  RooAbsPdf(other,name), x("x",this,other.x), mean("mean",this,other.mean),
58  sigmaL("sigmaL",this,other.sigmaL), sigmaR("sigmaR", this, other.sigmaR)
59 {
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 
64 Double_t RooBifurGauss::evaluate() const {
65  Double_t arg = x - mean;
66 
67  Double_t coef(0.0);
68 
69  if (arg < 0.0){
70  if (TMath::Abs(sigmaL) > 1e-30) {
71  coef = -0.5/(sigmaL*sigmaL);
72  }
73  } else {
74  if (TMath::Abs(sigmaR) > 1e-30) {
75  coef = -0.5/(sigmaR*sigmaR);
76  }
77  }
78 
79  return exp(coef*arg*arg);
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 
84 namespace {
85 //Author: Emmanouil Michalainas, CERN 20 AUGUST 2019
86 
87 template<class Tx, class Tm, class Tsl, class Tsr>
88 void compute( size_t batchSize,
89  double * __restrict output,
90  Tx X, Tm M, Tsl SL, Tsr SR)
91 {
92  for (size_t i=0; i<batchSize; i++) {
93  const double arg = X[i]-M[i];
94  output[i] = arg / ((arg < 0.0)*SL[i] + (arg >= 0.0)*SR[i]);
95  }
96 
97  for (size_t i=0; i<batchSize; i++) {
98  if (X[i]-M[i]>1e-30 || X[i]-M[i]<-1e-30) {
99  output[i] = _rf_fast_exp(-0.5*output[i]*output[i]);
100  }
101  else {
102  output[i] = 1.0;
103  }
104  }
105 }
106 };
107 
108 RooSpan<double> RooBifurGauss::evaluateBatch(std::size_t begin, std::size_t batchSize) const {
109  using namespace BatchHelpers;
110 
111  EvaluateInfo info = getInfo( {&x, &mean, &sigmaL, &sigmaR}, begin, batchSize );
112  if (info.nBatches == 0) {
113  return {};
114  }
115  auto output = _batchData.makeWritableBatchUnInit(begin, batchSize);
116  auto xData = x.getValBatch(begin, info.size);
117 
118  if (info.nBatches==1 && !xData.empty()) {
119  compute(info.size, output.data(), xData.data(),
120  BracketAdapter<double> (mean),
121  BracketAdapter<double> (sigmaL),
122  BracketAdapter<double> (sigmaR));
123  }
124  else {
125  compute(info.size, output.data(),
126  BracketAdapterWithMask (x,x.getValBatch(begin,info.size)),
127  BracketAdapterWithMask (mean,mean.getValBatch(begin,info.size)),
128  BracketAdapterWithMask (sigmaL,sigmaL.getValBatch(begin,info.size)),
129  BracketAdapterWithMask (sigmaR,sigmaR.getValBatch(begin,info.size)));
130  }
131  return output;
132 }
133 
134 
135 ////////////////////////////////////////////////////////////////////////////////
136 
137 Int_t RooBifurGauss::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
138 {
139  if (matchArgs(allVars,analVars,x)) return 1 ;
140  return 0 ;
141 }
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 
145 Double_t RooBifurGauss::analyticalIntegral(Int_t code, const char* rangeName) const
146 {
147  switch(code) {
148  case 1:
149  {
150  static Double_t root2 = sqrt(2.) ;
151  static Double_t rootPiBy2 = sqrt(atan2(0.0,-1.0)/2.0);
152 
153 // Double_t coefL(0.0), coefR(0.0);
154 // if (TMath::Abs(sigmaL) > 1e-30) {
155 // coefL = -0.5/(sigmaL*sigmaL);
156 // }
157 
158 // if (TMath::Abs(sigmaR) > 1e-30) {
159 // coefR = -0.5/(sigmaR*sigmaR);
160 // }
161 
162  Double_t xscaleL = root2*sigmaL;
163  Double_t xscaleR = root2*sigmaR;
164 
165  Double_t integral = 0.0;
166  if(x.max(rangeName) < mean)
167  {
168  integral = sigmaL * ( RooMath::erf((x.max(rangeName) - mean)/xscaleL) - RooMath::erf((x.min(rangeName) - mean)/xscaleL) );
169  }
170  else if (x.min(rangeName) > mean)
171  {
172  integral = sigmaR * ( RooMath::erf((x.max(rangeName) - mean)/xscaleR) - RooMath::erf((x.min(rangeName) - mean)/xscaleR) );
173  }
174  else
175  {
176  integral = sigmaR*RooMath::erf((x.max(rangeName) - mean)/xscaleR) - sigmaL*RooMath::erf((x.min(rangeName) - mean)/xscaleL);
177  }
178  // return rootPiBy2*(sigmaR*RooMath::erf((x.max(rangeName) - mean)/xscaleR) -
179  // sigmaL*RooMath::erf((x.min(rangeName) - mean)/xscaleL));
180  return integral*rootPiBy2;
181  }
182  }
183 
184  assert(0) ;
185  return 0 ; // to prevent compiler warnings
186 }