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
|
---|