44 const float Davismt2::RELATIVE_PRECISION = 0.00001;
45 const float Davismt2::ABSOLUTE_PRECISION = 0.0;
46 const float Davismt2::ZERO_MASS = 0.0;
47 const float Davismt2::MIN_MASS = 0.1;
48 const float Davismt2::SCANSTEP = 0.1;
50 Davismt2::Davismt2() {
58 Davismt2::~Davismt2() {}
60 double Davismt2::get_mt2() {
62 cout <<
"Davismt2::get_mt2() ==> Please set momenta first!" << endl;
71 void Davismt2::set_momenta(
double* pa0,
double* pb0,
double* pmiss0) {
83 Easq = masq + pax * pax + pay * pay;
94 Ebsq = mbsq + pbx * pbx + pby * pby;
99 pmissxsq = pmissx * pmissx;
100 pmissysq = pmissy * pmissy;
130 if (
sqrt(pmissxsq + pmissysq) / 100 >
scale)
136 masq = masq / scalesq;
137 mbsq = mbsq / scalesq;
145 Easq = Easq / scalesq;
146 Ebsq = Ebsq / scalesq;
147 pmissx = pmissx /
scale;
148 pmissy = pmissy /
scale;
149 pmissxsq = pmissxsq / scalesq;
150 pmissysq = pmissysq / scalesq;
151 mn = mn_unscale /
scale;
154 if (ABSOLUTE_PRECISION > 100. * RELATIVE_PRECISION)
155 precision = ABSOLUTE_PRECISION;
157 precision = 100. * RELATIVE_PRECISION;
160 void Davismt2::set_mn(
double mn0) {
162 mn_unscale = fabs(mn0);
163 mn = mn_unscale /
scale;
168 cout <<
" Davismt2::print() ==> pax = " << pax *
scale <<
"; pay = " << pay *
scale <<
"; ma = " << ma *
scale
170 cout <<
" Davismt2::print() ==> pbx = " << pbx *
scale <<
"; pby = " << pby *
scale <<
"; mb = " << mb *
scale
172 cout <<
" Davismt2::print() ==> pmissx = " << pmissx *
scale <<
"; pmissy = " << pmissy *
scale <<
";" << endl;
173 cout <<
" Davismt2::print() ==> mn = " << mn_unscale <<
";" << endl;
177 void Davismt2::mt2_massless() {
180 theta = atan(pay / pax);
184 double pxtemp, pytemp;
185 Easq = pax * pax + pay * pay;
186 Ebsq = pbx * pbx + pby * pby;
190 pxtemp = pax * c + pay *
s;
193 pxtemp = pbx * c + pby *
s;
194 pytemp = -s * pbx + c * pby;
197 pxtemp = pmissx * c + pmissy *
s;
198 pytemp = -s * pmissx + c * pmissy;
202 a2 = 1 - pbx * pbx / (Ebsq);
203 b2 = -pbx * pby / (Ebsq);
204 c2 = 1 - pby * pby / (Ebsq);
206 d21 = (Easq * pbx) / Ebsq;
207 d20 = -pmissx + (pbx * (pbx * pmissx + pby * pmissy)) / Ebsq;
208 e21 = (Easq * pby) / Ebsq;
209 e20 = -pmissy + (pby * (pbx * pmissx + pby * pmissy)) / Ebsq;
210 f22 = -(Easq * Easq / Ebsq);
211 f21 = -2 * Easq * (pbx * pmissx + pby * pmissy) / Ebsq;
212 f20 = mnsq + pmissxsq + pmissysq - (pbx * pmissx + pby * pmissy) * (pbx * pmissx + pby * pmissy) / Ebsq;
215 double Deltasq_low, Deltasq_high;
216 int nsols_high, nsols_low;
218 Deltasq_low = Deltasq0 + precision;
219 nsols_low = nsols_massless(Deltasq_low);
222 mt2_b = (double)
sqrt(Deltasq0 + mnsq);
234 double Deltasq_high1, Deltasq_high2;
235 Deltasq_high1 = 2 * Eb *
sqrt(pmissx * pmissx + pmissy * pmissy + mnsq) - 2 * pbx * pmissx - 2 * pby * pmissy;
236 Deltasq_high2 = 2 * Ea * mn;
238 if (Deltasq_high1 < Deltasq_high2)
239 Deltasq_high = Deltasq_high2;
241 Deltasq_high = Deltasq_high1;
243 nsols_high = nsols_massless(Deltasq_high);
246 if (nsols_high == nsols_low) {
249 double minmass, maxmass;
251 maxmass =
sqrt(mnsq + Deltasq_high);
252 for (
double mass = minmass + SCANSTEP;
mass < maxmass;
mass += SCANSTEP) {
255 nsols_high = nsols_massless(Deltasq_high);
256 if (nsols_high > 0) {
258 Deltasq_low = (
mass - SCANSTEP) * (
mass - SCANSTEP) - mnsq;
262 if (foundhigh == 0) {
264 cout <<
"Davismt2::mt2_massless() ==> Deltasq_high not found at event " <<
nevt << endl;
266 mt2_b = (double)
sqrt(Deltasq_low + mnsq);
271 if (nsols_high == nsols_low) {
273 cout <<
"Davismt2::mt2_massless() ==> error: nsols_low=nsols_high=" << nsols_high << endl;
275 cout <<
"Davismt2::mt2_massless() ==> Deltasq_high=" << Deltasq_high << endl;
277 cout <<
"Davismt2::mt2_massless() ==> Deltasq_low= " << Deltasq_low << endl;
279 mt2_b =
sqrt(mnsq + Deltasq_low);
282 double minmass, maxmass;
283 minmass =
sqrt(Deltasq_low + mnsq);
284 maxmass =
sqrt(Deltasq_high + mnsq);
285 while (maxmass - minmass > precision) {
286 double Delta_mid, midmass, nsols_mid;
287 midmass = (minmass + maxmass) / 2.;
288 Delta_mid = midmass * midmass - mnsq;
289 nsols_mid = nsols_massless(Delta_mid);
290 if (nsols_mid != nsols_low)
292 if (nsols_mid == nsols_low)
299 int Davismt2::nsols_massless(
double Dsq) {
301 delta = Dsq / (2 * Easq);
304 f1 = f12 * delta * delta + f10;
305 d2 = d21 * delta + d20;
306 e2 = e21 * delta + e20;
307 f2 = f22 * delta * delta + f21 * delta + f20;
315 b = -Dsq / (4 * Ea) + mnsq * Ea / Dsq;
317 b = Dsq / (4 * Ea) - mnsq * Ea / Dsq;
319 double A4, A3, A2, A1, A0;
322 A3 = 2 * a *
b2 / Ea;
323 A2 = (2 * a * a2 * b + c2 + 2 * a * d2) / (Easq);
324 A1 = (2 * b *
b2 + 2 * e2) / (Easq * Ea);
325 A0 = (a2 * b * b + 2 * b * d2 +
f2) / (Easq * Easq);
338 long double B3, B2, B1, B0;
343 long double C2, C1, C0;
344 C2 = -(A2 / 2 - 3 * A3sq / (16 * A4));
345 C1 = -(3 * A1 / 4. - A2 * A3 / (8 * A4));
346 C0 = -A0 + A1 * A3 / (16 * A4);
348 D1 = -B1 - (B3 * C1 * C1 / C2 - B3 * C0 - B2 * C1) / C2;
349 D0 = -B0 - B3 * C0 * C1 / (C2 * C2) + B2 * C0 / C2;
352 E0 = -C0 - C2 * D0 * D0 / (D1 *
D1) + C1 * D0 / D1;
354 long double t1, t2, t3, t4, t5;
364 nsol = signchange_n(t1, t2, t3, t4, t5) - signchange_p(t1, t2, t3, t4, t5);
371 void Davismt2::mt2_bisect() {
376 if (masq < MIN_MASS && mbsq < MIN_MASS) {
382 Deltasq0 = ma * (ma + 2 * mn);
386 a1 = 1 - pax * pax / (Easq);
387 b1 = -pax * pay / (Easq);
388 c1 = 1 - pay * pay / (Easq);
389 d1 = -pax * (Deltasq0 - masq) / (2 * Easq);
390 e1 = -pay * (Deltasq0 - masq) / (2 * Easq);
391 a2 = 1 - pbx * pbx / (Ebsq);
392 b2 = -pbx * pby / (Ebsq);
393 c2 = 1 - pby * pby / (Ebsq);
394 d2 = -pmissx + pbx * (Deltasq0 - mbsq) / (2 * Ebsq) + pbx * (pbx * pmissx + pby * pmissy) / (Ebsq);
395 e2 = -pmissy + pby * (Deltasq0 - mbsq) / (2 * Ebsq) + pby * (pbx * pmissx + pby * pmissy) / (Ebsq);
396 f2 = pmissx * pmissx + pmissy * pmissy -
397 ((Deltasq0 - mbsq) / (2 * Eb) + (pbx * pmissx + pby * pmissy) / Eb) *
398 ((Deltasq0 - mbsq) / (2 * Eb) + (pbx * pmissx + pby * pmissy) / Eb) +
404 y0 = (a1 * e1 -
b1 *
d1) / (
b1 *
b1 - a1 * c1);
407 double dis =
a2 * x0 * x0 + 2 *
b2 * x0 * y0 + c2 * y0 * y0 + 2 * d2 * x0 + 2 * e2 * y0 +
f2;
410 mt2_b = (double)
sqrt(mnsq + Deltasq0);
422 d21 = (Easq * pbx) / Ebsq;
423 d20 = ((masq - mbsq) * pbx) / (2. * Ebsq) - pmissx + (pbx * (pbx * pmissx + pby * pmissy)) / Ebsq;
424 e21 = (Easq * pby) / Ebsq;
425 e20 = ((masq - mbsq) * pby) / (2. * Ebsq) - pmissy + (pby * (pbx * pmissx + pby * pmissy)) / Ebsq;
426 f22 = -Easq * Easq / Ebsq;
427 f21 = (-2 * Easq * ((masq - mbsq) / (2. * Eb) + (pbx * pmissx + pby * pmissy) / Eb)) / Eb;
428 f20 = mnsq + pmissx * pmissx + pmissy * pmissy -
429 ((masq - mbsq) / (2. * Eb) + (pbx * pmissx + pby * pmissy) / Eb) *
430 ((masq - mbsq) / (2. * Eb) + (pbx * pmissx + pby * pmissy) / Eb);
435 double Deltasq_high1;
438 Deltasq_high1 = 2 * Eb *
sqrt(p2x0 * p2x0 + p2y0 * p2y0 + mnsq) - 2 * pbx * p2x0 - 2 * pby * p2y0 + mbsq;
442 double Deltasq_high2, Deltasq_high21, Deltasq_high22;
444 2 * Eb *
sqrt(pmissx * pmissx + pmissy * pmissy + mnsq) - 2 * pbx * pmissx - 2 * pby * pmissy + mbsq;
445 Deltasq_high22 = 2 * Ea * mn + masq;
447 if (Deltasq_high21 < Deltasq_high22)
448 Deltasq_high2 = Deltasq_high22;
450 Deltasq_high2 = Deltasq_high21;
454 if (Deltasq_high1 < Deltasq_high2)
455 Deltasq_high = Deltasq_high1;
457 Deltasq_high = Deltasq_high2;
460 Deltasq_low = Deltasq0;
463 if (nsols(Deltasq_low) > 0) {
465 mt2_b = (double)
sqrt(mnsq + Deltasq0);
469 int nsols_high, nsols_low;
471 nsols_low = nsols(Deltasq_low);
477 nsols_high = nsols(Deltasq_high);
479 if (nsols_high == nsols_low || nsols_high == 4) {
481 foundhigh = find_high(Deltasq_high);
482 if (foundhigh == 0) {
484 cout <<
"Davismt2::mt2_bisect() ==> Deltasq_high not found at event " <<
nevt << endl;
485 mt2_b =
sqrt(Deltasq_low + mnsq);
490 while (
sqrt(Deltasq_high + mnsq) -
sqrt(Deltasq_low + mnsq) > precision) {
491 double Deltasq_mid, nsols_mid;
493 Deltasq_mid = (Deltasq_high + Deltasq_low) / 2.;
494 nsols_mid = nsols(Deltasq_mid);
496 if (nsols_mid == 4) {
497 Deltasq_high = Deltasq_mid;
499 find_high(Deltasq_high);
503 if (nsols_mid != nsols_low)
504 Deltasq_high = Deltasq_mid;
505 if (nsols_mid == nsols_low)
506 Deltasq_low = Deltasq_mid;
508 mt2_b = (double)
sqrt(mnsq + Deltasq_high);
512 int Davismt2::find_high(
double& Deltasq_high) {
516 double Deltasq_low = (mn + ma) * (mn + ma) - mnsq;
518 double Deltasq_mid = (Deltasq_high + Deltasq_low) / 2.;
519 int nsols_mid = nsols(Deltasq_mid);
520 if (nsols_mid == 2) {
521 Deltasq_high = Deltasq_mid;
523 }
else if (nsols_mid == 4) {
524 Deltasq_high = Deltasq_mid;
526 }
else if (nsols_mid == 0) {
527 d1 = -pax * (Deltasq_mid - masq) / (2 * Easq);
528 e1 = -pay * (Deltasq_mid - masq) / (2 * Easq);
529 d2 = -pmissx + pbx * (Deltasq_mid - mbsq) / (2 * Ebsq) + pbx * (pbx * pmissx + pby * pmissy) / (Ebsq);
530 e2 = -pmissy + pby * (Deltasq_mid - mbsq) / (2 * Ebsq) + pby * (pbx * pmissx + pby * pmissy) / (Ebsq);
531 f2 = pmissx * pmissx + pmissy * pmissy -
532 ((Deltasq_mid - mbsq) / (2 * Eb) + (pbx * pmissx + pby * pmissy) / Eb) *
533 ((Deltasq_mid - mbsq) / (2 * Eb) + (pbx * pmissx + pby * pmissy) / Eb) +
536 double dis =
a2 * x0 * x0 + 2 *
b2 * x0 * y0 + c2 * y0 * y0 + 2 * d2 * x0 + 2 * e2 * y0 +
f2;
538 Deltasq_high = Deltasq_mid;
540 Deltasq_low = Deltasq_mid;
543 }
while (Deltasq_high - Deltasq_low > 0.001);
547 int Davismt2::scan_high(
double& Deltasq_high) {
552 double tempmass, maxmass;
554 maxmass =
sqrt(mnsq + Deltasq_high);
556 cout <<
"Davismt2::scan_high() ==> Deltasq_high = " << Deltasq_high << endl;
557 for (
double mass = tempmass + SCANSTEP;
mass < maxmass;
mass += SCANSTEP) {
559 nsols_high = nsols(Deltasq_high);
561 if (nsols_high > 0) {
570 int Davismt2::nsols(
double Dsq) {
571 double delta = (Dsq - masq) / (2 * Easq);
576 f1 = f12 * delta * delta + f10;
577 d2 = d21 * delta + d20;
578 e2 = e21 * delta + e20;
579 f2 = f22 * delta * delta + f21 * delta + f20;
583 long double A4, A3, A2, A1, A0;
591 4 *
a1 *
a2 *
c1 * e2 + 4 *
a1 *
a1 * c2 * e2) /
594 A2 = (4 *
a2 * c2 *
d1 *
d1 - 4 *
a2 *
c1 *
d1 * d2 - 4 *
a1 * c2 *
d1 * d2 + 4 *
a1 *
c1 * d2 * d2 -
595 8 *
a2 *
b2 *
d1 * e1 - 8 *
a2 *
b1 * d2 * e1 + 16 *
a1 *
b2 * d2 * e1 + 4 *
a2 *
a2 * e1 * e1 +
596 16 *
a2 *
b1 *
d1 * e2 - 8 *
a1 *
b2 *
d1 * e2 - 8 *
a1 *
b1 * d2 * e2 - 8 *
a1 *
a2 * e1 * e2 +
602 A1 = (-8 *
a2 *
d1 * d2 * e1 + 8 *
a1 * d2 * d2 * e1 + 8 *
a2 *
d1 *
d1 * e2 - 8 *
a1 *
d1 * d2 * e2 -
622 long double B3, B2, B1, B0;
628 long double C2, C1, C0;
629 C2 = -(A2 / 2 - 3 * A3sq / (16 * A4));
630 C1 = -(3 * A1 / 4. - A2 * A3 / (8 * A4));
631 C0 = -A0 + A1 * A3 / (16 * A4);
634 D1 = -B1 - (B3 * C1 * C1 / C2 - B3 * C0 - B2 * C1) / C2;
635 D0 = -B0 - B3 * C0 * C1 / (C2 * C2) + B2 * C0 / C2;
638 E0 = -C0 - C2 * D0 * D0 / (D1 *
D1) + C1 * D0 / D1;
640 long double t1, t2, t3, t4, t5;
650 nsol = signchange_n(t1, t2, t3, t4, t5) - signchange_p(t1, t2, t3, t4, t5);
660 int Davismt2::signchange_n(
long double t1,
long double t2,
long double t3,
long double t4,
long double t5) {
675 int Davismt2::signchange_p(
long double t1,
long double t2,
long double t3,
long double t4,
long double t5) {
const edm::EventSetup & c
Sin< T >::type sin(const T &t)
Geom::Theta< T > theta() const
static constexpr int verbose
Cos< T >::type cos(const T &t)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
static constexpr float b2
static constexpr float d1
static constexpr float b1