ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitCommon/MathTools/interface/Angle.h
Revision: 1.4
Committed: Sun Jan 24 21:00:19 2010 UTC (15 years, 3 months ago) by bendavid
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_032, Mit_031, Mit_025c_branch2, Mit_025c_branch1, Mit_030, Mit_029c, Mit_030_pre1, Mit_029a, Mit_029, Mit_029_pre1, Mit_028a, Mit_025c_branch0, Mit_028, Mit_027a, Mit_027, Mit_026, Mit_025e, Mit_025d, Mit_025c, Mit_025b, Mit_025a, Mit_025, Mit_025pre2, Mit_024b, Mit_025pre1, Mit_024a, Mit_024, Mit_023, Mit_022a, Mit_022, Mit_020d, TMit_020d, Mit_020c, Mit_021, Mit_021pre2, Mit_021pre1, Mit_020b, Mit_020a, Mit_020, Mit_020pre1, Mit_018, Mit_017, Mit_017pre3, Mit_017pre2, Mit_017pre1, V07-05-00, Mit_016, Mit_015b, Mit_015a, Mit_015, Mit_014e, Mit_014d, Mit_014c, Mit_014b, ConvRejection-10-06-09, Mit_014a, Mit_014, Mit_014pre3, Mit_014pre2, Mit_014pre1, Mit_013d, Mit_013c, Mit_013b, Mit_013a, Mit_013, Mit_013pre1, HEAD
Branch point for: Mit_025c_branch
Changes since 1.3: +10 -9 lines
Log Message:
Fix compiler errors and warnings moving to slc5_ia32_gcc434

File Contents

