CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/TopQuarkAnalysis/TopKinFitter/src/TtFullLepKinSolver.cc

Go to the documentation of this file.
00001 #include "TopQuarkAnalysis/TopKinFitter/interface/TtFullLepKinSolver.h"
00002 #include "TF2.h"
00003 
00004 TtFullLepKinSolver::TtFullLepKinSolver():
00005   topmass_begin(0),
00006   topmass_end(0),
00007   topmass_step(0),
00008   mw(80.4),
00009   mb(4.8),
00010   pxmiss_(0),
00011   pymiss_(0)
00012 {
00013   // That crude parametrisation has been obtained from a fit of O(1000) pythia events.
00014   // It is normalized to 1.
00015   EventShape_ = new TF2("landau2D","[0]*TMath::Landau(x,[1],[2],0)*TMath::Landau(y,[3],[4],0)",0,500,0,500);
00016   EventShape_->SetParameters(30.7137,56.2880,23.0744,59.1015,24.9145);
00017 }
00018 
00019 TtFullLepKinSolver::TtFullLepKinSolver(const double b, const double e, const double s, const std::vector<double>& nupars, const double mW, const double mB):
00020   topmass_begin(b),
00021   topmass_end(e),
00022   topmass_step(s),
00023   mw(mW),
00024   mb(mB),
00025   pxmiss_(0),
00026   pymiss_(0)
00027 {
00028   EventShape_ = new TF2("landau2D","[0]*TMath::Landau(x,[1],[2],0)*TMath::Landau(y,[3],[4],0)",0,500,0,500);
00029   EventShape_->SetParameters(nupars[0],nupars[1],nupars[2],nupars[3],nupars[4]);
00030 }
00031 
00032 //
00033 // destructor
00034 //
00035 TtFullLepKinSolver::~TtFullLepKinSolver() 
00036 {
00037   delete EventShape_;
00038 }
00039 
00040 TtDilepEvtSolution TtFullLepKinSolver::addKinSolInfo(TtDilepEvtSolution * asol) 
00041 {
00042   TtDilepEvtSolution fitsol(*asol);
00043   
00044   //antilepton and lepton
00045   TLorentzVector LV_e, LV_e_;
00046   //b and bbar quark
00047   TLorentzVector LV_b, LV_b_;
00048   
00049   bool hasMCinfo = true;
00050   if(fitsol.getGenN()) { // protect against non-dilept genevents
00051     genLV_n = TLorentzVector(fitsol.getGenN()->px(), fitsol.getGenN()->py(),
00052                              fitsol.getGenN()->pz(), fitsol.getGenN()->energy());
00053   } else hasMCinfo = false;
00054 
00055   if(fitsol.getGenNbar()) { // protect against non-dilept genevents
00056     genLV_n_ = TLorentzVector(fitsol.getGenNbar()->px(), fitsol.getGenNbar()->py(),
00057                               fitsol.getGenNbar()->pz(), fitsol.getGenNbar()->energy());
00058   } else hasMCinfo = false;
00059   // if MC is to be used to select the best top mass and is not available,
00060   // then nothing can be done. Stop here.
00061   if(useMCforBest_&&!hasMCinfo) return fitsol;
00062 
00063   // first lepton
00064   if (fitsol.getWpDecay() == "muon") {
00065     LV_e = TLorentzVector(fitsol.getMuonp().px(), fitsol.getMuonp().py(),
00066                           fitsol.getMuonp().pz(), fitsol.getMuonp().energy());
00067   } else if (fitsol.getWpDecay() == "electron") {
00068     LV_e = TLorentzVector(fitsol.getElectronp().px(), fitsol.getElectronp().py(),
00069                           fitsol.getElectronp().pz(), fitsol.getElectronp().energy());
00070   } else if (fitsol.getWpDecay() == "tau") {
00071     LV_e = TLorentzVector(fitsol.getTaup().px(), fitsol.getTaup().py(),
00072                           fitsol.getTaup().pz(), fitsol.getTaup().energy());
00073   }
00074     
00075   // second lepton
00076   if (fitsol.getWmDecay() == "muon") {
00077     LV_e_ = TLorentzVector(fitsol.getMuonm().px(), fitsol.getMuonm().py(),
00078                           fitsol.getMuonm().pz(), fitsol.getMuonm().energy());
00079   } else if (fitsol.getWmDecay() == "electron") {
00080     LV_e_ = TLorentzVector(fitsol.getElectronm().px(), fitsol.getElectronm().py(),
00081                            fitsol.getElectronm().pz(), fitsol.getElectronm().energy());
00082   } else if (fitsol.getWmDecay() == "tau") {
00083     LV_e_ = TLorentzVector(fitsol.getTaum().px(), fitsol.getTaum().py(),
00084                            fitsol.getTaum().pz(), fitsol.getTaum().energy());
00085   }
00086 
00087   // first jet
00088   LV_b = TLorentzVector(fitsol.getCalJetB().px(), fitsol.getCalJetB().py(),
00089                         fitsol.getCalJetB().pz(), fitsol.getCalJetB().energy());
00090 
00091   // second jet
00092   LV_b_ = TLorentzVector(fitsol.getCalJetBbar().px(), fitsol.getCalJetBbar().py(),
00093                          fitsol.getCalJetBbar().pz(), fitsol.getCalJetBbar().energy());
00094   
00095   //loop on top mass parameter
00096   double weightmax = -1e30;
00097   double mtmax = 0;
00098   for (double mt = topmass_begin; 
00099               mt < topmass_end + 0.5*topmass_step; 
00100               mt += topmass_step) {
00101     //cout << "mt = " << mt << endl;
00102     double q_coeff[5], q_sol[4];
00103     FindCoeff(LV_e, LV_e_, LV_b, LV_b_, mt, mt, pxmiss_, pymiss_, q_coeff);
00104     int NSol = quartic(q_coeff, q_sol);
00105     
00106     //loop on all solutions
00107     for (int isol = 0; isol < NSol; isol++) {
00108       TopRec(LV_e, LV_e_, LV_b, LV_b_, q_sol[isol]);
00109       double weight = useMCforBest_ ? WeightSolfromMC() : WeightSolfromShape();
00110       if (weight > weightmax) {
00111         weightmax =weight;
00112         mtmax = mt;
00113       }
00114     }
00115     
00116     //for (int i=0;i<5;i++) cout << " q_coeff["<<i<< "]= " << q_coeff[i];
00117     //cout << endl;
00118     
00119     //for (int i=0;i<4;i++) cout << " q_sol["<<i<< "]= " << q_sol[i];
00120     //cout << endl;
00121     //cout << "NSol_" << NSol << endl;
00122   }
00123   
00124   fitsol.setRecTopMass(mtmax);
00125   fitsol.setRecWeightMax(weightmax);
00126   
00127   return fitsol;
00128 }
00129 
00130 void
00131 TtFullLepKinSolver::SetConstraints(const double xx, const double yy)
00132 {
00133   pxmiss_ = xx;
00134   pymiss_ = yy;
00135 }
00136 
00137 TtFullLepKinSolver::NeutrinoSolution
00138 TtFullLepKinSolver::getNuSolution(const TLorentzVector& LV_l, 
00139                                   const TLorentzVector& LV_l_, 
00140                                   const TLorentzVector& LV_b, 
00141                                   const TLorentzVector& LV_b_)
00142 {
00143   math::XYZTLorentzVector maxLV_n  = math::XYZTLorentzVector(0,0,0,0); 
00144   math::XYZTLorentzVector maxLV_n_ = math::XYZTLorentzVector(0,0,0,0);   
00145 
00146   //loop on top mass parameter
00147   double weightmax = -1;
00148   for(double mt = topmass_begin; 
00149              mt < topmass_end + 0.5*topmass_step; 
00150              mt += topmass_step) {
00151     double q_coeff[5], q_sol[4];
00152     FindCoeff(LV_l, LV_l_, LV_b, LV_b_, mt, mt, pxmiss_, pymiss_, q_coeff);
00153     int NSol = quartic(q_coeff, q_sol);
00154     
00155     //loop on all solutions
00156     for (int isol = 0; isol < NSol; isol++) {
00157       TopRec(LV_l, LV_l_, LV_b, LV_b_, q_sol[isol]);
00158       double weight = WeightSolfromShape();
00159       if (weight > weightmax) {
00160         weightmax =weight;
00161         maxLV_n.SetPxPyPzE(LV_n.Px(), LV_n.Py(), LV_n.Pz(), LV_n.E());
00162         maxLV_n_.SetPxPyPzE(LV_n_.Px(), LV_n_.Py(), LV_n_.Pz(), LV_n_.E());
00163       }
00164     }
00165   }
00166   TtFullLepKinSolver::NeutrinoSolution nuSol;
00167   nuSol.neutrino    = reco::LeafCandidate(0, maxLV_n  );
00168   nuSol.neutrinoBar = reco::LeafCandidate(0, maxLV_n_ ); 
00169   nuSol.weight = weightmax; 
00170   return nuSol;
00171 }
00172 
00173 void
00174 TtFullLepKinSolver::FindCoeff(const TLorentzVector& al, 
00175                               const TLorentzVector& l,
00176                               const TLorentzVector& b_al,
00177                               const TLorentzVector& b_l,
00178                               const double mt, 
00179                               const double mat, 
00180                               const double px_miss, 
00181                               const double py_miss,
00182                               double* koeficienty)
00183 {
00184   double E, apom1, apom2, apom3;
00185   double k11, k21, k31, k41,  cpom1, cpom2, cpom3, l11, l21, l31, l41, l51, l61, k1, k2, k3, k4, k5,k6;
00186   double l1, l2, l3, l4, l5, l6, k15, k25, k35, k45;
00187 
00188   C = -al.Px()-b_al.Px()-l.Px()-b_l.Px() + px_miss;
00189   D = -al.Py()-b_al.Py()-l.Py()-b_l.Py() + py_miss;
00190 
00191   // right side of first two linear equations - missing pT
00192   
00193   E = (sqr(mt)-sqr(mw)-sqr(mb))/(2*b_al.E())-sqr(mw)/(2*al.E())-al.E()+al.Px()*b_al.Px()/b_al.E()+al.Py()*b_al.Py()/b_al.E()+al.Pz()*b_al.Pz()/b_al.E();
00194   F = (sqr(mat)-sqr(mw)-sqr(mb))/(2*b_l.E())-sqr(mw)/(2*l.E())-l.E()+l.Px()*b_l.Px()/b_l.E()+l.Py()*b_l.Py()/b_l.E()+l.Pz()*b_l.Pz()/b_l.E();
00195   
00196   m1 = al.Px()/al.E()-b_al.Px()/b_al.E();
00197   m2 = al.Py()/al.E()-b_al.Py()/b_al.E();
00198   m3 = al.Pz()/al.E()-b_al.Pz()/b_al.E();
00199   
00200   n1 = l.Px()/l.E()-b_l.Px()/b_l.E();
00201   n2 = l.Py()/l.E()-b_l.Py()/b_l.E();
00202   n3 = l.Pz()/l.E()-b_l.Pz()/b_l.E();
00203   
00204   pom = E-m1*C-m2*D;
00205   apom1 = sqr(al.Px())-sqr(al.E());
00206   apom2 = sqr(al.Py())-sqr(al.E());
00207   apom3 = sqr(al.Pz())-sqr(al.E());
00208   
00209   k11 = 1/sqr(al.E())*(pow(mw,4)/4+sqr(C)*apom1+sqr(D)*apom2+apom3*sqr(pom)/sqr(m3)+sqr(mw)*(al.Px()*C+al.Py()*D+al.Pz()*pom/m3)+2*al.Px()*al.Py()*C*D+2*al.Px()*al.Pz()*C*pom/m3+2*al.Py()*al.Pz()*D*pom/m3);
00210   k21 = 1/sqr(al.E())*(-2*C*m3*n3*apom1+2*apom3*n3*m1*pom/m3-sqr(mw)*m3*n3*al.Px()+sqr(mw)*m1*n3*al.Pz()-2*al.Px()*al.Py()*D*m3*n3+2*al.Px()*al.Pz()*C*m1*n3-2*al.Px()*al.Pz()*n3*pom+2*al.Py()*al.Pz()*D*m1*n3);
00211   k31 = 1/sqr(al.E())*(-2*D*m3*n3*apom2+2*apom3*n3*m2*pom/m3-sqr(mw)*m3*n3*al.Py()+sqr(mw)*m2*n3*al.Pz()-2*al.Px()*al.Py()*C*m3*n3+2*al.Px()*al.Pz()*C*m2*n3-2*al.Py()*al.Pz()*n3*pom+2*al.Py()*al.Pz()*D*m2*n3);
00212   k41 = 1/sqr(al.E())*(2*apom3*m1*m2*sqr(n3)+2*al.Px()*al.Py()*sqr(m3)*sqr(n3)-2*al.Px()*al.Pz()*m2*m3*sqr(n3)-2*al.Py()*al.Pz()*m1*m3*sqr(n3));
00213   k51 = 1/sqr(al.E())*(apom1*sqr(m3)*sqr(n3)+apom3*sqr(m1)*sqr(n3)-2*al.Px()*al.Pz()*m1*m3*sqr(n3));
00214   k61 = 1/sqr(al.E())*(apom2*sqr(m3)*sqr(n3)+apom3*sqr(m2)*sqr(n3)-2*al.Py()*al.Pz()*m2*m3*sqr(n3));
00215   
00216   cpom1 = sqr(l.Px())-sqr(l.E());
00217   cpom2 = sqr(l.Py())-sqr(l.E());
00218   cpom3 = sqr(l.Pz())-sqr(l.E());
00219   
00220   l11 = 1/sqr(l.E())*(pow(mw,4)/4+cpom3*sqr(F)/sqr(n3)+sqr(mw)*l.Pz()*F/n3);
00221   l21 = 1/sqr(l.E())*(-2*cpom3*F*m3*n1/n3+sqr(mw)*(l.Px()*m3*n3-l.Pz()*n1*m3)+2*l.Px()*l.Pz()*F*m3);
00222   l31 = 1/sqr(l.E())*(-2*cpom3*F*m3*n2/n3+sqr(mw)*(l.Py()*m3*n3-l.Pz()*n2*m3)+2*l.Py()*l.Pz()*F*m3);
00223   l41 = 1/sqr(l.E())*(2*cpom3*n1*n2*sqr(m3)+2*l.Px()*l.Py()*sqr(m3)*sqr(n3)-2*l.Px()*l.Pz()*n2*n3*sqr(m3)-2*l.Py()*l.Pz()*n1*n3*sqr(m3));
00224   l51 = 1/sqr(l.E())*(cpom1*sqr(m3)*sqr(n3)+cpom3*sqr(n1)*sqr(m3)-2*l.Px()*l.Pz()*n1*n3*sqr(m3));
00225   l61 = 1/sqr(l.E())*(cpom2*sqr(m3)*sqr(n3)+cpom3*sqr(n2)*sqr(m3)-2*l.Py()*l.Pz()*n2*n3*sqr(m3));
00226   
00227   k1 = k11*k61;
00228   k2 = k61*k21/k51;
00229   k3 = k31;
00230   k4 = k41/k51;
00231   k5 = k61/k51;
00232   k6 = 1;
00233   
00234   l1 = l11*k61;
00235   l2 = l21*k61/k51;
00236   l3 = l31;
00237   l4 = l41/k51;
00238   l5 = l51*k61/(sqr(k51));
00239   l6 = l61/k61;
00240   
00241   k15 = k1*l5-l1*k5;
00242   k25 = k2*l5-l2*k5;
00243   k35 = k3*l5-l3*k5;
00244   k45 = k4*l5-l4*k5;
00245   
00246   k16 = k1*l6-l1*k6;
00247   k26 = k2*l6-l2*k6;
00248   k36 = k3*l6-l3*k6;
00249   k46 = k4*l6-l4*k6;
00250   k56 = k5*l6-l5*k6;
00251 
00252   koeficienty[0] = k15*sqr(k36)-k35*k36*k16-k56*sqr(k16);
00253   koeficienty[1] = 2*k15*k36*k46+k25*sqr(k36)+k35*(-k46*k16-k36*k26)-k45*k36*k16-2*k56*k26*k16;
00254   koeficienty[2] = k15*sqr(k46)+2*k25*k36*k46+k35*(-k46*k26-k36*k56)-k56*(sqr(k26)+2*k56*k16)-k45*(k46*k16+k36*k26);
00255   koeficienty[3] = k25*sqr(k46)-k35*k46*k56-k45*(k46*k26+k36*k56)-2*sqr(k56)*k26;
00256   koeficienty[4] = -k45*k46*k56-pow(k56,3);
00257   
00258   // normalization of coefficients
00259   int moc=(int(log10(fabs(koeficienty[0])))+int(log10(fabs(koeficienty[4]))))/2;
00260   
00261   koeficienty[0]=koeficienty[0]/TMath::Power(10,moc);
00262   koeficienty[1]=koeficienty[1]/TMath::Power(10,moc);
00263   koeficienty[2]=koeficienty[2]/TMath::Power(10,moc);
00264   koeficienty[3]=koeficienty[3]/TMath::Power(10,moc);
00265   koeficienty[4]=koeficienty[4]/TMath::Power(10,moc);
00266 }
00267 
00268 void TtFullLepKinSolver::TopRec(const TLorentzVector& al, 
00269                                 const TLorentzVector& l,
00270                                 const TLorentzVector& b_al,
00271                                 const TLorentzVector& b_l, 
00272                                 const double sol)
00273 {
00274   TVector3 t_ttboost;
00275   TLorentzVector aux;
00276   double pxp, pyp, pzp, pup, pvp, pwp;
00277     
00278   pxp = sol*(m3*n3/k51);   
00279   pyp = -(m3*n3/k61)*(k56*pow(sol,2) + k26*sol + k16)/(k36 + k46*sol);
00280   pzp = -1/n3*(n1*pxp + n2*pyp - F);
00281   pwp = 1/m3*(m1*pxp + m2*pyp + pom);
00282   pup = C - pxp;
00283   pvp = D - pyp;
00284      
00285   LV_n_.SetXYZM(pxp, pyp, pzp, 0.0);
00286   LV_n.SetXYZM(pup, pvp, pwp, 0.0);
00287   
00288   LV_t_ = b_l + l + LV_n_;
00289   LV_t = b_al + al + LV_n;  
00290  
00291   aux = (LV_t_ + LV_t);
00292   t_ttboost = -aux.BoostVector();
00293   LV_tt_t_ = LV_t_;
00294   LV_tt_t = LV_t;
00295   LV_tt_t_.Boost(t_ttboost);
00296   LV_tt_t.Boost(t_ttboost); 
00297 }
00298 
00299 double
00300 TtFullLepKinSolver::WeightSolfromMC() const
00301 {
00302   double weight = 1;
00303   weight = ((LV_n.E() > genLV_n.E())? genLV_n.E()/LV_n.E(): LV_n.E()/genLV_n.E())
00304            *((LV_n_.E() > genLV_n_.E())? genLV_n_.E()/LV_n_.E(): LV_n_.E()/genLV_n_.E());
00305   return weight;
00306 }
00307 
00308 double
00309 TtFullLepKinSolver::WeightSolfromShape() const
00310 {
00311   return EventShape_->Eval(LV_n.E(),LV_n_.E());
00312 }
00313                      
00314 int
00315 TtFullLepKinSolver::quartic(double *koeficienty, double* koreny) const
00316 {
00317   double w, b0, b1, b2;
00318   double c[4];
00319   double d0, d1, h, t, z;
00320   double *px;
00321  
00322   if (koeficienty[4]==0.0) 
00323     return cubic(koeficienty, koreny);
00324   /* quartic problem? */
00325   w = koeficienty[3]/(4*koeficienty[4]);
00326   /* offset */
00327   b2 = -6*sqr(w) + koeficienty[2]/koeficienty[4];
00328   /* koeficienty. of shifted polynomial */
00329   b1 = (8*sqr(w) - 2*koeficienty[2]/koeficienty[4])*w + koeficienty[1]/koeficienty[4];
00330   b0 = ((-3*sqr(w) + koeficienty[2]/koeficienty[4])*w - koeficienty[1]/koeficienty[4])*w + koeficienty[0]/koeficienty[4];
00331 
00332   c[3] = 1.0;
00333   /* cubic resolvent */
00334   c[2] = b2;
00335   c[1] = -4*b0;
00336   c[0] = sqr(b1) - 4*b0*b2;
00337   
00338   cubic(c, koreny);
00339   z = koreny[0];
00340   //double z1=1.0,z2=2.0,z3=3.0;
00341   //TMath::RootsCubic(c,z1,z2,z3);
00342   //if (z2 !=0) z = z2;
00343   //if (z1 !=0) z = z1;
00344   /* only lowermost root needed */
00345 
00346   int nreal = 0;
00347   px = koreny;
00348   t = sqrt(0.25*sqr(z) - b0);
00349   for(int i=-1; i<=1; i+=2) {
00350     d0 = -0.5*z + i*t;
00351     /* coeffs. of quadratic factor */
00352     d1 = (t!=0.0)? -i*0.5*b1/t : i*sqrt(-z - b2);
00353     h = 0.25*sqr(d1) - d0;
00354     if (h>=0.0) {
00355       h = sqrt(h);
00356       nreal += 2;
00357       *px++ = -0.5*d1 - h - w;
00358       *px++ = -0.5*d1 + h - w;
00359     }
00360   }
00361 
00362   //  if (nreal==4) {
00363     /* sort results */
00364 //    if (koreny[2]<koreny[0]) SWAP(koreny[0], koreny[2]);
00365 //    if (koreny[3]<koreny[1]) SWAP(koreny[1], koreny[3]);
00366 //    if (koreny[1]<koreny[0]) SWAP(koreny[0], koreny[1]);
00367 //    if (koreny[3]<koreny[2]) SWAP(koreny[2], koreny[3]);
00368 //    if (koreny[2]<koreny[1]) SWAP(koreny[1], koreny[2]);
00369 //  }
00370   return nreal;
00371 
00372 }
00373 
00374 int
00375 TtFullLepKinSolver::cubic(const double *coeffs, double* koreny) const
00376 {
00377   unsigned nreal;
00378   double w, p, q, dis, h, phi;
00379   
00380   if (coeffs[3]!=0.0) {
00381     /* cubic problem? */
00382     w = coeffs[2]/(3*coeffs[3]);
00383     p = sqr(coeffs[1]/(3*coeffs[3])-sqr(w))*(coeffs[1]/(3*coeffs[3])-sqr(w));
00384     q = -0.5*(2*sqr(w)*w-(coeffs[1]*w-coeffs[0])/coeffs[3]);
00385     dis = sqr(q)+p;
00386     /* discriminant */
00387     if (dis<0.0) {
00388       /* 3 real solutions */
00389       h = q/sqrt(-p);
00390       if (h>1.0) h = 1.0;
00391       /* confine the argument of */
00392       if (h<-1.0) h = -1.0;
00393       /* acos to [-1;+1] */
00394       phi = acos(h);
00395       p = 2*TMath::Power(-p, 1.0/6.0);
00396       for(unsigned i=0; i<3; i++) 
00397         koreny[i] = p*cos((phi+2*i*TMath::Pi())/3.0) - w;
00398       if (koreny[1]<koreny[0]) SWAP(koreny[0], koreny[1]);
00399       /* sort results */
00400       if (koreny[2]<koreny[1]) SWAP(koreny[1], koreny[2]);
00401       if (koreny[1]<koreny[0]) SWAP(koreny[0], koreny[1]);
00402       nreal = 3;
00403     }
00404     else {
00405       /* only one real solution */
00406       dis = sqrt(dis);
00407       h = TMath::Power(fabs(q+dis), 1.0/3.0);
00408       p = TMath::Power(fabs(q-dis), 1.0/3.0);
00409       koreny[0] = ((q+dis>0.0)? h : -h) + ((q-dis>0.0)? p : -p) -  w;
00410       nreal = 1;
00411     }
00412 
00413     /* Perform one step of a Newton iteration in order to minimize
00414        round-off errors */
00415     for(unsigned i=0; i<nreal; i++) {
00416       h = coeffs[1] + koreny[i] * (2 * coeffs[2] + 3 * koreny[i] * coeffs[3]);
00417       if (h != 0.0)
00418         koreny[i] -= (coeffs[0] + koreny[i] * (coeffs[1] + koreny[i] * (coeffs[2] + koreny[i] * coeffs[3])))/h;
00419     }
00420   }
00421 
00422   else if (coeffs[2]!=0.0) {
00423     /* quadratic problem? */
00424     p = 0.5*coeffs[1]/coeffs[2];
00425     dis = sqr(p) - coeffs[0]/coeffs[2];
00426     if (dis>=0.0) {
00427       /* two real solutions */
00428       dis = sqrt(dis);
00429       koreny[0] = -p - dis;
00430       koreny[1] = -p + dis;
00431       nreal = 2;
00432     }
00433     else
00434       /* no real solution */
00435       nreal = 0;
00436   }
00437 
00438   else if (coeffs[1]!=0.0) {
00439     /* linear problem? */
00440     koreny[0] = -coeffs[0]/coeffs[1];
00441     nreal = 1;
00442   }
00443 
00444   else
00445     /* no equation */
00446     nreal = 0;
00447   
00448   return nreal;
00449 }
00450 
00451 
00452 void
00453 TtFullLepKinSolver::SWAP(double& realone, double& realtwo) const
00454 {
00455   if (realtwo < realone) {
00456     double aux = realtwo;
00457     realtwo = realone;
00458     realone = aux;
00459   }
00460 }