1 | // -*- C++ -*-
|
---|
2 | // ---------------------------------------------------------------------------
|
---|
3 | //
|
---|
4 | // This file is a part of the CLHEP - a Class Library for High Energy Physics.
|
---|
5 | //
|
---|
6 | // SpaceVector
|
---|
7 | //
|
---|
8 | // This is the implementation of those methods of the Hep3Vector class which
|
---|
9 | // originated from the ZOOM SpaceVector class. Several groups of these methods
|
---|
10 | // have been separated off into the following code units:
|
---|
11 | //
|
---|
12 | // SpaceVectorR.cc All methods involving rotation
|
---|
13 | // SpaceVectorD.cc All methods involving angle decomposition
|
---|
14 | // SpaceVectorP.cc Intrinsic properties and methods involving second vector
|
---|
15 | //
|
---|
16 |
|
---|
17 | #ifdef GNUPRAGMA
|
---|
18 | #pragma implementation
|
---|
19 | #endif
|
---|
20 |
|
---|
21 | #include "CLHEP/Vector/defs.h"
|
---|
22 | #include "CLHEP/Vector/ThreeVector.h"
|
---|
23 | #include "CLHEP/Vector/ZMxpv.h"
|
---|
24 | #include "CLHEP/Units/PhysicalConstants.h"
|
---|
25 |
|
---|
26 | #include <cmath>
|
---|
27 |
|
---|
28 | namespace CLHEP {
|
---|
29 |
|
---|
30 | //-*****************************
|
---|
31 | // - 1 -
|
---|
32 | // set (multiple components)
|
---|
33 | // in various coordinate systems
|
---|
34 | //
|
---|
35 | //-*****************************
|
---|
36 |
|
---|
37 | void Hep3Vector::setSpherical (
|
---|
38 | double r,
|
---|
39 | double theta,
|
---|
40 | double phi) {
|
---|
41 | if ( r < 0 ) {
|
---|
42 | ZMthrowC (ZMxpvNegativeR(
|
---|
43 | "Spherical coordinates set with negative R"));
|
---|
44 | // No special return needed if warning is ignored.
|
---|
45 | }
|
---|
46 | if ( (theta < 0) || (theta > CLHEP::pi) ) {
|
---|
47 | ZMthrowC (ZMxpvUnusualTheta(
|
---|
48 | "Spherical coordinates set with theta not in [0, PI]"));
|
---|
49 | // No special return needed if warning is ignored.
|
---|
50 | }
|
---|
51 | dz = r * cos(theta);
|
---|
52 | double rho ( r*sin(theta));
|
---|
53 | dy = rho * sin (phi);
|
---|
54 | dx = rho * cos (phi);
|
---|
55 | return;
|
---|
56 | } /* setSpherical (r, theta, phi) */
|
---|
57 |
|
---|
58 | void Hep3Vector::setCylindrical (
|
---|
59 | double rho,
|
---|
60 | double phi,
|
---|
61 | double z) {
|
---|
62 | if ( rho < 0 ) {
|
---|
63 | ZMthrowC (ZMxpvNegativeR(
|
---|
64 | "Cylindrical coordinates supplied with negative Rho"));
|
---|
65 | // No special return needed if warning is ignored.
|
---|
66 | }
|
---|
67 | dz = z;
|
---|
68 | dy = rho * sin (phi);
|
---|
69 | dx = rho * cos (phi);
|
---|
70 | return;
|
---|
71 | } /* setCylindrical (r, phi, z) */
|
---|
72 |
|
---|
73 | void Hep3Vector::setRhoPhiTheta (
|
---|
74 | double rho,
|
---|
75 | double phi,
|
---|
76 | double theta) {
|
---|
77 | if (rho == 0) {
|
---|
78 | ZMthrowC (ZMxpvZeroVector(
|
---|
79 | "Attempt set vector components rho, phi, theta with zero rho -- "
|
---|
80 | "zero vector is returned, ignoring theta and phi"));
|
---|
81 | dx = 0; dy = 0; dz = 0;
|
---|
82 | return;
|
---|
83 | }
|
---|
84 | if ( (theta == 0) || (theta == CLHEP::pi) ) {
|
---|
85 | ZMthrowA (ZMxpvInfiniteVector(
|
---|
86 | "Attempt set cylindrical vector vector with finite rho and "
|
---|
87 | "theta along the Z axis: infinite Z would be computed"));
|
---|
88 | }
|
---|
89 | if ( (theta < 0) || (theta > CLHEP::pi) ) {
|
---|
90 | ZMthrowC (ZMxpvUnusualTheta(
|
---|
91 | "Rho, phi, theta set with theta not in [0, PI]"));
|
---|
92 | // No special return needed if warning is ignored.
|
---|
93 | }
|
---|
94 | dz = rho / tan (theta);
|
---|
95 | dy = rho * sin (phi);
|
---|
96 | dx = rho * cos (phi);
|
---|
97 | return;
|
---|
98 | } /* setCyl (rho, phi, theta) */
|
---|
99 |
|
---|
100 | void Hep3Vector::setRhoPhiEta (
|
---|
101 | double rho,
|
---|
102 | double phi,
|
---|
103 | double eta ) {
|
---|
104 | if (rho == 0) {
|
---|
105 | ZMthrowC (ZMxpvZeroVector(
|
---|
106 | "Attempt set vector components rho, phi, eta with zero rho -- "
|
---|
107 | "zero vector is returned, ignoring eta and phi"));
|
---|
108 | dx = 0; dy = 0; dz = 0;
|
---|
109 | return;
|
---|
110 | }
|
---|
111 | double theta (2 * atan ( exp (-eta) ));
|
---|
112 | dz = rho / tan (theta);
|
---|
113 | dy = rho * sin (phi);
|
---|
114 | dx = rho * cos (phi);
|
---|
115 | return;
|
---|
116 | } /* setCyl (rho, phi, eta) */
|
---|
117 |
|
---|
118 | |
---|
119 |
|
---|
120 | //************
|
---|
121 | // - 3 -
|
---|
122 | // Comparisons
|
---|
123 | //
|
---|
124 | //************
|
---|
125 |
|
---|
126 | int Hep3Vector::compare (const Hep3Vector & v) const {
|
---|
127 | if ( dz > v.dz ) {
|
---|
128 | return 1;
|
---|
129 | } else if ( dz < v.dz ) {
|
---|
130 | return -1;
|
---|
131 | } else if ( dy > v.dy ) {
|
---|
132 | return 1;
|
---|
133 | } else if ( dy < v.dy ) {
|
---|
134 | return -1;
|
---|
135 | } else if ( dx > v.dx ) {
|
---|
136 | return 1;
|
---|
137 | } else if ( dx < v.dx ) {
|
---|
138 | return -1;
|
---|
139 | } else {
|
---|
140 | return 0;
|
---|
141 | }
|
---|
142 | } /* Compare */
|
---|
143 |
|
---|
144 |
|
---|
145 | bool Hep3Vector::operator > (const Hep3Vector & v) const {
|
---|
146 | return (compare(v) > 0);
|
---|
147 | }
|
---|
148 | bool Hep3Vector::operator < (const Hep3Vector & v) const {
|
---|
149 | return (compare(v) < 0);
|
---|
150 | }
|
---|
151 | bool Hep3Vector::operator>= (const Hep3Vector & v) const {
|
---|
152 | return (compare(v) >= 0);
|
---|
153 | }
|
---|
154 | bool Hep3Vector::operator<= (const Hep3Vector & v) const {
|
---|
155 | return (compare(v) <= 0);
|
---|
156 | }
|
---|
157 |
|
---|
158 | |
---|
159 |
|
---|
160 |
|
---|
161 | //-********
|
---|
162 | // Nearness
|
---|
163 | //-********
|
---|
164 |
|
---|
165 | // These methods all assume you can safely take mag2() of each vector.
|
---|
166 | // Absolutely safe but slower and much uglier alternatives were
|
---|
167 | // provided as build-time options in ZOOM SpaceVectors.
|
---|
168 | // Also, much smaller codes were provided tht assume you can square
|
---|
169 | // mag2() of each vector; but those return bad answers without warning
|
---|
170 | // when components exceed 10**90.
|
---|
171 | //
|
---|
172 | // IsNear, HowNear, and DeltaR are found in ThreeVector.cc
|
---|
173 |
|
---|
174 | double Hep3Vector::howParallel (const Hep3Vector & v) const {
|
---|
175 | // | V1 x V2 | / | V1 dot V2 |
|
---|
176 | double v1v2 = fabs(dot(v));
|
---|
177 | if ( v1v2 == 0 ) {
|
---|
178 | // Zero is parallel to no other vector except for zero.
|
---|
179 | return ( (mag2() == 0) && (v.mag2() == 0) ) ? 0 : 1;
|
---|
180 | }
|
---|
181 | Hep3Vector v1Xv2 ( cross(v) );
|
---|
182 | double abscross = v1Xv2.mag();
|
---|
183 | if ( abscross >= v1v2 ) {
|
---|
184 | return 1;
|
---|
185 | } else {
|
---|
186 | return abscross/v1v2;
|
---|
187 | }
|
---|
188 | } /* howParallel() */
|
---|
189 |
|
---|
190 | bool Hep3Vector::isParallel (const Hep3Vector & v,
|
---|
191 | double epsilon) const {
|
---|
192 | // | V1 x V2 | **2 <= epsilon **2 | V1 dot V2 | **2
|
---|
193 | // V1 is *this, V2 is v
|
---|
194 |
|
---|
195 | static const double TOOBIG = pow(2.0,507);
|
---|
196 | static const double SCALE = pow(2.0,-507);
|
---|
197 | double v1v2 = fabs(dot(v));
|
---|
198 | if ( v1v2 == 0 ) {
|
---|
199 | return ( (mag2() == 0) && (v.mag2() == 0) );
|
---|
200 | }
|
---|
201 | if ( v1v2 >= TOOBIG ) {
|
---|
202 | Hep3Vector sv1 ( *this * SCALE );
|
---|
203 | Hep3Vector sv2 ( v * SCALE );
|
---|
204 | Hep3Vector sv1Xsv2 = sv1.cross(sv2);
|
---|
205 | double x2 = sv1Xsv2.mag2();
|
---|
206 | double limit = v1v2*SCALE*SCALE;
|
---|
207 | limit = epsilon*epsilon*limit*limit;
|
---|
208 | return ( x2 <= limit );
|
---|
209 | }
|
---|
210 |
|
---|
211 | // At this point we know v1v2 can be squared.
|
---|
212 |
|
---|
213 | Hep3Vector v1Xv2 ( cross(v) );
|
---|
214 | if ( (fabs (v1Xv2.dx) > TOOBIG) ||
|
---|
215 | (fabs (v1Xv2.dy) > TOOBIG) ||
|
---|
216 | (fabs (v1Xv2.dz) > TOOBIG) ) {
|
---|
217 | return false;
|
---|
218 | }
|
---|
219 |
|
---|
220 | return ( (v1Xv2.mag2()) <= ((epsilon * v1v2) * (epsilon * v1v2)) );
|
---|
221 |
|
---|
222 | } /* isParallel() */
|
---|
223 |
|
---|
224 |
|
---|
225 | double Hep3Vector::howOrthogonal (const Hep3Vector & v) const {
|
---|
226 | // | V1 dot V2 | / | V1 x V2 |
|
---|
227 |
|
---|
228 | double v1v2 = fabs(dot(v));
|
---|
229 | //-| Safe because both v1 and v2 can be squared
|
---|
230 | if ( v1v2 == 0 ) {
|
---|
231 | return 0; // Even if one or both are 0, they are considered orthogonal
|
---|
232 | }
|
---|
233 | Hep3Vector v1Xv2 ( cross(v) );
|
---|
234 | double abscross = v1Xv2.mag();
|
---|
235 | if ( v1v2 >= abscross ) {
|
---|
236 | return 1;
|
---|
237 | } else {
|
---|
238 | return v1v2/abscross;
|
---|
239 | }
|
---|
240 |
|
---|
241 | } /* howOrthogonal() */
|
---|
242 |
|
---|
243 | bool Hep3Vector::isOrthogonal (const Hep3Vector & v,
|
---|
244 | double epsilon) const {
|
---|
245 | // | V1 x V2 | **2 <= epsilon **2 | V1 dot V2 | **2
|
---|
246 | // V1 is *this, V2 is v
|
---|
247 |
|
---|
248 | static const double TOOBIG = pow(2.0,507);
|
---|
249 | static const double SCALE = pow(2.0,-507);
|
---|
250 | double v1v2 = fabs(dot(v));
|
---|
251 | //-| Safe because both v1 and v2 can be squared
|
---|
252 | if ( v1v2 >= TOOBIG ) {
|
---|
253 | Hep3Vector sv1 ( *this * SCALE );
|
---|
254 | Hep3Vector sv2 ( v * SCALE );
|
---|
255 | Hep3Vector sv1Xsv2 = sv1.cross(sv2);
|
---|
256 | double x2 = sv1Xsv2.mag2();
|
---|
257 | double limit = epsilon*epsilon*x2;
|
---|
258 | double y2 = v1v2*SCALE*SCALE;
|
---|
259 | return ( y2*y2 <= limit );
|
---|
260 | }
|
---|
261 |
|
---|
262 | // At this point we know v1v2 can be squared.
|
---|
263 |
|
---|
264 | Hep3Vector eps_v1Xv2 ( cross(epsilon*v) );
|
---|
265 | if ( (fabs (eps_v1Xv2.dx) > TOOBIG) ||
|
---|
266 | (fabs (eps_v1Xv2.dy) > TOOBIG) ||
|
---|
267 | (fabs (eps_v1Xv2.dz) > TOOBIG) ) {
|
---|
268 | return true;
|
---|
269 | }
|
---|
270 |
|
---|
271 | // At this point we know all the math we need can be done.
|
---|
272 |
|
---|
273 | return ( v1v2*v1v2 <= eps_v1Xv2.mag2() );
|
---|
274 |
|
---|
275 | } /* isOrthogonal() */
|
---|
276 |
|
---|
277 | double Hep3Vector::setTolerance (double tol) {
|
---|
278 | // Set the tolerance for Hep3Vectors to be considered near one another
|
---|
279 | double oldTolerance (tolerance);
|
---|
280 | tolerance = tol;
|
---|
281 | return oldTolerance;
|
---|
282 | }
|
---|
283 |
|
---|
284 | |
---|
285 |
|
---|
286 | //-***********************
|
---|
287 | // Helper Methods:
|
---|
288 | // negativeInfinity()
|
---|
289 | //-***********************
|
---|
290 |
|
---|
291 | double Hep3Vector::negativeInfinity() const {
|
---|
292 | // A byte-order-independent way to return -Infinity
|
---|
293 | struct Dib {
|
---|
294 | union {
|
---|
295 | double d;
|
---|
296 | unsigned char i[8];
|
---|
297 | } u;
|
---|
298 | };
|
---|
299 | Dib negOne;
|
---|
300 | Dib posTwo;
|
---|
301 | negOne.u.d = -1.0;
|
---|
302 | posTwo.u.d = 2.0;
|
---|
303 | Dib value;
|
---|
304 | int k;
|
---|
305 | for (k=0; k<8; k++) {
|
---|
306 | value.u.i[k] = negOne.u.i[k] | posTwo.u.i[k];
|
---|
307 | }
|
---|
308 | return value.u.d;
|
---|
309 | }
|
---|
310 |
|
---|
311 | } // namespace CLHEP
|
---|
312 |
|
---|
313 |
|
---|