source: trunk/CLHEP/src/SpaceVector.cc@ 20

Last change on this file since 20 was 4, checked in by Pavel Demin, 16 years ago

first commit

File size: 8.0 KB
Line 
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
28namespace CLHEP {
29
30//-*****************************
31// - 1 -
32// set (multiple components)
33// in various coordinate systems
34//
35//-*****************************
36
37void 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
58void 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
73void 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
100void 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
126int 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
145bool Hep3Vector::operator > (const Hep3Vector & v) const {
146 return (compare(v) > 0);
147}
148bool Hep3Vector::operator < (const Hep3Vector & v) const {
149 return (compare(v) < 0);
150}
151bool Hep3Vector::operator>= (const Hep3Vector & v) const {
152 return (compare(v) >= 0);
153}
154bool 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
174double 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
190bool 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
225double 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
243bool 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
277double 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
291double 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
Note: See TracBrowser for help on using the repository browser.