10 cached_momenta_ =
false;
12 m_ = max(test_mass, 0.);
16 const TLorentzVector &visible_B,
17 double invisible_px,
double invisible_py){
18 cached_momenta_ =
false;
20 mA_ = max(visible_A.M(), 0.);
23 mB_ = max(visible_B.M(), 0.);
31 void MT2::SetMomenta(
double visible_mass_a,
double visible_px_a,
double visible_py_a,
32 double visible_mass_b,
double visible_px_b,
double visible_py_b,
33 double invisible_px,
double invisible_py){
34 cached_momenta_ =
false;
36 mA_ = max(visible_mass_a, 0.);
39 mB_ = max(visible_mass_b, 0.);
53 double invisible_py_a)
const{
54 Rotate(invisible_px_a, invisible_py_a, rotation_angle_);
55 double invisible_px_b = x_ - invisible_px_a;
56 double invisible_py_b = y_ - invisible_py_a;
58 swap(invisible_px_a, invisible_px_b);
59 swap(invisible_py_a, invisible_py_b);
61 double mta = ComputeMT(mA_, xA_, yA_, m_, invisible_px_a, invisible_py_a);
62 double mtb = ComputeMT(mB_, xB_, yB_, m_, invisible_px_b, invisible_py_b);
63 return mta>mtb ? mta : mtb;
67 TLorentzVector &invisible_b)
const{
69 double invisible_px_a = 0.5*(x_+deltaX_);
70 double invisible_py_a = 0.5*(y_+deltaY_);
71 double invisible_px_b = 0.5*(x_-deltaX_);
72 double invisible_py_b = 0.5*(y_-deltaY_);
74 swap(invisible_px_a, invisible_px_b);
75 swap(invisible_py_a, invisible_py_b);
77 Rotate(invisible_px_a, invisible_py_a, -rotation_angle_);
78 Rotate(invisible_px_b, invisible_py_b, -rotation_angle_);
79 invisible_a.SetXYZM(invisible_px_a, invisible_py_a, 0., m_);
80 invisible_b.SetXYZM(invisible_px_b, invisible_py_b, 0., m_);
84 double &invisible_py_a,
85 double &invisible_px_b,
86 double &invisible_py_b)
const{
88 invisible_px_a = 0.5*(x_+deltaX_);
89 invisible_py_a = 0.5*(y_+deltaY_);
90 invisible_px_b = 0.5*(x_-deltaX_);
91 invisible_py_b = 0.5*(y_-deltaY_);
93 swap(invisible_px_a, invisible_px_b);
94 swap(invisible_py_a, invisible_py_b);
96 Rotate(invisible_px_a, invisible_py_a, -rotation_angle_);
97 Rotate(invisible_px_b, invisible_py_b, -rotation_angle_);
110 sides_swapped_ =
true;
112 sides_swapped_ =
false;
114 rotation_angle_ = -atan2(yA_, xA_);
115 Rotate(xA_, yA_, rotation_angle_);
116 Rotate(xB_, yB_, rotation_angle_);
117 Rotate(x_, y_, rotation_angle_);
121 double pt = hypot(y, x);
128 if(cached_mt2_)
return;
130 double lower_bound, upper_bound;
131 ComputeUnbalancedMT2(lower_bound, upper_bound);
132 double middle = lower_bound + 0.5*(upper_bound - lower_bound);
133 unbalanced_ = upper_bound-lower_bound;
134 while(lower_bound < middle && middle < upper_bound){
135 unsigned num_solutions = GetNumSolutions(middle);
136 if(num_solutions > 1){
137 upper_bound = middle;
139 lower_bound = middle;
141 middle = lower_bound + 0.5*(upper_bound - lower_bound);
149 lower_bound = m_ + mA_;
151 if(mA_ == 0. && m_ == 0. ){
153 double alpha = (x_*yB_ - xB_*y_)/(xA_*yB_ - xB_*yA_);
154 double beta = (xA_*y_ - x_*yA_)/(xA_*yB_ - xB_*yA_);
155 if(alpha >= 0. && beta >= 0.){
156 deltaX_ = 2.*alpha*xA_ - x_;
157 deltaY_ = 2.*alpha*yA_ - y_;
160 cached_momenta_ =
true;
164 double xa_mina = m_/mA_ * xA_;
165 double ya_mina = m_/mA_ * yA_;
166 lower_bound = m_ + mA_;
167 upper_bound = ComputeMT(mB_, xB_, yB_, m_, x_-xa_mina, y_-ya_mina);
168 if(upper_bound <= lower_bound){
169 upper_bound = lower_bound;
170 deltaX_ = 2.*xa_mina - x_;
171 deltaY_ = 2.*ya_mina - y_;
172 cached_momenta_ =
true;
175 if(lower_bound > upper_bound){
177 lower_bound = m_ + mA_;
178 double mta = ComputeMT(mA_, xA_, yA_, m_, 0.5*x_, 0.5*y_);
179 double mtb = ComputeMT(mB_, xB_, yB_, m_, 0.5*x_, 0.5*y_);
180 upper_bound = max(mta, mtb);
181 if(upper_bound < lower_bound){
183 upper_bound = lower_bound;
189 double m2,
double x2,
double y2){
190 return sqrt(m1*m1+m2*m2+2.*(sqrt((m1*m1+x1*x1+y1*y1)*(m2*m2+x2*x2+y2*y2))-x1*x2-y1*y2));
194 if(cached_momenta_)
return;
198 long double c4, c3, c2, c1, c0;
199 GetCoefficients(mt2_, c4, c3, c2, c1, c0);
200 double high = 10000.;
203 while(num_solutions == 0 && high < numeric_limits<double>::max()){
208 double middle = low + 0.5*(high-low);
209 while(low < middle && middle < high){
211 if(num_solutions == 0){
216 middle = low + 0.5*(high-low);
221 long double T2 = 4.*m_*m_ + x_*x_ + y_*y_;
222 long double zetaA2 = xA_*x_ + yA_*y_ + mt2_*mt2_ - mA_*mA_ - m_*m_;
223 long double ETA2 = mA_*mA_ + xA_*xA_ + yA_*yA_;
224 long double XA2 = mA_*mA_ + xA_*xA_;
225 long double YA2 = mA_*mA_ + yA_*yA_;
226 long double kappaA2 = xA_*yA_;
227 long double chiA3 = ETA2*x_ - xA_*zetaA2;
228 long double gammaA3 = ETA2*y_ - yA_*zetaA2;
229 long double lambdaA4 = ETA2*T2 - zetaA2*zetaA2;
230 long double xiA4 = kappaA2*kappaA2 - XA2*YA2;
231 long double rhoA5 = kappaA2*gammaA3 + XA2*chiA3;
232 long double sigmaA6 = gammaA3*gammaA3 - XA2*lambdaA4;
233 double dya1 = (kappaA2*deltaX_-gammaA3+sqrt(xiA4*deltaX_*deltaX_-2.*rhoA5*deltaX_+sigmaA6))/XA2;
234 double dya2 = (kappaA2*deltaX_-gammaA3-sqrt(xiA4*deltaX_*deltaX_-2.*rhoA5*deltaX_+sigmaA6))/XA2;
237 double mta1 = ComputeMT(mA_, xA_, yA_, m_, 0.5*(x_+deltaX_), 0.5*(y_+dya1));
238 double mtb1 = ComputeMT(mB_, xB_, yB_, m_, 0.5*(x_-deltaX_), 0.5*(y_-dya1));
239 double mta2 = ComputeMT(mA_, xA_, yA_, m_, 0.5*(x_+deltaX_), 0.5*(y_+dya2));
240 double mtb2 = ComputeMT(mB_, xB_, yB_, m_, 0.5*(x_-deltaX_), 0.5*(y_-dya2));
241 double mt21 = max(mta1, mtb1);
242 double mt22 = max(mta2, mtb2);
249 cached_momenta_ =
true;
253 long double c4, c3, c2, c1, c0;
254 GetCoefficients(mt, c4, c3, c2, c1, c0);
264 long double &c0)
const{
265 long double T2 = 4.*m_*m_ + x_*x_ + y_*y_;
266 long double zetaA2 = xA_*x_ + yA_*y_ + mt*mt - mA_*mA_ - m_*m_;
267 long double ETA2 = mA_*mA_ + xA_*xA_ + yA_*yA_;
268 long double XA2 = mA_*mA_ + xA_*xA_;
269 long double YA2 = mA_*mA_ + yA_*yA_;
270 long double kappaA2 = xA_*yA_;
271 long double chiA3 = ETA2*x_ - xA_*zetaA2;
272 long double gammaA3 = ETA2*y_ - yA_*zetaA2;
273 long double lambdaA4 = ETA2*T2 - zetaA2*zetaA2;
274 long double xiA4 = kappaA2*kappaA2 - XA2*YA2;
275 long double rhoA5 = kappaA2*gammaA3 + XA2*chiA3;
276 long double sigmaA6 = gammaA3*gammaA3 - XA2*lambdaA4;
277 long double zetaB2 = xB_*x_ + yB_*y_ + mt*mt - mB_*mB_ - m_*m_;
278 long double ETB2 = mB_*mB_ + xB_*xB_ + yB_*yB_;
279 long double XB2 = mB_*mB_ + xB_*xB_;
280 long double YB2 = mB_*mB_ + yB_*yB_;
281 long double kappaB2 = xB_*yB_;
282 long double chiB3 = ETB2*x_ - xB_*zetaB2;
283 long double gammaB3 = ETB2*y_ - yB_*zetaB2;
284 long double lambdaB4 = ETB2*T2 - zetaB2*zetaB2;
288 long double D4 = XA2*kappaB2 - kappaA2*XB2;
289 long double F5 = gammaA3*XB2 + XA2*gammaB3;
290 long double G6 = XA2*XA2*YB2 - 2.*XA2*kappaA2*kappaB2 + kappaA2*kappaA2*XB2 + xiA4*XB2;
291 long double H7 = XA2*gammaA3*kappaB2 - kappaA2*gammaA3*XB2 - rhoA5*XB2 - XA2*XA2*chiB3 - XA2*kappaA2*gammaB3;
292 long double J8 = gammaA3*gammaA3*XB2 + sigmaA6*XB2 + 2.*XA2*gammaA3*gammaB3 + XA2*XA2*lambdaB4;
293 c4 = G6*G6 - 4.*D4*D4*xiA4;
294 c3 = 4.*(G6*H7 - 2.*xiA4*D4*F5 + 2.*rhoA5*D4*D4);
295 c2 = 2.*(G6*J8 + 2.*H7*H7 - 2.*xiA4*F5*F5 + 8.*rhoA5*D4*F5 - 2.*sigmaA6*D4*D4);
296 c1 = 4.*(H7*J8 - 2.*sigmaA6*D4*F5 + 2.*rhoA5*F5*F5);
297 c0 = J8*J8 - 4.*sigmaA6*F5*F5;
unsigned NumRoots(const Polynomial< CoeffType > &poly)
void ComputeMomenta() const
void SetMomenta(const TLorentzVector &visible_A, const TLorentzVector &visible_B, double invisible_px, double invisible_py)
static void Rotate(double &x, double &y, double phi)
void ComputeUnbalancedMT2(double &lower_bound, double &upper_bound) const
void GetInvisibleMomenta(TLorentzVector &invisible_a, TLorentzVector &invisible_b) const
double IsUnbalanced() const
void GetCoefficients(double mt, long double &c4, long double &c3, long double &c2, long double &c1, long double &c0) const
double GetTrialMT2(double invisible_px_a, double invisible_py_a) const
static double ComputeMT(double m1, double x1, double y1, double m2, double x2, double y2)
unsigned GetNumSolutions(double mt) const
void SetTestMass(double test_mass)