105 #ifndef LESTER_TESTWHETHERELLIPSESAREDISJOINT_H 106 #define LESTER_TESTWHETHERELLIPSESAREDISJOINT_H 184 throw "precondition violation";
234 bool __private_ellipsesAreDisjoint(
const double coeffLamPow3,
const double coeffLamPow2,
const double coeffLamPow1,
const double coeffLamPow0);
249 const double coeffLamPow3 = e1.
det;
252 const double coeffLamPow0 = e2.
det;
256 if (fabs(coeffLamPow3) >= fabs(coeffLamPow0)) {
267 if(coeffLamPow3==0) {
274 const double a = coeffLamPow2 / coeffLamPow3;
275 const double b = coeffLamPow1 / coeffLamPow3;
276 const double c = coeffLamPow0 / coeffLamPow3;
278 #ifdef LESTER_DEEP_FIDDLE 280 const double thing1 = -3.0*b + a*a;
281 const double thing2 = -27.0*c*c + 18.0*c*a*b + a*a*b*b - 4.0*a*a*a*c - 4.0*b*b*b;
283 << (thing1>0) <<
" && " << (thing2>0) <<
" && [[ " << (a>=0) <<
" " << (3.0*a*c + b*a*a - 4.0*b*b<0) <<
" ] or " 284 <<
"[ " << (a< 0) <<
" ] =("<< ((a >= 0 && 3.0*a*c + b*a*a - 4.0*b*b< 0 /*&& thing2 > 0*/) ||
285 (a < 0 )) <<
")] " << (
286 ( (a >= 0 && thing1 > 0 && 3.0*a*c + b*a*a - 4.0*b*b< 0 && thing2 > 0) ||
287 (a < 0 && thing1 > 0 && thing2 > 0))
294 const double thing1 = -3.0*b + a*a;
295 if (thing1<=0)
return false;
296 const double thing2 = -27.0*c*c + 18.0*c*a*b + a*a*b*b - 4.0*a*a*a*c - 4.0*b*b*b;
297 if (thing2<=0)
return false;
300 const bool ans = ( (a >= 0 && 3.0*a*c + b*a*a - 4.0*b*b< 0 ) ||
301 (a < 0 /*&& thing1 > 0*/ ));
317 #ifndef ASYMM_MT2_BISECT_H 318 #define ASYMM_MT2_BISECT_H 329 static const int MT2_ERROR=-1;
332 const double mVis1,
const double pxVis1,
const double pyVis1,
333 const double mVis2,
const double pxVis2,
const double pyVis2,
334 const double pxMiss,
const double pyMiss,
335 const double mInvis1,
const double mInvis2,
336 const double desiredPrecisionOnMT2=0,
337 const bool useDeciSectionsInitially=
true 340 const double mT2_Sq = get_mT2_Sq(
341 mVis1, pxVis1, pyVis1,
342 mVis2, pxVis2, pyVis2,
345 desiredPrecisionOnMT2,
346 useDeciSectionsInitially);
347 if (mT2_Sq==MT2_ERROR) {
354 static bool first =
true;
355 if (first && printIfFirst) {
358 <<
"#=========================================================\n" 359 <<
"# To disable this message, place a call to \n" 361 <<
"# asymm_mt2_lester_bisect::disableCopyrightMessage();\n" 363 <<
"# somewhere before you begin to calculate your MT2 values.\n" 364 <<
"#=========================================================\n" 365 <<
"# You are calculating symmetric or asymmetric MT2 using\n" 366 <<
"# the implementation defined in:\n" 368 <<
"# http://arxiv.org/abs/1411.4312\n" 370 <<
"# Please cite the paper above if you use the MT2 values\n" 371 <<
"# for a scholarly purpose. For the variable MT2 itself,\n" 372 <<
"# please also cite:\n" 374 <<
"# http://arxiv.org/abs/hep-ph/9906349\n" 375 <<
"#=========================================================\n" 382 const double mVis1,
const double pxVis1,
const double pyVis1,
383 const double mVis2,
const double pxVis2,
const double pyVis2,
384 const double pxMiss,
const double pyMiss,
385 const double mInvis1,
const double mInvis2,
386 const double desiredPrecisionOnMT2=0,
387 const bool useDeciSectionsInitially=
true 391 disableCopyrightMessage(
true);
393 const double m1Min = mVis1+mInvis1;
394 const double m2Min = mVis2+mInvis2;
399 mVis2, pxVis2, pyVis2,
400 mVis1, pxVis1, pyVis1,
403 desiredPrecisionOnMT2
408 assert(m1Min<=m2Min);
410 const double mMin = m2Min;
414 const double msSq = mVis1*mVis1;
415 const double sx = pxVis1;
416 const double sy = pyVis1;
417 const double mpSq = mInvis1*mInvis1;
419 const double mtSq = mVis2*mVis2;
420 const double tx = pxVis2;
421 const double ty = pyVis2;
422 const double mqSq = mInvis2*mInvis2;
424 const double sSq = sx*sx + sy*sy;
425 const double tSq = tx*tx + ty*ty;
426 const double pMissSq = pxMiss*pxMiss + pyMiss*pyMiss;
427 const double massSqSum = msSq + mtSq + mpSq + mqSq;
428 const double scaleSq = (massSqSum + sSq + tSq + pMissSq)/8.0;
433 std::cout <<
"\nMOO ";
439 const double scale = sqrt(scaleSq);
442 double mLower = mMin;
443 double mUpper = mMin + scale;
444 unsigned int attempts=0;
445 const unsigned int maxAttempts=10000;
449 const double mUpperSq = mUpper*mUpper;
464 if (attempts>=maxAttempts) {
465 std::cerr <<
"MT2 algorithm failed to find upper bound to MT2" << std::endl;
478 bool goLow = useDeciSectionsInitially;
479 while(desiredPrecisionOnMT2<=0 || mUpper-mLower>desiredPrecisionOnMT2) {
481 const double trialM = ( goLow ?
482 (mLower*15+mUpper)/16
484 (mUpper + mLower)/2.0
487 if (trialM<=mLower || trialM>=mUpper) {
490 std::cout <<
" MACHINE_PREC " << std::setprecision(10) << mLower <<
" " << trialM <<
" " << mUpper <<
" " << mUpper-mLower <<
" " << desiredPrecisionOnMT2 << std::endl;
492 return trialM*trialM;
494 const double trialMSq = trialM * trialM;
515 std::cout <<
" THROW " << std::endl;
517 return mLower*mLower;
521 const double mAns = (mLower+mUpper)/2.0;
524 std::cout <<
" USER_PREC " << std::endl;
529 static double lestermax(
const double x,
const double y) {
533 const double mtSq,
const double tx,
const double ty,
535 const double pxmiss,
const double pymiss
537 const double txSq = tx*tx;
538 const double tySq = ty*ty;
539 const double pxmissSq = pxmiss*pxmiss;
540 const double pymissSq = pymiss*pymiss;
543 const double c_xx = +4.0* mtSq + 4.0* tySq;
545 const double c_yy = +4.0* mtSq + 4.0* txSq;
547 const double c_xy = -4.0* tx*ty;
549 const double c_x = -4.0* mtSq*pxmiss - 2.0* mqSq*tx + 2.0* mSq*tx - 2.0* mtSq*tx +
550 4.0* pymiss*tx*ty - 4.0* pxmiss*tySq;
552 const double c_y = -4.0* mtSq*pymiss - 4.0* pymiss*txSq - 2.0* mqSq*ty + 2.0* mSq*ty - 2.0* mtSq*ty +
555 const double c = - mqSq*mqSq + 2*mqSq*mSq - mSq*mSq + 2*mqSq*mtSq + 2*mSq*mtSq - mtSq*mtSq +
556 4.0* mtSq*pxmissSq + 4.0* mtSq*pymissSq + 4.0* mqSq*pxmiss*tx -
557 4.0* mSq*pxmiss*tx + 4.0* mtSq*pxmiss*tx + 4.0* mqSq*txSq +
558 4.0* pymissSq*txSq + 4.0* mqSq*pymiss*ty - 4.0* mSq*pymiss*ty +
559 4.0* mtSq*pymiss*ty - 8.0* pxmiss*pymiss*tx*ty + 4.0* mqSq*tySq +
568 std::cout <<
"Version is : 2014_11_13" << std::endl;
572 double MT(
double px1,
double px2,
double py1,
double py2,
double m1 ,
double m2){
573 double E1 = sqrt(px1*px1+py1*py1+m1*m1);
574 double E2 = sqrt(px2*px2+py2*py2+m2*m2);
575 double Msq = (E1+E2)*(E1+E2)-(px1+px2)*(px1+px2)-(py1+py2)*(py1+py2);
576 if (Msq < 0) Msq = 0;
580 std::pair <double,double>
ben_findsols(
double MT2,
double px,
double py,
double visM,
double Ma,
double pxb,
double pyb,
double metx,
double mety,
double visMb,
double Mb){
583 std::pair <double,double> sols;
589 double Pt = sqrt(px*px+py*py);
590 double E = sqrt(Pt*Pt+visM*visM);
596 double Ma4 = Ma2*Ma2;
599 double px4 = px2*px2;
600 double py4 = py2*py2;
603 double TermA = E2*px-M2*px+Ma2*px-px2*px-px*py2;
604 double TermB = -2.*px*py;
605 double TermSqy0 = E4*E2-2.*E4*M2-2.*E4*Ma2-2.*E4*px2-2.*E4*py2+E2*M4-2.*E2*M2*Ma2+2.*E2*M2*px2+2.*E2*M2*py2+E2*Ma4+2.*E2*Ma2*px2-2.*E2*Ma2*py2+E2*px4+2.*E2*px2*py2+E2*py4;
606 double TermSqy1 = -4.*E4*py+4.*E2*M2*py-4.*E2*Ma2*py+4.*E2*px2*py+4.*E2*py3;
607 double TermSqy2 = -4.*E4+4.*E2*px2+4.*E2*py2;
612 if (TermSqy1*TermSqy1-4.*TermSqy0*TermSqy2 < 0){
616 double sol1 = (-TermSqy1 - sqrt(TermSqy1*TermSqy1-4.*TermSqy0*TermSqy2))/(2.*TermSqy2);
617 double sol2 = (-TermSqy1 + sqrt(TermSqy1*TermSqy1-4.*TermSqy0*TermSqy2))/(2.*TermSqy2);
625 double myclose = 99999999.;
626 for (
double metpy = low; metpy<=high; metpy+=(high-low)/10000.){
627 double metpx = -(TermB*metpy+TermA-sqrt(TermSqy0+TermSqy1*metpy+TermSqy2*metpy*metpy))*0.5/(E2-px2);
628 double metpx2 = -(TermB*metpy+TermA+sqrt(TermSqy0+TermSqy1*metpy+TermSqy2*metpy*metpy))*0.5/(E2-px2);
629 double mt1a =
MT(px,metpx,py,metpy,visM,Ma);
630 double mt1b =
MT(px,metpx2,py,metpy,visM,Ma);
631 double metpxb = metx-metpx;
632 double metpx2b = metx-metpx2;
633 double mt2a =
MT(pxb,metpxb,pyb,mety-metpy,visMb,Mb);
634 double mt2b =
MT(pxb,metpx2b,pyb,mety-metpy,visMb,Mb);
635 if (fabs(mt1a-mt2a) < myclose){
636 myclose = fabs(mt1a-mt2a);
640 if (fabs(mt1b-mt2b) < myclose){
641 myclose = fabs(mt1b-mt2b);
EllipseParams(const double c_xx2, const double c_yy2, const double c_xy2, const double c_x2, const double c_y2, const double c2)
static double get_mT2(const double mVis1, const double pxVis1, const double pyVis1, const double mVis2, const double pxVis2, const double pyVis2, const double pxMiss, const double pyMiss, const double mInvis1, const double mInvis2, const double desiredPrecisionOnMT2=0, const bool useDeciSectionsInitially=true)
bool operator==(const EllipseParams &other) const
bool __private_ellipsesAreDisjoint(const double coeffLamPow3, const double coeffLamPow2, const double coeffLamPow1, const double coeffLamPow0)
double MT(double px1, double px2, double py1, double py2, double m1, double m2)
static double lestermax(const double x, const double y)
double lesterFactor(const EllipseParams &e2) const
static const Lester::EllipseParams helper(const double mSq, const double mtSq, const double tx, const double ty, const double mqSq, const double pxmiss, const double pymiss)
EllipseParams(const double x0, const double y0)
static double get_mT2_Sq(const double mVis1, const double pxVis1, const double pyVis1, const double mVis2, const double pxVis2, const double pyVis2, const double pxMiss, const double pyMiss, const double mInvis1, const double mInvis2, const double desiredPrecisionOnMT2=0, const bool useDeciSectionsInitially=true)
bool ellipsesAreDisjoint(const EllipseParams &e1, const EllipseParams &e2)
std::pair< double, double > ben_findsols(double MT2, double px, double py, double visM, double Ma, double pxb, double pyb, double metx, double mety, double visMb, double Mb)
static void disableCopyrightMessage(const bool printIfFirst=false)