annotate DEPENDENCIES/generic/include/boost/math/quaternion.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
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 */