[4] | 1 | // -*- C++ -*-
|
---|
| 2 | // $Id: LorentzVectorC.cc,v 1.1 2008-06-04 14:15:06 demin Exp $
|
---|
| 3 | // ---------------------------------------------------------------------------
|
---|
| 4 | //
|
---|
| 5 | // This file is a part of the CLHEP - a Class Library for High Energy Physics.
|
---|
| 6 | //
|
---|
| 7 | // This is the implementation of the HepLorentzVector class:
|
---|
| 8 | // Those methods originating with ZOOM dealing with comparison (other than
|
---|
| 9 | // isSpaceLike, isLightlike, isTimelike, which are in the main part.)
|
---|
| 10 | //
|
---|
| 11 | // 11/29/05 mf in deltaR, replaced the direct subtraction
|
---|
| 12 | // pp.phi() - w.getV().phi() with pp.deltaRPhi(w.getV()) which behaves
|
---|
| 13 | // correctly across the 2pi boundary.
|
---|
| 14 |
|
---|
| 15 | #ifdef GNUPRAGMA
|
---|
| 16 | #pragma implementation
|
---|
| 17 | #endif
|
---|
| 18 |
|
---|
| 19 | #include "CLHEP/Vector/defs.h"
|
---|
| 20 | #include "CLHEP/Vector/LorentzVector.h"
|
---|
| 21 |
|
---|
| 22 | #include <cmath>
|
---|
| 23 |
|
---|
| 24 | namespace CLHEP {
|
---|
| 25 |
|
---|
| 26 | //-***********
|
---|
| 27 | // Comparisons
|
---|
| 28 | //-***********
|
---|
| 29 |
|
---|
| 30 | int HepLorentzVector::compare (const HepLorentzVector & w) const {
|
---|
| 31 | if ( ee > w.ee ) {
|
---|
| 32 | return 1;
|
---|
| 33 | } else if ( ee < w.ee ) {
|
---|
| 34 | return -1;
|
---|
| 35 | } else {
|
---|
| 36 | return ( pp.compare(w.pp) );
|
---|
| 37 | }
|
---|
| 38 | } /* Compare */
|
---|
| 39 |
|
---|
| 40 | bool HepLorentzVector::operator > (const HepLorentzVector & w) const {
|
---|
| 41 | return (compare(w) > 0);
|
---|
| 42 | }
|
---|
| 43 | bool HepLorentzVector::operator < (const HepLorentzVector & w) const {
|
---|
| 44 | return (compare(w) < 0);
|
---|
| 45 | }
|
---|
| 46 | bool HepLorentzVector::operator>= (const HepLorentzVector & w) const {
|
---|
| 47 | return (compare(w) >= 0);
|
---|
| 48 | }
|
---|
| 49 | bool HepLorentzVector::operator<= (const HepLorentzVector & w) const {
|
---|
| 50 | return (compare(w) <= 0);
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | //-********
|
---|
| 54 | // isNear
|
---|
| 55 | // howNear
|
---|
| 56 | //-********
|
---|
| 57 |
|
---|
| 58 | bool HepLorentzVector::isNear(const HepLorentzVector & w,
|
---|
| 59 | double epsilon) const {
|
---|
| 60 | double limit = fabs(pp.dot(w.pp));
|
---|
| 61 | limit += .25*((ee+w.ee)*(ee+w.ee));
|
---|
| 62 | limit *= epsilon*epsilon;
|
---|
| 63 | double delta = (pp - w.pp).mag2();
|
---|
| 64 | delta += (ee-w.ee)*(ee-w.ee);
|
---|
| 65 | return (delta <= limit );
|
---|
| 66 | } /* isNear() */
|
---|
| 67 |
|
---|
| 68 | double HepLorentzVector::howNear(const HepLorentzVector & w) const {
|
---|
| 69 | double wdw = fabs(pp.dot(w.pp)) + .25*((ee+w.ee)*(ee+w.ee));
|
---|
| 70 | double delta = (pp - w.pp).mag2() + (ee-w.ee)*(ee-w.ee);
|
---|
| 71 | if ( (wdw > 0) && (delta < wdw) ) {
|
---|
| 72 | return sqrt (delta/wdw);
|
---|
| 73 | } else if ( (wdw == 0) && (delta == 0) ) {
|
---|
| 74 | return 0;
|
---|
| 75 | } else {
|
---|
| 76 | return 1;
|
---|
| 77 | }
|
---|
| 78 | } /* howNear() */
|
---|
| 79 |
|
---|
| 80 | //-*********
|
---|
| 81 | // isNearCM
|
---|
| 82 | // howNearCM
|
---|
| 83 | //-*********
|
---|
| 84 |
|
---|
| 85 | bool HepLorentzVector::isNearCM
|
---|
| 86 | (const HepLorentzVector & w, double epsilon) const {
|
---|
| 87 |
|
---|
| 88 | double tTotal = (ee + w.ee);
|
---|
| 89 | Hep3Vector vTotal (pp + w.pp);
|
---|
| 90 | double vTotal2 = vTotal.mag2();
|
---|
| 91 |
|
---|
| 92 | if ( vTotal2 >= tTotal*tTotal ) {
|
---|
| 93 | // Either one or both vectors are spacelike, or the dominant T components
|
---|
| 94 | // are in opposite directions. So boosting and testing makes no sense;
|
---|
| 95 | // but we do consider two exactly equal vectors to be equal in any frame,
|
---|
| 96 | // even if they are spacelike and can't be boosted to a CM frame.
|
---|
| 97 | return (*this == w);
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | if ( vTotal2 == 0 ) { // no boost needed!
|
---|
| 101 | return (isNear(w, epsilon));
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | // Find the boost to the CM frame. We know that the total vector is timelike.
|
---|
| 105 |
|
---|
| 106 | double tRecip = 1./tTotal;
|
---|
| 107 | Hep3Vector boost ( vTotal * (-tRecip) );
|
---|
| 108 |
|
---|
| 109 | //-| Note that you could do pp/t and not be terribly inefficient since
|
---|
| 110 | //-| SpaceVector/t itself takes 1/t and multiplies. The code here saves
|
---|
| 111 | //-| a redundant check for t=0.
|
---|
| 112 |
|
---|
| 113 | // Boost both vectors. Since we have the same boost, there is no need
|
---|
| 114 | // to repeat the beta and gamma calculation; and there is no question
|
---|
| 115 | // about beta >= 1. That is why we don't just call w.boosted().
|
---|
| 116 |
|
---|
| 117 | double b2 = vTotal2*tRecip*tRecip;
|
---|
| 118 |
|
---|
| 119 | register double gamma = sqrt(1./(1.-b2));
|
---|
| 120 | register double boostDotV1 = boost.dot(pp);
|
---|
| 121 | register double gm1_b2 = (gamma-1)/b2;
|
---|
| 122 |
|
---|
| 123 | HepLorentzVector w1 ( pp + ((gm1_b2)*boostDotV1+gamma*ee) * boost,
|
---|
| 124 | gamma * (ee + boostDotV1) );
|
---|
| 125 |
|
---|
| 126 | register double boostDotV2 = boost.dot(w.pp);
|
---|
| 127 | HepLorentzVector w2 ( w.pp + ((gm1_b2)*boostDotV2+gamma*w.ee) * boost,
|
---|
| 128 | gamma * (w.ee + boostDotV2) );
|
---|
| 129 |
|
---|
| 130 | return (w1.isNear(w2, epsilon));
|
---|
| 131 |
|
---|
| 132 | } /* isNearCM() */
|
---|
| 133 |
|
---|
| 134 | double HepLorentzVector::howNearCM(const HepLorentzVector & w) const {
|
---|
| 135 |
|
---|
| 136 | double tTotal = (ee + w.ee);
|
---|
| 137 | Hep3Vector vTotal (pp + w.pp);
|
---|
| 138 | double vTotal2 = vTotal.mag2();
|
---|
| 139 |
|
---|
| 140 | if ( vTotal2 >= tTotal*tTotal ) {
|
---|
| 141 | // Either one or both vectors are spacelike, or the dominant T components
|
---|
| 142 | // are in opposite directions. So boosting and testing makes no sense;
|
---|
| 143 | // but we do consider two exactly equal vectors to be equal in any frame,
|
---|
| 144 | // even if they are spacelike and can't be boosted to a CM frame.
|
---|
| 145 | if (*this == w) {
|
---|
| 146 | return 0;
|
---|
| 147 | } else {
|
---|
| 148 | return 1;
|
---|
| 149 | }
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | if ( vTotal2 == 0 ) { // no boost needed!
|
---|
| 153 | return (howNear(w));
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 | // Find the boost to the CM frame. We know that the total vector is timelike.
|
---|
| 157 |
|
---|
| 158 | double tRecip = 1./tTotal;
|
---|
| 159 | Hep3Vector boost ( vTotal * (-tRecip) );
|
---|
| 160 |
|
---|
| 161 | //-| Note that you could do pp/t and not be terribly inefficient since
|
---|
| 162 | //-| SpaceVector/t itself takes 1/t and multiplies. The code here saves
|
---|
| 163 | //-| a redundant check for t=0.
|
---|
| 164 |
|
---|
| 165 | // Boost both vectors. Since we have the same boost, there is no need
|
---|
| 166 | // to repeat the beta and gamma calculation; and there is no question
|
---|
| 167 | // about beta >= 1. That is why we don't just call w.boosted().
|
---|
| 168 |
|
---|
| 169 | double b2 = vTotal2*tRecip*tRecip;
|
---|
| 170 | if ( b2 >= 1 ) { // NaN-proofing
|
---|
| 171 | ZMthrowC ( ZMxpvTachyonic (
|
---|
| 172 | "boost vector in howNearCM appears to be tachyonic"));
|
---|
| 173 | }
|
---|
| 174 | register double gamma = sqrt(1./(1.-b2));
|
---|
| 175 | register double boostDotV1 = boost.dot(pp);
|
---|
| 176 | register double gm1_b2 = (gamma-1)/b2;
|
---|
| 177 |
|
---|
| 178 | HepLorentzVector w1 ( pp + ((gm1_b2)*boostDotV1+gamma*ee) * boost,
|
---|
| 179 | gamma * (ee + boostDotV1) );
|
---|
| 180 |
|
---|
| 181 | register double boostDotV2 = boost.dot(w.pp);
|
---|
| 182 | HepLorentzVector w2 ( w.pp + ((gm1_b2)*boostDotV2+gamma*w.ee) * boost,
|
---|
| 183 | gamma * (w.ee + boostDotV2) );
|
---|
| 184 |
|
---|
| 185 | return (w1.howNear(w2));
|
---|
| 186 |
|
---|
| 187 | } /* howNearCM() */
|
---|
| 188 |
|
---|
| 189 | //-************
|
---|
| 190 | // deltaR
|
---|
| 191 | // isParallel
|
---|
| 192 | // howParallel
|
---|
| 193 | // howLightlike
|
---|
| 194 | //-************
|
---|
| 195 |
|
---|
| 196 | double HepLorentzVector::deltaR ( const HepLorentzVector & w ) const {
|
---|
| 197 |
|
---|
| 198 | double a = eta() - w.eta();
|
---|
| 199 | double b = pp.deltaPhi(w.getV());
|
---|
| 200 |
|
---|
| 201 | return sqrt ( a*a + b*b );
|
---|
| 202 |
|
---|
| 203 | } /* deltaR */
|
---|
| 204 |
|
---|
| 205 | // If the difference (in the Euclidean norm) of the normalized (in Euclidean
|
---|
| 206 | // norm) 4-vectors is small, then those 4-vectors are considered nearly
|
---|
| 207 | // parallel.
|
---|
| 208 |
|
---|
| 209 | bool HepLorentzVector::isParallel (const HepLorentzVector & w, double epsilon) const {
|
---|
| 210 | double norm = euclideanNorm();
|
---|
| 211 | double wnorm = w.euclideanNorm();
|
---|
| 212 | if ( norm == 0 ) {
|
---|
| 213 | if ( wnorm == 0 ) {
|
---|
| 214 | return true;
|
---|
| 215 | } else {
|
---|
| 216 | return false;
|
---|
| 217 | }
|
---|
| 218 | }
|
---|
| 219 | if ( wnorm == 0 ) {
|
---|
| 220 | return false;
|
---|
| 221 | }
|
---|
| 222 | HepLorentzVector w1 = *this / norm;
|
---|
| 223 | HepLorentzVector w2 = w / wnorm;
|
---|
| 224 | return ( (w1-w2).euclideanNorm2() <= epsilon*epsilon );
|
---|
| 225 | } /* isParallel */
|
---|
| 226 |
|
---|
| 227 |
|
---|
| 228 | double HepLorentzVector::howParallel (const HepLorentzVector & w) const {
|
---|
| 229 |
|
---|
| 230 | double norm = euclideanNorm();
|
---|
| 231 | double wnorm = w.euclideanNorm();
|
---|
| 232 | if ( norm == 0 ) {
|
---|
| 233 | if ( wnorm == 0 ) {
|
---|
| 234 | return 0;
|
---|
| 235 | } else {
|
---|
| 236 | return 1;
|
---|
| 237 | }
|
---|
| 238 | }
|
---|
| 239 | if ( wnorm == 0 ) {
|
---|
| 240 | return 1;
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 | HepLorentzVector w1 = *this / norm;
|
---|
| 244 | HepLorentzVector w2 = w / wnorm;
|
---|
| 245 | double x = (w1-w2).euclideanNorm();
|
---|
| 246 | return (x < 1) ? x : 1;
|
---|
| 247 |
|
---|
| 248 | } /* howParallel */
|
---|
| 249 |
|
---|
| 250 | double HepLorentzVector::howLightlike() const {
|
---|
| 251 | double m2 = fabs(restMass2());
|
---|
| 252 | double twoT2 = 2*ee*ee;
|
---|
| 253 | if (m2 < twoT2) {
|
---|
| 254 | return m2/twoT2;
|
---|
| 255 | } else {
|
---|
| 256 | return 1;
|
---|
| 257 | }
|
---|
| 258 | } /* HowLightlike */
|
---|
| 259 |
|
---|
| 260 | } // namespace CLHEP
|
---|