# Content
1 //--------------------------------------------------------------------------------------------------
2 // $Id: Angle.h,v 1.3 2009/07/20 03:12:22 loizides Exp $
3 //
4 // Angle classes, with automatic range checking. SignedAngle ranges from -PI to PI, UnsignedAngle
5 // from 0 to 2PI. The two types of angle convert implicitly into double.
6 //
7 // The Angle classes reimplement (inline) most arithmetic operators, instead of relying on the
8 // implicit conversion to double and converting the result back when it is assigned to an Angle
9 // variable. There are two reasons for this:
10 //
11 // 1) Temporary values are kept in range (example: std::cout << alpha+beta)
12 // 2) Optimization (the difference of two Angles is guaranteed to lie less
13 // than 2PI outside the allowed range, for example)
14 //
15 // The only exception is multiplication: the "2" in "2 * alpha" could be interpreted as a length. If
16 // you want the result of a multiplication to be bounded, assign it to a temporary Angle, or use *=.
17 //
18 // Due to operator ambiguity, some mixed-type arithmetics might fail:
19 // for example, (int + Angle) or (Angle / long)
20 // The most common operations are supported:
21 // double +- angle; angle +-/ double; angle / int
22 //
23 // Comparison between Angles is done via conversion to double. Make sure you do not compare a
24 // SignedAngle to an UnsignedAngle.
25 //
26 // Since the bounds and return types for the two classes are different, operators cannot be factored
27 // in a single superclass.
28 //
29 // In C++, implicit conversion operators are shallow - they are not nested. Therefore, if you want
30 // to convert a SignedAngle into an UnsignedAngle, you need an intermediate cast into double. For
31 // example:
32 //
33 // SignedAngle s; UnsignedAngle u = double(s);
34 //
35 // Adding a direct conversion between the two types of angle would result in several ambiguities.
36 //
37 // Author: C.Paus (stolen from CDF implementation of Paolo Gatti, University of Padova / INFN,
38 // therefore not all our coding conventions fulfilled)
39 //--------------------------------------------------------------------------------------------------
40
41 #ifndef MITCOMMON_MATHTOOLS_ANGLE_H
42 #define MITCOMMON_MATHTOOLS_ANGLE_H
43
44 #include <Riostream.h>
45 #include <Rtypes.h>
46 #include <math.h>
47 #include <limits>
48
49 namespace mithep
50 {
51 //--------------------------------------------------------------------------------------------------
52 //
53 // Signed angles, ranging from -PI to +PI
54 //
55 //--------------------------------------------------------------------------------------------------
56 class SignedAngle
57 {
58 public:
59 // Constructor
60 SignedAngle(double angle = 0.0);
61
62 // No destructor; use standard copy constructor and assignment operator
63
64 // Implicit conversion to double
65 operator double() const;
66
67 // Self-modifying operations
68 SignedAngle& operator += (const SignedAngle& other);
69 SignedAngle& operator -= (const SignedAngle& other);
70 SignedAngle& operator *= (double other);
71 SignedAngle& operator /= (double other);
72
73 // Other operations
74 friend SignedAngle operator + (double me, const SignedAngle& other);
75 SignedAngle operator + (const SignedAngle& other) const;
76 SignedAngle operator + (double other) const;
77 friend SignedAngle operator - (double me, const SignedAngle& other);
78 SignedAngle operator - (const SignedAngle& other) const;
79 SignedAngle operator - (double other) const;
80 SignedAngle operator / (double other) const;
81 SignedAngle operator / (int other) const;
82
83 // I/O
84 //friend std::ostream& operator << (std::ostream& out, const SignedAngle& me)
85 // { out << me.fValue; return out; }
86
87 //friend std::istream& operator >> (std::istream& in, SignedAngle& me)
88 // { in >> me.fValue; me.FixRangeSlow(); return in; }
89
90 private:
91 // Enforce the correct range for the angle's value. The first version is faster, but assumes
92 // the current value is within 2PI of the correct range. The second version is slower but
93 // always works
94 void FixRangeFast();
95 void FixRangeSlow();
96
97 double fValue;
98
99 ClassDef(SignedAngle, 0) // Signed angle class
100 };
101
102
103 //--------------------------------------------------------------------------------------------------
104 //
105 // Unsigned angles, ranging from 0 to 2PI
106 //
107 //--------------------------------------------------------------------------------------------------
108 class UnsignedAngle
109 {
110 public:
111 // Constructor
112 UnsignedAngle(double angle = 0.0);
113
114 // No destructor; use standard copy constructor and assignment operator
115
116 // Implicit conversion to double
117 operator double() const;
118
119 // Self-modifying operations
120 UnsignedAngle& operator += (const UnsignedAngle& other);
121 UnsignedAngle& operator -= (const UnsignedAngle& other);
122 UnsignedAngle& operator *= (double other);
123 UnsignedAngle& operator /= (double other);
124
125 // Other operations
126 friend UnsignedAngle operator + (double me, const UnsignedAngle& other);
127 UnsignedAngle operator + (const UnsignedAngle& other) const;
128 UnsignedAngle operator + (double other) const;
129 friend UnsignedAngle operator - (double me, const UnsignedAngle& other);
130 UnsignedAngle operator - (const UnsignedAngle& other) const;
131 UnsignedAngle operator - (double other) const;
132 UnsignedAngle operator / (double other) const;
133 UnsignedAngle operator / (int other) const;
134
135 // I/O
136 // friend std::ostream& operator << (std::ostream& out, const UnsignedAngle& me)
137 // { out << me.fValue; return out; }
138 // friend std::istream& operator >> (std::istream& in, UnsignedAngle& me)
139 // { in >> me.fValue; me.FixRangeSlow(); return in; }
140
141 private:
142 // Enforce the correct range for the angle's value. The first version is faster,
143 // but assumes the current value is within 2PI of the correct range.
144 // The second version is slower but always works.
145
146 void FixRangeFast();
147 void FixRangeSlow();
148
149 double fValue;
150
151 ClassDef(UnsignedAngle, 0) // Unsigned angle class
152 };
153
154 // By default, "Angles" are unsigned (CDF convention: 0-2PI range).
155 typedef UnsignedAngle Angle;
156
157 //--------------------------------------------------------------------------------------------------
158 inline
159 void mithep::SignedAngle::FixRangeFast()
160 {
161 if (fValue >= M_PI)
162 fValue -= 2 * M_PI;
163 else if (fValue < -M_PI)
164 fValue += 2 * M_PI;
165 }
166
167 //--------------------------------------------------------------------------------------------------
168 inline
169 void mithep::SignedAngle::FixRangeSlow()
170 {
171 if (fValue < -M_PI) {
172 if (fValue < double(std::numeric_limits<int>::min()) * 2 * M_PI)
173 std::cout << "@SUB=SignedAngle::FixRangeSlow"
174 << "Angle out of range: " << fValue << std::endl;
175 else {
176 int shift = int((M_PI - fValue) / (2 * M_PI));
177 fValue += shift * 2 * M_PI;
178 }
179 }
180 // The previous step might have brought -3PI to +PI, so no 'else' here.
181 if (fValue >= M_PI) {
182 if (fValue > double(std::numeric_limits<int>::max()) * 2 * M_PI) {
183 std::cout << "@SUB=SignedAngle::FixRangeSlow"
184 << "Angle out of range: " << fValue << std::endl;
185 }
186 else {
187 int shift = int((fValue + M_PI) / (2 * M_PI));
188 fValue -= shift * 2 * M_PI;
189 }
190 }
191 }
192
193
194 //--------------------------------------------------------------------------------------------------
195 inline
196 mithep::SignedAngle::SignedAngle(double angle)
197 : fValue(angle)
198 {
199 // Constructor
200
201 FixRangeSlow();
202 }
203
204 //--------------------------------------------------------------------------------------------------
205 inline
206 mithep::SignedAngle::operator double() const
207 {
208 // Implicit conversion to double
209 return fValue;
210 }
211
212 // Self-modifying operations
213 //--------------------------------------------------------------------------------------------------
214 inline
215 mithep::SignedAngle& mithep::SignedAngle::operator += (const mithep::SignedAngle& other)
216 {
217 fValue += other.fValue;
218 FixRangeFast(); // other.fValue is guaranteed to be in range
219 return *this;
220 }
221
222 //--------------------------------------------------------------------------------------------------
223 inline
224 mithep::SignedAngle& mithep::SignedAngle::operator -= (const mithep::SignedAngle& other)
225 {
226 fValue -= other.fValue;
227 FixRangeFast(); // other.fValue is guaranteed to be in range
228 return *this;
229 }
230
231 //--------------------------------------------------------------------------------------------------
232 inline
233 mithep::SignedAngle& mithep::SignedAngle::operator *= (double other)
234 {
235 fValue *= other;
236 FixRangeSlow();
237 return *this;
238 }
239
240 //--------------------------------------------------------------------------------------------------
241 inline
242 mithep::SignedAngle& mithep::SignedAngle::operator /= (double other)
243 {
244 fValue /= other;
245 FixRangeSlow();
246 return *this;
247 }
248
249 // Other operations
250 //--------------------------------------------------------------------------------------------------
251 inline
252 mithep::SignedAngle operator + (double me, const mithep::SignedAngle& other)
253 {
254 mithep::SignedAngle result(me);
255 result += other;
256 return result;
257 }
258
259 //--------------------------------------------------------------------------------------------------
260 inline
261 mithep::SignedAngle mithep::SignedAngle::operator + (const mithep::SignedAngle& other) const
262 {
263 mithep::SignedAngle result(*this);
264 result += other;
265 return result;
266 }
267
268 //--------------------------------------------------------------------------------------------------
269 inline
270 mithep::SignedAngle mithep::SignedAngle::operator + (double other) const
271 {
272 return mithep::SignedAngle(fValue + other);
273 }
274
275 //--------------------------------------------------------------------------------------------------
276 inline
277 mithep::SignedAngle operator - (double me, const mithep::SignedAngle& other)
278 {
279 mithep::SignedAngle result(me);
280 result -= other;
281 return result;
282 }
283
284 //--------------------------------------------------------------------------------------------------
285 inline
286 mithep::SignedAngle mithep::SignedAngle::operator - (const mithep::SignedAngle& other) const
287 {
288 mithep::SignedAngle result(*this);
289 result -= other;
290 return result;
291 }
292
293 //--------------------------------------------------------------------------------------------------
294 inline
295 mithep::SignedAngle mithep::SignedAngle::operator - (double other) const
296 {
297 return mithep::SignedAngle(fValue - other);
298 }
299
300 //--------------------------------------------------------------------------------------------------
301 inline
302 mithep::SignedAngle mithep::SignedAngle::operator / (double other) const
303 {
304 mithep::SignedAngle result(*this);
305 result /= other;
306 return result;
307 }
308
309 //--------------------------------------------------------------------------------------------------
310 inline
311 mithep::SignedAngle mithep::SignedAngle::operator / (int other) const
312 {
313 mithep::SignedAngle result(*this);
314 result /= other;
315 return result;
316 }
317
318 //--------------------------------------------------------------------------------------------------
319 inline
320 void mithep::UnsignedAngle::FixRangeFast()
321 {
322 if (fValue >= 2 * M_PI)
323 fValue -= 2 * M_PI;
324 else if (fValue < 0)
325 fValue += 2 * M_PI;
326 }
327
328 //--------------------------------------------------------------------------------------------------
329 inline
330 void mithep::UnsignedAngle::FixRangeSlow()
331 {
332 if (fValue < 0) {
333 if (fValue < double(std::numeric_limits<int>::min()) * 2 * M_PI)
334 std::cout << "@SUB=UnsignedAngle::FixRangeSlow"
335 << "Angle out of range: " << fValue << std::endl;
336 else {
337 int shift = 1 - int(fValue / (2 * M_PI));
338 fValue += shift * 2 * M_PI;
339 }
340 }
341 // The previous step might have brought -2PI to +2PI, so no 'else' here.
342 if (fValue >= 2 * M_PI) {
343 if (fValue > double(std::numeric_limits<int>::max()) * 2 * M_PI)
344 std::cout << "@SUB=UnsignedAngle::FixRangeSlow"
345 << "Angle out of range: " << fValue << std::endl;
346 else {
347 int shift = int(fValue / (2 * M_PI));
348 fValue -= shift * 2 * M_PI;
349 }
350 }
351 }
352
353 //--------------------------------------------------------------------------------------------------
354 inline
355 mithep::UnsignedAngle::UnsignedAngle(double angle)
356 : fValue(angle)
357 {
358 // Constructor
359 FixRangeSlow();
360 }
361
362 //--------------------------------------------------------------------------------------------------
363 inline
364 mithep::UnsignedAngle::operator double() const
365 {
366 // Implicit conversion to double
367
368 return fValue;
369 }
370
371 // Self-modifying operations
372 //--------------------------------------------------------------------------------------------------
373 inline
374 mithep::UnsignedAngle& mithep::UnsignedAngle::operator += (const mithep::UnsignedAngle& other)
375 {
376 fValue += other.fValue;
377 FixRangeFast(); // other.fValue is guaranteed to be in range
378 return *this;
379 }
380
381 //--------------------------------------------------------------------------------------------------
382 inline
383 mithep::UnsignedAngle& mithep::UnsignedAngle::operator -= (const mithep::UnsignedAngle& other)
384 {
385 fValue -= other.fValue;
386 FixRangeFast(); // other.fValue is guaranteed to be in range
387 return *this;
388 }
389
390 //--------------------------------------------------------------------------------------------------
391 inline
392 mithep::UnsignedAngle& mithep::UnsignedAngle::operator *= (double other)
393 {
394 fValue *= other;
395 FixRangeSlow();
396 return *this;
397 }
398
399 //--------------------------------------------------------------------------------------------------
400 inline
401 mithep::UnsignedAngle& mithep::UnsignedAngle::operator /= (double other)
402 {
403 fValue /= other;
404 FixRangeSlow();
405 return *this;
406 }
407
408 // Other operations
409 //--------------------------------------------------------------------------------------------------
410 inline
411 mithep::UnsignedAngle operator + (double me, const mithep::UnsignedAngle& other)
412 {
413 mithep::UnsignedAngle result(me);
414 result += other;
415 return result;
416 }
417
418 //--------------------------------------------------------------------------------------------------
419 inline
420 mithep::UnsignedAngle mithep::UnsignedAngle::operator + (const mithep::UnsignedAngle& other) const
421 {
422 mithep::UnsignedAngle result(*this);
423 result += other;
424 return result;
425 }
426
427 //--------------------------------------------------------------------------------------------------
428 inline
429 mithep::UnsignedAngle mithep::UnsignedAngle::operator + (double other) const
430 {
431 return mithep::UnsignedAngle(fValue + other);
432 }
433
434 //--------------------------------------------------------------------------------------------------
435 inline
436 mithep::UnsignedAngle operator - (double me, const mithep::UnsignedAngle& other)
437 {
438 mithep::UnsignedAngle result(me);
439 result -= other;
440 return result;
441 }
442
443 //--------------------------------------------------------------------------------------------------
444 inline
445 mithep::UnsignedAngle mithep::UnsignedAngle::operator - (const mithep::UnsignedAngle& other) const
446 {
447 mithep::UnsignedAngle result(*this);
448 result -= other;
449 return result;
450 }
451
452 //--------------------------------------------------------------------------------------------------
453 inline
454 mithep::UnsignedAngle mithep::UnsignedAngle::operator - (double other) const
455 {
456 return mithep::UnsignedAngle(fValue - other);
457 }
458
459 //--------------------------------------------------------------------------------------------------
460 inline
461 mithep::UnsignedAngle mithep::UnsignedAngle::operator / (double other) const
462 {
463 mithep::UnsignedAngle result(*this);
464 result /= other;
465 return result;
466 }
467
468 //--------------------------------------------------------------------------------------------------
469 inline
470 mithep::UnsignedAngle mithep::UnsignedAngle::operator / (int other) const
471 {
472 mithep::UnsignedAngle result(*this);
473 result /= other;
474 return result;
475 }
476 } //close namespace here because of friend declarations
477 #endif