Chris@16
|
1 // boost quaternion.hpp header file
|
Chris@16
|
2
|
Chris@16
|
3 // (C) Copyright Hubert Holin 2001.
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
5 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 // See http://www.boost.org for updates, documentation, and revision history.
|
Chris@16
|
9
|
Chris@16
|
10 #ifndef BOOST_QUATERNION_HPP
|
Chris@16
|
11 #define BOOST_QUATERNION_HPP
|
Chris@16
|
12
|
Chris@16
|
13
|
Chris@16
|
14 #include <complex>
|
Chris@16
|
15 #include <iosfwd> // for the "<<" and ">>" operators
|
Chris@16
|
16 #include <sstream> // for the "<<" operator
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/config.hpp> // for BOOST_NO_STD_LOCALE
|
Chris@16
|
19 #include <boost/detail/workaround.hpp>
|
Chris@16
|
20 #ifndef BOOST_NO_STD_LOCALE
|
Chris@16
|
21 #include <locale> // for the "<<" operator
|
Chris@16
|
22 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
23
|
Chris@16
|
24 #include <valarray>
|
Chris@16
|
25
|
Chris@16
|
26
|
Chris@16
|
27
|
Chris@16
|
28 #include <boost/math/special_functions/sinc.hpp> // for the Sinus cardinal
|
Chris@16
|
29 #include <boost/math/special_functions/sinhc.hpp> // for the Hyperbolic Sinus cardinal
|
Chris@16
|
30
|
Chris@16
|
31
|
Chris@16
|
32 namespace boost
|
Chris@16
|
33 {
|
Chris@16
|
34 namespace math
|
Chris@16
|
35 {
|
Chris@16
|
36 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
37 // gcc 2.95.x uses expression templates for valarray calculations, but
|
Chris@16
|
38 // the result is not conforming. We need BOOST_GET_VALARRAY to get an
|
Chris@16
|
39 // actual valarray result when we need to call a member function
|
Chris@16
|
40 #define BOOST_GET_VALARRAY(T,x) ::std::valarray<T>(x)
|
Chris@16
|
41 // gcc 2.95.x has an "std::ios" class that is similar to
|
Chris@16
|
42 // "std::ios_base", so we just use a #define
|
Chris@16
|
43 #define BOOST_IOS_BASE ::std::ios
|
Chris@16
|
44 // gcc 2.x ignores function scope using declarations,
|
Chris@16
|
45 // put them in the scope of the enclosing namespace instead:
|
Chris@16
|
46 using ::std::valarray;
|
Chris@16
|
47 using ::std::sqrt;
|
Chris@16
|
48 using ::std::cos;
|
Chris@16
|
49 using ::std::sin;
|
Chris@16
|
50 using ::std::exp;
|
Chris@16
|
51 using ::std::cosh;
|
Chris@16
|
52 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
53
|
Chris@16
|
54 #define BOOST_QUATERNION_ACCESSOR_GENERATOR(type) \
|
Chris@16
|
55 type real() const \
|
Chris@16
|
56 { \
|
Chris@16
|
57 return(a); \
|
Chris@16
|
58 } \
|
Chris@16
|
59 \
|
Chris@16
|
60 quaternion<type> unreal() const \
|
Chris@16
|
61 { \
|
Chris@16
|
62 return(quaternion<type>(static_cast<type>(0),b,c,d)); \
|
Chris@16
|
63 } \
|
Chris@16
|
64 \
|
Chris@16
|
65 type R_component_1() const \
|
Chris@16
|
66 { \
|
Chris@16
|
67 return(a); \
|
Chris@16
|
68 } \
|
Chris@16
|
69 \
|
Chris@16
|
70 type R_component_2() const \
|
Chris@16
|
71 { \
|
Chris@16
|
72 return(b); \
|
Chris@16
|
73 } \
|
Chris@16
|
74 \
|
Chris@16
|
75 type R_component_3() const \
|
Chris@16
|
76 { \
|
Chris@16
|
77 return(c); \
|
Chris@16
|
78 } \
|
Chris@16
|
79 \
|
Chris@16
|
80 type R_component_4() const \
|
Chris@16
|
81 { \
|
Chris@16
|
82 return(d); \
|
Chris@16
|
83 } \
|
Chris@16
|
84 \
|
Chris@16
|
85 ::std::complex<type> C_component_1() const \
|
Chris@16
|
86 { \
|
Chris@16
|
87 return(::std::complex<type>(a,b)); \
|
Chris@16
|
88 } \
|
Chris@16
|
89 \
|
Chris@16
|
90 ::std::complex<type> C_component_2() const \
|
Chris@16
|
91 { \
|
Chris@16
|
92 return(::std::complex<type>(c,d)); \
|
Chris@16
|
93 }
|
Chris@16
|
94
|
Chris@16
|
95
|
Chris@16
|
96 #define BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type) \
|
Chris@16
|
97 template<typename X> \
|
Chris@16
|
98 quaternion<type> & operator = (quaternion<X> const & a_affecter) \
|
Chris@16
|
99 { \
|
Chris@16
|
100 a = static_cast<type>(a_affecter.R_component_1()); \
|
Chris@16
|
101 b = static_cast<type>(a_affecter.R_component_2()); \
|
Chris@16
|
102 c = static_cast<type>(a_affecter.R_component_3()); \
|
Chris@16
|
103 d = static_cast<type>(a_affecter.R_component_4()); \
|
Chris@16
|
104 \
|
Chris@16
|
105 return(*this); \
|
Chris@16
|
106 } \
|
Chris@16
|
107 \
|
Chris@16
|
108 quaternion<type> & operator = (quaternion<type> const & a_affecter) \
|
Chris@16
|
109 { \
|
Chris@16
|
110 a = a_affecter.a; \
|
Chris@16
|
111 b = a_affecter.b; \
|
Chris@16
|
112 c = a_affecter.c; \
|
Chris@16
|
113 d = a_affecter.d; \
|
Chris@16
|
114 \
|
Chris@16
|
115 return(*this); \
|
Chris@16
|
116 } \
|
Chris@16
|
117 \
|
Chris@16
|
118 quaternion<type> & operator = (type const & a_affecter) \
|
Chris@16
|
119 { \
|
Chris@16
|
120 a = a_affecter; \
|
Chris@16
|
121 \
|
Chris@16
|
122 b = c = d = static_cast<type>(0); \
|
Chris@16
|
123 \
|
Chris@16
|
124 return(*this); \
|
Chris@16
|
125 } \
|
Chris@16
|
126 \
|
Chris@16
|
127 quaternion<type> & operator = (::std::complex<type> const & a_affecter) \
|
Chris@16
|
128 { \
|
Chris@16
|
129 a = a_affecter.real(); \
|
Chris@16
|
130 b = a_affecter.imag(); \
|
Chris@16
|
131 \
|
Chris@16
|
132 c = d = static_cast<type>(0); \
|
Chris@16
|
133 \
|
Chris@16
|
134 return(*this); \
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137
|
Chris@16
|
138 #define BOOST_QUATERNION_MEMBER_DATA_GENERATOR(type) \
|
Chris@16
|
139 type a; \
|
Chris@16
|
140 type b; \
|
Chris@16
|
141 type c; \
|
Chris@16
|
142 type d;
|
Chris@16
|
143
|
Chris@16
|
144
|
Chris@16
|
145 template<typename T>
|
Chris@16
|
146 class quaternion
|
Chris@16
|
147 {
|
Chris@16
|
148 public:
|
Chris@16
|
149
|
Chris@16
|
150 typedef T value_type;
|
Chris@16
|
151
|
Chris@16
|
152
|
Chris@16
|
153 // constructor for H seen as R^4
|
Chris@16
|
154 // (also default constructor)
|
Chris@16
|
155
|
Chris@16
|
156 explicit quaternion( T const & requested_a = T(),
|
Chris@16
|
157 T const & requested_b = T(),
|
Chris@16
|
158 T const & requested_c = T(),
|
Chris@16
|
159 T const & requested_d = T())
|
Chris@16
|
160 : a(requested_a),
|
Chris@16
|
161 b(requested_b),
|
Chris@16
|
162 c(requested_c),
|
Chris@16
|
163 d(requested_d)
|
Chris@16
|
164 {
|
Chris@16
|
165 // nothing to do!
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168
|
Chris@16
|
169 // constructor for H seen as C^2
|
Chris@16
|
170
|
Chris@16
|
171 explicit quaternion( ::std::complex<T> const & z0,
|
Chris@16
|
172 ::std::complex<T> const & z1 = ::std::complex<T>())
|
Chris@16
|
173 : a(z0.real()),
|
Chris@16
|
174 b(z0.imag()),
|
Chris@16
|
175 c(z1.real()),
|
Chris@16
|
176 d(z1.imag())
|
Chris@16
|
177 {
|
Chris@16
|
178 // nothing to do!
|
Chris@16
|
179 }
|
Chris@16
|
180
|
Chris@16
|
181
|
Chris@16
|
182 // UNtemplated copy constructor
|
Chris@16
|
183 // (this is taken care of by the compiler itself)
|
Chris@16
|
184
|
Chris@16
|
185
|
Chris@16
|
186 // templated copy constructor
|
Chris@16
|
187
|
Chris@16
|
188 template<typename X>
|
Chris@16
|
189 explicit quaternion(quaternion<X> const & a_recopier)
|
Chris@16
|
190 : a(static_cast<T>(a_recopier.R_component_1())),
|
Chris@16
|
191 b(static_cast<T>(a_recopier.R_component_2())),
|
Chris@16
|
192 c(static_cast<T>(a_recopier.R_component_3())),
|
Chris@16
|
193 d(static_cast<T>(a_recopier.R_component_4()))
|
Chris@16
|
194 {
|
Chris@16
|
195 // nothing to do!
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198
|
Chris@16
|
199 // destructor
|
Chris@16
|
200 // (this is taken care of by the compiler itself)
|
Chris@16
|
201
|
Chris@16
|
202
|
Chris@16
|
203 // accessors
|
Chris@16
|
204 //
|
Chris@16
|
205 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
|
Chris@16
|
206 // but unlike them there is no meaningful notion of "imaginary part".
|
Chris@16
|
207 // Instead there is an "unreal part" which itself is a quaternion, and usually
|
Chris@16
|
208 // nothing simpler (as opposed to the complex number case).
|
Chris@16
|
209 // However, for practicallity, there are accessors for the other components
|
Chris@16
|
210 // (these are necessary for the templated copy constructor, for instance).
|
Chris@16
|
211
|
Chris@16
|
212 BOOST_QUATERNION_ACCESSOR_GENERATOR(T)
|
Chris@16
|
213
|
Chris@16
|
214 // assignment operators
|
Chris@16
|
215
|
Chris@16
|
216 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T)
|
Chris@16
|
217
|
Chris@16
|
218 // other assignment-related operators
|
Chris@16
|
219 //
|
Chris@16
|
220 // NOTE: Quaternion multiplication is *NOT* commutative;
|
Chris@16
|
221 // symbolically, "q *= rhs;" means "q = q * rhs;"
|
Chris@16
|
222 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
|
Chris@16
|
223
|
Chris@16
|
224 quaternion<T> & operator += (T const & rhs)
|
Chris@16
|
225 {
|
Chris@16
|
226 T at = a + rhs; // exception guard
|
Chris@16
|
227
|
Chris@16
|
228 a = at;
|
Chris@16
|
229
|
Chris@16
|
230 return(*this);
|
Chris@16
|
231 }
|
Chris@16
|
232
|
Chris@16
|
233
|
Chris@16
|
234 quaternion<T> & operator += (::std::complex<T> const & rhs)
|
Chris@16
|
235 {
|
Chris@16
|
236 T at = a + rhs.real(); // exception guard
|
Chris@16
|
237 T bt = b + rhs.imag(); // exception guard
|
Chris@16
|
238
|
Chris@16
|
239 a = at;
|
Chris@16
|
240 b = bt;
|
Chris@16
|
241
|
Chris@16
|
242 return(*this);
|
Chris@16
|
243 }
|
Chris@16
|
244
|
Chris@16
|
245
|
Chris@16
|
246 template<typename X>
|
Chris@16
|
247 quaternion<T> & operator += (quaternion<X> const & rhs)
|
Chris@16
|
248 {
|
Chris@16
|
249 T at = a + static_cast<T>(rhs.R_component_1()); // exception guard
|
Chris@16
|
250 T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard
|
Chris@16
|
251 T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard
|
Chris@16
|
252 T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard
|
Chris@16
|
253
|
Chris@16
|
254 a = at;
|
Chris@16
|
255 b = bt;
|
Chris@16
|
256 c = ct;
|
Chris@16
|
257 d = dt;
|
Chris@16
|
258
|
Chris@16
|
259 return(*this);
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262
|
Chris@16
|
263
|
Chris@16
|
264 quaternion<T> & operator -= (T const & rhs)
|
Chris@16
|
265 {
|
Chris@16
|
266 T at = a - rhs; // exception guard
|
Chris@16
|
267
|
Chris@16
|
268 a = at;
|
Chris@16
|
269
|
Chris@16
|
270 return(*this);
|
Chris@16
|
271 }
|
Chris@16
|
272
|
Chris@16
|
273
|
Chris@16
|
274 quaternion<T> & operator -= (::std::complex<T> const & rhs)
|
Chris@16
|
275 {
|
Chris@16
|
276 T at = a - rhs.real(); // exception guard
|
Chris@16
|
277 T bt = b - rhs.imag(); // exception guard
|
Chris@16
|
278
|
Chris@16
|
279 a = at;
|
Chris@16
|
280 b = bt;
|
Chris@16
|
281
|
Chris@16
|
282 return(*this);
|
Chris@16
|
283 }
|
Chris@16
|
284
|
Chris@16
|
285
|
Chris@16
|
286 template<typename X>
|
Chris@16
|
287 quaternion<T> & operator -= (quaternion<X> const & rhs)
|
Chris@16
|
288 {
|
Chris@16
|
289 T at = a - static_cast<T>(rhs.R_component_1()); // exception guard
|
Chris@16
|
290 T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard
|
Chris@16
|
291 T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard
|
Chris@16
|
292 T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard
|
Chris@16
|
293
|
Chris@16
|
294 a = at;
|
Chris@16
|
295 b = bt;
|
Chris@16
|
296 c = ct;
|
Chris@16
|
297 d = dt;
|
Chris@16
|
298
|
Chris@16
|
299 return(*this);
|
Chris@16
|
300 }
|
Chris@16
|
301
|
Chris@16
|
302
|
Chris@16
|
303 quaternion<T> & operator *= (T const & rhs)
|
Chris@16
|
304 {
|
Chris@16
|
305 T at = a * rhs; // exception guard
|
Chris@16
|
306 T bt = b * rhs; // exception guard
|
Chris@16
|
307 T ct = c * rhs; // exception guard
|
Chris@16
|
308 T dt = d * rhs; // exception guard
|
Chris@16
|
309
|
Chris@16
|
310 a = at;
|
Chris@16
|
311 b = bt;
|
Chris@16
|
312 c = ct;
|
Chris@16
|
313 d = dt;
|
Chris@16
|
314
|
Chris@16
|
315 return(*this);
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318
|
Chris@16
|
319 quaternion<T> & operator *= (::std::complex<T> const & rhs)
|
Chris@16
|
320 {
|
Chris@16
|
321 T ar = rhs.real();
|
Chris@16
|
322 T br = rhs.imag();
|
Chris@16
|
323
|
Chris@16
|
324 T at = +a*ar-b*br;
|
Chris@16
|
325 T bt = +a*br+b*ar;
|
Chris@16
|
326 T ct = +c*ar+d*br;
|
Chris@16
|
327 T dt = -c*br+d*ar;
|
Chris@16
|
328
|
Chris@16
|
329 a = at;
|
Chris@16
|
330 b = bt;
|
Chris@16
|
331 c = ct;
|
Chris@16
|
332 d = dt;
|
Chris@16
|
333
|
Chris@16
|
334 return(*this);
|
Chris@16
|
335 }
|
Chris@16
|
336
|
Chris@16
|
337
|
Chris@16
|
338 template<typename X>
|
Chris@16
|
339 quaternion<T> & operator *= (quaternion<X> const & rhs)
|
Chris@16
|
340 {
|
Chris@16
|
341 T ar = static_cast<T>(rhs.R_component_1());
|
Chris@16
|
342 T br = static_cast<T>(rhs.R_component_2());
|
Chris@16
|
343 T cr = static_cast<T>(rhs.R_component_3());
|
Chris@16
|
344 T dr = static_cast<T>(rhs.R_component_4());
|
Chris@16
|
345
|
Chris@16
|
346 T at = +a*ar-b*br-c*cr-d*dr;
|
Chris@16
|
347 T bt = +a*br+b*ar+c*dr-d*cr; //(a*br+ar*b)+(c*dr-cr*d);
|
Chris@16
|
348 T ct = +a*cr-b*dr+c*ar+d*br; //(a*cr+ar*c)+(d*br-dr*b);
|
Chris@16
|
349 T dt = +a*dr+b*cr-c*br+d*ar; //(a*dr+ar*d)+(b*cr-br*c);
|
Chris@16
|
350
|
Chris@16
|
351 a = at;
|
Chris@16
|
352 b = bt;
|
Chris@16
|
353 c = ct;
|
Chris@16
|
354 d = dt;
|
Chris@16
|
355
|
Chris@16
|
356 return(*this);
|
Chris@16
|
357 }
|
Chris@16
|
358
|
Chris@16
|
359
|
Chris@16
|
360
|
Chris@16
|
361 quaternion<T> & operator /= (T const & rhs)
|
Chris@16
|
362 {
|
Chris@16
|
363 T at = a / rhs; // exception guard
|
Chris@16
|
364 T bt = b / rhs; // exception guard
|
Chris@16
|
365 T ct = c / rhs; // exception guard
|
Chris@16
|
366 T dt = d / rhs; // exception guard
|
Chris@16
|
367
|
Chris@16
|
368 a = at;
|
Chris@16
|
369 b = bt;
|
Chris@16
|
370 c = ct;
|
Chris@16
|
371 d = dt;
|
Chris@16
|
372
|
Chris@16
|
373 return(*this);
|
Chris@16
|
374 }
|
Chris@16
|
375
|
Chris@16
|
376
|
Chris@16
|
377 quaternion<T> & operator /= (::std::complex<T> const & rhs)
|
Chris@16
|
378 {
|
Chris@16
|
379 T ar = rhs.real();
|
Chris@16
|
380 T br = rhs.imag();
|
Chris@16
|
381
|
Chris@16
|
382 T denominator = ar*ar+br*br;
|
Chris@16
|
383
|
Chris@16
|
384 T at = (+a*ar+b*br)/denominator; //(a*ar+b*br)/denominator;
|
Chris@16
|
385 T bt = (-a*br+b*ar)/denominator; //(ar*b-a*br)/denominator;
|
Chris@16
|
386 T ct = (+c*ar-d*br)/denominator; //(ar*c-d*br)/denominator;
|
Chris@16
|
387 T dt = (+c*br+d*ar)/denominator; //(ar*d+br*c)/denominator;
|
Chris@16
|
388
|
Chris@16
|
389 a = at;
|
Chris@16
|
390 b = bt;
|
Chris@16
|
391 c = ct;
|
Chris@16
|
392 d = dt;
|
Chris@16
|
393
|
Chris@16
|
394 return(*this);
|
Chris@16
|
395 }
|
Chris@16
|
396
|
Chris@16
|
397
|
Chris@16
|
398 template<typename X>
|
Chris@16
|
399 quaternion<T> & operator /= (quaternion<X> const & rhs)
|
Chris@16
|
400 {
|
Chris@16
|
401 T ar = static_cast<T>(rhs.R_component_1());
|
Chris@16
|
402 T br = static_cast<T>(rhs.R_component_2());
|
Chris@16
|
403 T cr = static_cast<T>(rhs.R_component_3());
|
Chris@16
|
404 T dr = static_cast<T>(rhs.R_component_4());
|
Chris@16
|
405
|
Chris@16
|
406 T denominator = ar*ar+br*br+cr*cr+dr*dr;
|
Chris@16
|
407
|
Chris@16
|
408 T at = (+a*ar+b*br+c*cr+d*dr)/denominator; //(a*ar+b*br+c*cr+d*dr)/denominator;
|
Chris@16
|
409 T bt = (-a*br+b*ar-c*dr+d*cr)/denominator; //((ar*b-a*br)+(cr*d-c*dr))/denominator;
|
Chris@16
|
410 T ct = (-a*cr+b*dr+c*ar-d*br)/denominator; //((ar*c-a*cr)+(dr*b-d*br))/denominator;
|
Chris@16
|
411 T dt = (-a*dr-b*cr+c*br+d*ar)/denominator; //((ar*d-a*dr)+(br*c-b*cr))/denominator;
|
Chris@16
|
412
|
Chris@16
|
413 a = at;
|
Chris@16
|
414 b = bt;
|
Chris@16
|
415 c = ct;
|
Chris@16
|
416 d = dt;
|
Chris@16
|
417
|
Chris@16
|
418 return(*this);
|
Chris@16
|
419 }
|
Chris@16
|
420
|
Chris@16
|
421
|
Chris@16
|
422 protected:
|
Chris@16
|
423
|
Chris@16
|
424 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(T)
|
Chris@16
|
425
|
Chris@16
|
426
|
Chris@16
|
427 private:
|
Chris@16
|
428
|
Chris@16
|
429 };
|
Chris@16
|
430
|
Chris@16
|
431
|
Chris@16
|
432 // declaration of quaternion specialization
|
Chris@16
|
433
|
Chris@16
|
434 template<> class quaternion<float>;
|
Chris@16
|
435 template<> class quaternion<double>;
|
Chris@16
|
436 template<> class quaternion<long double>;
|
Chris@16
|
437
|
Chris@16
|
438
|
Chris@16
|
439 // helper templates for converting copy constructors (declaration)
|
Chris@16
|
440
|
Chris@16
|
441 namespace detail
|
Chris@16
|
442 {
|
Chris@16
|
443
|
Chris@16
|
444 template< typename T,
|
Chris@16
|
445 typename U
|
Chris@16
|
446 >
|
Chris@16
|
447 quaternion<T> quaternion_type_converter(quaternion<U> const & rhs);
|
Chris@16
|
448 }
|
Chris@16
|
449
|
Chris@16
|
450
|
Chris@16
|
451 // implementation of quaternion specialization
|
Chris@16
|
452
|
Chris@16
|
453
|
Chris@16
|
454 #define BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(type) \
|
Chris@16
|
455 explicit quaternion( type const & requested_a = static_cast<type>(0), \
|
Chris@16
|
456 type const & requested_b = static_cast<type>(0), \
|
Chris@16
|
457 type const & requested_c = static_cast<type>(0), \
|
Chris@16
|
458 type const & requested_d = static_cast<type>(0)) \
|
Chris@16
|
459 : a(requested_a), \
|
Chris@16
|
460 b(requested_b), \
|
Chris@16
|
461 c(requested_c), \
|
Chris@16
|
462 d(requested_d) \
|
Chris@16
|
463 { \
|
Chris@16
|
464 } \
|
Chris@16
|
465 \
|
Chris@16
|
466 explicit quaternion( ::std::complex<type> const & z0, \
|
Chris@16
|
467 ::std::complex<type> const & z1 = ::std::complex<type>()) \
|
Chris@16
|
468 : a(z0.real()), \
|
Chris@16
|
469 b(z0.imag()), \
|
Chris@16
|
470 c(z1.real()), \
|
Chris@16
|
471 d(z1.imag()) \
|
Chris@16
|
472 { \
|
Chris@16
|
473 }
|
Chris@16
|
474
|
Chris@16
|
475
|
Chris@16
|
476 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
|
Chris@16
|
477 quaternion<type> & operator += (type const & rhs) \
|
Chris@16
|
478 { \
|
Chris@16
|
479 a += rhs; \
|
Chris@16
|
480 \
|
Chris@16
|
481 return(*this); \
|
Chris@16
|
482 }
|
Chris@16
|
483
|
Chris@16
|
484 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
|
Chris@16
|
485 quaternion<type> & operator += (::std::complex<type> const & rhs) \
|
Chris@16
|
486 { \
|
Chris@16
|
487 a += rhs.real(); \
|
Chris@16
|
488 b += rhs.imag(); \
|
Chris@16
|
489 \
|
Chris@16
|
490 return(*this); \
|
Chris@16
|
491 }
|
Chris@16
|
492
|
Chris@16
|
493 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type) \
|
Chris@16
|
494 template<typename X> \
|
Chris@16
|
495 quaternion<type> & operator += (quaternion<X> const & rhs) \
|
Chris@16
|
496 { \
|
Chris@16
|
497 a += static_cast<type>(rhs.R_component_1()); \
|
Chris@16
|
498 b += static_cast<type>(rhs.R_component_2()); \
|
Chris@16
|
499 c += static_cast<type>(rhs.R_component_3()); \
|
Chris@16
|
500 d += static_cast<type>(rhs.R_component_4()); \
|
Chris@16
|
501 \
|
Chris@16
|
502 return(*this); \
|
Chris@16
|
503 }
|
Chris@16
|
504
|
Chris@16
|
505 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
|
Chris@16
|
506 quaternion<type> & operator -= (type const & rhs) \
|
Chris@16
|
507 { \
|
Chris@16
|
508 a -= rhs; \
|
Chris@16
|
509 \
|
Chris@16
|
510 return(*this); \
|
Chris@16
|
511 }
|
Chris@16
|
512
|
Chris@16
|
513 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
|
Chris@16
|
514 quaternion<type> & operator -= (::std::complex<type> const & rhs) \
|
Chris@16
|
515 { \
|
Chris@16
|
516 a -= rhs.real(); \
|
Chris@16
|
517 b -= rhs.imag(); \
|
Chris@16
|
518 \
|
Chris@16
|
519 return(*this); \
|
Chris@16
|
520 }
|
Chris@16
|
521
|
Chris@16
|
522 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type) \
|
Chris@16
|
523 template<typename X> \
|
Chris@16
|
524 quaternion<type> & operator -= (quaternion<X> const & rhs) \
|
Chris@16
|
525 { \
|
Chris@16
|
526 a -= static_cast<type>(rhs.R_component_1()); \
|
Chris@16
|
527 b -= static_cast<type>(rhs.R_component_2()); \
|
Chris@16
|
528 c -= static_cast<type>(rhs.R_component_3()); \
|
Chris@16
|
529 d -= static_cast<type>(rhs.R_component_4()); \
|
Chris@16
|
530 \
|
Chris@16
|
531 return(*this); \
|
Chris@16
|
532 }
|
Chris@16
|
533
|
Chris@16
|
534 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
|
Chris@16
|
535 quaternion<type> & operator *= (type const & rhs) \
|
Chris@16
|
536 { \
|
Chris@16
|
537 a *= rhs; \
|
Chris@16
|
538 b *= rhs; \
|
Chris@16
|
539 c *= rhs; \
|
Chris@16
|
540 d *= rhs; \
|
Chris@16
|
541 \
|
Chris@16
|
542 return(*this); \
|
Chris@16
|
543 }
|
Chris@16
|
544
|
Chris@16
|
545 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
|
Chris@16
|
546 quaternion<type> & operator *= (::std::complex<type> const & rhs) \
|
Chris@16
|
547 { \
|
Chris@16
|
548 type ar = rhs.real(); \
|
Chris@16
|
549 type br = rhs.imag(); \
|
Chris@16
|
550 \
|
Chris@16
|
551 type at = +a*ar-b*br; \
|
Chris@16
|
552 type bt = +a*br+b*ar; \
|
Chris@16
|
553 type ct = +c*ar+d*br; \
|
Chris@16
|
554 type dt = -c*br+d*ar; \
|
Chris@16
|
555 \
|
Chris@16
|
556 a = at; \
|
Chris@16
|
557 b = bt; \
|
Chris@16
|
558 c = ct; \
|
Chris@16
|
559 d = dt; \
|
Chris@16
|
560 \
|
Chris@16
|
561 return(*this); \
|
Chris@16
|
562 }
|
Chris@16
|
563
|
Chris@16
|
564 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type) \
|
Chris@16
|
565 template<typename X> \
|
Chris@16
|
566 quaternion<type> & operator *= (quaternion<X> const & rhs) \
|
Chris@16
|
567 { \
|
Chris@16
|
568 type ar = static_cast<type>(rhs.R_component_1()); \
|
Chris@16
|
569 type br = static_cast<type>(rhs.R_component_2()); \
|
Chris@16
|
570 type cr = static_cast<type>(rhs.R_component_3()); \
|
Chris@16
|
571 type dr = static_cast<type>(rhs.R_component_4()); \
|
Chris@16
|
572 \
|
Chris@16
|
573 type at = +a*ar-b*br-c*cr-d*dr; \
|
Chris@16
|
574 type bt = +a*br+b*ar+c*dr-d*cr; \
|
Chris@16
|
575 type ct = +a*cr-b*dr+c*ar+d*br; \
|
Chris@16
|
576 type dt = +a*dr+b*cr-c*br+d*ar; \
|
Chris@16
|
577 \
|
Chris@16
|
578 a = at; \
|
Chris@16
|
579 b = bt; \
|
Chris@16
|
580 c = ct; \
|
Chris@16
|
581 d = dt; \
|
Chris@16
|
582 \
|
Chris@16
|
583 return(*this); \
|
Chris@16
|
584 }
|
Chris@16
|
585
|
Chris@16
|
586 // There is quite a lot of repetition in the code below. This is intentional.
|
Chris@16
|
587 // The last conditional block is the normal form, and the others merely
|
Chris@16
|
588 // consist of workarounds for various compiler deficiencies. Hopefuly, when
|
Chris@16
|
589 // more compilers are conformant and we can retire support for those that are
|
Chris@16
|
590 // not, we will be able to remove the clutter. This is makes the situation
|
Chris@16
|
591 // (painfully) explicit.
|
Chris@16
|
592
|
Chris@16
|
593 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
|
Chris@16
|
594 quaternion<type> & operator /= (type const & rhs) \
|
Chris@16
|
595 { \
|
Chris@16
|
596 a /= rhs; \
|
Chris@16
|
597 b /= rhs; \
|
Chris@16
|
598 c /= rhs; \
|
Chris@16
|
599 d /= rhs; \
|
Chris@16
|
600 \
|
Chris@16
|
601 return(*this); \
|
Chris@16
|
602 }
|
Chris@16
|
603
|
Chris@16
|
604 #if defined(__GNUC__) && (__GNUC__ < 3)
|
Chris@16
|
605 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
|
Chris@16
|
606 quaternion<type> & operator /= (::std::complex<type> const & rhs) \
|
Chris@16
|
607 { \
|
Chris@16
|
608 using ::std::valarray; \
|
Chris@16
|
609 \
|
Chris@16
|
610 valarray<type> tr(2); \
|
Chris@16
|
611 \
|
Chris@16
|
612 tr[0] = rhs.real(); \
|
Chris@16
|
613 tr[1] = rhs.imag(); \
|
Chris@16
|
614 \
|
Chris@16
|
615 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
|
Chris@16
|
616 \
|
Chris@16
|
617 tr *= mixam; \
|
Chris@16
|
618 \
|
Chris@16
|
619 valarray<type> tt(4); \
|
Chris@16
|
620 \
|
Chris@16
|
621 tt[0] = +a*tr[0]+b*tr[1]; \
|
Chris@16
|
622 tt[1] = -a*tr[1]+b*tr[0]; \
|
Chris@16
|
623 tt[2] = +c*tr[0]-d*tr[1]; \
|
Chris@16
|
624 tt[3] = +c*tr[1]+d*tr[0]; \
|
Chris@16
|
625 \
|
Chris@16
|
626 tr *= tr; \
|
Chris@16
|
627 \
|
Chris@16
|
628 tt *= (mixam/tr.sum()); \
|
Chris@16
|
629 \
|
Chris@16
|
630 a = tt[0]; \
|
Chris@16
|
631 b = tt[1]; \
|
Chris@16
|
632 c = tt[2]; \
|
Chris@16
|
633 d = tt[3]; \
|
Chris@16
|
634 \
|
Chris@16
|
635 return(*this); \
|
Chris@16
|
636 }
|
Chris@16
|
637 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
Chris@16
|
638 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
|
Chris@16
|
639 quaternion<type> & operator /= (::std::complex<type> const & rhs) \
|
Chris@16
|
640 { \
|
Chris@16
|
641 using ::std::valarray; \
|
Chris@16
|
642 using ::std::abs; \
|
Chris@16
|
643 \
|
Chris@16
|
644 valarray<type> tr(2); \
|
Chris@16
|
645 \
|
Chris@16
|
646 tr[0] = rhs.real(); \
|
Chris@16
|
647 tr[1] = rhs.imag(); \
|
Chris@16
|
648 \
|
Chris@16
|
649 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
|
Chris@16
|
650 \
|
Chris@16
|
651 tr *= mixam; \
|
Chris@16
|
652 \
|
Chris@16
|
653 valarray<type> tt(4); \
|
Chris@16
|
654 \
|
Chris@16
|
655 tt[0] = +a*tr[0]+b*tr[1]; \
|
Chris@16
|
656 tt[1] = -a*tr[1]+b*tr[0]; \
|
Chris@16
|
657 tt[2] = +c*tr[0]-d*tr[1]; \
|
Chris@16
|
658 tt[3] = +c*tr[1]+d*tr[0]; \
|
Chris@16
|
659 \
|
Chris@16
|
660 tr *= tr; \
|
Chris@16
|
661 \
|
Chris@16
|
662 tt *= (mixam/tr.sum()); \
|
Chris@16
|
663 \
|
Chris@16
|
664 a = tt[0]; \
|
Chris@16
|
665 b = tt[1]; \
|
Chris@16
|
666 c = tt[2]; \
|
Chris@16
|
667 d = tt[3]; \
|
Chris@16
|
668 \
|
Chris@16
|
669 return(*this); \
|
Chris@16
|
670 }
|
Chris@16
|
671 #else
|
Chris@16
|
672 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
|
Chris@16
|
673 quaternion<type> & operator /= (::std::complex<type> const & rhs) \
|
Chris@16
|
674 { \
|
Chris@16
|
675 using ::std::valarray; \
|
Chris@16
|
676 \
|
Chris@16
|
677 valarray<type> tr(2); \
|
Chris@16
|
678 \
|
Chris@16
|
679 tr[0] = rhs.real(); \
|
Chris@16
|
680 tr[1] = rhs.imag(); \
|
Chris@16
|
681 \
|
Chris@16
|
682 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
|
Chris@16
|
683 \
|
Chris@16
|
684 tr *= mixam; \
|
Chris@16
|
685 \
|
Chris@16
|
686 valarray<type> tt(4); \
|
Chris@16
|
687 \
|
Chris@16
|
688 tt[0] = +a*tr[0]+b*tr[1]; \
|
Chris@16
|
689 tt[1] = -a*tr[1]+b*tr[0]; \
|
Chris@16
|
690 tt[2] = +c*tr[0]-d*tr[1]; \
|
Chris@16
|
691 tt[3] = +c*tr[1]+d*tr[0]; \
|
Chris@16
|
692 \
|
Chris@16
|
693 tr *= tr; \
|
Chris@16
|
694 \
|
Chris@16
|
695 tt *= (mixam/tr.sum()); \
|
Chris@16
|
696 \
|
Chris@16
|
697 a = tt[0]; \
|
Chris@16
|
698 b = tt[1]; \
|
Chris@16
|
699 c = tt[2]; \
|
Chris@16
|
700 d = tt[3]; \
|
Chris@16
|
701 \
|
Chris@16
|
702 return(*this); \
|
Chris@16
|
703 }
|
Chris@16
|
704 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
|
Chris@16
|
705
|
Chris@16
|
706 #if defined(__GNUC__) && (__GNUC__ < 3)
|
Chris@16
|
707 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
|
Chris@16
|
708 template<typename X> \
|
Chris@16
|
709 quaternion<type> & operator /= (quaternion<X> const & rhs) \
|
Chris@16
|
710 { \
|
Chris@16
|
711 using ::std::valarray; \
|
Chris@16
|
712 \
|
Chris@16
|
713 valarray<type> tr(4); \
|
Chris@16
|
714 \
|
Chris@16
|
715 tr[0] = static_cast<type>(rhs.R_component_1()); \
|
Chris@16
|
716 tr[1] = static_cast<type>(rhs.R_component_2()); \
|
Chris@16
|
717 tr[2] = static_cast<type>(rhs.R_component_3()); \
|
Chris@16
|
718 tr[3] = static_cast<type>(rhs.R_component_4()); \
|
Chris@16
|
719 \
|
Chris@16
|
720 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
|
Chris@16
|
721 \
|
Chris@16
|
722 tr *= mixam; \
|
Chris@16
|
723 \
|
Chris@16
|
724 valarray<type> tt(4); \
|
Chris@16
|
725 \
|
Chris@16
|
726 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
|
Chris@16
|
727 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
|
Chris@16
|
728 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
|
Chris@16
|
729 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
|
Chris@16
|
730 \
|
Chris@16
|
731 tr *= tr; \
|
Chris@16
|
732 \
|
Chris@16
|
733 tt *= (mixam/tr.sum()); \
|
Chris@16
|
734 \
|
Chris@16
|
735 a = tt[0]; \
|
Chris@16
|
736 b = tt[1]; \
|
Chris@16
|
737 c = tt[2]; \
|
Chris@16
|
738 d = tt[3]; \
|
Chris@16
|
739 \
|
Chris@16
|
740 return(*this); \
|
Chris@16
|
741 }
|
Chris@16
|
742 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
Chris@16
|
743 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
|
Chris@16
|
744 template<typename X> \
|
Chris@16
|
745 quaternion<type> & operator /= (quaternion<X> const & rhs) \
|
Chris@16
|
746 { \
|
Chris@16
|
747 using ::std::valarray; \
|
Chris@16
|
748 using ::std::abs; \
|
Chris@16
|
749 \
|
Chris@16
|
750 valarray<type> tr(4); \
|
Chris@16
|
751 \
|
Chris@16
|
752 tr[0] = static_cast<type>(rhs.R_component_1()); \
|
Chris@16
|
753 tr[1] = static_cast<type>(rhs.R_component_2()); \
|
Chris@16
|
754 tr[2] = static_cast<type>(rhs.R_component_3()); \
|
Chris@16
|
755 tr[3] = static_cast<type>(rhs.R_component_4()); \
|
Chris@16
|
756 \
|
Chris@16
|
757 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
|
Chris@16
|
758 \
|
Chris@16
|
759 tr *= mixam; \
|
Chris@16
|
760 \
|
Chris@16
|
761 valarray<type> tt(4); \
|
Chris@16
|
762 \
|
Chris@16
|
763 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
|
Chris@16
|
764 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
|
Chris@16
|
765 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
|
Chris@16
|
766 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
|
Chris@16
|
767 \
|
Chris@16
|
768 tr *= tr; \
|
Chris@16
|
769 \
|
Chris@16
|
770 tt *= (mixam/tr.sum()); \
|
Chris@16
|
771 \
|
Chris@16
|
772 a = tt[0]; \
|
Chris@16
|
773 b = tt[1]; \
|
Chris@16
|
774 c = tt[2]; \
|
Chris@16
|
775 d = tt[3]; \
|
Chris@16
|
776 \
|
Chris@16
|
777 return(*this); \
|
Chris@16
|
778 }
|
Chris@16
|
779 #else
|
Chris@16
|
780 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
|
Chris@16
|
781 template<typename X> \
|
Chris@16
|
782 quaternion<type> & operator /= (quaternion<X> const & rhs) \
|
Chris@16
|
783 { \
|
Chris@16
|
784 using ::std::valarray; \
|
Chris@16
|
785 \
|
Chris@16
|
786 valarray<type> tr(4); \
|
Chris@16
|
787 \
|
Chris@16
|
788 tr[0] = static_cast<type>(rhs.R_component_1()); \
|
Chris@16
|
789 tr[1] = static_cast<type>(rhs.R_component_2()); \
|
Chris@16
|
790 tr[2] = static_cast<type>(rhs.R_component_3()); \
|
Chris@16
|
791 tr[3] = static_cast<type>(rhs.R_component_4()); \
|
Chris@16
|
792 \
|
Chris@16
|
793 type mixam = static_cast<type>(1)/(abs(tr).max)(); \
|
Chris@16
|
794 \
|
Chris@16
|
795 tr *= mixam; \
|
Chris@16
|
796 \
|
Chris@16
|
797 valarray<type> tt(4); \
|
Chris@16
|
798 \
|
Chris@16
|
799 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
|
Chris@16
|
800 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
|
Chris@16
|
801 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
|
Chris@16
|
802 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
|
Chris@16
|
803 \
|
Chris@16
|
804 tr *= tr; \
|
Chris@16
|
805 \
|
Chris@16
|
806 tt *= (mixam/tr.sum()); \
|
Chris@16
|
807 \
|
Chris@16
|
808 a = tt[0]; \
|
Chris@16
|
809 b = tt[1]; \
|
Chris@16
|
810 c = tt[2]; \
|
Chris@16
|
811 d = tt[3]; \
|
Chris@16
|
812 \
|
Chris@16
|
813 return(*this); \
|
Chris@16
|
814 }
|
Chris@16
|
815 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
|
Chris@16
|
816
|
Chris@16
|
817 #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
|
Chris@16
|
818 BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
|
Chris@16
|
819 BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
|
Chris@16
|
820 BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type)
|
Chris@16
|
821
|
Chris@16
|
822 #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
|
Chris@16
|
823 BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
|
Chris@16
|
824 BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
|
Chris@16
|
825 BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type)
|
Chris@16
|
826
|
Chris@16
|
827 #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
|
Chris@16
|
828 BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
|
Chris@16
|
829 BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
|
Chris@16
|
830 BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type)
|
Chris@16
|
831
|
Chris@16
|
832 #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type) \
|
Chris@16
|
833 BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
|
Chris@16
|
834 BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
|
Chris@16
|
835 BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)
|
Chris@16
|
836
|
Chris@16
|
837 #define BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(type) \
|
Chris@16
|
838 BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
|
Chris@16
|
839 BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
|
Chris@16
|
840 BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
|
Chris@16
|
841 BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type)
|
Chris@16
|
842
|
Chris@16
|
843
|
Chris@16
|
844 template<>
|
Chris@16
|
845 class quaternion<float>
|
Chris@16
|
846 {
|
Chris@16
|
847 public:
|
Chris@16
|
848
|
Chris@16
|
849 typedef float value_type;
|
Chris@16
|
850
|
Chris@16
|
851 BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(float)
|
Chris@16
|
852
|
Chris@16
|
853 // UNtemplated copy constructor
|
Chris@16
|
854 // (this is taken care of by the compiler itself)
|
Chris@16
|
855
|
Chris@16
|
856 // explicit copy constructors (precision-loosing converters)
|
Chris@16
|
857
|
Chris@16
|
858 explicit quaternion(quaternion<double> const & a_recopier)
|
Chris@16
|
859 {
|
Chris@16
|
860 *this = detail::quaternion_type_converter<float, double>(a_recopier);
|
Chris@16
|
861 }
|
Chris@16
|
862
|
Chris@16
|
863 explicit quaternion(quaternion<long double> const & a_recopier)
|
Chris@16
|
864 {
|
Chris@16
|
865 *this = detail::quaternion_type_converter<float, long double>(a_recopier);
|
Chris@16
|
866 }
|
Chris@16
|
867
|
Chris@16
|
868 // destructor
|
Chris@16
|
869 // (this is taken care of by the compiler itself)
|
Chris@16
|
870
|
Chris@16
|
871 // accessors
|
Chris@16
|
872 //
|
Chris@16
|
873 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
|
Chris@16
|
874 // but unlike them there is no meaningful notion of "imaginary part".
|
Chris@16
|
875 // Instead there is an "unreal part" which itself is a quaternion, and usually
|
Chris@16
|
876 // nothing simpler (as opposed to the complex number case).
|
Chris@16
|
877 // However, for practicallity, there are accessors for the other components
|
Chris@16
|
878 // (these are necessary for the templated copy constructor, for instance).
|
Chris@16
|
879
|
Chris@16
|
880 BOOST_QUATERNION_ACCESSOR_GENERATOR(float)
|
Chris@16
|
881
|
Chris@16
|
882 // assignment operators
|
Chris@16
|
883
|
Chris@16
|
884 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(float)
|
Chris@16
|
885
|
Chris@16
|
886 // other assignment-related operators
|
Chris@16
|
887 //
|
Chris@16
|
888 // NOTE: Quaternion multiplication is *NOT* commutative;
|
Chris@16
|
889 // symbolically, "q *= rhs;" means "q = q * rhs;"
|
Chris@16
|
890 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
|
Chris@16
|
891
|
Chris@16
|
892 BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(float)
|
Chris@16
|
893
|
Chris@16
|
894
|
Chris@16
|
895 protected:
|
Chris@16
|
896
|
Chris@16
|
897 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(float)
|
Chris@16
|
898
|
Chris@16
|
899
|
Chris@16
|
900 private:
|
Chris@16
|
901
|
Chris@16
|
902 };
|
Chris@16
|
903
|
Chris@16
|
904
|
Chris@16
|
905 template<>
|
Chris@16
|
906 class quaternion<double>
|
Chris@16
|
907 {
|
Chris@16
|
908 public:
|
Chris@16
|
909
|
Chris@16
|
910 typedef double value_type;
|
Chris@16
|
911
|
Chris@16
|
912 BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(double)
|
Chris@16
|
913
|
Chris@16
|
914 // UNtemplated copy constructor
|
Chris@16
|
915 // (this is taken care of by the compiler itself)
|
Chris@16
|
916
|
Chris@16
|
917 // converting copy constructor
|
Chris@16
|
918
|
Chris@16
|
919 explicit quaternion(quaternion<float> const & a_recopier)
|
Chris@16
|
920 {
|
Chris@16
|
921 *this = detail::quaternion_type_converter<double, float>(a_recopier);
|
Chris@16
|
922 }
|
Chris@16
|
923
|
Chris@16
|
924 // explicit copy constructors (precision-loosing converters)
|
Chris@16
|
925
|
Chris@16
|
926 explicit quaternion(quaternion<long double> const & a_recopier)
|
Chris@16
|
927 {
|
Chris@16
|
928 *this = detail::quaternion_type_converter<double, long double>(a_recopier);
|
Chris@16
|
929 }
|
Chris@16
|
930
|
Chris@16
|
931 // destructor
|
Chris@16
|
932 // (this is taken care of by the compiler itself)
|
Chris@16
|
933
|
Chris@16
|
934 // accessors
|
Chris@16
|
935 //
|
Chris@16
|
936 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
|
Chris@16
|
937 // but unlike them there is no meaningful notion of "imaginary part".
|
Chris@16
|
938 // Instead there is an "unreal part" which itself is a quaternion, and usually
|
Chris@16
|
939 // nothing simpler (as opposed to the complex number case).
|
Chris@16
|
940 // However, for practicallity, there are accessors for the other components
|
Chris@16
|
941 // (these are necessary for the templated copy constructor, for instance).
|
Chris@16
|
942
|
Chris@16
|
943 BOOST_QUATERNION_ACCESSOR_GENERATOR(double)
|
Chris@16
|
944
|
Chris@16
|
945 // assignment operators
|
Chris@16
|
946
|
Chris@16
|
947 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(double)
|
Chris@16
|
948
|
Chris@16
|
949 // other assignment-related operators
|
Chris@16
|
950 //
|
Chris@16
|
951 // NOTE: Quaternion multiplication is *NOT* commutative;
|
Chris@16
|
952 // symbolically, "q *= rhs;" means "q = q * rhs;"
|
Chris@16
|
953 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
|
Chris@16
|
954
|
Chris@16
|
955 BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(double)
|
Chris@16
|
956
|
Chris@16
|
957
|
Chris@16
|
958 protected:
|
Chris@16
|
959
|
Chris@16
|
960 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(double)
|
Chris@16
|
961
|
Chris@16
|
962
|
Chris@16
|
963 private:
|
Chris@16
|
964
|
Chris@16
|
965 };
|
Chris@16
|
966
|
Chris@16
|
967
|
Chris@16
|
968 template<>
|
Chris@16
|
969 class quaternion<long double>
|
Chris@16
|
970 {
|
Chris@16
|
971 public:
|
Chris@16
|
972
|
Chris@16
|
973 typedef long double value_type;
|
Chris@16
|
974
|
Chris@16
|
975 BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(long double)
|
Chris@16
|
976
|
Chris@16
|
977 // UNtemplated copy constructor
|
Chris@16
|
978 // (this is taken care of by the compiler itself)
|
Chris@16
|
979
|
Chris@16
|
980 // converting copy constructors
|
Chris@16
|
981
|
Chris@16
|
982 explicit quaternion(quaternion<float> const & a_recopier)
|
Chris@16
|
983 {
|
Chris@16
|
984 *this = detail::quaternion_type_converter<long double, float>(a_recopier);
|
Chris@16
|
985 }
|
Chris@16
|
986
|
Chris@16
|
987 explicit quaternion(quaternion<double> const & a_recopier)
|
Chris@16
|
988 {
|
Chris@16
|
989 *this = detail::quaternion_type_converter<long double, double>(a_recopier);
|
Chris@16
|
990 }
|
Chris@16
|
991
|
Chris@16
|
992 // destructor
|
Chris@16
|
993 // (this is taken care of by the compiler itself)
|
Chris@16
|
994
|
Chris@16
|
995 // accessors
|
Chris@16
|
996 //
|
Chris@16
|
997 // Note: Like complex number, quaternions do have a meaningful notion of "real part",
|
Chris@16
|
998 // but unlike them there is no meaningful notion of "imaginary part".
|
Chris@16
|
999 // Instead there is an "unreal part" which itself is a quaternion, and usually
|
Chris@16
|
1000 // nothing simpler (as opposed to the complex number case).
|
Chris@16
|
1001 // However, for practicallity, there are accessors for the other components
|
Chris@16
|
1002 // (these are necessary for the templated copy constructor, for instance).
|
Chris@16
|
1003
|
Chris@16
|
1004 BOOST_QUATERNION_ACCESSOR_GENERATOR(long double)
|
Chris@16
|
1005
|
Chris@16
|
1006 // assignment operators
|
Chris@16
|
1007
|
Chris@16
|
1008 BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(long double)
|
Chris@16
|
1009
|
Chris@16
|
1010 // other assignment-related operators
|
Chris@16
|
1011 //
|
Chris@16
|
1012 // NOTE: Quaternion multiplication is *NOT* commutative;
|
Chris@16
|
1013 // symbolically, "q *= rhs;" means "q = q * rhs;"
|
Chris@16
|
1014 // and "q /= rhs;" means "q = q * inverse_of(rhs);"
|
Chris@16
|
1015
|
Chris@16
|
1016 BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(long double)
|
Chris@16
|
1017
|
Chris@16
|
1018
|
Chris@16
|
1019 protected:
|
Chris@16
|
1020
|
Chris@16
|
1021 BOOST_QUATERNION_MEMBER_DATA_GENERATOR(long double)
|
Chris@16
|
1022
|
Chris@16
|
1023
|
Chris@16
|
1024 private:
|
Chris@16
|
1025
|
Chris@16
|
1026 };
|
Chris@16
|
1027
|
Chris@16
|
1028
|
Chris@16
|
1029 #undef BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR
|
Chris@16
|
1030 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR
|
Chris@16
|
1031 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR
|
Chris@16
|
1032 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR
|
Chris@16
|
1033 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR
|
Chris@16
|
1034 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1
|
Chris@16
|
1035 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2
|
Chris@16
|
1036 #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3
|
Chris@16
|
1037 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1
|
Chris@16
|
1038 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2
|
Chris@16
|
1039 #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3
|
Chris@16
|
1040 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1
|
Chris@16
|
1041 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2
|
Chris@16
|
1042 #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3
|
Chris@16
|
1043 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1
|
Chris@16
|
1044 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2
|
Chris@16
|
1045 #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3
|
Chris@16
|
1046
|
Chris@16
|
1047 #undef BOOST_QUATERNION_CONSTRUCTOR_GENERATOR
|
Chris@16
|
1048
|
Chris@16
|
1049
|
Chris@16
|
1050 #undef BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR
|
Chris@16
|
1051
|
Chris@16
|
1052 #undef BOOST_QUATERNION_MEMBER_DATA_GENERATOR
|
Chris@16
|
1053
|
Chris@16
|
1054 #undef BOOST_QUATERNION_ACCESSOR_GENERATOR
|
Chris@16
|
1055
|
Chris@16
|
1056
|
Chris@16
|
1057 // operators
|
Chris@16
|
1058
|
Chris@16
|
1059 #define BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op) \
|
Chris@16
|
1060 { \
|
Chris@16
|
1061 quaternion<T> res(lhs); \
|
Chris@16
|
1062 res op##= rhs; \
|
Chris@16
|
1063 return(res); \
|
Chris@16
|
1064 }
|
Chris@16
|
1065
|
Chris@16
|
1066 #define BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
|
Chris@16
|
1067 template<typename T> \
|
Chris@16
|
1068 inline quaternion<T> operator op (T const & lhs, quaternion<T> const & rhs) \
|
Chris@16
|
1069 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
|
Chris@16
|
1070
|
Chris@16
|
1071 #define BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
|
Chris@16
|
1072 template<typename T> \
|
Chris@16
|
1073 inline quaternion<T> operator op (quaternion<T> const & lhs, T const & rhs) \
|
Chris@16
|
1074 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
|
Chris@16
|
1075
|
Chris@16
|
1076 #define BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
|
Chris@16
|
1077 template<typename T> \
|
Chris@16
|
1078 inline quaternion<T> operator op (::std::complex<T> const & lhs, quaternion<T> const & rhs) \
|
Chris@16
|
1079 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
|
Chris@16
|
1080
|
Chris@16
|
1081 #define BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
|
Chris@16
|
1082 template<typename T> \
|
Chris@16
|
1083 inline quaternion<T> operator op (quaternion<T> const & lhs, ::std::complex<T> const & rhs) \
|
Chris@16
|
1084 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
|
Chris@16
|
1085
|
Chris@16
|
1086 #define BOOST_QUATERNION_OPERATOR_GENERATOR_3(op) \
|
Chris@16
|
1087 template<typename T> \
|
Chris@16
|
1088 inline quaternion<T> operator op (quaternion<T> const & lhs, quaternion<T> const & rhs) \
|
Chris@16
|
1089 BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
|
Chris@16
|
1090
|
Chris@16
|
1091 #define BOOST_QUATERNION_OPERATOR_GENERATOR(op) \
|
Chris@16
|
1092 BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
|
Chris@16
|
1093 BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
|
Chris@16
|
1094 BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
|
Chris@16
|
1095 BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
|
Chris@16
|
1096 BOOST_QUATERNION_OPERATOR_GENERATOR_3(op)
|
Chris@16
|
1097
|
Chris@16
|
1098
|
Chris@16
|
1099 BOOST_QUATERNION_OPERATOR_GENERATOR(+)
|
Chris@16
|
1100 BOOST_QUATERNION_OPERATOR_GENERATOR(-)
|
Chris@16
|
1101 BOOST_QUATERNION_OPERATOR_GENERATOR(*)
|
Chris@16
|
1102 BOOST_QUATERNION_OPERATOR_GENERATOR(/)
|
Chris@16
|
1103
|
Chris@16
|
1104
|
Chris@16
|
1105 #undef BOOST_QUATERNION_OPERATOR_GENERATOR
|
Chris@16
|
1106
|
Chris@16
|
1107 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_L
|
Chris@16
|
1108 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_R
|
Chris@16
|
1109 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_L
|
Chris@16
|
1110 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_R
|
Chris@16
|
1111 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_3
|
Chris@16
|
1112
|
Chris@16
|
1113 #undef BOOST_QUATERNION_OPERATOR_GENERATOR_BODY
|
Chris@16
|
1114
|
Chris@16
|
1115
|
Chris@16
|
1116 template<typename T>
|
Chris@16
|
1117 inline quaternion<T> operator + (quaternion<T> const & q)
|
Chris@16
|
1118 {
|
Chris@16
|
1119 return(q);
|
Chris@16
|
1120 }
|
Chris@16
|
1121
|
Chris@16
|
1122
|
Chris@16
|
1123 template<typename T>
|
Chris@16
|
1124 inline quaternion<T> operator - (quaternion<T> const & q)
|
Chris@16
|
1125 {
|
Chris@16
|
1126 return(quaternion<T>(-q.R_component_1(),-q.R_component_2(),-q.R_component_3(),-q.R_component_4()));
|
Chris@16
|
1127 }
|
Chris@16
|
1128
|
Chris@16
|
1129
|
Chris@16
|
1130 template<typename T>
|
Chris@16
|
1131 inline bool operator == (T const & lhs, quaternion<T> const & rhs)
|
Chris@16
|
1132 {
|
Chris@16
|
1133 return (
|
Chris@16
|
1134 (rhs.R_component_1() == lhs)&&
|
Chris@16
|
1135 (rhs.R_component_2() == static_cast<T>(0))&&
|
Chris@16
|
1136 (rhs.R_component_3() == static_cast<T>(0))&&
|
Chris@16
|
1137 (rhs.R_component_4() == static_cast<T>(0))
|
Chris@16
|
1138 );
|
Chris@16
|
1139 }
|
Chris@16
|
1140
|
Chris@16
|
1141
|
Chris@16
|
1142 template<typename T>
|
Chris@16
|
1143 inline bool operator == (quaternion<T> const & lhs, T const & rhs)
|
Chris@16
|
1144 {
|
Chris@16
|
1145 return (
|
Chris@16
|
1146 (lhs.R_component_1() == rhs)&&
|
Chris@16
|
1147 (lhs.R_component_2() == static_cast<T>(0))&&
|
Chris@16
|
1148 (lhs.R_component_3() == static_cast<T>(0))&&
|
Chris@16
|
1149 (lhs.R_component_4() == static_cast<T>(0))
|
Chris@16
|
1150 );
|
Chris@16
|
1151 }
|
Chris@16
|
1152
|
Chris@16
|
1153
|
Chris@16
|
1154 template<typename T>
|
Chris@16
|
1155 inline bool operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs)
|
Chris@16
|
1156 {
|
Chris@16
|
1157 return (
|
Chris@16
|
1158 (rhs.R_component_1() == lhs.real())&&
|
Chris@16
|
1159 (rhs.R_component_2() == lhs.imag())&&
|
Chris@16
|
1160 (rhs.R_component_3() == static_cast<T>(0))&&
|
Chris@16
|
1161 (rhs.R_component_4() == static_cast<T>(0))
|
Chris@16
|
1162 );
|
Chris@16
|
1163 }
|
Chris@16
|
1164
|
Chris@16
|
1165
|
Chris@16
|
1166 template<typename T>
|
Chris@16
|
1167 inline bool operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
|
Chris@16
|
1168 {
|
Chris@16
|
1169 return (
|
Chris@16
|
1170 (lhs.R_component_1() == rhs.real())&&
|
Chris@16
|
1171 (lhs.R_component_2() == rhs.imag())&&
|
Chris@16
|
1172 (lhs.R_component_3() == static_cast<T>(0))&&
|
Chris@16
|
1173 (lhs.R_component_4() == static_cast<T>(0))
|
Chris@16
|
1174 );
|
Chris@16
|
1175 }
|
Chris@16
|
1176
|
Chris@16
|
1177
|
Chris@16
|
1178 template<typename T>
|
Chris@16
|
1179 inline bool operator == (quaternion<T> const & lhs, quaternion<T> const & rhs)
|
Chris@16
|
1180 {
|
Chris@16
|
1181 return (
|
Chris@16
|
1182 (rhs.R_component_1() == lhs.R_component_1())&&
|
Chris@16
|
1183 (rhs.R_component_2() == lhs.R_component_2())&&
|
Chris@16
|
1184 (rhs.R_component_3() == lhs.R_component_3())&&
|
Chris@16
|
1185 (rhs.R_component_4() == lhs.R_component_4())
|
Chris@16
|
1186 );
|
Chris@16
|
1187 }
|
Chris@16
|
1188
|
Chris@16
|
1189
|
Chris@16
|
1190 #define BOOST_QUATERNION_NOT_EQUAL_GENERATOR \
|
Chris@16
|
1191 { \
|
Chris@16
|
1192 return(!(lhs == rhs)); \
|
Chris@16
|
1193 }
|
Chris@16
|
1194
|
Chris@16
|
1195 template<typename T>
|
Chris@16
|
1196 inline bool operator != (T const & lhs, quaternion<T> const & rhs)
|
Chris@16
|
1197 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
|
Chris@16
|
1198
|
Chris@16
|
1199 template<typename T>
|
Chris@16
|
1200 inline bool operator != (quaternion<T> const & lhs, T const & rhs)
|
Chris@16
|
1201 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
|
Chris@16
|
1202
|
Chris@16
|
1203 template<typename T>
|
Chris@16
|
1204 inline bool operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs)
|
Chris@16
|
1205 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
|
Chris@16
|
1206
|
Chris@16
|
1207 template<typename T>
|
Chris@16
|
1208 inline bool operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
|
Chris@16
|
1209 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
|
Chris@16
|
1210
|
Chris@16
|
1211 template<typename T>
|
Chris@16
|
1212 inline bool operator != (quaternion<T> const & lhs, quaternion<T> const & rhs)
|
Chris@16
|
1213 BOOST_QUATERNION_NOT_EQUAL_GENERATOR
|
Chris@16
|
1214
|
Chris@16
|
1215 #undef BOOST_QUATERNION_NOT_EQUAL_GENERATOR
|
Chris@16
|
1216
|
Chris@16
|
1217
|
Chris@16
|
1218 // Note: we allow the following formats, whith a, b, c, and d reals
|
Chris@16
|
1219 // a
|
Chris@16
|
1220 // (a), (a,b), (a,b,c), (a,b,c,d)
|
Chris@16
|
1221 // (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))
|
Chris@16
|
1222 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1223 template<typename T>
|
Chris@16
|
1224 std::istream & operator >> ( ::std::istream & is,
|
Chris@16
|
1225 quaternion<T> & q)
|
Chris@16
|
1226 #else
|
Chris@16
|
1227 template<typename T, typename charT, class traits>
|
Chris@16
|
1228 ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
|
Chris@16
|
1229 quaternion<T> & q)
|
Chris@16
|
1230 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1231 {
|
Chris@16
|
1232 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1233 typedef char charT;
|
Chris@16
|
1234 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1235
|
Chris@16
|
1236 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1237 #else
|
Chris@16
|
1238 const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
|
Chris@16
|
1239 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1240
|
Chris@16
|
1241 T a = T();
|
Chris@16
|
1242 T b = T();
|
Chris@16
|
1243 T c = T();
|
Chris@16
|
1244 T d = T();
|
Chris@16
|
1245
|
Chris@16
|
1246 ::std::complex<T> u = ::std::complex<T>();
|
Chris@16
|
1247 ::std::complex<T> v = ::std::complex<T>();
|
Chris@16
|
1248
|
Chris@16
|
1249 charT ch = charT();
|
Chris@16
|
1250 char cc;
|
Chris@16
|
1251
|
Chris@16
|
1252 is >> ch; // get the first lexeme
|
Chris@16
|
1253
|
Chris@16
|
1254 if (!is.good()) goto finish;
|
Chris@16
|
1255
|
Chris@16
|
1256 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1257 cc = ch;
|
Chris@16
|
1258 #else
|
Chris@16
|
1259 cc = ct.narrow(ch, char());
|
Chris@16
|
1260 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1261
|
Chris@16
|
1262 if (cc == '(') // read "(", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
|
Chris@16
|
1263 {
|
Chris@16
|
1264 is >> ch; // get the second lexeme
|
Chris@16
|
1265
|
Chris@16
|
1266 if (!is.good()) goto finish;
|
Chris@16
|
1267
|
Chris@16
|
1268 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1269 cc = ch;
|
Chris@16
|
1270 #else
|
Chris@16
|
1271 cc = ct.narrow(ch, char());
|
Chris@16
|
1272 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1273
|
Chris@16
|
1274 if (cc == '(') // read "((", possible: ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
|
Chris@16
|
1275 {
|
Chris@16
|
1276 is.putback(ch);
|
Chris@16
|
1277
|
Chris@16
|
1278 is >> u; // we extract the first and second components
|
Chris@16
|
1279 a = u.real();
|
Chris@16
|
1280 b = u.imag();
|
Chris@16
|
1281
|
Chris@16
|
1282 if (!is.good()) goto finish;
|
Chris@16
|
1283
|
Chris@16
|
1284 is >> ch; // get the next lexeme
|
Chris@16
|
1285
|
Chris@16
|
1286 if (!is.good()) goto finish;
|
Chris@16
|
1287
|
Chris@16
|
1288 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1289 cc = ch;
|
Chris@16
|
1290 #else
|
Chris@16
|
1291 cc = ct.narrow(ch, char());
|
Chris@16
|
1292 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1293
|
Chris@16
|
1294 if (cc == ')') // format: ((a)) or ((a,b))
|
Chris@16
|
1295 {
|
Chris@16
|
1296 q = quaternion<T>(a,b);
|
Chris@16
|
1297 }
|
Chris@16
|
1298 else if (cc == ',') // read "((a)," or "((a,b),", possible: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
|
Chris@16
|
1299 {
|
Chris@16
|
1300 is >> v; // we extract the third and fourth components
|
Chris@16
|
1301 c = v.real();
|
Chris@16
|
1302 d = v.imag();
|
Chris@16
|
1303
|
Chris@16
|
1304 if (!is.good()) goto finish;
|
Chris@16
|
1305
|
Chris@16
|
1306 is >> ch; // get the last lexeme
|
Chris@16
|
1307
|
Chris@16
|
1308 if (!is.good()) goto finish;
|
Chris@16
|
1309
|
Chris@16
|
1310 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1311 cc = ch;
|
Chris@16
|
1312 #else
|
Chris@16
|
1313 cc = ct.narrow(ch, char());
|
Chris@16
|
1314 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1315
|
Chris@16
|
1316 if (cc == ')') // format: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)) or ((a,b,),(c,d,))
|
Chris@16
|
1317 {
|
Chris@16
|
1318 q = quaternion<T>(a,b,c,d);
|
Chris@16
|
1319 }
|
Chris@16
|
1320 else // error
|
Chris@16
|
1321 {
|
Chris@16
|
1322 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1323 is.setstate(::std::ios::failbit);
|
Chris@16
|
1324 #else
|
Chris@16
|
1325 is.setstate(::std::ios_base::failbit);
|
Chris@16
|
1326 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1327 }
|
Chris@16
|
1328 }
|
Chris@16
|
1329 else // error
|
Chris@16
|
1330 {
|
Chris@16
|
1331 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1332 is.setstate(::std::ios::failbit);
|
Chris@16
|
1333 #else
|
Chris@16
|
1334 is.setstate(::std::ios_base::failbit);
|
Chris@16
|
1335 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1336 }
|
Chris@16
|
1337 }
|
Chris@16
|
1338 else // read "(a", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
|
Chris@16
|
1339 {
|
Chris@16
|
1340 is.putback(ch);
|
Chris@16
|
1341
|
Chris@16
|
1342 is >> a; // we extract the first component
|
Chris@16
|
1343
|
Chris@16
|
1344 if (!is.good()) goto finish;
|
Chris@16
|
1345
|
Chris@16
|
1346 is >> ch; // get the third lexeme
|
Chris@16
|
1347
|
Chris@16
|
1348 if (!is.good()) goto finish;
|
Chris@16
|
1349
|
Chris@16
|
1350 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1351 cc = ch;
|
Chris@16
|
1352 #else
|
Chris@16
|
1353 cc = ct.narrow(ch, char());
|
Chris@16
|
1354 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1355
|
Chris@16
|
1356 if (cc == ')') // format: (a)
|
Chris@16
|
1357 {
|
Chris@16
|
1358 q = quaternion<T>(a);
|
Chris@16
|
1359 }
|
Chris@16
|
1360 else if (cc == ',') // read "(a,", possible: (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
|
Chris@16
|
1361 {
|
Chris@16
|
1362 is >> ch; // get the fourth lexeme
|
Chris@16
|
1363
|
Chris@16
|
1364 if (!is.good()) goto finish;
|
Chris@16
|
1365
|
Chris@16
|
1366 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1367 cc = ch;
|
Chris@16
|
1368 #else
|
Chris@16
|
1369 cc = ct.narrow(ch, char());
|
Chris@16
|
1370 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1371
|
Chris@16
|
1372 if (cc == '(') // read "(a,(", possible: (a,(c)), (a,(c,d))
|
Chris@16
|
1373 {
|
Chris@16
|
1374 is.putback(ch);
|
Chris@16
|
1375
|
Chris@16
|
1376 is >> v; // we extract the third and fourth component
|
Chris@16
|
1377
|
Chris@16
|
1378 c = v.real();
|
Chris@16
|
1379 d = v.imag();
|
Chris@16
|
1380
|
Chris@16
|
1381 if (!is.good()) goto finish;
|
Chris@16
|
1382
|
Chris@16
|
1383 is >> ch; // get the ninth lexeme
|
Chris@16
|
1384
|
Chris@16
|
1385 if (!is.good()) goto finish;
|
Chris@16
|
1386
|
Chris@16
|
1387 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1388 cc = ch;
|
Chris@16
|
1389 #else
|
Chris@16
|
1390 cc = ct.narrow(ch, char());
|
Chris@16
|
1391 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1392
|
Chris@16
|
1393 if (cc == ')') // format: (a,(c)) or (a,(c,d))
|
Chris@16
|
1394 {
|
Chris@16
|
1395 q = quaternion<T>(a,b,c,d);
|
Chris@16
|
1396 }
|
Chris@16
|
1397 else // error
|
Chris@16
|
1398 {
|
Chris@16
|
1399 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1400 is.setstate(::std::ios::failbit);
|
Chris@16
|
1401 #else
|
Chris@16
|
1402 is.setstate(::std::ios_base::failbit);
|
Chris@16
|
1403 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1404 }
|
Chris@16
|
1405 }
|
Chris@16
|
1406 else // read "(a,b", possible: (a,b), (a,b,c), (a,b,c,d)
|
Chris@16
|
1407 {
|
Chris@16
|
1408 is.putback(ch);
|
Chris@16
|
1409
|
Chris@16
|
1410 is >> b; // we extract the second component
|
Chris@16
|
1411
|
Chris@16
|
1412 if (!is.good()) goto finish;
|
Chris@16
|
1413
|
Chris@16
|
1414 is >> ch; // get the fifth lexeme
|
Chris@16
|
1415
|
Chris@16
|
1416 if (!is.good()) goto finish;
|
Chris@16
|
1417
|
Chris@16
|
1418 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1419 cc = ch;
|
Chris@16
|
1420 #else
|
Chris@16
|
1421 cc = ct.narrow(ch, char());
|
Chris@16
|
1422 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1423
|
Chris@16
|
1424 if (cc == ')') // format: (a,b)
|
Chris@16
|
1425 {
|
Chris@16
|
1426 q = quaternion<T>(a,b);
|
Chris@16
|
1427 }
|
Chris@16
|
1428 else if (cc == ',') // read "(a,b,", possible: (a,b,c), (a,b,c,d)
|
Chris@16
|
1429 {
|
Chris@16
|
1430 is >> c; // we extract the third component
|
Chris@16
|
1431
|
Chris@16
|
1432 if (!is.good()) goto finish;
|
Chris@16
|
1433
|
Chris@16
|
1434 is >> ch; // get the seventh lexeme
|
Chris@16
|
1435
|
Chris@16
|
1436 if (!is.good()) goto finish;
|
Chris@16
|
1437
|
Chris@16
|
1438 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1439 cc = ch;
|
Chris@16
|
1440 #else
|
Chris@16
|
1441 cc = ct.narrow(ch, char());
|
Chris@16
|
1442 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1443
|
Chris@16
|
1444 if (cc == ')') // format: (a,b,c)
|
Chris@16
|
1445 {
|
Chris@16
|
1446 q = quaternion<T>(a,b,c);
|
Chris@16
|
1447 }
|
Chris@16
|
1448 else if (cc == ',') // read "(a,b,c,", possible: (a,b,c,d)
|
Chris@16
|
1449 {
|
Chris@16
|
1450 is >> d; // we extract the fourth component
|
Chris@16
|
1451
|
Chris@16
|
1452 if (!is.good()) goto finish;
|
Chris@16
|
1453
|
Chris@16
|
1454 is >> ch; // get the ninth lexeme
|
Chris@16
|
1455
|
Chris@16
|
1456 if (!is.good()) goto finish;
|
Chris@16
|
1457
|
Chris@16
|
1458 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1459 cc = ch;
|
Chris@16
|
1460 #else
|
Chris@16
|
1461 cc = ct.narrow(ch, char());
|
Chris@16
|
1462 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1463
|
Chris@16
|
1464 if (cc == ')') // format: (a,b,c,d)
|
Chris@16
|
1465 {
|
Chris@16
|
1466 q = quaternion<T>(a,b,c,d);
|
Chris@16
|
1467 }
|
Chris@16
|
1468 else // error
|
Chris@16
|
1469 {
|
Chris@16
|
1470 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1471 is.setstate(::std::ios::failbit);
|
Chris@16
|
1472 #else
|
Chris@16
|
1473 is.setstate(::std::ios_base::failbit);
|
Chris@16
|
1474 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1475 }
|
Chris@16
|
1476 }
|
Chris@16
|
1477 else // error
|
Chris@16
|
1478 {
|
Chris@16
|
1479 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1480 is.setstate(::std::ios::failbit);
|
Chris@16
|
1481 #else
|
Chris@16
|
1482 is.setstate(::std::ios_base::failbit);
|
Chris@16
|
1483 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1484 }
|
Chris@16
|
1485 }
|
Chris@16
|
1486 else // error
|
Chris@16
|
1487 {
|
Chris@16
|
1488 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1489 is.setstate(::std::ios::failbit);
|
Chris@16
|
1490 #else
|
Chris@16
|
1491 is.setstate(::std::ios_base::failbit);
|
Chris@16
|
1492 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1493 }
|
Chris@16
|
1494 }
|
Chris@16
|
1495 }
|
Chris@16
|
1496 else // error
|
Chris@16
|
1497 {
|
Chris@16
|
1498 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1499 is.setstate(::std::ios::failbit);
|
Chris@16
|
1500 #else
|
Chris@16
|
1501 is.setstate(::std::ios_base::failbit);
|
Chris@16
|
1502 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1503 }
|
Chris@16
|
1504 }
|
Chris@16
|
1505 }
|
Chris@16
|
1506 else // format: a
|
Chris@16
|
1507 {
|
Chris@16
|
1508 is.putback(ch);
|
Chris@16
|
1509
|
Chris@16
|
1510 is >> a; // we extract the first component
|
Chris@16
|
1511
|
Chris@16
|
1512 if (!is.good()) goto finish;
|
Chris@16
|
1513
|
Chris@16
|
1514 q = quaternion<T>(a);
|
Chris@16
|
1515 }
|
Chris@16
|
1516
|
Chris@16
|
1517 finish:
|
Chris@16
|
1518 return(is);
|
Chris@16
|
1519 }
|
Chris@16
|
1520
|
Chris@16
|
1521
|
Chris@16
|
1522 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1523 template<typename T>
|
Chris@16
|
1524 ::std::ostream & operator << ( ::std::ostream & os,
|
Chris@16
|
1525 quaternion<T> const & q)
|
Chris@16
|
1526 #else
|
Chris@16
|
1527 template<typename T, typename charT, class traits>
|
Chris@16
|
1528 ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
|
Chris@16
|
1529 quaternion<T> const & q)
|
Chris@16
|
1530 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1531 {
|
Chris@16
|
1532 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1533 ::std::ostringstream s;
|
Chris@16
|
1534 #else
|
Chris@16
|
1535 ::std::basic_ostringstream<charT,traits> s;
|
Chris@16
|
1536 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1537
|
Chris@16
|
1538 s.flags(os.flags());
|
Chris@16
|
1539 #ifdef BOOST_NO_STD_LOCALE
|
Chris@16
|
1540 #else
|
Chris@16
|
1541 s.imbue(os.getloc());
|
Chris@16
|
1542 #endif /* BOOST_NO_STD_LOCALE */
|
Chris@16
|
1543 s.precision(os.precision());
|
Chris@16
|
1544
|
Chris@16
|
1545 s << '(' << q.R_component_1() << ','
|
Chris@16
|
1546 << q.R_component_2() << ','
|
Chris@16
|
1547 << q.R_component_3() << ','
|
Chris@16
|
1548 << q.R_component_4() << ')';
|
Chris@16
|
1549
|
Chris@16
|
1550 return os << s.str();
|
Chris@16
|
1551 }
|
Chris@16
|
1552
|
Chris@16
|
1553
|
Chris@16
|
1554 // values
|
Chris@16
|
1555
|
Chris@16
|
1556 template<typename T>
|
Chris@16
|
1557 inline T real(quaternion<T> const & q)
|
Chris@16
|
1558 {
|
Chris@16
|
1559 return(q.real());
|
Chris@16
|
1560 }
|
Chris@16
|
1561
|
Chris@16
|
1562
|
Chris@16
|
1563 template<typename T>
|
Chris@16
|
1564 inline quaternion<T> unreal(quaternion<T> const & q)
|
Chris@16
|
1565 {
|
Chris@16
|
1566 return(q.unreal());
|
Chris@16
|
1567 }
|
Chris@16
|
1568
|
Chris@16
|
1569
|
Chris@16
|
1570 #define BOOST_QUATERNION_VALARRAY_LOADER \
|
Chris@16
|
1571 using ::std::valarray; \
|
Chris@16
|
1572 \
|
Chris@16
|
1573 valarray<T> temp(4); \
|
Chris@16
|
1574 \
|
Chris@16
|
1575 temp[0] = q.R_component_1(); \
|
Chris@16
|
1576 temp[1] = q.R_component_2(); \
|
Chris@16
|
1577 temp[2] = q.R_component_3(); \
|
Chris@16
|
1578 temp[3] = q.R_component_4();
|
Chris@16
|
1579
|
Chris@16
|
1580
|
Chris@16
|
1581 template<typename T>
|
Chris@16
|
1582 inline T sup(quaternion<T> const & q)
|
Chris@16
|
1583 {
|
Chris@16
|
1584 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
Chris@16
|
1585 using ::std::abs;
|
Chris@16
|
1586 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
|
Chris@16
|
1587
|
Chris@16
|
1588 BOOST_QUATERNION_VALARRAY_LOADER
|
Chris@16
|
1589
|
Chris@16
|
1590 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1591 return((BOOST_GET_VALARRAY(T, abs(temp)).max)());
|
Chris@16
|
1592 #else
|
Chris@16
|
1593 return((abs(temp).max)());
|
Chris@16
|
1594 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1595 }
|
Chris@16
|
1596
|
Chris@16
|
1597
|
Chris@16
|
1598 template<typename T>
|
Chris@16
|
1599 inline T l1(quaternion<T> const & q)
|
Chris@16
|
1600 {
|
Chris@16
|
1601 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
Chris@16
|
1602 using ::std::abs;
|
Chris@16
|
1603 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
|
Chris@16
|
1604
|
Chris@16
|
1605 BOOST_QUATERNION_VALARRAY_LOADER
|
Chris@16
|
1606
|
Chris@16
|
1607 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1608 return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
|
Chris@16
|
1609 #else
|
Chris@16
|
1610 return(abs(temp).sum());
|
Chris@16
|
1611 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1612 }
|
Chris@16
|
1613
|
Chris@16
|
1614
|
Chris@16
|
1615 template<typename T>
|
Chris@16
|
1616 inline T abs(quaternion<T> const & q)
|
Chris@16
|
1617 {
|
Chris@16
|
1618 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
Chris@16
|
1619 using ::std::abs;
|
Chris@16
|
1620 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
|
Chris@16
|
1621
|
Chris@16
|
1622 using ::std::sqrt;
|
Chris@16
|
1623
|
Chris@16
|
1624 BOOST_QUATERNION_VALARRAY_LOADER
|
Chris@16
|
1625
|
Chris@16
|
1626 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1627 T maxim = (BOOST_GET_VALARRAY(T, abs(temp)).max)(); // overflow protection
|
Chris@16
|
1628 #else
|
Chris@16
|
1629 T maxim = (abs(temp).max)(); // overflow protection
|
Chris@16
|
1630 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1631
|
Chris@16
|
1632 if (maxim == static_cast<T>(0))
|
Chris@16
|
1633 {
|
Chris@16
|
1634 return(maxim);
|
Chris@16
|
1635 }
|
Chris@16
|
1636 else
|
Chris@16
|
1637 {
|
Chris@16
|
1638 T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions
|
Chris@16
|
1639
|
Chris@16
|
1640 temp *= mixam;
|
Chris@16
|
1641
|
Chris@16
|
1642 temp *= temp;
|
Chris@16
|
1643
|
Chris@16
|
1644 return(maxim*sqrt(temp.sum()));
|
Chris@16
|
1645 }
|
Chris@16
|
1646
|
Chris@16
|
1647 //return(sqrt(norm(q)));
|
Chris@16
|
1648 }
|
Chris@16
|
1649
|
Chris@16
|
1650
|
Chris@16
|
1651 #undef BOOST_QUATERNION_VALARRAY_LOADER
|
Chris@16
|
1652
|
Chris@16
|
1653
|
Chris@16
|
1654 // Note: This is the Cayley norm, not the Euclidian norm...
|
Chris@16
|
1655
|
Chris@16
|
1656 template<typename T>
|
Chris@16
|
1657 inline T norm(quaternion<T>const & q)
|
Chris@16
|
1658 {
|
Chris@16
|
1659 return(real(q*conj(q)));
|
Chris@16
|
1660 }
|
Chris@16
|
1661
|
Chris@16
|
1662
|
Chris@16
|
1663 template<typename T>
|
Chris@16
|
1664 inline quaternion<T> conj(quaternion<T> const & q)
|
Chris@16
|
1665 {
|
Chris@16
|
1666 return(quaternion<T>( +q.R_component_1(),
|
Chris@16
|
1667 -q.R_component_2(),
|
Chris@16
|
1668 -q.R_component_3(),
|
Chris@16
|
1669 -q.R_component_4()));
|
Chris@16
|
1670 }
|
Chris@16
|
1671
|
Chris@16
|
1672
|
Chris@16
|
1673 template<typename T>
|
Chris@16
|
1674 inline quaternion<T> spherical( T const & rho,
|
Chris@16
|
1675 T const & theta,
|
Chris@16
|
1676 T const & phi1,
|
Chris@16
|
1677 T const & phi2)
|
Chris@16
|
1678 {
|
Chris@16
|
1679 using ::std::cos;
|
Chris@16
|
1680 using ::std::sin;
|
Chris@16
|
1681
|
Chris@16
|
1682 //T a = cos(theta)*cos(phi1)*cos(phi2);
|
Chris@16
|
1683 //T b = sin(theta)*cos(phi1)*cos(phi2);
|
Chris@16
|
1684 //T c = sin(phi1)*cos(phi2);
|
Chris@16
|
1685 //T d = sin(phi2);
|
Chris@16
|
1686
|
Chris@16
|
1687 T courrant = static_cast<T>(1);
|
Chris@16
|
1688
|
Chris@16
|
1689 T d = sin(phi2);
|
Chris@16
|
1690
|
Chris@16
|
1691 courrant *= cos(phi2);
|
Chris@16
|
1692
|
Chris@16
|
1693 T c = sin(phi1)*courrant;
|
Chris@16
|
1694
|
Chris@16
|
1695 courrant *= cos(phi1);
|
Chris@16
|
1696
|
Chris@16
|
1697 T b = sin(theta)*courrant;
|
Chris@16
|
1698 T a = cos(theta)*courrant;
|
Chris@16
|
1699
|
Chris@16
|
1700 return(rho*quaternion<T>(a,b,c,d));
|
Chris@16
|
1701 }
|
Chris@16
|
1702
|
Chris@16
|
1703
|
Chris@16
|
1704 template<typename T>
|
Chris@16
|
1705 inline quaternion<T> semipolar( T const & rho,
|
Chris@16
|
1706 T const & alpha,
|
Chris@16
|
1707 T const & theta1,
|
Chris@16
|
1708 T const & theta2)
|
Chris@16
|
1709 {
|
Chris@16
|
1710 using ::std::cos;
|
Chris@16
|
1711 using ::std::sin;
|
Chris@16
|
1712
|
Chris@16
|
1713 T a = cos(alpha)*cos(theta1);
|
Chris@16
|
1714 T b = cos(alpha)*sin(theta1);
|
Chris@16
|
1715 T c = sin(alpha)*cos(theta2);
|
Chris@16
|
1716 T d = sin(alpha)*sin(theta2);
|
Chris@16
|
1717
|
Chris@16
|
1718 return(rho*quaternion<T>(a,b,c,d));
|
Chris@16
|
1719 }
|
Chris@16
|
1720
|
Chris@16
|
1721
|
Chris@16
|
1722 template<typename T>
|
Chris@16
|
1723 inline quaternion<T> multipolar( T const & rho1,
|
Chris@16
|
1724 T const & theta1,
|
Chris@16
|
1725 T const & rho2,
|
Chris@16
|
1726 T const & theta2)
|
Chris@16
|
1727 {
|
Chris@16
|
1728 using ::std::cos;
|
Chris@16
|
1729 using ::std::sin;
|
Chris@16
|
1730
|
Chris@16
|
1731 T a = rho1*cos(theta1);
|
Chris@16
|
1732 T b = rho1*sin(theta1);
|
Chris@16
|
1733 T c = rho2*cos(theta2);
|
Chris@16
|
1734 T d = rho2*sin(theta2);
|
Chris@16
|
1735
|
Chris@16
|
1736 return(quaternion<T>(a,b,c,d));
|
Chris@16
|
1737 }
|
Chris@16
|
1738
|
Chris@16
|
1739
|
Chris@16
|
1740 template<typename T>
|
Chris@16
|
1741 inline quaternion<T> cylindrospherical( T const & t,
|
Chris@16
|
1742 T const & radius,
|
Chris@16
|
1743 T const & longitude,
|
Chris@16
|
1744 T const & latitude)
|
Chris@16
|
1745 {
|
Chris@16
|
1746 using ::std::cos;
|
Chris@16
|
1747 using ::std::sin;
|
Chris@16
|
1748
|
Chris@16
|
1749
|
Chris@16
|
1750
|
Chris@16
|
1751 T b = radius*cos(longitude)*cos(latitude);
|
Chris@16
|
1752 T c = radius*sin(longitude)*cos(latitude);
|
Chris@16
|
1753 T d = radius*sin(latitude);
|
Chris@16
|
1754
|
Chris@16
|
1755 return(quaternion<T>(t,b,c,d));
|
Chris@16
|
1756 }
|
Chris@16
|
1757
|
Chris@16
|
1758
|
Chris@16
|
1759 template<typename T>
|
Chris@16
|
1760 inline quaternion<T> cylindrical(T const & r,
|
Chris@16
|
1761 T const & angle,
|
Chris@16
|
1762 T const & h1,
|
Chris@16
|
1763 T const & h2)
|
Chris@16
|
1764 {
|
Chris@16
|
1765 using ::std::cos;
|
Chris@16
|
1766 using ::std::sin;
|
Chris@16
|
1767
|
Chris@16
|
1768 T a = r*cos(angle);
|
Chris@16
|
1769 T b = r*sin(angle);
|
Chris@16
|
1770
|
Chris@16
|
1771 return(quaternion<T>(a,b,h1,h2));
|
Chris@16
|
1772 }
|
Chris@16
|
1773
|
Chris@16
|
1774
|
Chris@16
|
1775 // transcendentals
|
Chris@16
|
1776 // (please see the documentation)
|
Chris@16
|
1777
|
Chris@16
|
1778
|
Chris@16
|
1779 template<typename T>
|
Chris@16
|
1780 inline quaternion<T> exp(quaternion<T> const & q)
|
Chris@16
|
1781 {
|
Chris@16
|
1782 using ::std::exp;
|
Chris@16
|
1783 using ::std::cos;
|
Chris@16
|
1784
|
Chris@16
|
1785 using ::boost::math::sinc_pi;
|
Chris@16
|
1786
|
Chris@16
|
1787 T u = exp(real(q));
|
Chris@16
|
1788
|
Chris@16
|
1789 T z = abs(unreal(q));
|
Chris@16
|
1790
|
Chris@16
|
1791 T w = sinc_pi(z);
|
Chris@16
|
1792
|
Chris@16
|
1793 return(u*quaternion<T>(cos(z),
|
Chris@16
|
1794 w*q.R_component_2(), w*q.R_component_3(),
|
Chris@16
|
1795 w*q.R_component_4()));
|
Chris@16
|
1796 }
|
Chris@16
|
1797
|
Chris@16
|
1798
|
Chris@16
|
1799 template<typename T>
|
Chris@16
|
1800 inline quaternion<T> cos(quaternion<T> const & q)
|
Chris@16
|
1801 {
|
Chris@16
|
1802 using ::std::sin;
|
Chris@16
|
1803 using ::std::cos;
|
Chris@16
|
1804 using ::std::cosh;
|
Chris@16
|
1805
|
Chris@16
|
1806 using ::boost::math::sinhc_pi;
|
Chris@16
|
1807
|
Chris@16
|
1808 T z = abs(unreal(q));
|
Chris@16
|
1809
|
Chris@16
|
1810 T w = -sin(q.real())*sinhc_pi(z);
|
Chris@16
|
1811
|
Chris@16
|
1812 return(quaternion<T>(cos(q.real())*cosh(z),
|
Chris@16
|
1813 w*q.R_component_2(), w*q.R_component_3(),
|
Chris@16
|
1814 w*q.R_component_4()));
|
Chris@16
|
1815 }
|
Chris@16
|
1816
|
Chris@16
|
1817
|
Chris@16
|
1818 template<typename T>
|
Chris@16
|
1819 inline quaternion<T> sin(quaternion<T> const & q)
|
Chris@16
|
1820 {
|
Chris@16
|
1821 using ::std::sin;
|
Chris@16
|
1822 using ::std::cos;
|
Chris@16
|
1823 using ::std::cosh;
|
Chris@16
|
1824
|
Chris@16
|
1825 using ::boost::math::sinhc_pi;
|
Chris@16
|
1826
|
Chris@16
|
1827 T z = abs(unreal(q));
|
Chris@16
|
1828
|
Chris@16
|
1829 T w = +cos(q.real())*sinhc_pi(z);
|
Chris@16
|
1830
|
Chris@16
|
1831 return(quaternion<T>(sin(q.real())*cosh(z),
|
Chris@16
|
1832 w*q.R_component_2(), w*q.R_component_3(),
|
Chris@16
|
1833 w*q.R_component_4()));
|
Chris@16
|
1834 }
|
Chris@16
|
1835
|
Chris@16
|
1836
|
Chris@16
|
1837 template<typename T>
|
Chris@16
|
1838 inline quaternion<T> tan(quaternion<T> const & q)
|
Chris@16
|
1839 {
|
Chris@16
|
1840 return(sin(q)/cos(q));
|
Chris@16
|
1841 }
|
Chris@16
|
1842
|
Chris@16
|
1843
|
Chris@16
|
1844 template<typename T>
|
Chris@16
|
1845 inline quaternion<T> cosh(quaternion<T> const & q)
|
Chris@16
|
1846 {
|
Chris@16
|
1847 return((exp(+q)+exp(-q))/static_cast<T>(2));
|
Chris@16
|
1848 }
|
Chris@16
|
1849
|
Chris@16
|
1850
|
Chris@16
|
1851 template<typename T>
|
Chris@16
|
1852 inline quaternion<T> sinh(quaternion<T> const & q)
|
Chris@16
|
1853 {
|
Chris@16
|
1854 return((exp(+q)-exp(-q))/static_cast<T>(2));
|
Chris@16
|
1855 }
|
Chris@16
|
1856
|
Chris@16
|
1857
|
Chris@16
|
1858 template<typename T>
|
Chris@16
|
1859 inline quaternion<T> tanh(quaternion<T> const & q)
|
Chris@16
|
1860 {
|
Chris@16
|
1861 return(sinh(q)/cosh(q));
|
Chris@16
|
1862 }
|
Chris@16
|
1863
|
Chris@16
|
1864
|
Chris@16
|
1865 template<typename T>
|
Chris@16
|
1866 quaternion<T> pow(quaternion<T> const & q,
|
Chris@16
|
1867 int n)
|
Chris@16
|
1868 {
|
Chris@16
|
1869 if (n > 1)
|
Chris@16
|
1870 {
|
Chris@16
|
1871 int m = n>>1;
|
Chris@16
|
1872
|
Chris@16
|
1873 quaternion<T> result = pow(q, m);
|
Chris@16
|
1874
|
Chris@16
|
1875 result *= result;
|
Chris@16
|
1876
|
Chris@16
|
1877 if (n != (m<<1))
|
Chris@16
|
1878 {
|
Chris@16
|
1879 result *= q; // n odd
|
Chris@16
|
1880 }
|
Chris@16
|
1881
|
Chris@16
|
1882 return(result);
|
Chris@16
|
1883 }
|
Chris@16
|
1884 else if (n == 1)
|
Chris@16
|
1885 {
|
Chris@16
|
1886 return(q);
|
Chris@16
|
1887 }
|
Chris@16
|
1888 else if (n == 0)
|
Chris@16
|
1889 {
|
Chris@16
|
1890 return(quaternion<T>(static_cast<T>(1)));
|
Chris@16
|
1891 }
|
Chris@16
|
1892 else /* n < 0 */
|
Chris@16
|
1893 {
|
Chris@16
|
1894 return(pow(quaternion<T>(static_cast<T>(1))/q,-n));
|
Chris@16
|
1895 }
|
Chris@16
|
1896 }
|
Chris@16
|
1897
|
Chris@16
|
1898
|
Chris@16
|
1899 // helper templates for converting copy constructors (definition)
|
Chris@16
|
1900
|
Chris@16
|
1901 namespace detail
|
Chris@16
|
1902 {
|
Chris@16
|
1903
|
Chris@16
|
1904 template< typename T,
|
Chris@16
|
1905 typename U
|
Chris@16
|
1906 >
|
Chris@16
|
1907 quaternion<T> quaternion_type_converter(quaternion<U> const & rhs)
|
Chris@16
|
1908 {
|
Chris@16
|
1909 return(quaternion<T>( static_cast<T>(rhs.R_component_1()),
|
Chris@16
|
1910 static_cast<T>(rhs.R_component_2()),
|
Chris@16
|
1911 static_cast<T>(rhs.R_component_3()),
|
Chris@16
|
1912 static_cast<T>(rhs.R_component_4())));
|
Chris@16
|
1913 }
|
Chris@16
|
1914 }
|
Chris@16
|
1915 }
|
Chris@16
|
1916 }
|
Chris@16
|
1917
|
Chris@16
|
1918
|
Chris@16
|
1919 #if BOOST_WORKAROUND(__GNUC__, < 3)
|
Chris@16
|
1920 #undef BOOST_GET_VALARRAY
|
Chris@16
|
1921 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
|
Chris@16
|
1922
|
Chris@16
|
1923
|
Chris@16
|
1924 #endif /* BOOST_QUATERNION_HPP */
|