38 ClassImp(RooLegendre);
43 inline double a(
int p,
int l,
int m) {
44 double r = TMath::Factorial(l+m)/TMath::Factorial(m+p)/TMath::Factorial(p)/TMath::Factorial(l-m-2*p);
46 return p%2==0 ? r : -r ;
49 void throwIfNoMathMore() {
50 #ifndef R__HAS_MATHMORE
51 throw std::runtime_error(
"RooLegendre needs functions from MathMore. It is not available in this root build.");
55 void checkCoeffs(
int m1,
int l1,
int m2,
int l2) {
56 if (m1 < 0 || m2 < 0) {
57 throw std::invalid_argument(
"RooLegendre: m coefficients need to be >= 0.");
59 if (l1 < m1 || l2 < m2) {
60 throw std::invalid_argument(
"RooLegendre: m coefficients need to be smaller than corresponding l.");
67 RooLegendre::RooLegendre() :
68 _l1(1),_m1(1),_l2(0),_m2(0)
77 RooLegendre::RooLegendre(
const char* name,
const char* title, RooAbsReal& ctheta,
int l,
int m)
78 : RooAbsReal(name, title)
79 , _ctheta(
"ctheta",
"ctheta", this, ctheta)
80 , _l1(l),_m1(m),_l2(0),_m2(0)
82 checkCoeffs(_m1, _l1, _m2, _l2);
89 RooLegendre::RooLegendre(
const char* name,
const char* title, RooAbsReal& ctheta,
int l1,
int m1,
int l2,
int m2)
90 : RooAbsReal(name, title)
91 , _ctheta(
"ctheta",
"ctheta", this, ctheta)
92 , _l1(l1),_m1(m1),_l2(l2),_m2(m2)
94 checkCoeffs(_m1, _l1, _m2, _l2);
101 RooLegendre::RooLegendre(
const RooLegendre& other,
const char* name)
102 : RooAbsReal(other, name)
103 , _ctheta(
"ctheta", this, other._ctheta)
104 , _l1(other._l1), _m1(other._m1)
105 , _l2(other._l2), _m2(other._m2)
112 Double_t RooLegendre::evaluate()
const
114 #ifdef R__HAS_MATHMORE
116 double ctheta = std::max(-1., std::min((
double)_ctheta, +1.));
117 if (_l1!=0||_m1!=0) r *= ROOT::Math::assoc_legendre(_l1,_m1,ctheta);
118 if (_l2!=0||_m2!=0) r *= ROOT::Math::assoc_legendre(_l2,_m2,ctheta);
119 if ((_m1+_m2)%2==1) r = -r;
133 void compute(
size_t batchSize,
const int l1,
const int m1,
const int l2,
const int m2,
134 double * __restrict output,
135 double const * __restrict TH)
137 #ifdef R__HAS_MATHMORE
138 double legendre1=1.0, legendreMinus1=1.0;
140 legendre1 = ROOT::Math::internal::legendre(l1,m1,1.0);
141 legendreMinus1 = ROOT::Math::internal::legendre(l1,m1,-1.0);
144 legendre1 *= ROOT::Math::internal::legendre(l2,m2,1.0);
145 legendreMinus1 *= ROOT::Math::internal::legendre(l2,m2,-1.0);
148 for (
size_t i=0; i<batchSize; i++) {
150 output[i] = legendreMinus1;
151 }
else if (TH[i] >= 1.0) {
152 output[i] = legendre1;
157 output[i] *= ROOT::Math::internal::legendre(l1,m1,TH[i]);
160 output[i] *= ROOT::Math::internal::legendre(l2,m2,TH[i]);
166 (void) batchSize, (
void) l1, (void)m1, (
void)l2, (
void)m2, (
void)output, (
void)TH;
172 RooSpan<double> RooLegendre::evaluateBatch(std::size_t begin, std::size_t batchSize)
const {
173 auto cthetaData = _ctheta.getValBatch(begin, batchSize);
175 if (cthetaData.empty()) {
179 batchSize = cthetaData.size();
180 auto output = _batchData.makeWritableBatchUnInit(begin, batchSize);
182 compute(batchSize, _l1, _m1, _l2, _m2, output.data(), cthetaData.data());
191 Bool_t fullRange(
const RooRealProxy& x ,
const char* range)
193 return range == 0 || strlen(range) == 0
194 ? std::fabs(x.min() + 1.) < 1.e-8 && std::fabs(x.max() - 1.) < 1.e-8
195 : std::fabs(x.min(range) + 1.) < 1.e-8 && std::fabs(x.max(range) - 1.) < 1.e-8;
201 Int_t RooLegendre::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars,
const char* rangeName)
const
204 if (fullRange(_ctheta,rangeName) && matchArgs(allVars, analVars, _ctheta))
return 1;
212 Double_t RooLegendre::analyticalIntegral(Int_t code,
const char* )
const
215 if ( _m1==_m2 )
return ( _l1 == _l2) ? TMath::Factorial(_l1+_m2)/TMath::Factorial(_l1-_m1)*double(2)/(2*_l1+1) : 0.;
216 if ( (_l1+_l2-_m1-_m2)%2 != 0 )
return 0;
226 for (
int p1=0; 2*p1 <= _l1-_m1 ;++p1) {
227 double a1 = a(p1,_l1,_m1);
228 for (
int p2=0; 2*p2 <= _l2-_m2 ; ++p2) {
229 double a2 = a(p2,_l2,_m2);
230 r+= a1*a2*TMath::Gamma(
double(_l1+_l2-_m1-_m2-2*p1-2*p2+1)/2 )*TMath::Gamma(
double(_m1+_m2+2*p1+2*p2+2)/2 );
233 r /= TMath::Gamma(
double(_l1+_l2+3)/2 );
235 if ((_m1+_m2)%2==1) r = -r;
241 Int_t RooLegendre::getMaxVal(
const RooArgSet& )
const {
242 if (_m1==0&&_m2==0)
return 1;
244 if (_l1<3&&_l2<3)
return 1;
249 inline double maxSingle(
int i,
int j) {
257 static const double m2[3] = { 3,3 };
261 Double_t RooLegendre::maxVal( Int_t )
const {
262 return maxSingle(_l1,_m1)*maxSingle(_l2,_m2);