1 // boost octonion.hpp header file 2 3 // (C) Copyright Hubert Holin 2001. 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 8 // See http://www.boost.org for updates, documentation, and revision history. 9 10 11 #ifndef BOOST_OCTONION_HPP 12 #define BOOST_OCTONION_HPP 13 14 #include <boost/math/quaternion.hpp> 15 16 17 namespace boost 18 { 19 namespace math 20 { 21 #if BOOST_WORKAROUND(__GNUC__, < 3) 22 // gcc 2.95.x uses expression templates for valarray calculations, but 23 // the result is not conforming. We need BOOST_GET_VALARRAY to get an 24 // actual valarray result when we need to call a member function 25 #define BOOST_GET_VALARRAY(T,x) ::std::valarray<T>(x) 26 // gcc 2.95.x has an "std::ios" class that is similar to 27 // "std::ios_base", so we just use a #define 28 #define BOOST_IOS_BASE ::std::ios 29 // gcc 2.x ignores function scope using declarations, 30 // put them in the scope of the enclosing namespace instead: 31 using ::std::valarray; 32 using ::std::sqrt; 33 using ::std::cos; 34 using ::std::sin; 35 using ::std::exp; 36 using ::std::cosh; 37 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 38 39 #define BOOST_OCTONION_ACCESSOR_GENERATOR(type) \ 40 type real() const \ 41 { \ 42 return(a); \ 43 } \ 44 \ 45 octonion<type> unreal() const \ 46 { \ 47 return( octonion<type>(static_cast<type>(0),b,c,d,e,f,g,h)); \ 48 } \ 49 \ 50 type R_component_1() const \ 51 { \ 52 return(a); \ 53 } \ 54 \ 55 type R_component_2() const \ 56 { \ 57 return(b); \ 58 } \ 59 \ 60 type R_component_3() const \ 61 { \ 62 return(c); \ 63 } \ 64 \ 65 type R_component_4() const \ 66 { \ 67 return(d); \ 68 } \ 69 \ 70 type R_component_5() const \ 71 { \ 72 return(e); \ 73 } \ 74 \ 75 type R_component_6() const \ 76 { \ 77 return(f); \ 78 } \ 79 \ 80 type R_component_7() const \ 81 { \ 82 return(g); \ 83 } \ 84 \ 85 type R_component_8() const \ 86 { \ 87 return(h); \ 88 } \ 89 \ 90 ::std::complex<type> C_component_1() const \ 91 { \ 92 return(::std::complex<type>(a,b)); \ 93 } \ 94 \ 95 ::std::complex<type> C_component_2() const \ 96 { \ 97 return(::std::complex<type>(c,d)); \ 98 } \ 99 \ 100 ::std::complex<type> C_component_3() const \ 101 { \ 102 return(::std::complex<type>(e,f)); \ 103 } \ 104 \ 105 ::std::complex<type> C_component_4() const \ 106 { \ 107 return(::std::complex<type>(g,h)); \ 108 } \ 109 \ 110 ::boost::math::quaternion<type> H_component_1() const \ 111 { \ 112 return(::boost::math::quaternion<type>(a,b,c,d)); \ 113 } \ 114 \ 115 ::boost::math::quaternion<type> H_component_2() const \ 116 { \ 117 return(::boost::math::quaternion<type>(e,f,g,h)); \ 118 } 119 120 121 #define BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(type) \ 122 template<typename X> \ 123 octonion<type> & operator = (octonion<X> const & a_affecter) \ 124 { \ 125 a = static_cast<type>(a_affecter.R_component_1()); \ 126 b = static_cast<type>(a_affecter.R_component_2()); \ 127 c = static_cast<type>(a_affecter.R_component_3()); \ 128 d = static_cast<type>(a_affecter.R_component_4()); \ 129 e = static_cast<type>(a_affecter.R_component_5()); \ 130 f = static_cast<type>(a_affecter.R_component_6()); \ 131 g = static_cast<type>(a_affecter.R_component_7()); \ 132 h = static_cast<type>(a_affecter.R_component_8()); \ 133 \ 134 return(*this); \ 135 } \ 136 \ 137 octonion<type> & operator = (octonion<type> const & a_affecter) \ 138 { \ 139 a = a_affecter.a; \ 140 b = a_affecter.b; \ 141 c = a_affecter.c; \ 142 d = a_affecter.d; \ 143 e = a_affecter.e; \ 144 f = a_affecter.f; \ 145 g = a_affecter.g; \ 146 h = a_affecter.h; \ 147 \ 148 return(*this); \ 149 } \ 150 \ 151 octonion<type> & operator = (type const & a_affecter) \ 152 { \ 153 a = a_affecter; \ 154 \ 155 b = c = d = e = f= g = h = static_cast<type>(0); \ 156 \ 157 return(*this); \ 158 } \ 159 \ 160 octonion<type> & operator = (::std::complex<type> const & a_affecter) \ 161 { \ 162 a = a_affecter.real(); \ 163 b = a_affecter.imag(); \ 164 \ 165 c = d = e = f = g = h = static_cast<type>(0); \ 166 \ 167 return(*this); \ 168 } \ 169 \ 170 octonion<type> & operator = (::boost::math::quaternion<type> const & a_affecter) \ 171 { \ 172 a = a_affecter.R_component_1(); \ 173 b = a_affecter.R_component_2(); \ 174 c = a_affecter.R_component_3(); \ 175 d = a_affecter.R_component_4(); \ 176 \ 177 e = f = g = h = static_cast<type>(0); \ 178 \ 179 return(*this); \ 180 } 181 182 183 #define BOOST_OCTONION_MEMBER_DATA_GENERATOR(type) \ 184 type a; \ 185 type b; \ 186 type c; \ 187 type d; \ 188 type e; \ 189 type f; \ 190 type g; \ 191 type h; \ 192 193 194 template<typename T> 195 class octonion 196 { 197 public: 198 199 typedef T value_type; 200 201 // constructor for O seen as R^8 202 // (also default constructor) 203 octonion(T const & requested_a=T (),T const & requested_b=T (),T const & requested_c=T (),T const & requested_d=T (),T const & requested_e=T (),T const & requested_f=T (),T const & requested_g=T (),T const & requested_h=T ())204 explicit octonion( T const & requested_a = T(), 205 T const & requested_b = T(), 206 T const & requested_c = T(), 207 T const & requested_d = T(), 208 T const & requested_e = T(), 209 T const & requested_f = T(), 210 T const & requested_g = T(), 211 T const & requested_h = T()) 212 : a(requested_a), 213 b(requested_b), 214 c(requested_c), 215 d(requested_d), 216 e(requested_e), 217 f(requested_f), 218 g(requested_g), 219 h(requested_h) 220 { 221 // nothing to do! 222 } 223 224 225 // constructor for H seen as C^4 226 octonion(::std::complex<T> const & z0,::std::complex<T> const & z1=::std::complex<T> (),::std::complex<T> const & z2=::std::complex<T> (),::std::complex<T> const & z3=::std::complex<T> ())227 explicit octonion( ::std::complex<T> const & z0, 228 ::std::complex<T> const & z1 = ::std::complex<T>(), 229 ::std::complex<T> const & z2 = ::std::complex<T>(), 230 ::std::complex<T> const & z3 = ::std::complex<T>()) 231 : a(z0.real()), 232 b(z0.imag()), 233 c(z1.real()), 234 d(z1.imag()), 235 e(z2.real()), 236 f(z2.imag()), 237 g(z3.real()), 238 h(z3.imag()) 239 { 240 // nothing to do! 241 } 242 243 244 // constructor for O seen as H^2 245 octonion(::boost::math::quaternion<T> const & q0,::boost::math::quaternion<T> const & q1=::boost::math::quaternion<T> ())246 explicit octonion( ::boost::math::quaternion<T> const & q0, 247 ::boost::math::quaternion<T> const & q1 = ::boost::math::quaternion<T>()) 248 : a(q0.R_component_1()), 249 b(q0.R_component_2()), 250 c(q0.R_component_3()), 251 d(q0.R_component_4()), 252 e(q1.R_component_1()), 253 f(q1.R_component_2()), 254 g(q1.R_component_3()), 255 h(q1.R_component_4()) 256 { 257 // nothing to do! 258 } 259 260 261 // UNtemplated copy constructor 262 // (this is taken care of by the compiler itself) 263 264 265 // templated copy constructor 266 267 template<typename X> octonion(octonion<X> const & a_recopier)268 explicit octonion(octonion<X> const & a_recopier) 269 : a(static_cast<T>(a_recopier.R_component_1())), 270 b(static_cast<T>(a_recopier.R_component_2())), 271 c(static_cast<T>(a_recopier.R_component_3())), 272 d(static_cast<T>(a_recopier.R_component_4())), 273 e(static_cast<T>(a_recopier.R_component_5())), 274 f(static_cast<T>(a_recopier.R_component_6())), 275 g(static_cast<T>(a_recopier.R_component_7())), 276 h(static_cast<T>(a_recopier.R_component_8())) 277 { 278 // nothing to do! 279 } 280 281 282 // destructor 283 // (this is taken care of by the compiler itself) 284 285 286 // accessors 287 // 288 // Note: Like complex number, octonions do have a meaningful notion of "real part", 289 // but unlike them there is no meaningful notion of "imaginary part". 290 // Instead there is an "unreal part" which itself is an octonion, and usually 291 // nothing simpler (as opposed to the complex number case). 292 // However, for practicallity, there are accessors for the other components 293 // (these are necessary for the templated copy constructor, for instance). 294 295 BOOST_OCTONION_ACCESSOR_GENERATOR(T) 296 297 // assignment operators 298 299 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(T) 300 301 // other assignment-related operators 302 // 303 // NOTE: Octonion multiplication is *NOT* commutative; 304 // symbolically, "q *= rhs;" means "q = q * rhs;" 305 // and "q /= rhs;" means "q = q * inverse_of(rhs);"; 306 // octonion multiplication is also *NOT* associative 307 308 octonion<T> & operator += (T const & rhs) 309 { 310 T at = a + rhs; // exception guard 311 312 a = at; 313 314 return(*this); 315 } 316 317 operator +=(::std::complex<T> const & rhs)318 octonion<T> & operator += (::std::complex<T> const & rhs) 319 { 320 T at = a + rhs.real(); // exception guard 321 T bt = b + rhs.imag(); // exception guard 322 323 a = at; 324 b = bt; 325 326 return(*this); 327 } 328 329 operator +=(::boost::math::quaternion<T> const & rhs)330 octonion<T> & operator += (::boost::math::quaternion<T> const & rhs) 331 { 332 T at = a + rhs.R_component_1(); // exception guard 333 T bt = b + rhs.R_component_2(); // exception guard 334 T ct = c + rhs.R_component_3(); // exception guard 335 T dt = d + rhs.R_component_4(); // exception guard 336 337 a = at; 338 b = bt; 339 c = ct; 340 d = dt; 341 342 return(*this); 343 } 344 345 346 template<typename X> operator +=(octonion<X> const & rhs)347 octonion<T> & operator += (octonion<X> const & rhs) 348 { 349 T at = a + static_cast<T>(rhs.R_component_1()); // exception guard 350 T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard 351 T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard 352 T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard 353 T et = e + static_cast<T>(rhs.R_component_5()); // exception guard 354 T ft = f + static_cast<T>(rhs.R_component_6()); // exception guard 355 T gt = g + static_cast<T>(rhs.R_component_7()); // exception guard 356 T ht = h + static_cast<T>(rhs.R_component_8()); // exception guard 357 358 a = at; 359 b = bt; 360 c = ct; 361 d = dt; 362 e = et; 363 f = ft; 364 g = gt; 365 h = ht; 366 367 return(*this); 368 } 369 370 371 operator -=(T const & rhs)372 octonion<T> & operator -= (T const & rhs) 373 { 374 T at = a - rhs; // exception guard 375 376 a = at; 377 378 return(*this); 379 } 380 381 operator -=(::std::complex<T> const & rhs)382 octonion<T> & operator -= (::std::complex<T> const & rhs) 383 { 384 T at = a - rhs.real(); // exception guard 385 T bt = b - rhs.imag(); // exception guard 386 387 a = at; 388 b = bt; 389 390 return(*this); 391 } 392 393 operator -=(::boost::math::quaternion<T> const & rhs)394 octonion<T> & operator -= (::boost::math::quaternion<T> const & rhs) 395 { 396 T at = a - rhs.R_component_1(); // exception guard 397 T bt = b - rhs.R_component_2(); // exception guard 398 T ct = c - rhs.R_component_3(); // exception guard 399 T dt = d - rhs.R_component_4(); // exception guard 400 401 a = at; 402 b = bt; 403 c = ct; 404 d = dt; 405 406 return(*this); 407 } 408 409 410 template<typename X> operator -=(octonion<X> const & rhs)411 octonion<T> & operator -= (octonion<X> const & rhs) 412 { 413 T at = a - static_cast<T>(rhs.R_component_1()); // exception guard 414 T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard 415 T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard 416 T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard 417 T et = e - static_cast<T>(rhs.R_component_5()); // exception guard 418 T ft = f - static_cast<T>(rhs.R_component_6()); // exception guard 419 T gt = g - static_cast<T>(rhs.R_component_7()); // exception guard 420 T ht = h - static_cast<T>(rhs.R_component_8()); // exception guard 421 422 a = at; 423 b = bt; 424 c = ct; 425 d = dt; 426 e = et; 427 f = ft; 428 g = gt; 429 h = ht; 430 431 return(*this); 432 } 433 434 operator *=(T const & rhs)435 octonion<T> & operator *= (T const & rhs) 436 { 437 T at = a * rhs; // exception guard 438 T bt = b * rhs; // exception guard 439 T ct = c * rhs; // exception guard 440 T dt = d * rhs; // exception guard 441 T et = e * rhs; // exception guard 442 T ft = f * rhs; // exception guard 443 T gt = g * rhs; // exception guard 444 T ht = h * rhs; // exception guard 445 446 a = at; 447 b = bt; 448 c = ct; 449 d = dt; 450 e = et; 451 f = ft; 452 g = gt; 453 h = ht; 454 455 return(*this); 456 } 457 458 operator *=(::std::complex<T> const & rhs)459 octonion<T> & operator *= (::std::complex<T> const & rhs) 460 { 461 T ar = rhs.real(); 462 T br = rhs.imag(); 463 464 T at = +a*ar-b*br; 465 T bt = +a*br+b*ar; 466 T ct = +c*ar+d*br; 467 T dt = -c*br+d*ar; 468 T et = +e*ar+f*br; 469 T ft = -e*br+f*ar; 470 T gt = +g*ar-h*br; 471 T ht = +g*br+h*ar; 472 473 a = at; 474 b = bt; 475 c = ct; 476 d = dt; 477 e = et; 478 f = ft; 479 g = gt; 480 h = ht; 481 482 return(*this); 483 } 484 485 operator *=(::boost::math::quaternion<T> const & rhs)486 octonion<T> & operator *= (::boost::math::quaternion<T> const & rhs) 487 { 488 T ar = rhs.R_component_1(); 489 T br = rhs.R_component_2(); 490 T cr = rhs.R_component_2(); 491 T dr = rhs.R_component_2(); 492 493 T at = +a*ar-b*br-c*cr-d*dr; 494 T bt = +a*br+b*ar+c*dr-d*cr; 495 T ct = +a*cr-b*dr+c*ar+d*br; 496 T dt = +a*dr+b*cr-c*br+d*ar; 497 T et = +e*ar+f*br+g*cr+h*dr; 498 T ft = -e*br+f*ar-g*dr+h*cr; 499 T gt = -e*cr+f*dr+g*ar-h*br; 500 T ht = -e*dr-f*cr+g*br+h*ar; 501 502 a = at; 503 b = bt; 504 c = ct; 505 d = dt; 506 e = et; 507 f = ft; 508 g = gt; 509 h = ht; 510 511 return(*this); 512 } 513 514 515 template<typename X> operator *=(octonion<X> const & rhs)516 octonion<T> & operator *= (octonion<X> const & rhs) 517 { 518 T ar = static_cast<T>(rhs.R_component_1()); 519 T br = static_cast<T>(rhs.R_component_2()); 520 T cr = static_cast<T>(rhs.R_component_3()); 521 T dr = static_cast<T>(rhs.R_component_4()); 522 T er = static_cast<T>(rhs.R_component_5()); 523 T fr = static_cast<T>(rhs.R_component_6()); 524 T gr = static_cast<T>(rhs.R_component_7()); 525 T hr = static_cast<T>(rhs.R_component_8()); 526 527 T at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr; 528 T bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr; 529 T ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr; 530 T dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er; 531 T et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr; 532 T ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr; 533 T gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br; 534 T ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar; 535 536 a = at; 537 b = bt; 538 c = ct; 539 d = dt; 540 e = et; 541 f = ft; 542 g = gt; 543 h = ht; 544 545 return(*this); 546 } 547 548 operator /=(T const & rhs)549 octonion<T> & operator /= (T const & rhs) 550 { 551 T at = a / rhs; // exception guard 552 T bt = b / rhs; // exception guard 553 T ct = c / rhs; // exception guard 554 T dt = d / rhs; // exception guard 555 T et = e / rhs; // exception guard 556 T ft = f / rhs; // exception guard 557 T gt = g / rhs; // exception guard 558 T ht = h / rhs; // exception guard 559 560 a = at; 561 b = bt; 562 c = ct; 563 d = dt; 564 e = et; 565 f = ft; 566 g = gt; 567 h = ht; 568 569 return(*this); 570 } 571 572 operator /=(::std::complex<T> const & rhs)573 octonion<T> & operator /= (::std::complex<T> const & rhs) 574 { 575 T ar = rhs.real(); 576 T br = rhs.imag(); 577 578 T denominator = ar*ar+br*br; 579 580 T at = (+a*ar-b*br)/denominator; 581 T bt = (-a*br+b*ar)/denominator; 582 T ct = (+c*ar-d*br)/denominator; 583 T dt = (+c*br+d*ar)/denominator; 584 T et = (+e*ar-f*br)/denominator; 585 T ft = (+e*br+f*ar)/denominator; 586 T gt = (+g*ar+h*br)/denominator; 587 T ht = (+g*br+h*ar)/denominator; 588 589 a = at; 590 b = bt; 591 c = ct; 592 d = dt; 593 e = et; 594 f = ft; 595 g = gt; 596 h = ht; 597 598 return(*this); 599 } 600 601 operator /=(::boost::math::quaternion<T> const & rhs)602 octonion<T> & operator /= (::boost::math::quaternion<T> const & rhs) 603 { 604 T ar = rhs.R_component_1(); 605 T br = rhs.R_component_2(); 606 T cr = rhs.R_component_2(); 607 T dr = rhs.R_component_2(); 608 609 T denominator = ar*ar+br*br+cr*cr+dr*dr; 610 611 T at = (+a*ar+b*br+c*cr+d*dr)/denominator; 612 T bt = (-a*br+b*ar-c*dr+d*cr)/denominator; 613 T ct = (-a*cr+b*dr+c*ar-d*br)/denominator; 614 T dt = (-a*dr-b*cr+c*br+d*ar)/denominator; 615 T et = (+e*ar-f*br-g*cr-h*dr)/denominator; 616 T ft = (+e*br+f*ar+g*dr-h*cr)/denominator; 617 T gt = (+e*cr-f*dr+g*ar+h*br)/denominator; 618 T ht = (+e*dr+f*cr-g*br+h*ar)/denominator; 619 620 a = at; 621 b = bt; 622 c = ct; 623 d = dt; 624 e = et; 625 f = ft; 626 g = gt; 627 h = ht; 628 629 return(*this); 630 } 631 632 633 template<typename X> operator /=(octonion<X> const & rhs)634 octonion<T> & operator /= (octonion<X> const & rhs) 635 { 636 T ar = static_cast<T>(rhs.R_component_1()); 637 T br = static_cast<T>(rhs.R_component_2()); 638 T cr = static_cast<T>(rhs.R_component_3()); 639 T dr = static_cast<T>(rhs.R_component_4()); 640 T er = static_cast<T>(rhs.R_component_5()); 641 T fr = static_cast<T>(rhs.R_component_6()); 642 T gr = static_cast<T>(rhs.R_component_7()); 643 T hr = static_cast<T>(rhs.R_component_8()); 644 645 T denominator = ar*ar+br*br+cr*cr+dr*dr+er*er+fr*fr+gr*gr+hr*hr; 646 647 T at = (+a*ar+b*br+c*cr+d*dr+e*er+f*fr+g*gr+h*hr)/denominator; 648 T bt = (-a*br+b*ar-c*dr+d*cr-e*fr+f*er+g*hr-h*gr)/denominator; 649 T ct = (-a*cr+b*dr+c*ar-d*br-e*gr-f*hr+g*er+h*fr)/denominator; 650 T dt = (-a*dr-b*cr+c*br+d*ar-e*hr+f*gr-g*fr+h*er)/denominator; 651 T et = (-a*er+b*fr+c*gr+d*hr+e*ar-f*br-g*cr-h*dr)/denominator; 652 T ft = (-a*fr-b*er+c*hr-d*gr+e*br+f*ar+g*dr-h*cr)/denominator; 653 T gt = (-a*gr-b*hr-c*er+d*fr+e*cr-f*dr+g*ar+h*br)/denominator; 654 T ht = (-a*hr+b*gr-c*fr-d*er+e*dr+f*cr-g*br+h*ar)/denominator; 655 656 a = at; 657 b = bt; 658 c = ct; 659 d = dt; 660 e = et; 661 f = ft; 662 g = gt; 663 h = ht; 664 665 return(*this); 666 } 667 668 669 protected: 670 671 BOOST_OCTONION_MEMBER_DATA_GENERATOR(T) 672 673 674 private: 675 676 }; 677 678 679 // declaration of octonion specialization 680 681 template<> class octonion<float>; 682 template<> class octonion<double>; 683 template<> class octonion<long double>; 684 685 686 // helper templates for converting copy constructors (declaration) 687 688 namespace detail 689 { 690 691 template< typename T, 692 typename U 693 > 694 octonion<T> octonion_type_converter(octonion<U> const & rhs); 695 } 696 697 698 // implementation of octonion specialization 699 700 701 #define BOOST_OCTONION_CONSTRUCTOR_GENERATOR(type) \ 702 explicit octonion( type const & requested_a = static_cast<type>(0), \ 703 type const & requested_b = static_cast<type>(0), \ 704 type const & requested_c = static_cast<type>(0), \ 705 type const & requested_d = static_cast<type>(0), \ 706 type const & requested_e = static_cast<type>(0), \ 707 type const & requested_f = static_cast<type>(0), \ 708 type const & requested_g = static_cast<type>(0), \ 709 type const & requested_h = static_cast<type>(0)) \ 710 : a(requested_a), \ 711 b(requested_b), \ 712 c(requested_c), \ 713 d(requested_d), \ 714 e(requested_e), \ 715 f(requested_f), \ 716 g(requested_g), \ 717 h(requested_h) \ 718 { \ 719 } \ 720 \ 721 explicit octonion( ::std::complex<type> const & z0, \ 722 ::std::complex<type> const & z1 = ::std::complex<type>(), \ 723 ::std::complex<type> const & z2 = ::std::complex<type>(), \ 724 ::std::complex<type> const & z3 = ::std::complex<type>()) \ 725 : a(z0.real()), \ 726 b(z0.imag()), \ 727 c(z1.real()), \ 728 d(z1.imag()), \ 729 e(z2.real()), \ 730 f(z2.imag()), \ 731 g(z3.real()), \ 732 h(z3.imag()) \ 733 { \ 734 } \ 735 \ 736 explicit octonion( ::boost::math::quaternion<type> const & q0, \ 737 ::boost::math::quaternion<type> const & q1 = ::boost::math::quaternion<type>()) \ 738 : a(q0.R_component_1()), \ 739 b(q0.R_component_2()), \ 740 c(q0.R_component_3()), \ 741 d(q0.R_component_4()), \ 742 e(q1.R_component_1()), \ 743 f(q1.R_component_2()), \ 744 g(q1.R_component_3()), \ 745 h(q1.R_component_4()) \ 746 { \ 747 } 748 749 750 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \ 751 octonion<type> & operator += (type const & rhs) \ 752 { \ 753 a += rhs; \ 754 \ 755 return(*this); \ 756 } 757 758 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \ 759 octonion<type> & operator += (::std::complex<type> const & rhs) \ 760 { \ 761 a += rhs.real(); \ 762 b += rhs.imag(); \ 763 \ 764 return(*this); \ 765 } 766 767 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \ 768 octonion<type> & operator += (::boost::math::quaternion<type> const & rhs) \ 769 { \ 770 a += rhs.R_component_1(); \ 771 b += rhs.R_component_2(); \ 772 c += rhs.R_component_3(); \ 773 d += rhs.R_component_4(); \ 774 \ 775 return(*this); \ 776 } 777 778 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type) \ 779 template<typename X> \ 780 octonion<type> & operator += (octonion<X> const & rhs) \ 781 { \ 782 a += static_cast<type>(rhs.R_component_1()); \ 783 b += static_cast<type>(rhs.R_component_2()); \ 784 c += static_cast<type>(rhs.R_component_3()); \ 785 d += static_cast<type>(rhs.R_component_4()); \ 786 e += static_cast<type>(rhs.R_component_5()); \ 787 f += static_cast<type>(rhs.R_component_6()); \ 788 g += static_cast<type>(rhs.R_component_7()); \ 789 h += static_cast<type>(rhs.R_component_8()); \ 790 \ 791 return(*this); \ 792 } 793 794 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \ 795 octonion<type> & operator -= (type const & rhs) \ 796 { \ 797 a -= rhs; \ 798 \ 799 return(*this); \ 800 } 801 802 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \ 803 octonion<type> & operator -= (::std::complex<type> const & rhs) \ 804 { \ 805 a -= rhs.real(); \ 806 b -= rhs.imag(); \ 807 \ 808 return(*this); \ 809 } 810 811 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \ 812 octonion<type> & operator -= (::boost::math::quaternion<type> const & rhs) \ 813 { \ 814 a -= rhs.R_component_1(); \ 815 b -= rhs.R_component_2(); \ 816 c -= rhs.R_component_3(); \ 817 d -= rhs.R_component_4(); \ 818 \ 819 return(*this); \ 820 } 821 822 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type) \ 823 template<typename X> \ 824 octonion<type> & operator -= (octonion<X> const & rhs) \ 825 { \ 826 a -= static_cast<type>(rhs.R_component_1()); \ 827 b -= static_cast<type>(rhs.R_component_2()); \ 828 c -= static_cast<type>(rhs.R_component_3()); \ 829 d -= static_cast<type>(rhs.R_component_4()); \ 830 e -= static_cast<type>(rhs.R_component_5()); \ 831 f -= static_cast<type>(rhs.R_component_6()); \ 832 g -= static_cast<type>(rhs.R_component_7()); \ 833 h -= static_cast<type>(rhs.R_component_8()); \ 834 \ 835 return(*this); \ 836 } 837 838 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \ 839 octonion<type> & operator *= (type const & rhs) \ 840 { \ 841 a *= rhs; \ 842 b *= rhs; \ 843 c *= rhs; \ 844 d *= rhs; \ 845 e *= rhs; \ 846 f *= rhs; \ 847 g *= rhs; \ 848 h *= rhs; \ 849 \ 850 return(*this); \ 851 } 852 853 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \ 854 octonion<type> & operator *= (::std::complex<type> const & rhs) \ 855 { \ 856 type ar = rhs.real(); \ 857 type br = rhs.imag(); \ 858 \ 859 type at = +a*ar-b*br; \ 860 type bt = +a*br+b*ar; \ 861 type ct = +c*ar+d*br; \ 862 type dt = -c*br+d*ar; \ 863 type et = +e*ar+f*br; \ 864 type ft = -e*br+f*ar; \ 865 type gt = +g*ar-h*br; \ 866 type ht = +g*br+h*ar; \ 867 \ 868 a = at; \ 869 b = bt; \ 870 c = ct; \ 871 d = dt; \ 872 e = et; \ 873 f = ft; \ 874 g = gt; \ 875 h = ht; \ 876 \ 877 return(*this); \ 878 } 879 880 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \ 881 octonion<type> & operator *= (::boost::math::quaternion<type> const & rhs) \ 882 { \ 883 type ar = rhs.R_component_1(); \ 884 type br = rhs.R_component_2(); \ 885 type cr = rhs.R_component_2(); \ 886 type dr = rhs.R_component_2(); \ 887 \ 888 type at = +a*ar-b*br-c*cr-d*dr; \ 889 type bt = +a*br+b*ar+c*dr-d*cr; \ 890 type ct = +a*cr-b*dr+c*ar+d*br; \ 891 type dt = +a*dr+b*cr-c*br+d*ar; \ 892 type et = +e*ar+f*br+g*cr+h*dr; \ 893 type ft = -e*br+f*ar-g*dr+h*cr; \ 894 type gt = -e*cr+f*dr+g*ar-h*br; \ 895 type ht = -e*dr-f*cr+g*br+h*ar; \ 896 \ 897 a = at; \ 898 b = bt; \ 899 c = ct; \ 900 d = dt; \ 901 e = et; \ 902 f = ft; \ 903 g = gt; \ 904 h = ht; \ 905 \ 906 return(*this); \ 907 } 908 909 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type) \ 910 template<typename X> \ 911 octonion<type> & operator *= (octonion<X> const & rhs) \ 912 { \ 913 type ar = static_cast<type>(rhs.R_component_1()); \ 914 type br = static_cast<type>(rhs.R_component_2()); \ 915 type cr = static_cast<type>(rhs.R_component_3()); \ 916 type dr = static_cast<type>(rhs.R_component_4()); \ 917 type er = static_cast<type>(rhs.R_component_5()); \ 918 type fr = static_cast<type>(rhs.R_component_6()); \ 919 type gr = static_cast<type>(rhs.R_component_7()); \ 920 type hr = static_cast<type>(rhs.R_component_8()); \ 921 \ 922 type at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr; \ 923 type bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr; \ 924 type ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr; \ 925 type dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er; \ 926 type et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr; \ 927 type ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr; \ 928 type gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br; \ 929 type ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar; \ 930 \ 931 a = at; \ 932 b = bt; \ 933 c = ct; \ 934 d = dt; \ 935 e = et; \ 936 f = ft; \ 937 g = gt; \ 938 h = ht; \ 939 \ 940 return(*this); \ 941 } 942 943 // There is quite a lot of repetition in the code below. This is intentional. 944 // The last conditional block is the normal form, and the others merely 945 // consist of workarounds for various compiler deficiencies. Hopefuly, when 946 // more compilers are conformant and we can retire support for those that are 947 // not, we will be able to remove the clutter. This is makes the situation 948 // (painfully) explicit. 949 950 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \ 951 octonion<type> & operator /= (type const & rhs) \ 952 { \ 953 a /= rhs; \ 954 b /= rhs; \ 955 c /= rhs; \ 956 d /= rhs; \ 957 \ 958 return(*this); \ 959 } 960 961 #if defined(__GNUC__) && (__GNUC__ < 3) 962 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \ 963 octonion<type> & operator /= (::std::complex<type> const & rhs) \ 964 { \ 965 using ::std::valarray; \ 966 \ 967 valarray<type> tr(2); \ 968 \ 969 tr[0] = rhs.real(); \ 970 tr[1] = rhs.imag(); \ 971 \ 972 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \ 973 \ 974 tr *= mixam; \ 975 \ 976 valarray<type> tt(8); \ 977 \ 978 tt[0] = +a*tr[0]-b*tr[1]; \ 979 tt[1] = -a*tr[1]+b*tr[0]; \ 980 tt[2] = +c*tr[0]-d*tr[1]; \ 981 tt[3] = +c*tr[1]+d*tr[0]; \ 982 tt[4] = +e*tr[0]-f*tr[1]; \ 983 tt[5] = +e*tr[1]+f*tr[0]; \ 984 tt[6] = +g*tr[0]+h*tr[1]; \ 985 tt[7] = +g*tr[1]+h*tr[0]; \ 986 \ 987 tr *= tr; \ 988 \ 989 tt *= (mixam/tr.sum()); \ 990 \ 991 a = tt[0]; \ 992 b = tt[1]; \ 993 c = tt[2]; \ 994 d = tt[3]; \ 995 e = tt[4]; \ 996 f = tt[5]; \ 997 g = tt[6]; \ 998 h = tt[7]; \ 999 \ 1000 return(*this); \ 1001 } 1002 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) 1003 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \ 1004 octonion<type> & operator /= (::std::complex<type> const & rhs) \ 1005 { \ 1006 using ::std::valarray; \ 1007 using ::std::abs; \ 1008 \ 1009 valarray<type> tr(2); \ 1010 \ 1011 tr[0] = rhs.real(); \ 1012 tr[1] = rhs.imag(); \ 1013 \ 1014 type mixam = static_cast<type>(1)/(abs(tr).max)(); \ 1015 \ 1016 tr *= mixam; \ 1017 \ 1018 valarray<type> tt(8); \ 1019 \ 1020 tt[0] = +a*tr[0]-b*tr[1]; \ 1021 tt[1] = -a*tr[1]+b*tr[0]; \ 1022 tt[2] = +c*tr[0]-d*tr[1]; \ 1023 tt[3] = +c*tr[1]+d*tr[0]; \ 1024 tt[4] = +e*tr[0]-f*tr[1]; \ 1025 tt[5] = +e*tr[1]+f*tr[0]; \ 1026 tt[6] = +g*tr[0]+h*tr[1]; \ 1027 tt[7] = +g*tr[1]+h*tr[0]; \ 1028 \ 1029 tr *= tr; \ 1030 \ 1031 tt *= (mixam/tr.sum()); \ 1032 \ 1033 a = tt[0]; \ 1034 b = tt[1]; \ 1035 c = tt[2]; \ 1036 d = tt[3]; \ 1037 e = tt[4]; \ 1038 f = tt[5]; \ 1039 g = tt[6]; \ 1040 h = tt[7]; \ 1041 \ 1042 return(*this); \ 1043 } 1044 #else 1045 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \ 1046 octonion<type> & operator /= (::std::complex<type> const & rhs) \ 1047 { \ 1048 using ::std::valarray; \ 1049 \ 1050 valarray<type> tr(2); \ 1051 \ 1052 tr[0] = rhs.real(); \ 1053 tr[1] = rhs.imag(); \ 1054 \ 1055 type mixam = static_cast<type>(1)/(abs(tr).max)(); \ 1056 \ 1057 tr *= mixam; \ 1058 \ 1059 valarray<type> tt(8); \ 1060 \ 1061 tt[0] = +a*tr[0]-b*tr[1]; \ 1062 tt[1] = -a*tr[1]+b*tr[0]; \ 1063 tt[2] = +c*tr[0]-d*tr[1]; \ 1064 tt[3] = +c*tr[1]+d*tr[0]; \ 1065 tt[4] = +e*tr[0]-f*tr[1]; \ 1066 tt[5] = +e*tr[1]+f*tr[0]; \ 1067 tt[6] = +g*tr[0]+h*tr[1]; \ 1068 tt[7] = +g*tr[1]+h*tr[0]; \ 1069 \ 1070 tr *= tr; \ 1071 \ 1072 tt *= (mixam/tr.sum()); \ 1073 \ 1074 a = tt[0]; \ 1075 b = tt[1]; \ 1076 c = tt[2]; \ 1077 d = tt[3]; \ 1078 e = tt[4]; \ 1079 f = tt[5]; \ 1080 g = tt[6]; \ 1081 h = tt[7]; \ 1082 \ 1083 return(*this); \ 1084 } 1085 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ 1086 1087 #if defined(__GNUC__) && (__GNUC__ < 3) 1088 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \ 1089 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \ 1090 { \ 1091 using ::std::valarray; \ 1092 \ 1093 valarray<type> tr(4); \ 1094 \ 1095 tr[0] = static_cast<type>(rhs.R_component_1()); \ 1096 tr[1] = static_cast<type>(rhs.R_component_2()); \ 1097 tr[2] = static_cast<type>(rhs.R_component_3()); \ 1098 tr[3] = static_cast<type>(rhs.R_component_4()); \ 1099 \ 1100 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();\ 1101 \ 1102 tr *= mixam; \ 1103 \ 1104 valarray<type> tt(8); \ 1105 \ 1106 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \ 1107 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \ 1108 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \ 1109 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \ 1110 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ 1111 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ 1112 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ 1113 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ 1114 \ 1115 tr *= tr; \ 1116 \ 1117 tt *= (mixam/tr.sum()); \ 1118 \ 1119 a = tt[0]; \ 1120 b = tt[1]; \ 1121 c = tt[2]; \ 1122 d = tt[3]; \ 1123 e = tt[4]; \ 1124 f = tt[5]; \ 1125 g = tt[6]; \ 1126 h = tt[7]; \ 1127 \ 1128 return(*this); \ 1129 } 1130 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) 1131 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \ 1132 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \ 1133 { \ 1134 using ::std::valarray; \ 1135 using ::std::abs; \ 1136 \ 1137 valarray<type> tr(4); \ 1138 \ 1139 tr[0] = static_cast<type>(rhs.R_component_1()); \ 1140 tr[1] = static_cast<type>(rhs.R_component_2()); \ 1141 tr[2] = static_cast<type>(rhs.R_component_3()); \ 1142 tr[3] = static_cast<type>(rhs.R_component_4()); \ 1143 \ 1144 type mixam = static_cast<type>(1)/(abs(tr).max)(); \ 1145 \ 1146 tr *= mixam; \ 1147 \ 1148 valarray<type> tt(8); \ 1149 \ 1150 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \ 1151 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \ 1152 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \ 1153 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \ 1154 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ 1155 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ 1156 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ 1157 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ 1158 \ 1159 tr *= tr; \ 1160 \ 1161 tt *= (mixam/tr.sum()); \ 1162 \ 1163 a = tt[0]; \ 1164 b = tt[1]; \ 1165 c = tt[2]; \ 1166 d = tt[3]; \ 1167 e = tt[4]; \ 1168 f = tt[5]; \ 1169 g = tt[6]; \ 1170 h = tt[7]; \ 1171 \ 1172 return(*this); \ 1173 } 1174 #else 1175 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \ 1176 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \ 1177 { \ 1178 using ::std::valarray; \ 1179 \ 1180 valarray<type> tr(4); \ 1181 \ 1182 tr[0] = static_cast<type>(rhs.R_component_1()); \ 1183 tr[1] = static_cast<type>(rhs.R_component_2()); \ 1184 tr[2] = static_cast<type>(rhs.R_component_3()); \ 1185 tr[3] = static_cast<type>(rhs.R_component_4()); \ 1186 \ 1187 type mixam = static_cast<type>(1)/(abs(tr).max)(); \ 1188 \ 1189 tr *= mixam; \ 1190 \ 1191 valarray<type> tt(8); \ 1192 \ 1193 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \ 1194 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \ 1195 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \ 1196 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \ 1197 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ 1198 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ 1199 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ 1200 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ 1201 \ 1202 tr *= tr; \ 1203 \ 1204 tt *= (mixam/tr.sum()); \ 1205 \ 1206 a = tt[0]; \ 1207 b = tt[1]; \ 1208 c = tt[2]; \ 1209 d = tt[3]; \ 1210 e = tt[4]; \ 1211 f = tt[5]; \ 1212 g = tt[6]; \ 1213 h = tt[7]; \ 1214 \ 1215 return(*this); \ 1216 } 1217 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ 1218 1219 #if defined(__GNUC__) && (__GNUC__ < 3) 1220 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \ 1221 template<typename X> \ 1222 octonion<type> & operator /= (octonion<X> const & rhs) \ 1223 { \ 1224 using ::std::valarray; \ 1225 \ 1226 valarray<type> tr(8); \ 1227 \ 1228 tr[0] = static_cast<type>(rhs.R_component_1()); \ 1229 tr[1] = static_cast<type>(rhs.R_component_2()); \ 1230 tr[2] = static_cast<type>(rhs.R_component_3()); \ 1231 tr[3] = static_cast<type>(rhs.R_component_4()); \ 1232 tr[4] = static_cast<type>(rhs.R_component_5()); \ 1233 tr[5] = static_cast<type>(rhs.R_component_6()); \ 1234 tr[6] = static_cast<type>(rhs.R_component_7()); \ 1235 tr[7] = static_cast<type>(rhs.R_component_8()); \ 1236 \ 1237 type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)();\ 1238 \ 1239 tr *= mixam; \ 1240 \ 1241 valarray<type> tt(8); \ 1242 \ 1243 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]+e*tr[4]+f*tr[5]+g*tr[6]+h*tr[7]; \ 1244 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]-e*tr[5]+f*tr[4]+g*tr[7]-h*tr[6]; \ 1245 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]-e*tr[6]-f*tr[7]+g*tr[4]+h*tr[5]; \ 1246 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]-e*tr[7]+f*tr[6]-g*tr[5]+h*tr[4]; \ 1247 tt[4] = -a*tr[4]+b*tr[5]+c*tr[6]+d*tr[7]+e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ 1248 tt[5] = -a*tr[5]-b*tr[4]+c*tr[7]-d*tr[6]+e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ 1249 tt[6] = -a*tr[6]-b*tr[7]-c*tr[4]+d*tr[5]+e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ 1250 tt[7] = -a*tr[7]+b*tr[6]-c*tr[5]-d*tr[4]+e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ 1251 \ 1252 tr *= tr; \ 1253 \ 1254 tt *= (mixam/tr.sum()); \ 1255 \ 1256 a = tt[0]; \ 1257 b = tt[1]; \ 1258 c = tt[2]; \ 1259 d = tt[3]; \ 1260 e = tt[4]; \ 1261 f = tt[5]; \ 1262 g = tt[6]; \ 1263 h = tt[7]; \ 1264 \ 1265 return(*this); \ 1266 } 1267 #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) 1268 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \ 1269 template<typename X> \ 1270 octonion<type> & operator /= (octonion<X> const & rhs) \ 1271 { \ 1272 using ::std::valarray; \ 1273 using ::std::abs; \ 1274 \ 1275 valarray<type> tr(8); \ 1276 \ 1277 tr[0] = static_cast<type>(rhs.R_component_1()); \ 1278 tr[1] = static_cast<type>(rhs.R_component_2()); \ 1279 tr[2] = static_cast<type>(rhs.R_component_3()); \ 1280 tr[3] = static_cast<type>(rhs.R_component_4()); \ 1281 tr[4] = static_cast<type>(rhs.R_component_5()); \ 1282 tr[5] = static_cast<type>(rhs.R_component_6()); \ 1283 tr[6] = static_cast<type>(rhs.R_component_7()); \ 1284 tr[7] = static_cast<type>(rhs.R_component_8()); \ 1285 \ 1286 type mixam = static_cast<type>(1)/(abs(tr).max)(); \ 1287 \ 1288 tr *= mixam; \ 1289 \ 1290 valarray<type> tt(8); \ 1291 \ 1292 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]+e*tr[4]+f*tr[5]+g*tr[6]+h*tr[7]; \ 1293 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]-e*tr[5]+f*tr[4]+g*tr[7]-h*tr[6]; \ 1294 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]-e*tr[6]-f*tr[7]+g*tr[4]+h*tr[5]; \ 1295 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]-e*tr[7]+f*tr[6]-g*tr[5]+h*tr[4]; \ 1296 tt[4] = -a*tr[4]+b*tr[5]+c*tr[6]+d*tr[7]+e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ 1297 tt[5] = -a*tr[5]-b*tr[4]+c*tr[7]-d*tr[6]+e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ 1298 tt[6] = -a*tr[6]-b*tr[7]-c*tr[4]+d*tr[5]+e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ 1299 tt[7] = -a*tr[7]+b*tr[6]-c*tr[5]-d*tr[4]+e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ 1300 \ 1301 tr *= tr; \ 1302 \ 1303 tt *= (mixam/tr.sum()); \ 1304 \ 1305 a = tt[0]; \ 1306 b = tt[1]; \ 1307 c = tt[2]; \ 1308 d = tt[3]; \ 1309 e = tt[4]; \ 1310 f = tt[5]; \ 1311 g = tt[6]; \ 1312 h = tt[7]; \ 1313 \ 1314 return(*this); \ 1315 } 1316 #else 1317 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \ 1318 template<typename X> \ 1319 octonion<type> & operator /= (octonion<X> const & rhs) \ 1320 { \ 1321 using ::std::valarray; \ 1322 \ 1323 valarray<type> tr(8); \ 1324 \ 1325 tr[0] = static_cast<type>(rhs.R_component_1()); \ 1326 tr[1] = static_cast<type>(rhs.R_component_2()); \ 1327 tr[2] = static_cast<type>(rhs.R_component_3()); \ 1328 tr[3] = static_cast<type>(rhs.R_component_4()); \ 1329 tr[4] = static_cast<type>(rhs.R_component_5()); \ 1330 tr[5] = static_cast<type>(rhs.R_component_6()); \ 1331 tr[6] = static_cast<type>(rhs.R_component_7()); \ 1332 tr[7] = static_cast<type>(rhs.R_component_8()); \ 1333 \ 1334 type mixam = static_cast<type>(1)/(abs(tr).max)(); \ 1335 \ 1336 tr *= mixam; \ 1337 \ 1338 valarray<type> tt(8); \ 1339 \ 1340 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]+e*tr[4]+f*tr[5]+g*tr[6]+h*tr[7]; \ 1341 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]-e*tr[5]+f*tr[4]+g*tr[7]-h*tr[6]; \ 1342 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]-e*tr[6]-f*tr[7]+g*tr[4]+h*tr[5]; \ 1343 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]-e*tr[7]+f*tr[6]-g*tr[5]+h*tr[4]; \ 1344 tt[4] = -a*tr[4]+b*tr[5]+c*tr[6]+d*tr[7]+e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \ 1345 tt[5] = -a*tr[5]-b*tr[4]+c*tr[7]-d*tr[6]+e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \ 1346 tt[6] = -a*tr[6]-b*tr[7]-c*tr[4]+d*tr[5]+e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \ 1347 tt[7] = -a*tr[7]+b*tr[6]-c*tr[5]-d*tr[4]+e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \ 1348 \ 1349 tr *= tr; \ 1350 \ 1351 tt *= (mixam/tr.sum()); \ 1352 \ 1353 a = tt[0]; \ 1354 b = tt[1]; \ 1355 c = tt[2]; \ 1356 d = tt[3]; \ 1357 e = tt[4]; \ 1358 f = tt[5]; \ 1359 g = tt[6]; \ 1360 h = tt[7]; \ 1361 \ 1362 return(*this); \ 1363 } 1364 #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ 1365 1366 1367 #define BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \ 1368 BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \ 1369 BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \ 1370 BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \ 1371 BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type) 1372 1373 #define BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \ 1374 BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \ 1375 BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \ 1376 BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \ 1377 BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type) 1378 1379 #define BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \ 1380 BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \ 1381 BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \ 1382 BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \ 1383 BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type) 1384 1385 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR(type) \ 1386 BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \ 1387 BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \ 1388 BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \ 1389 BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) 1390 1391 #define BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(type) \ 1392 BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \ 1393 BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \ 1394 BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \ 1395 BOOST_OCTONION_MEMBER_DIV_GENERATOR(type) 1396 1397 1398 template<> 1399 class octonion<float> 1400 { 1401 public: 1402 1403 typedef float value_type; 1404 1405 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(float) 1406 1407 // UNtemplated copy constructor 1408 // (this is taken care of by the compiler itself) 1409 1410 // explicit copy constructors (precision-loosing converters) 1411 octonion(octonion<double> const & a_recopier)1412 explicit octonion(octonion<double> const & a_recopier) 1413 { 1414 *this = detail::octonion_type_converter<float, double>(a_recopier); 1415 } 1416 octonion(octonion<long double> const & a_recopier)1417 explicit octonion(octonion<long double> const & a_recopier) 1418 { 1419 *this = detail::octonion_type_converter<float, long double>(a_recopier); 1420 } 1421 1422 // destructor 1423 // (this is taken care of by the compiler itself) 1424 1425 // accessors 1426 // 1427 // Note: Like complex number, octonions do have a meaningful notion of "real part", 1428 // but unlike them there is no meaningful notion of "imaginary part". 1429 // Instead there is an "unreal part" which itself is an octonion, and usually 1430 // nothing simpler (as opposed to the complex number case). 1431 // However, for practicallity, there are accessors for the other components 1432 // (these are necessary for the templated copy constructor, for instance). 1433 1434 BOOST_OCTONION_ACCESSOR_GENERATOR(float) 1435 1436 // assignment operators 1437 1438 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(float) 1439 1440 // other assignment-related operators 1441 // 1442 // NOTE: Octonion multiplication is *NOT* commutative; 1443 // symbolically, "q *= rhs;" means "q = q * rhs;" 1444 // and "q /= rhs;" means "q = q * inverse_of(rhs);"; 1445 // octonion multiplication is also *NOT* associative 1446 1447 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(float) 1448 1449 1450 protected: 1451 1452 BOOST_OCTONION_MEMBER_DATA_GENERATOR(float) 1453 1454 1455 private: 1456 1457 }; 1458 1459 1460 template<> 1461 class octonion<double> 1462 { 1463 public: 1464 1465 typedef double value_type; 1466 1467 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(double) 1468 1469 // UNtemplated copy constructor 1470 // (this is taken care of by the compiler itself) 1471 1472 // converting copy constructor 1473 octonion(octonion<float> const & a_recopier)1474 explicit octonion(octonion<float> const & a_recopier) 1475 { 1476 *this = detail::octonion_type_converter<double, float>(a_recopier); 1477 } 1478 1479 // explicit copy constructors (precision-loosing converters) 1480 octonion(octonion<long double> const & a_recopier)1481 explicit octonion(octonion<long double> const & a_recopier) 1482 { 1483 *this = detail::octonion_type_converter<double, long double>(a_recopier); 1484 } 1485 1486 // destructor 1487 // (this is taken care of by the compiler itself) 1488 1489 // accessors 1490 // 1491 // Note: Like complex number, octonions do have a meaningful notion of "real part", 1492 // but unlike them there is no meaningful notion of "imaginary part". 1493 // Instead there is an "unreal part" which itself is an octonion, and usually 1494 // nothing simpler (as opposed to the complex number case). 1495 // However, for practicallity, there are accessors for the other components 1496 // (these are necessary for the templated copy constructor, for instance). 1497 1498 BOOST_OCTONION_ACCESSOR_GENERATOR(double) 1499 1500 // assignment operators 1501 1502 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(double) 1503 1504 // other assignment-related operators 1505 // 1506 // NOTE: Octonion multiplication is *NOT* commutative; 1507 // symbolically, "q *= rhs;" means "q = q * rhs;" 1508 // and "q /= rhs;" means "q = q * inverse_of(rhs);"; 1509 // octonion multiplication is also *NOT* associative 1510 1511 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(double) 1512 1513 1514 protected: 1515 1516 BOOST_OCTONION_MEMBER_DATA_GENERATOR(double) 1517 1518 1519 private: 1520 1521 }; 1522 1523 1524 template<> 1525 class octonion<long double> 1526 { 1527 public: 1528 1529 typedef long double value_type; 1530 1531 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(long double) 1532 1533 // UNtemplated copy constructor 1534 // (this is taken care of by the compiler itself) 1535 1536 // converting copy constructor 1537 octonion(octonion<float> const & a_recopier)1538 explicit octonion(octonion<float> const & a_recopier) 1539 { 1540 *this = detail::octonion_type_converter<long double, float>(a_recopier); 1541 } 1542 1543 octonion(octonion<double> const & a_recopier)1544 explicit octonion(octonion<double> const & a_recopier) 1545 { 1546 *this = detail::octonion_type_converter<long double, double>(a_recopier); 1547 } 1548 1549 1550 // destructor 1551 // (this is taken care of by the compiler itself) 1552 1553 // accessors 1554 // 1555 // Note: Like complex number, octonions do have a meaningful notion of "real part", 1556 // but unlike them there is no meaningful notion of "imaginary part". 1557 // Instead there is an "unreal part" which itself is an octonion, and usually 1558 // nothing simpler (as opposed to the complex number case). 1559 // However, for practicallity, there are accessors for the other components 1560 // (these are necessary for the templated copy constructor, for instance). 1561 1562 BOOST_OCTONION_ACCESSOR_GENERATOR(long double) 1563 1564 // assignment operators 1565 1566 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(long double) 1567 1568 // other assignment-related operators 1569 // 1570 // NOTE: Octonion multiplication is *NOT* commutative; 1571 // symbolically, "q *= rhs;" means "q = q * rhs;" 1572 // and "q /= rhs;" means "q = q * inverse_of(rhs);"; 1573 // octonion multiplication is also *NOT* associative 1574 1575 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(long double) 1576 1577 1578 protected: 1579 1580 BOOST_OCTONION_MEMBER_DATA_GENERATOR(long double) 1581 1582 1583 private: 1584 1585 }; 1586 1587 1588 #undef BOOST_OCTONION_CONSTRUCTOR_GENERATOR 1589 1590 #undef BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR 1591 1592 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR 1593 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR 1594 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR 1595 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR 1596 1597 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_1 1598 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_2 1599 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_3 1600 #undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_4 1601 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_1 1602 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_2 1603 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_3 1604 #undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_4 1605 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_1 1606 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_2 1607 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_3 1608 #undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_4 1609 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_1 1610 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_2 1611 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_3 1612 #undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_4 1613 1614 1615 #undef BOOST_OCTONION_MEMBER_DATA_GENERATOR 1616 1617 #undef BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR 1618 1619 #undef BOOST_OCTONION_ACCESSOR_GENERATOR 1620 1621 1622 // operators 1623 1624 #define BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) \ 1625 { \ 1626 octonion<T> res(lhs); \ 1627 res op##= rhs; \ 1628 return(res); \ 1629 } 1630 1631 #define BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \ 1632 template<typename T> \ 1633 inline octonion<T> operator op (T const & lhs, octonion<T> const & rhs) \ 1634 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) 1635 1636 #define BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \ 1637 template<typename T> \ 1638 inline octonion<T> operator op (octonion<T> const & lhs, T const & rhs) \ 1639 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) 1640 1641 #define BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \ 1642 template<typename T> \ 1643 inline octonion<T> operator op (::std::complex<T> const & lhs, octonion<T> const & rhs) \ 1644 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) 1645 1646 #define BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \ 1647 template<typename T> \ 1648 inline octonion<T> operator op (octonion<T> const & lhs, ::std::complex<T> const & rhs) \ 1649 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) 1650 1651 #define BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \ 1652 template<typename T> \ 1653 inline octonion<T> operator op (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs) \ 1654 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) 1655 1656 #define BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \ 1657 template<typename T> \ 1658 inline octonion<T> operator op (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs) \ 1659 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) 1660 1661 #define BOOST_OCTONION_OPERATOR_GENERATOR_4(op) \ 1662 template<typename T> \ 1663 inline octonion<T> operator op (octonion<T> const & lhs, octonion<T> const & rhs) \ 1664 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) 1665 1666 #define BOOST_OCTONION_OPERATOR_GENERATOR(op) \ 1667 BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \ 1668 BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \ 1669 BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \ 1670 BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \ 1671 BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \ 1672 BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \ 1673 BOOST_OCTONION_OPERATOR_GENERATOR_4(op) 1674 1675 1676 BOOST_OCTONION_OPERATOR_GENERATOR(+) 1677 BOOST_OCTONION_OPERATOR_GENERATOR(-) 1678 BOOST_OCTONION_OPERATOR_GENERATOR(*) 1679 BOOST_OCTONION_OPERATOR_GENERATOR(/) 1680 1681 1682 #undef BOOST_OCTONION_OPERATOR_GENERATOR 1683 1684 #undef BOOST_OCTONION_OPERATOR_GENERATOR_1_L 1685 #undef BOOST_OCTONION_OPERATOR_GENERATOR_1_R 1686 #undef BOOST_OCTONION_OPERATOR_GENERATOR_2_L 1687 #undef BOOST_OCTONION_OPERATOR_GENERATOR_2_R 1688 #undef BOOST_OCTONION_OPERATOR_GENERATOR_3_L 1689 #undef BOOST_OCTONION_OPERATOR_GENERATOR_3_R 1690 #undef BOOST_OCTONION_OPERATOR_GENERATOR_4 1691 1692 #undef BOOST_OCTONION_OPERATOR_GENERATOR_BODY 1693 1694 1695 template<typename T> operator +(octonion<T> const & o)1696 inline octonion<T> operator + (octonion<T> const & o) 1697 { 1698 return(o); 1699 } 1700 1701 1702 template<typename T> operator -(octonion<T> const & o)1703 inline octonion<T> operator - (octonion<T> const & o) 1704 { 1705 return(octonion<T>(-o.R_component_1(),-o.R_component_2(),-o.R_component_3(),-o.R_component_4(),-o.R_component_5(),-o.R_component_6(),-o.R_component_7(),-o.R_component_8())); 1706 } 1707 1708 1709 template<typename T> operator ==(T const & lhs,octonion<T> const & rhs)1710 inline bool operator == (T const & lhs, octonion<T> const & rhs) 1711 { 1712 return( 1713 (rhs.R_component_1() == lhs)&& 1714 (rhs.R_component_2() == static_cast<T>(0))&& 1715 (rhs.R_component_3() == static_cast<T>(0))&& 1716 (rhs.R_component_4() == static_cast<T>(0))&& 1717 (rhs.R_component_5() == static_cast<T>(0))&& 1718 (rhs.R_component_6() == static_cast<T>(0))&& 1719 (rhs.R_component_7() == static_cast<T>(0))&& 1720 (rhs.R_component_8() == static_cast<T>(0)) 1721 ); 1722 } 1723 1724 1725 template<typename T> operator ==(octonion<T> const & lhs,T const & rhs)1726 inline bool operator == (octonion<T> const & lhs, T const & rhs) 1727 { 1728 return( 1729 (lhs.R_component_1() == rhs)&& 1730 (lhs.R_component_2() == static_cast<T>(0))&& 1731 (lhs.R_component_3() == static_cast<T>(0))&& 1732 (lhs.R_component_4() == static_cast<T>(0))&& 1733 (lhs.R_component_5() == static_cast<T>(0))&& 1734 (lhs.R_component_6() == static_cast<T>(0))&& 1735 (lhs.R_component_7() == static_cast<T>(0))&& 1736 (lhs.R_component_8() == static_cast<T>(0)) 1737 ); 1738 } 1739 1740 1741 template<typename T> operator ==(::std::complex<T> const & lhs,octonion<T> const & rhs)1742 inline bool operator == (::std::complex<T> const & lhs, octonion<T> const & rhs) 1743 { 1744 return( 1745 (rhs.R_component_1() == lhs.real())&& 1746 (rhs.R_component_2() == lhs.imag())&& 1747 (rhs.R_component_3() == static_cast<T>(0))&& 1748 (rhs.R_component_4() == static_cast<T>(0))&& 1749 (rhs.R_component_5() == static_cast<T>(0))&& 1750 (rhs.R_component_6() == static_cast<T>(0))&& 1751 (rhs.R_component_7() == static_cast<T>(0))&& 1752 (rhs.R_component_8() == static_cast<T>(0)) 1753 ); 1754 } 1755 1756 1757 template<typename T> operator ==(octonion<T> const & lhs,::std::complex<T> const & rhs)1758 inline bool operator == (octonion<T> const & lhs, ::std::complex<T> const & rhs) 1759 { 1760 return( 1761 (lhs.R_component_1() == rhs.real())&& 1762 (lhs.R_component_2() == rhs.imag())&& 1763 (lhs.R_component_3() == static_cast<T>(0))&& 1764 (lhs.R_component_4() == static_cast<T>(0))&& 1765 (lhs.R_component_5() == static_cast<T>(0))&& 1766 (lhs.R_component_6() == static_cast<T>(0))&& 1767 (lhs.R_component_7() == static_cast<T>(0))&& 1768 (lhs.R_component_8() == static_cast<T>(0)) 1769 ); 1770 } 1771 1772 1773 template<typename T> operator ==(::boost::math::quaternion<T> const & lhs,octonion<T> const & rhs)1774 inline bool operator == (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs) 1775 { 1776 return( 1777 (rhs.R_component_1() == lhs.R_component_1())&& 1778 (rhs.R_component_2() == lhs.R_component_2())&& 1779 (rhs.R_component_3() == lhs.R_component_3())&& 1780 (rhs.R_component_4() == lhs.R_component_4())&& 1781 (rhs.R_component_5() == static_cast<T>(0))&& 1782 (rhs.R_component_6() == static_cast<T>(0))&& 1783 (rhs.R_component_7() == static_cast<T>(0))&& 1784 (rhs.R_component_8() == static_cast<T>(0)) 1785 ); 1786 } 1787 1788 1789 template<typename T> operator ==(octonion<T> const & lhs,::boost::math::quaternion<T> const & rhs)1790 inline bool operator == (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs) 1791 { 1792 return( 1793 (lhs.R_component_1() == rhs.R_component_1())&& 1794 (lhs.R_component_2() == rhs.R_component_2())&& 1795 (lhs.R_component_3() == rhs.R_component_3())&& 1796 (lhs.R_component_4() == rhs.R_component_4())&& 1797 (lhs.R_component_5() == static_cast<T>(0))&& 1798 (lhs.R_component_6() == static_cast<T>(0))&& 1799 (lhs.R_component_7() == static_cast<T>(0))&& 1800 (lhs.R_component_8() == static_cast<T>(0)) 1801 ); 1802 } 1803 1804 1805 template<typename T> operator ==(octonion<T> const & lhs,octonion<T> const & rhs)1806 inline bool operator == (octonion<T> const & lhs, octonion<T> const & rhs) 1807 { 1808 return( 1809 (rhs.R_component_1() == lhs.R_component_1())&& 1810 (rhs.R_component_2() == lhs.R_component_2())&& 1811 (rhs.R_component_3() == lhs.R_component_3())&& 1812 (rhs.R_component_4() == lhs.R_component_4())&& 1813 (rhs.R_component_5() == lhs.R_component_5())&& 1814 (rhs.R_component_6() == lhs.R_component_6())&& 1815 (rhs.R_component_7() == lhs.R_component_7())&& 1816 (rhs.R_component_8() == lhs.R_component_8()) 1817 ); 1818 } 1819 1820 1821 #define BOOST_OCTONION_NOT_EQUAL_GENERATOR \ 1822 { \ 1823 return(!(lhs == rhs)); \ 1824 } 1825 1826 template<typename T> 1827 inline bool operator != (T const & lhs, octonion<T> const & rhs) 1828 BOOST_OCTONION_NOT_EQUAL_GENERATOR 1829 1830 template<typename T> 1831 inline bool operator != (octonion<T> const & lhs, T const & rhs) 1832 BOOST_OCTONION_NOT_EQUAL_GENERATOR 1833 1834 template<typename T> 1835 inline bool operator != (::std::complex<T> const & lhs, octonion<T> const & rhs) 1836 BOOST_OCTONION_NOT_EQUAL_GENERATOR 1837 1838 template<typename T> 1839 inline bool operator != (octonion<T> const & lhs, ::std::complex<T> const & rhs) 1840 BOOST_OCTONION_NOT_EQUAL_GENERATOR 1841 1842 template<typename T> 1843 inline bool operator != (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs) 1844 BOOST_OCTONION_NOT_EQUAL_GENERATOR 1845 1846 template<typename T> 1847 inline bool operator != (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs) 1848 BOOST_OCTONION_NOT_EQUAL_GENERATOR 1849 1850 template<typename T> 1851 inline bool operator != (octonion<T> const & lhs, octonion<T> const & rhs) 1852 BOOST_OCTONION_NOT_EQUAL_GENERATOR 1853 1854 #undef BOOST_OCTONION_NOT_EQUAL_GENERATOR 1855 1856 1857 // Note: the default values in the constructors of the complex and quaternions make for 1858 // a very complex and ambiguous situation; we have made choices to disambiguate. 1859 1860 #if BOOST_WORKAROUND(__GNUC__, < 3) 1861 template<typename T> 1862 ::std::istream & operator >> ( ::std::istream & is, 1863 octonion<T>& o) 1864 #else 1865 template<typename T, typename charT, class traits> 1866 ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is, 1867 octonion<T> & o) 1868 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 1869 { 1870 #if BOOST_WORKAROUND(__GNUC__, < 3) 1871 typedef char charT; 1872 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 1873 1874 #ifdef BOOST_NO_STD_LOCALE 1875 #else 1876 const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc()); 1877 #endif /* BOOST_NO_STD_LOCALE */ 1878 1879 T a = T(); 1880 T b = T(); 1881 T c = T(); 1882 T d = T(); 1883 T e = T(); 1884 T f = T(); 1885 T g = T(); 1886 T h = T(); 1887 1888 ::std::complex<T> u = ::std::complex<T>(); 1889 ::std::complex<T> v = ::std::complex<T>(); 1890 ::std::complex<T> x = ::std::complex<T>(); 1891 ::std::complex<T> y = ::std::complex<T>(); 1892 1893 ::boost::math::quaternion<T> p = ::boost::math::quaternion<T>(); 1894 ::boost::math::quaternion<T> q = ::boost::math::quaternion<T>(); 1895 1896 charT ch = charT(); 1897 char cc; 1898 1899 is >> ch; // get the first lexeme 1900 1901 if (!is.good()) goto finish; 1902 1903 #ifdef BOOST_NO_STD_LOCALE 1904 cc = ch; 1905 #else 1906 cc = ct.narrow(ch, char()); 1907 #endif /* BOOST_NO_STD_LOCALE */ 1908 1909 if (cc == '(') // read "(" 1910 { 1911 is >> ch; // get the second lexeme 1912 1913 if (!is.good()) goto finish; 1914 1915 #ifdef BOOST_NO_STD_LOCALE 1916 cc = ch; 1917 #else 1918 cc = ct.narrow(ch, char()); 1919 #endif /* BOOST_NO_STD_LOCALE */ 1920 1921 if (cc == '(') // read "((" 1922 { 1923 is >> ch; // get the third lexeme 1924 1925 if (!is.good()) goto finish; 1926 1927 #ifdef BOOST_NO_STD_LOCALE 1928 cc = ch; 1929 #else 1930 cc = ct.narrow(ch, char()); 1931 #endif /* BOOST_NO_STD_LOCALE */ 1932 1933 if (cc == '(') // read "(((" 1934 { 1935 is.putback(ch); 1936 1937 is >> u; // read "((u" 1938 1939 if (!is.good()) goto finish; 1940 1941 is >> ch; // get the next lexeme 1942 1943 if (!is.good()) goto finish; 1944 1945 #ifdef BOOST_NO_STD_LOCALE 1946 cc = ch; 1947 #else 1948 cc = ct.narrow(ch, char()); 1949 #endif /* BOOST_NO_STD_LOCALE */ 1950 1951 if (cc == ')') // read "((u)" 1952 { 1953 is >> ch; // get the next lexeme 1954 1955 if (!is.good()) goto finish; 1956 1957 #ifdef BOOST_NO_STD_LOCALE 1958 cc = ch; 1959 #else 1960 cc = ct.narrow(ch, char()); 1961 #endif /* BOOST_NO_STD_LOCALE */ 1962 1963 if (cc == ')') // format: (((a))), (((a,b))) 1964 { 1965 o = octonion<T>(u); 1966 } 1967 else if (cc == ',') // read "((u)," 1968 { 1969 p = ::boost::math::quaternion<T>(u); 1970 1971 is >> q; // read "((u),q" 1972 1973 if (!is.good()) goto finish; 1974 1975 is >> ch; // get the next lexeme 1976 1977 if (!is.good()) goto finish; 1978 1979 #ifdef BOOST_NO_STD_LOCALE 1980 cc = ch; 1981 #else 1982 cc = ct.narrow(ch, char()); 1983 #endif /* BOOST_NO_STD_LOCALE */ 1984 1985 if (cc == ')') // format: (((a)),q), (((a,b)),q) 1986 { 1987 o = octonion<T>(p,q); 1988 } 1989 else // error 1990 { 1991 #if BOOST_WORKAROUND(__GNUC__, < 3) 1992 is.setstate(::std::ios::failbit); 1993 #else 1994 is.setstate(::std::ios_base::failbit); 1995 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 1996 } 1997 } 1998 else // error 1999 { 2000 #if BOOST_WORKAROUND(__GNUC__, < 3) 2001 is.setstate(::std::ios::failbit); 2002 #else 2003 is.setstate(::std::ios_base::failbit); 2004 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2005 } 2006 } 2007 else if (cc ==',') // read "((u," 2008 { 2009 is >> v; // read "((u,v" 2010 2011 if (!is.good()) goto finish; 2012 2013 is >> ch; // get the next lexeme 2014 2015 if (!is.good()) goto finish; 2016 2017 #ifdef BOOST_NO_STD_LOCALE 2018 cc = ch; 2019 #else 2020 cc = ct.narrow(ch, char()); 2021 #endif /* BOOST_NO_STD_LOCALE */ 2022 2023 if (cc == ')') // read "((u,v)" 2024 { 2025 p = ::boost::math::quaternion<T>(u,v); 2026 2027 is >> ch; // get the next lexeme 2028 2029 if (!is.good()) goto finish; 2030 2031 #ifdef BOOST_NO_STD_LOCALE 2032 cc = ch; 2033 #else 2034 cc = ct.narrow(ch, char()); 2035 #endif /* BOOST_NO_STD_LOCALE */ 2036 2037 if (cc == ')') // format: (((a),v)), (((a,b),v)) 2038 { 2039 o = octonion<T>(p); 2040 } 2041 else if (cc == ',') // read "((u,v)," 2042 { 2043 is >> q; // read "(p,q" 2044 2045 if (!is.good()) goto finish; 2046 2047 is >> ch; // get the next lexeme 2048 2049 if (!is.good()) goto finish; 2050 2051 #ifdef BOOST_NO_STD_LOCALE 2052 cc = ch; 2053 #else 2054 cc = ct.narrow(ch, char()); 2055 #endif /* BOOST_NO_STD_LOCALE */ 2056 2057 if (cc == ')') // format: (((a),v),q), (((a,b),v),q) 2058 { 2059 o = octonion<T>(p,q); 2060 } 2061 else // error 2062 { 2063 #if BOOST_WORKAROUND(__GNUC__, < 3) 2064 is.setstate(::std::ios::failbit); 2065 #else 2066 is.setstate(::std::ios_base::failbit); 2067 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2068 } 2069 } 2070 else // error 2071 { 2072 #if BOOST_WORKAROUND(__GNUC__, < 3) 2073 is.setstate(::std::ios::failbit); 2074 #else 2075 is.setstate(::std::ios_base::failbit); 2076 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2077 } 2078 } 2079 else // error 2080 { 2081 #if BOOST_WORKAROUND(__GNUC__, < 3) 2082 is.setstate(::std::ios::failbit); 2083 #else 2084 is.setstate(::std::ios_base::failbit); 2085 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2086 } 2087 } 2088 else // error 2089 { 2090 #if BOOST_WORKAROUND(__GNUC__, < 3) 2091 is.setstate(::std::ios::failbit); 2092 #else 2093 is.setstate(::std::ios_base::failbit); 2094 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2095 } 2096 } 2097 else // read "((a" 2098 { 2099 is.putback(ch); 2100 2101 is >> a; // we extract the first component 2102 2103 if (!is.good()) goto finish; 2104 2105 is >> ch; // get the next lexeme 2106 2107 if (!is.good()) goto finish; 2108 2109 #ifdef BOOST_NO_STD_LOCALE 2110 cc = ch; 2111 #else 2112 cc = ct.narrow(ch, char()); 2113 #endif /* BOOST_NO_STD_LOCALE */ 2114 2115 if (cc == ')') // read "((a)" 2116 { 2117 is >> ch; // get the next lexeme 2118 2119 if (!is.good()) goto finish; 2120 2121 #ifdef BOOST_NO_STD_LOCALE 2122 cc = ch; 2123 #else 2124 cc = ct.narrow(ch, char()); 2125 #endif /* BOOST_NO_STD_LOCALE */ 2126 2127 if (cc == ')') // read "((a))" 2128 { 2129 o = octonion<T>(a); 2130 } 2131 else if (cc == ',') // read "((a)," 2132 { 2133 is >> ch; // get the next lexeme 2134 2135 if (!is.good()) goto finish; 2136 2137 #ifdef BOOST_NO_STD_LOCALE 2138 cc = ch; 2139 #else 2140 cc = ct.narrow(ch, char()); 2141 #endif /* BOOST_NO_STD_LOCALE */ 2142 2143 if (cc == '(') // read "((a),(" 2144 { 2145 is >> ch; // get the next lexeme 2146 2147 if (!is.good()) goto finish; 2148 2149 #ifdef BOOST_NO_STD_LOCALE 2150 cc = ch; 2151 #else 2152 cc = ct.narrow(ch, char()); 2153 #endif /* BOOST_NO_STD_LOCALE */ 2154 2155 if (cc == '(') // read "((a),((" 2156 { 2157 is.putback(ch); 2158 2159 is.putback(ch); // we backtrack twice, with the same value! 2160 2161 is >> q; // read "((a),q" 2162 2163 if (!is.good()) goto finish; 2164 2165 is >> ch; // get the next lexeme 2166 2167 if (!is.good()) goto finish; 2168 2169 #ifdef BOOST_NO_STD_LOCALE 2170 cc = ch; 2171 #else 2172 cc = ct.narrow(ch, char()); 2173 #endif /* BOOST_NO_STD_LOCALE */ 2174 2175 if (cc == ')') // read "((a),q)" 2176 { 2177 p = ::boost::math::quaternion<T>(a); 2178 2179 o = octonion<T>(p,q); 2180 } 2181 else // error 2182 { 2183 #if BOOST_WORKAROUND(__GNUC__, < 3) 2184 is.setstate(::std::ios::failbit); 2185 #else 2186 is.setstate(::std::ios_base::failbit); 2187 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2188 } 2189 } 2190 else // read "((a),(c" or "((a),(e" 2191 { 2192 is.putback(ch); 2193 2194 is >> c; 2195 2196 if (!is.good()) goto finish; 2197 2198 is >> ch; // get the next lexeme 2199 2200 if (!is.good()) goto finish; 2201 2202 #ifdef BOOST_NO_STD_LOCALE 2203 cc = ch; 2204 #else 2205 cc = ct.narrow(ch, char()); 2206 #endif /* BOOST_NO_STD_LOCALE */ 2207 2208 if (cc == ')') // read "((a),(c)" (ambiguity resolution) 2209 { 2210 is >> ch; // get the next lexeme 2211 2212 if (!is.good()) goto finish; 2213 2214 #ifdef BOOST_NO_STD_LOCALE 2215 cc = ch; 2216 #else 2217 cc = ct.narrow(ch, char()); 2218 #endif /* BOOST_NO_STD_LOCALE */ 2219 2220 if (cc == ')') // read "((a),(c))" 2221 { 2222 o = octonion<T>(a,b,c); 2223 } 2224 else if (cc == ',') // read "((a),(c)," 2225 { 2226 u = ::std::complex<T>(a); 2227 2228 v = ::std::complex<T>(c); 2229 2230 is >> x; // read "((a),(c),x" 2231 2232 if (!is.good()) goto finish; 2233 2234 is >> ch; // get the next lexeme 2235 2236 if (!is.good()) goto finish; 2237 2238 #ifdef BOOST_NO_STD_LOCALE 2239 cc = ch; 2240 #else 2241 cc = ct.narrow(ch, char()); 2242 #endif /* BOOST_NO_STD_LOCALE */ 2243 2244 if (cc == ')') // read "((a),(c),x)" 2245 { 2246 o = octonion<T>(u,v,x); 2247 } 2248 else if (cc == ',') // read "((a),(c),x," 2249 { 2250 is >> y; // read "((a),(c),x,y" 2251 2252 if (!is.good()) goto finish; 2253 2254 is >> ch; // get the next lexeme 2255 2256 if (!is.good()) goto finish; 2257 2258 #ifdef BOOST_NO_STD_LOCALE 2259 cc = ch; 2260 #else 2261 cc = ct.narrow(ch, char()); 2262 #endif /* BOOST_NO_STD_LOCALE */ 2263 2264 if (cc == ')') // read "((a),(c),x,y)" 2265 { 2266 o = octonion<T>(u,v,x,y); 2267 } 2268 else // error 2269 { 2270 #if BOOST_WORKAROUND(__GNUC__, < 3) 2271 is.setstate(::std::ios::failbit); 2272 #else 2273 is.setstate(::std::ios_base::failbit); 2274 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2275 } 2276 } 2277 else // error 2278 { 2279 #if BOOST_WORKAROUND(__GNUC__, < 3) 2280 is.setstate(::std::ios::failbit); 2281 #else 2282 is.setstate(::std::ios_base::failbit); 2283 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2284 } 2285 } 2286 else // error 2287 { 2288 #if BOOST_WORKAROUND(__GNUC__, < 3) 2289 is.setstate(::std::ios::failbit); 2290 #else 2291 is.setstate(::std::ios_base::failbit); 2292 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2293 } 2294 } 2295 else if (cc == ',') // read "((a),(c," or "((a),(e," 2296 { 2297 is >> ch; // get the next lexeme 2298 2299 if (!is.good()) goto finish; 2300 2301 #ifdef BOOST_NO_STD_LOCALE 2302 cc = ch; 2303 #else 2304 cc = ct.narrow(ch, char()); 2305 #endif /* BOOST_NO_STD_LOCALE */ 2306 2307 if (cc == '(') // read "((a),(e,(" (ambiguity resolution) 2308 { 2309 p = ::boost::math::quaternion<T>(a); 2310 2311 x = ::std::complex<T>(c); // "c" was actually "e" 2312 2313 is.putback(ch); // we can only backtrace once 2314 2315 is >> y; // read "((a),(e,y" 2316 2317 if (!is.good()) goto finish; 2318 2319 is >> ch; // get the next lexeme 2320 2321 #ifdef BOOST_NO_STD_LOCALE 2322 cc = ch; 2323 #else 2324 cc = ct.narrow(ch, char()); 2325 #endif /* BOOST_NO_STD_LOCALE */ 2326 2327 if (cc == ')') // read "((a),(e,y)" 2328 { 2329 q = ::boost::math::quaternion<T>(x,y); 2330 2331 is >> ch; // get the next lexeme 2332 2333 #ifdef BOOST_NO_STD_LOCALE 2334 cc = ch; 2335 #else 2336 cc = ct.narrow(ch, char()); 2337 #endif /* BOOST_NO_STD_LOCALE */ 2338 2339 if (cc == ')') // read "((a),(e,y))" 2340 { 2341 o = octonion<T>(p,q); 2342 } 2343 else // error 2344 { 2345 #if BOOST_WORKAROUND(__GNUC__, < 3) 2346 is.setstate(::std::ios::failbit); 2347 #else 2348 is.setstate(::std::ios_base::failbit); 2349 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2350 } 2351 } 2352 else // error 2353 { 2354 #if BOOST_WORKAROUND(__GNUC__, < 3) 2355 is.setstate(::std::ios::failbit); 2356 #else 2357 is.setstate(::std::ios_base::failbit); 2358 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2359 } 2360 } 2361 else // read "((a),(c,d" or "((a),(e,f" 2362 { 2363 is.putback(ch); 2364 2365 is >> d; 2366 2367 if (!is.good()) goto finish; 2368 2369 is >> ch; // get the next lexeme 2370 2371 if (!is.good()) goto finish; 2372 2373 #ifdef BOOST_NO_STD_LOCALE 2374 cc = ch; 2375 #else 2376 cc = ct.narrow(ch, char()); 2377 #endif /* BOOST_NO_STD_LOCALE */ 2378 2379 if (cc == ')') // read "((a),(c,d)" (ambiguity resolution) 2380 { 2381 is >> ch; // get the next lexeme 2382 2383 if (!is.good()) goto finish; 2384 2385 #ifdef BOOST_NO_STD_LOCALE 2386 cc = ch; 2387 #else 2388 cc = ct.narrow(ch, char()); 2389 #endif /* BOOST_NO_STD_LOCALE */ 2390 2391 if (cc == ')') // read "((a),(c,d))" 2392 { 2393 o = octonion<T>(a,b,c,d); 2394 } 2395 else if (cc == ',') // read "((a),(c,d)," 2396 { 2397 u = ::std::complex<T>(a); 2398 2399 v = ::std::complex<T>(c,d); 2400 2401 is >> x; // read "((a),(c,d),x" 2402 2403 if (!is.good()) goto finish; 2404 2405 is >> ch; // get the next lexeme 2406 2407 if (!is.good()) goto finish; 2408 2409 #ifdef BOOST_NO_STD_LOCALE 2410 cc = ch; 2411 #else 2412 cc = ct.narrow(ch, char()); 2413 #endif /* BOOST_NO_STD_LOCALE */ 2414 2415 if (cc == ')') // read "((a),(c,d),x)" 2416 { 2417 o = octonion<T>(u,v,x); 2418 } 2419 else if (cc == ',') // read "((a),(c,d),x," 2420 { 2421 is >> y; // read "((a),(c,d),x,y" 2422 2423 if (!is.good()) goto finish; 2424 2425 is >> ch; // get the next lexeme 2426 2427 if (!is.good()) goto finish; 2428 2429 #ifdef BOOST_NO_STD_LOCALE 2430 cc = ch; 2431 #else 2432 cc = ct.narrow(ch, char()); 2433 #endif /* BOOST_NO_STD_LOCALE */ 2434 2435 if (cc == ')') // read "((a),(c,d),x,y)" 2436 { 2437 o = octonion<T>(u,v,x,y); 2438 } 2439 else // error 2440 { 2441 #if BOOST_WORKAROUND(__GNUC__, < 3) 2442 is.setstate(::std::ios::failbit); 2443 #else 2444 is.setstate(::std::ios_base::failbit); 2445 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2446 } 2447 } 2448 else // error 2449 { 2450 #if BOOST_WORKAROUND(__GNUC__, < 3) 2451 is.setstate(::std::ios::failbit); 2452 #else 2453 is.setstate(::std::ios_base::failbit); 2454 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2455 } 2456 } 2457 else // error 2458 { 2459 #if BOOST_WORKAROUND(__GNUC__, < 3) 2460 is.setstate(::std::ios::failbit); 2461 #else 2462 is.setstate(::std::ios_base::failbit); 2463 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2464 } 2465 } 2466 else if (cc == ',') // read "((a),(e,f," (ambiguity resolution) 2467 { 2468 p = ::boost::math::quaternion<T>(a); 2469 2470 is >> g; // read "((a),(e,f,g" (too late to backtrack) 2471 2472 if (!is.good()) goto finish; 2473 2474 is >> ch; // get the next lexeme 2475 2476 if (!is.good()) goto finish; 2477 2478 #ifdef BOOST_NO_STD_LOCALE 2479 cc = ch; 2480 #else 2481 cc = ct.narrow(ch, char()); 2482 #endif /* BOOST_NO_STD_LOCALE */ 2483 2484 if (cc == ')') // read "((a),(e,f,g)" 2485 { 2486 q = ::boost::math::quaternion<T>(c,d,g); // "c" was actually "e", and "d" was actually "f" 2487 2488 is >> ch; // get the next lexeme 2489 2490 if (!is.good()) goto finish; 2491 2492 #ifdef BOOST_NO_STD_LOCALE 2493 cc = ch; 2494 #else 2495 cc = ct.narrow(ch, char()); 2496 #endif /* BOOST_NO_STD_LOCALE */ 2497 2498 if (cc == ')') // read "((a),(e,f,g))" 2499 { 2500 o = octonion<T>(p,q); 2501 } 2502 else // error 2503 { 2504 #if BOOST_WORKAROUND(__GNUC__, < 3) 2505 is.setstate(::std::ios::failbit); 2506 #else 2507 is.setstate(::std::ios_base::failbit); 2508 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2509 } 2510 } 2511 else if (cc == ',') // read "((a),(e,f,g," 2512 { 2513 is >> h; // read "((a),(e,f,g,h" 2514 2515 if (!is.good()) goto finish; 2516 2517 is >> ch; // get the next lexeme 2518 2519 if (!is.good()) goto finish; 2520 2521 #ifdef BOOST_NO_STD_LOCALE 2522 cc = ch; 2523 #else 2524 cc = ct.narrow(ch, char()); 2525 #endif /* BOOST_NO_STD_LOCALE */ 2526 2527 if (cc == ')') // read "((a),(e,f,g,h)" 2528 { 2529 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" was actually "e", and "d" was actually "f" 2530 2531 is >> ch; // get the next lexeme 2532 2533 if (!is.good()) goto finish; 2534 2535 #ifdef BOOST_NO_STD_LOCALE 2536 cc = ch; 2537 #else 2538 cc = ct.narrow(ch, char()); 2539 #endif /* BOOST_NO_STD_LOCALE */ 2540 2541 if (cc == ')') // read "((a),(e,f,g,h))" 2542 { 2543 o = octonion<T>(p,q); 2544 } 2545 else // error 2546 { 2547 #if BOOST_WORKAROUND(__GNUC__, < 3) 2548 is.setstate(::std::ios::failbit); 2549 #else 2550 is.setstate(::std::ios_base::failbit); 2551 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2552 } 2553 } 2554 else // error 2555 { 2556 #if BOOST_WORKAROUND(__GNUC__, < 3) 2557 is.setstate(::std::ios::failbit); 2558 #else 2559 is.setstate(::std::ios_base::failbit); 2560 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2561 } 2562 } 2563 else // error 2564 { 2565 #if BOOST_WORKAROUND(__GNUC__, < 3) 2566 is.setstate(::std::ios::failbit); 2567 #else 2568 is.setstate(::std::ios_base::failbit); 2569 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2570 } 2571 } 2572 else // error 2573 { 2574 #if BOOST_WORKAROUND(__GNUC__, < 3) 2575 is.setstate(::std::ios::failbit); 2576 #else 2577 is.setstate(::std::ios_base::failbit); 2578 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2579 } 2580 } 2581 } 2582 else // error 2583 { 2584 #if BOOST_WORKAROUND(__GNUC__, < 3) 2585 is.setstate(::std::ios::failbit); 2586 #else 2587 is.setstate(::std::ios_base::failbit); 2588 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2589 } 2590 } 2591 } 2592 else // read "((a),c" (ambiguity resolution) 2593 { 2594 is.putback(ch); 2595 2596 is >> c; // we extract the third component 2597 2598 if (!is.good()) goto finish; 2599 2600 is >> ch; // get the next lexeme 2601 2602 if (!is.good()) goto finish; 2603 2604 #ifdef BOOST_NO_STD_LOCALE 2605 cc = ch; 2606 #else 2607 cc = ct.narrow(ch, char()); 2608 #endif /* BOOST_NO_STD_LOCALE */ 2609 2610 if (cc == ')') // read "((a),c)" 2611 { 2612 o = octonion<T>(a,b,c); 2613 } 2614 else if (cc == ',') // read "((a),c," 2615 { 2616 is >> x; // read "((a),c,x" 2617 2618 if (!is.good()) goto finish; 2619 2620 is >> ch; // get the next lexeme 2621 2622 if (!is.good()) goto finish; 2623 2624 #ifdef BOOST_NO_STD_LOCALE 2625 cc = ch; 2626 #else 2627 cc = ct.narrow(ch, char()); 2628 #endif /* BOOST_NO_STD_LOCALE */ 2629 2630 if (cc == ')') // read "((a),c,x)" 2631 { 2632 o = octonion<T>(a,b,c,d,x.real(),x.imag()); 2633 } 2634 else if (cc == ',') // read "((a),c,x," 2635 { 2636 is >> y;if (!is.good()) goto finish; // read "((a),c,x,y" 2637 2638 is >> ch; // get the next lexeme 2639 2640 if (!is.good()) goto finish; 2641 2642 #ifdef BOOST_NO_STD_LOCALE 2643 cc = ch; 2644 #else 2645 cc = ct.narrow(ch, char()); 2646 #endif /* BOOST_NO_STD_LOCALE */ 2647 2648 if (cc == ')') // read "((a),c,x,y)" 2649 { 2650 o = octonion<T>(a,b,c,d,x.real(),x.imag(),y.real(),y.imag()); 2651 } 2652 else // error 2653 { 2654 #if BOOST_WORKAROUND(__GNUC__, < 3) 2655 is.setstate(::std::ios::failbit); 2656 #else 2657 is.setstate(::std::ios_base::failbit); 2658 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2659 } 2660 } 2661 else // error 2662 { 2663 #if BOOST_WORKAROUND(__GNUC__, < 3) 2664 is.setstate(::std::ios::failbit); 2665 #else 2666 is.setstate(::std::ios_base::failbit); 2667 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2668 } 2669 } 2670 else // error 2671 { 2672 #if BOOST_WORKAROUND(__GNUC__, < 3) 2673 is.setstate(::std::ios::failbit); 2674 #else 2675 is.setstate(::std::ios_base::failbit); 2676 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2677 } 2678 } 2679 } 2680 else // error 2681 { 2682 #if BOOST_WORKAROUND(__GNUC__, < 3) 2683 is.setstate(::std::ios::failbit); 2684 #else 2685 is.setstate(::std::ios_base::failbit); 2686 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2687 } 2688 } 2689 else if (cc ==',') // read "((a," 2690 { 2691 is >> ch; // get the next lexeme 2692 2693 if (!is.good()) goto finish; 2694 2695 #ifdef BOOST_NO_STD_LOCALE 2696 cc = ch; 2697 #else 2698 cc = ct.narrow(ch, char()); 2699 #endif /* BOOST_NO_STD_LOCALE */ 2700 2701 if (cc == '(') // read "((a,(" 2702 { 2703 u = ::std::complex<T>(a); 2704 2705 is.putback(ch); // can only backtrack so much 2706 2707 is >> v; // read "((a,v" 2708 2709 if (!is.good()) goto finish; 2710 2711 is >> ch; // get the next lexeme 2712 2713 if (!is.good()) goto finish; 2714 2715 #ifdef BOOST_NO_STD_LOCALE 2716 cc = ch; 2717 #else 2718 cc = ct.narrow(ch, char()); 2719 #endif /* BOOST_NO_STD_LOCALE */ 2720 2721 if (cc == ')') // read "((a,v)" 2722 { 2723 is >> ch; // get the next lexeme 2724 2725 if (!is.good()) goto finish; 2726 2727 #ifdef BOOST_NO_STD_LOCALE 2728 cc = ch; 2729 #else 2730 cc = ct.narrow(ch, char()); 2731 #endif /* BOOST_NO_STD_LOCALE */ 2732 2733 if (cc == ')') // read "((a,v))" 2734 { 2735 o = octonion<T>(u,v); 2736 } 2737 else if (cc == ',') // read "((a,v)," 2738 { 2739 p = ::boost::math::quaternion<T>(u,v); 2740 2741 is >> q; // read "((a,v),q" 2742 2743 if (!is.good()) goto finish; 2744 2745 is >> ch; // get the next lexeme 2746 2747 if (!is.good()) goto finish; 2748 2749 #ifdef BOOST_NO_STD_LOCALE 2750 cc = ch; 2751 #else 2752 cc = ct.narrow(ch, char()); 2753 #endif /* BOOST_NO_STD_LOCALE */ 2754 2755 if (cc == ')') // read "((a,v),q)" 2756 { 2757 o = octonion<T>(p,q); 2758 } 2759 else // error 2760 { 2761 #if BOOST_WORKAROUND(__GNUC__, < 3) 2762 is.setstate(::std::ios::failbit); 2763 #else 2764 is.setstate(::std::ios_base::failbit); 2765 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2766 } 2767 } 2768 else // error 2769 { 2770 #if BOOST_WORKAROUND(__GNUC__, < 3) 2771 is.setstate(::std::ios::failbit); 2772 #else 2773 is.setstate(::std::ios_base::failbit); 2774 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2775 } 2776 } 2777 else // error 2778 { 2779 #if BOOST_WORKAROUND(__GNUC__, < 3) 2780 is.setstate(::std::ios::failbit); 2781 #else 2782 is.setstate(::std::ios_base::failbit); 2783 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2784 } 2785 } 2786 else 2787 { 2788 is.putback(ch); 2789 2790 is >> b; // read "((a,b" 2791 2792 if (!is.good()) goto finish; 2793 2794 is >> ch; // get the next lexeme 2795 2796 if (!is.good()) goto finish; 2797 2798 #ifdef BOOST_NO_STD_LOCALE 2799 cc = ch; 2800 #else 2801 cc = ct.narrow(ch, char()); 2802 #endif /* BOOST_NO_STD_LOCALE */ 2803 2804 if (cc == ')') // read "((a,b)" 2805 { 2806 is >> ch; // get the next lexeme 2807 2808 if (!is.good()) goto finish; 2809 2810 #ifdef BOOST_NO_STD_LOCALE 2811 cc = ch; 2812 #else 2813 cc = ct.narrow(ch, char()); 2814 #endif /* BOOST_NO_STD_LOCALE */ 2815 2816 if (cc == ')') // read "((a,b))" 2817 { 2818 o = octonion<T>(a,b); 2819 } 2820 else if (cc == ',') // read "((a,b)," 2821 { 2822 is >> ch; // get the next lexeme 2823 2824 if (!is.good()) goto finish; 2825 2826 #ifdef BOOST_NO_STD_LOCALE 2827 cc = ch; 2828 #else 2829 cc = ct.narrow(ch, char()); 2830 #endif /* BOOST_NO_STD_LOCALE */ 2831 2832 if (cc == '(') // read "((a,b),(" 2833 { 2834 is >> ch; // get the next lexeme 2835 2836 if (!is.good()) goto finish; 2837 2838 #ifdef BOOST_NO_STD_LOCALE 2839 cc = ch; 2840 #else 2841 cc = ct.narrow(ch, char()); 2842 #endif /* BOOST_NO_STD_LOCALE */ 2843 2844 if (cc == '(') // read "((a,b),((" 2845 { 2846 p = ::boost::math::quaternion<T>(a,b); 2847 2848 is.putback(ch); 2849 2850 is.putback(ch); // we backtrack twice, with the same value 2851 2852 is >> q; // read "((a,b),q" 2853 2854 if (!is.good()) goto finish; 2855 2856 is >> ch; // get the next lexeme 2857 2858 if (!is.good()) goto finish; 2859 2860 #ifdef BOOST_NO_STD_LOCALE 2861 cc = ch; 2862 #else 2863 cc = ct.narrow(ch, char()); 2864 #endif /* BOOST_NO_STD_LOCALE */ 2865 2866 if (cc == ')') // read "((a,b),q)" 2867 { 2868 o = octonion<T>(p,q); 2869 } 2870 else // error 2871 { 2872 #if BOOST_WORKAROUND(__GNUC__, < 3) 2873 is.setstate(::std::ios::failbit); 2874 #else 2875 is.setstate(::std::ios_base::failbit); 2876 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2877 } 2878 } 2879 else // read "((a,b),(c" or "((a,b),(e" 2880 { 2881 is.putback(ch); 2882 2883 is >> c; 2884 2885 if (!is.good()) goto finish; 2886 2887 is >> ch; // get the next lexeme 2888 2889 if (!is.good()) goto finish; 2890 2891 #ifdef BOOST_NO_STD_LOCALE 2892 cc = ch; 2893 #else 2894 cc = ct.narrow(ch, char()); 2895 #endif /* BOOST_NO_STD_LOCALE */ 2896 2897 if (cc == ')') // read "((a,b),(c)" (ambiguity resolution) 2898 { 2899 is >> ch; // get the next lexeme 2900 2901 if (!is.good()) goto finish; 2902 2903 #ifdef BOOST_NO_STD_LOCALE 2904 cc = ch; 2905 #else 2906 cc = ct.narrow(ch, char()); 2907 #endif /* BOOST_NO_STD_LOCALE */ 2908 2909 if (cc == ')') // read "((a,b),(c))" 2910 { 2911 o = octonion<T>(a,b,c); 2912 } 2913 else if (cc == ',') // read "((a,b),(c)," 2914 { 2915 u = ::std::complex<T>(a,b); 2916 2917 v = ::std::complex<T>(c); 2918 2919 is >> x; // read "((a,b),(c),x" 2920 2921 if (!is.good()) goto finish; 2922 2923 is >> ch; // get the next lexeme 2924 2925 if (!is.good()) goto finish; 2926 2927 #ifdef BOOST_NO_STD_LOCALE 2928 cc = ch; 2929 #else 2930 cc = ct.narrow(ch, char()); 2931 #endif /* BOOST_NO_STD_LOCALE */ 2932 2933 if (cc == ')') // read "((a,b),(c),x)" 2934 { 2935 o = octonion<T>(u,v,x); 2936 } 2937 else if (cc == ',') // read "((a,b),(c),x," 2938 { 2939 is >> y; // read "((a,b),(c),x,y" 2940 2941 if (!is.good()) goto finish; 2942 2943 is >> ch; // get the next lexeme 2944 2945 if (!is.good()) goto finish; 2946 2947 #ifdef BOOST_NO_STD_LOCALE 2948 cc = ch; 2949 #else 2950 cc = ct.narrow(ch, char()); 2951 #endif /* BOOST_NO_STD_LOCALE */ 2952 2953 if (cc == ')') // read "((a,b),(c),x,y)" 2954 { 2955 o = octonion<T>(u,v,x,y); 2956 } 2957 else // error 2958 { 2959 #if BOOST_WORKAROUND(__GNUC__, < 3) 2960 is.setstate(::std::ios::failbit); 2961 #else 2962 is.setstate(::std::ios_base::failbit); 2963 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2964 } 2965 } 2966 else // error 2967 { 2968 #if BOOST_WORKAROUND(__GNUC__, < 3) 2969 is.setstate(::std::ios::failbit); 2970 #else 2971 is.setstate(::std::ios_base::failbit); 2972 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2973 } 2974 } 2975 else // error 2976 { 2977 #if BOOST_WORKAROUND(__GNUC__, < 3) 2978 is.setstate(::std::ios::failbit); 2979 #else 2980 is.setstate(::std::ios_base::failbit); 2981 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 2982 } 2983 } 2984 else if (cc == ',') // read "((a,b),(c," or "((a,b),(e," 2985 { 2986 is >> ch; // get the next lexeme 2987 2988 if (!is.good()) goto finish; 2989 2990 #ifdef BOOST_NO_STD_LOCALE 2991 cc = ch; 2992 #else 2993 cc = ct.narrow(ch, char()); 2994 #endif /* BOOST_NO_STD_LOCALE */ 2995 2996 if (cc == '(') // read "((a,b),(e,(" (ambiguity resolution) 2997 { 2998 u = ::std::complex<T>(a,b); 2999 3000 x = ::std::complex<T>(c); // "c" is actually "e" 3001 3002 is.putback(ch); 3003 3004 is >> y; // read "((a,b),(e,y" 3005 3006 if (!is.good()) goto finish; 3007 3008 is >> ch; // get the next lexeme 3009 3010 if (!is.good()) goto finish; 3011 3012 #ifdef BOOST_NO_STD_LOCALE 3013 cc = ch; 3014 #else 3015 cc = ct.narrow(ch, char()); 3016 #endif /* BOOST_NO_STD_LOCALE */ 3017 3018 if (cc == ')') // read "((a,b),(e,y)" 3019 { 3020 is >> ch; // get the next lexeme 3021 3022 if (!is.good()) goto finish; 3023 3024 #ifdef BOOST_NO_STD_LOCALE 3025 cc = ch; 3026 #else 3027 cc = ct.narrow(ch, char()); 3028 #endif /* BOOST_NO_STD_LOCALE */ 3029 3030 if (cc == ')') // read "((a,b),(e,y))" 3031 { 3032 o = octonion<T>(u,v,x,y); 3033 } 3034 else // error 3035 { 3036 #if BOOST_WORKAROUND(__GNUC__, < 3) 3037 is.setstate(::std::ios::failbit); 3038 #else 3039 is.setstate(::std::ios_base::failbit); 3040 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3041 } 3042 } 3043 else // error 3044 { 3045 #if BOOST_WORKAROUND(__GNUC__, < 3) 3046 is.setstate(::std::ios::failbit); 3047 #else 3048 is.setstate(::std::ios_base::failbit); 3049 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3050 } 3051 } 3052 else // read "((a,b),(c,d" or "((a,b),(e,f" 3053 { 3054 is.putback(ch); 3055 3056 is >> d; 3057 3058 if (!is.good()) goto finish; 3059 3060 is >> ch; // get the next lexeme 3061 3062 if (!is.good()) goto finish; 3063 3064 #ifdef BOOST_NO_STD_LOCALE 3065 cc = ch; 3066 #else 3067 cc = ct.narrow(ch, char()); 3068 #endif /* BOOST_NO_STD_LOCALE */ 3069 3070 if (cc == ')') // read "((a,b),(c,d)" (ambiguity resolution) 3071 { 3072 u = ::std::complex<T>(a,b); 3073 3074 v = ::std::complex<T>(c,d); 3075 3076 is >> ch; // get the next lexeme 3077 3078 if (!is.good()) goto finish; 3079 3080 #ifdef BOOST_NO_STD_LOCALE 3081 cc = ch; 3082 #else 3083 cc = ct.narrow(ch, char()); 3084 #endif /* BOOST_NO_STD_LOCALE */ 3085 3086 if (cc == ')') // read "((a,b),(c,d))" 3087 { 3088 o = octonion<T>(u,v); 3089 } 3090 else if (cc == ',') // read "((a,b),(c,d)," 3091 { 3092 is >> x; // read "((a,b),(c,d),x 3093 3094 if (!is.good()) goto finish; 3095 3096 is >> ch; // get the next lexeme 3097 3098 if (!is.good()) goto finish; 3099 3100 #ifdef BOOST_NO_STD_LOCALE 3101 cc = ch; 3102 #else 3103 cc = ct.narrow(ch, char()); 3104 #endif /* BOOST_NO_STD_LOCALE */ 3105 3106 if (cc == ')') // read "((a,b),(c,d),x)" 3107 { 3108 o = octonion<T>(u,v,x); 3109 } 3110 else if (cc == ',') // read "((a,b),(c,d),x," 3111 { 3112 is >> y; // read "((a,b),(c,d),x,y" 3113 3114 if (!is.good()) goto finish; 3115 3116 is >> ch; // get the next lexeme 3117 3118 if (!is.good()) goto finish; 3119 3120 #ifdef BOOST_NO_STD_LOCALE 3121 cc = ch; 3122 #else 3123 cc = ct.narrow(ch, char()); 3124 #endif /* BOOST_NO_STD_LOCALE */ 3125 3126 if (cc == ')') // read "((a,b),(c,d),x,y)" 3127 { 3128 o = octonion<T>(u,v,x,y); 3129 } 3130 else // error 3131 { 3132 #if BOOST_WORKAROUND(__GNUC__, < 3) 3133 is.setstate(::std::ios::failbit); 3134 #else 3135 is.setstate(::std::ios_base::failbit); 3136 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3137 } 3138 } 3139 else // error 3140 { 3141 #if BOOST_WORKAROUND(__GNUC__, < 3) 3142 is.setstate(::std::ios::failbit); 3143 #else 3144 is.setstate(::std::ios_base::failbit); 3145 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3146 } 3147 } 3148 else // error 3149 { 3150 #if BOOST_WORKAROUND(__GNUC__, < 3) 3151 is.setstate(::std::ios::failbit); 3152 #else 3153 is.setstate(::std::ios_base::failbit); 3154 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3155 } 3156 } 3157 else if (cc == ',') // read "((a,b),(e,f," (ambiguity resolution) 3158 { 3159 p = ::boost::math::quaternion<T>(a,b); // too late to backtrack 3160 3161 is >> g; // read "((a,b),(e,f,g" 3162 3163 if (!is.good()) goto finish; 3164 3165 is >> ch; // get the next lexeme 3166 3167 if (!is.good()) goto finish; 3168 3169 #ifdef BOOST_NO_STD_LOCALE 3170 cc = ch; 3171 #else 3172 cc = ct.narrow(ch, char()); 3173 #endif /* BOOST_NO_STD_LOCALE */ 3174 3175 if (cc == ')') // read "((a,b),(e,f,g)" 3176 { 3177 is >> ch; // get the next lexeme 3178 3179 if (!is.good()) goto finish; 3180 3181 #ifdef BOOST_NO_STD_LOCALE 3182 cc = ch; 3183 #else 3184 cc = ct.narrow(ch, char()); 3185 #endif /* BOOST_NO_STD_LOCALE */ 3186 3187 if (cc == ')') // read "((a,b),(e,f,g))" 3188 { 3189 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f" 3190 3191 o = octonion<T>(p,q); 3192 } 3193 else // error 3194 { 3195 #if BOOST_WORKAROUND(__GNUC__, < 3) 3196 is.setstate(::std::ios::failbit); 3197 #else 3198 is.setstate(::std::ios_base::failbit); 3199 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3200 } 3201 } 3202 else if (cc == ',') // read "((a,b),(e,f,g," 3203 { 3204 is >> h; // read "((a,b),(e,f,g,h" 3205 3206 if (!is.good()) goto finish; 3207 3208 is >> ch; // get the next lexeme 3209 3210 if (!is.good()) goto finish; 3211 3212 #ifdef BOOST_NO_STD_LOCALE 3213 cc = ch; 3214 #else 3215 cc = ct.narrow(ch, char()); 3216 #endif /* BOOST_NO_STD_LOCALE */ 3217 3218 if (cc == ')') // read "((a,b),(e,f,g,h)" 3219 { 3220 is >> ch; // get the next lexeme 3221 3222 if (!is.good()) goto finish; 3223 3224 #ifdef BOOST_NO_STD_LOCALE 3225 cc = ch; 3226 #else 3227 cc = ct.narrow(ch, char()); 3228 #endif /* BOOST_NO_STD_LOCALE */ 3229 3230 if (cc == ')') // read ((a,b),(e,f,g,h))" 3231 { 3232 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f" 3233 3234 o = octonion<T>(p,q); 3235 } 3236 else // error 3237 { 3238 #if BOOST_WORKAROUND(__GNUC__, < 3) 3239 is.setstate(::std::ios::failbit); 3240 #else 3241 is.setstate(::std::ios_base::failbit); 3242 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3243 } 3244 } 3245 else // error 3246 { 3247 #if BOOST_WORKAROUND(__GNUC__, < 3) 3248 is.setstate(::std::ios::failbit); 3249 #else 3250 is.setstate(::std::ios_base::failbit); 3251 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3252 } 3253 } 3254 else // error 3255 { 3256 #if BOOST_WORKAROUND(__GNUC__, < 3) 3257 is.setstate(::std::ios::failbit); 3258 #else 3259 is.setstate(::std::ios_base::failbit); 3260 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3261 } 3262 } 3263 else // error 3264 { 3265 #if BOOST_WORKAROUND(__GNUC__, < 3) 3266 is.setstate(::std::ios::failbit); 3267 #else 3268 is.setstate(::std::ios_base::failbit); 3269 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3270 } 3271 } 3272 } 3273 else // error 3274 { 3275 #if BOOST_WORKAROUND(__GNUC__, < 3) 3276 is.setstate(::std::ios::failbit); 3277 #else 3278 is.setstate(::std::ios_base::failbit); 3279 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3280 } 3281 } 3282 } 3283 else // error 3284 { 3285 #if BOOST_WORKAROUND(__GNUC__, < 3) 3286 is.setstate(::std::ios::failbit); 3287 #else 3288 is.setstate(::std::ios_base::failbit); 3289 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3290 } 3291 } 3292 else // error 3293 { 3294 #if BOOST_WORKAROUND(__GNUC__, < 3) 3295 is.setstate(::std::ios::failbit); 3296 #else 3297 is.setstate(::std::ios_base::failbit); 3298 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3299 } 3300 } 3301 else if (cc == ',') // read "((a,b," 3302 { 3303 is >> c; // read "((a,b,c" 3304 3305 if (!is.good()) goto finish; 3306 3307 is >> ch; // get the next lexeme 3308 3309 if (!is.good()) goto finish; 3310 3311 #ifdef BOOST_NO_STD_LOCALE 3312 cc = ch; 3313 #else 3314 cc = ct.narrow(ch, char()); 3315 #endif /* BOOST_NO_STD_LOCALE */ 3316 3317 if (cc == ')') // read "((a,b,c)" 3318 { 3319 is >> ch; // get the next lexeme 3320 3321 if (!is.good()) goto finish; 3322 3323 #ifdef BOOST_NO_STD_LOCALE 3324 cc = ch; 3325 #else 3326 cc = ct.narrow(ch, char()); 3327 #endif /* BOOST_NO_STD_LOCALE */ 3328 3329 if (cc == ')') // read "((a,b,c))" 3330 { 3331 o = octonion<T>(a,b,c); 3332 } 3333 else if (cc == ',') // read "((a,b,c)," 3334 { 3335 p = ::boost::math::quaternion<T>(a,b,c); 3336 3337 is >> q; // read "((a,b,c),q" 3338 3339 if (!is.good()) goto finish; 3340 3341 is >> ch; // get the next lexeme 3342 3343 if (!is.good()) goto finish; 3344 3345 #ifdef BOOST_NO_STD_LOCALE 3346 cc = ch; 3347 #else 3348 cc = ct.narrow(ch, char()); 3349 #endif /* BOOST_NO_STD_LOCALE */ 3350 3351 if (cc == ')') // read "((a,b,c),q)" 3352 { 3353 o = octonion<T>(p,q); 3354 } 3355 else // error 3356 { 3357 #if BOOST_WORKAROUND(__GNUC__, < 3) 3358 is.setstate(::std::ios::failbit); 3359 #else 3360 is.setstate(::std::ios_base::failbit); 3361 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3362 } 3363 } 3364 else // error 3365 { 3366 #if BOOST_WORKAROUND(__GNUC__, < 3) 3367 is.setstate(::std::ios::failbit); 3368 #else 3369 is.setstate(::std::ios_base::failbit); 3370 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3371 } 3372 } 3373 else if (cc == ',') // read "((a,b,c," 3374 { 3375 is >> d; // read "((a,b,c,d" 3376 3377 if (!is.good()) goto finish; 3378 3379 is >> ch; // get the next lexeme 3380 3381 if (!is.good()) goto finish; 3382 3383 #ifdef BOOST_NO_STD_LOCALE 3384 cc = ch; 3385 #else 3386 cc = ct.narrow(ch, char()); 3387 #endif /* BOOST_NO_STD_LOCALE */ 3388 3389 if (cc == ')') // read "((a,b,c,d)" 3390 { 3391 is >> ch; // get the next lexeme 3392 3393 if (!is.good()) goto finish; 3394 3395 #ifdef BOOST_NO_STD_LOCALE 3396 cc = ch; 3397 #else 3398 cc = ct.narrow(ch, char()); 3399 #endif /* BOOST_NO_STD_LOCALE */ 3400 3401 if (cc == ')') // read "((a,b,c,d))" 3402 { 3403 o = octonion<T>(a,b,c,d); 3404 } 3405 else if (cc == ',') // read "((a,b,c,d)," 3406 { 3407 p = ::boost::math::quaternion<T>(a,b,c,d); 3408 3409 is >> q; // read "((a,b,c,d),q" 3410 3411 if (!is.good()) goto finish; 3412 3413 is >> ch; // get the next lexeme 3414 3415 if (!is.good()) goto finish; 3416 3417 #ifdef BOOST_NO_STD_LOCALE 3418 cc = ch; 3419 #else 3420 cc = ct.narrow(ch, char()); 3421 #endif /* BOOST_NO_STD_LOCALE */ 3422 3423 if (cc == ')') // read "((a,b,c,d),q)" 3424 { 3425 o = octonion<T>(p,q); 3426 } 3427 else // error 3428 { 3429 #if BOOST_WORKAROUND(__GNUC__, < 3) 3430 is.setstate(::std::ios::failbit); 3431 #else 3432 is.setstate(::std::ios_base::failbit); 3433 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3434 } 3435 } 3436 else // error 3437 { 3438 #if BOOST_WORKAROUND(__GNUC__, < 3) 3439 is.setstate(::std::ios::failbit); 3440 #else 3441 is.setstate(::std::ios_base::failbit); 3442 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3443 } 3444 } 3445 else // error 3446 { 3447 #if BOOST_WORKAROUND(__GNUC__, < 3) 3448 is.setstate(::std::ios::failbit); 3449 #else 3450 is.setstate(::std::ios_base::failbit); 3451 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3452 } 3453 } 3454 else // error 3455 { 3456 #if BOOST_WORKAROUND(__GNUC__, < 3) 3457 is.setstate(::std::ios::failbit); 3458 #else 3459 is.setstate(::std::ios_base::failbit); 3460 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3461 } 3462 } 3463 else // error 3464 { 3465 #if BOOST_WORKAROUND(__GNUC__, < 3) 3466 is.setstate(::std::ios::failbit); 3467 #else 3468 is.setstate(::std::ios_base::failbit); 3469 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3470 } 3471 } 3472 } 3473 else // error 3474 { 3475 #if BOOST_WORKAROUND(__GNUC__, < 3) 3476 is.setstate(::std::ios::failbit); 3477 #else 3478 is.setstate(::std::ios_base::failbit); 3479 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3480 } 3481 } 3482 } 3483 else // read "(a" 3484 { 3485 is.putback(ch); 3486 3487 is >> a; // we extract the first component 3488 3489 if (!is.good()) goto finish; 3490 3491 is >> ch; // get the next lexeme 3492 3493 if (!is.good()) goto finish; 3494 3495 #ifdef BOOST_NO_STD_LOCALE 3496 cc = ch; 3497 #else 3498 cc = ct.narrow(ch, char()); 3499 #endif /* BOOST_NO_STD_LOCALE */ 3500 3501 if (cc == ')') // read "(a)" 3502 { 3503 o = octonion<T>(a); 3504 } 3505 else if (cc == ',') // read "(a," 3506 { 3507 is >> ch; // get the next lexeme 3508 3509 if (!is.good()) goto finish; 3510 3511 #ifdef BOOST_NO_STD_LOCALE 3512 cc = ch; 3513 #else 3514 cc = ct.narrow(ch, char()); 3515 #endif /* BOOST_NO_STD_LOCALE */ 3516 3517 if (cc == '(') // read "(a,(" 3518 { 3519 is >> ch; // get the next lexeme 3520 3521 if (!is.good()) goto finish; 3522 3523 #ifdef BOOST_NO_STD_LOCALE 3524 cc = ch; 3525 #else 3526 cc = ct.narrow(ch, char()); 3527 #endif /* BOOST_NO_STD_LOCALE */ 3528 3529 if (cc == '(') // read "(a,((" 3530 { 3531 p = ::boost::math::quaternion<T>(a); 3532 3533 is.putback(ch); 3534 3535 is.putback(ch); // we backtrack twice, with the same value 3536 3537 is >> q; // read "(a,q" 3538 3539 if (!is.good()) goto finish; 3540 3541 is >> ch; // get the next lexeme 3542 3543 if (!is.good()) goto finish; 3544 3545 #ifdef BOOST_NO_STD_LOCALE 3546 cc = ch; 3547 #else 3548 cc = ct.narrow(ch, char()); 3549 #endif /* BOOST_NO_STD_LOCALE */ 3550 3551 if (cc == ')') // read "(a,q)" 3552 { 3553 o = octonion<T>(p,q); 3554 } 3555 else // error 3556 { 3557 #if BOOST_WORKAROUND(__GNUC__, < 3) 3558 is.setstate(::std::ios::failbit); 3559 #else 3560 is.setstate(::std::ios_base::failbit); 3561 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3562 } 3563 } 3564 else // read "(a,(c" or "(a,(e" 3565 { 3566 is.putback(ch); 3567 3568 is >> c; 3569 3570 if (!is.good()) goto finish; 3571 3572 is >> ch; // get the next lexeme 3573 3574 if (!is.good()) goto finish; 3575 3576 #ifdef BOOST_NO_STD_LOCALE 3577 cc = ch; 3578 #else 3579 cc = ct.narrow(ch, char()); 3580 #endif /* BOOST_NO_STD_LOCALE */ 3581 3582 if (cc == ')') // read "(a,(c)" (ambiguity resolution) 3583 { 3584 is >> ch; // get the next lexeme 3585 3586 if (!is.good()) goto finish; 3587 3588 #ifdef BOOST_NO_STD_LOCALE 3589 cc = ch; 3590 #else 3591 cc = ct.narrow(ch, char()); 3592 #endif /* BOOST_NO_STD_LOCALE */ 3593 3594 if (cc == ')') // read "(a,(c))" 3595 { 3596 o = octonion<T>(a,b,c); 3597 } 3598 else if (cc == ',') // read "(a,(c)," 3599 { 3600 u = ::std::complex<T>(a); 3601 3602 v = ::std::complex<T>(c); 3603 3604 is >> x; // read "(a,(c),x" 3605 3606 if (!is.good()) goto finish; 3607 3608 is >> ch; // get the next lexeme 3609 3610 if (!is.good()) goto finish; 3611 3612 #ifdef BOOST_NO_STD_LOCALE 3613 cc = ch; 3614 #else 3615 cc = ct.narrow(ch, char()); 3616 #endif /* BOOST_NO_STD_LOCALE */ 3617 3618 if (cc == ')') // read "(a,(c),x)" 3619 { 3620 o = octonion<T>(u,v,x); 3621 } 3622 else if (cc == ',') // read "(a,(c),x," 3623 { 3624 is >> y; // read "(a,(c),x,y" 3625 3626 if (!is.good()) goto finish; 3627 3628 is >> ch; // get the next lexeme 3629 3630 if (!is.good()) goto finish; 3631 3632 #ifdef BOOST_NO_STD_LOCALE 3633 cc = ch; 3634 #else 3635 cc = ct.narrow(ch, char()); 3636 #endif /* BOOST_NO_STD_LOCALE */ 3637 3638 if (cc == ')') // read "(a,(c),x,y)" 3639 { 3640 o = octonion<T>(u,v,x,y); 3641 } 3642 else // error 3643 { 3644 #if BOOST_WORKAROUND(__GNUC__, < 3) 3645 is.setstate(::std::ios::failbit); 3646 #else 3647 is.setstate(::std::ios_base::failbit); 3648 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3649 } 3650 } 3651 else // error 3652 { 3653 #if BOOST_WORKAROUND(__GNUC__, < 3) 3654 is.setstate(::std::ios::failbit); 3655 #else 3656 is.setstate(::std::ios_base::failbit); 3657 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3658 } 3659 } 3660 else // error 3661 { 3662 #if BOOST_WORKAROUND(__GNUC__, < 3) 3663 is.setstate(::std::ios::failbit); 3664 #else 3665 is.setstate(::std::ios_base::failbit); 3666 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3667 } 3668 } 3669 else if (cc == ',') // read "(a,(c," or "(a,(e," 3670 { 3671 is >> ch; // get the next lexeme 3672 3673 if (!is.good()) goto finish; 3674 3675 #ifdef BOOST_NO_STD_LOCALE 3676 cc = ch; 3677 #else 3678 cc = ct.narrow(ch, char()); 3679 #endif /* BOOST_NO_STD_LOCALE */ 3680 3681 if (cc == '(') // read "(a,(e,(" (ambiguity resolution) 3682 { 3683 u = ::std::complex<T>(a); 3684 3685 x = ::std::complex<T>(c); // "c" is actually "e" 3686 3687 is.putback(ch); // we backtrack 3688 3689 is >> y; // read "(a,(e,y" 3690 3691 if (!is.good()) goto finish; 3692 3693 is >> ch; // get the next lexeme 3694 3695 if (!is.good()) goto finish; 3696 3697 #ifdef BOOST_NO_STD_LOCALE 3698 cc = ch; 3699 #else 3700 cc = ct.narrow(ch, char()); 3701 #endif /* BOOST_NO_STD_LOCALE */ 3702 3703 if (cc == ')') // read "(a,(e,y)" 3704 { 3705 is >> ch; // get the next lexeme 3706 3707 if (!is.good()) goto finish; 3708 3709 #ifdef BOOST_NO_STD_LOCALE 3710 cc = ch; 3711 #else 3712 cc = ct.narrow(ch, char()); 3713 #endif /* BOOST_NO_STD_LOCALE */ 3714 3715 if (cc == ')') // read "(a,(e,y))" 3716 { 3717 o = octonion<T>(u,v,x,y); 3718 } 3719 else // error 3720 { 3721 #if BOOST_WORKAROUND(__GNUC__, < 3) 3722 is.setstate(::std::ios::failbit); 3723 #else 3724 is.setstate(::std::ios_base::failbit); 3725 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3726 } 3727 } 3728 else // error 3729 { 3730 #if BOOST_WORKAROUND(__GNUC__, < 3) 3731 is.setstate(::std::ios::failbit); 3732 #else 3733 is.setstate(::std::ios_base::failbit); 3734 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3735 } 3736 } 3737 else // read "(a,(c,d" or "(a,(e,f" 3738 { 3739 is.putback(ch); 3740 3741 is >> d; 3742 3743 if (!is.good()) goto finish; 3744 3745 is >> ch; // get the next lexeme 3746 3747 if (!is.good()) goto finish; 3748 3749 #ifdef BOOST_NO_STD_LOCALE 3750 cc = ch; 3751 #else 3752 cc = ct.narrow(ch, char()); 3753 #endif /* BOOST_NO_STD_LOCALE */ 3754 3755 if (cc == ')') // read "(a,(c,d)" (ambiguity resolution) 3756 { 3757 is >> ch; // get the next lexeme 3758 3759 if (!is.good()) goto finish; 3760 3761 #ifdef BOOST_NO_STD_LOCALE 3762 cc = ch; 3763 #else 3764 cc = ct.narrow(ch, char()); 3765 #endif /* BOOST_NO_STD_LOCALE */ 3766 3767 if (cc == ')') // read "(a,(c,d))" 3768 { 3769 o = octonion<T>(a,b,c,d); 3770 } 3771 else if (cc == ',') // read "(a,(c,d)," 3772 { 3773 u = ::std::complex<T>(a); 3774 3775 v = ::std::complex<T>(c,d); 3776 3777 is >> x; // read "(a,(c,d),x" 3778 3779 if (!is.good()) goto finish; 3780 3781 is >> ch; // get the next lexeme 3782 3783 if (!is.good()) goto finish; 3784 3785 #ifdef BOOST_NO_STD_LOCALE 3786 cc = ch; 3787 #else 3788 cc = ct.narrow(ch, char()); 3789 #endif /* BOOST_NO_STD_LOCALE */ 3790 3791 if (cc == ')') // read "(a,(c,d),x)" 3792 { 3793 o = octonion<T>(u,v,x); 3794 } 3795 else if (cc == ',') // read "(a,(c,d),x," 3796 { 3797 is >> y; // read "(a,(c,d),x,y" 3798 3799 if (!is.good()) goto finish; 3800 3801 is >> ch; // get the next lexeme 3802 3803 if (!is.good()) goto finish; 3804 3805 #ifdef BOOST_NO_STD_LOCALE 3806 cc = ch; 3807 #else 3808 cc = ct.narrow(ch, char()); 3809 #endif /* BOOST_NO_STD_LOCALE */ 3810 3811 if (cc == ')') // read "(a,(c,d),x,y)" 3812 { 3813 o = octonion<T>(u,v,x,y); 3814 } 3815 else // error 3816 { 3817 #if BOOST_WORKAROUND(__GNUC__, < 3) 3818 is.setstate(::std::ios::failbit); 3819 #else 3820 is.setstate(::std::ios_base::failbit); 3821 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3822 } 3823 } 3824 else // error 3825 { 3826 #if BOOST_WORKAROUND(__GNUC__, < 3) 3827 is.setstate(::std::ios::failbit); 3828 #else 3829 is.setstate(::std::ios_base::failbit); 3830 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3831 } 3832 } 3833 else // error 3834 { 3835 #if BOOST_WORKAROUND(__GNUC__, < 3) 3836 is.setstate(::std::ios::failbit); 3837 #else 3838 is.setstate(::std::ios_base::failbit); 3839 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3840 } 3841 } 3842 else if (cc == ',') // read "(a,(e,f," (ambiguity resolution) 3843 { 3844 p = ::boost::math::quaternion<T>(a); 3845 3846 is >> g; // read "(a,(e,f,g" 3847 3848 if (!is.good()) goto finish; 3849 3850 is >> ch; // get the next lexeme 3851 3852 if (!is.good()) goto finish; 3853 3854 #ifdef BOOST_NO_STD_LOCALE 3855 cc = ch; 3856 #else 3857 cc = ct.narrow(ch, char()); 3858 #endif /* BOOST_NO_STD_LOCALE */ 3859 3860 if (cc == ')') // read "(a,(e,f,g)" 3861 { 3862 is >> ch; // get the next lexeme 3863 3864 if (!is.good()) goto finish; 3865 3866 #ifdef BOOST_NO_STD_LOCALE 3867 cc = ch; 3868 #else 3869 cc = ct.narrow(ch, char()); 3870 #endif /* BOOST_NO_STD_LOCALE */ 3871 3872 if (cc == ')') // read "(a,(e,f,g))" 3873 { 3874 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f" 3875 3876 o = octonion<T>(p,q); 3877 } 3878 else // error 3879 { 3880 #if BOOST_WORKAROUND(__GNUC__, < 3) 3881 is.setstate(::std::ios::failbit); 3882 #else 3883 is.setstate(::std::ios_base::failbit); 3884 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3885 } 3886 } 3887 else if (cc == ',') // read "(a,(e,f,g," 3888 { 3889 is >> h; // read "(a,(e,f,g,h" 3890 3891 if (!is.good()) goto finish; 3892 3893 is >> ch; // get the next lexeme 3894 3895 if (!is.good()) goto finish; 3896 3897 #ifdef BOOST_NO_STD_LOCALE 3898 cc = ch; 3899 #else 3900 cc = ct.narrow(ch, char()); 3901 #endif /* BOOST_NO_STD_LOCALE */ 3902 3903 if (cc == ')') // read "(a,(e,f,g,h)" 3904 { 3905 is >> ch; // get the next lexeme 3906 3907 if (!is.good()) goto finish; 3908 3909 #ifdef BOOST_NO_STD_LOCALE 3910 cc = ch; 3911 #else 3912 cc = ct.narrow(ch, char()); 3913 #endif /* BOOST_NO_STD_LOCALE */ 3914 3915 if (cc == ')') // read "(a,(e,f,g,h))" 3916 { 3917 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f" 3918 3919 o = octonion<T>(p,q); 3920 } 3921 else // error 3922 { 3923 #if BOOST_WORKAROUND(__GNUC__, < 3) 3924 is.setstate(::std::ios::failbit); 3925 #else 3926 is.setstate(::std::ios_base::failbit); 3927 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3928 } 3929 } 3930 else // error 3931 { 3932 #if BOOST_WORKAROUND(__GNUC__, < 3) 3933 is.setstate(::std::ios::failbit); 3934 #else 3935 is.setstate(::std::ios_base::failbit); 3936 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3937 } 3938 } 3939 else // error 3940 { 3941 #if BOOST_WORKAROUND(__GNUC__, < 3) 3942 is.setstate(::std::ios::failbit); 3943 #else 3944 is.setstate(::std::ios_base::failbit); 3945 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3946 } 3947 } 3948 else // error 3949 { 3950 #if BOOST_WORKAROUND(__GNUC__, < 3) 3951 is.setstate(::std::ios::failbit); 3952 #else 3953 is.setstate(::std::ios_base::failbit); 3954 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3955 } 3956 } 3957 } 3958 else // error 3959 { 3960 #if BOOST_WORKAROUND(__GNUC__, < 3) 3961 is.setstate(::std::ios::failbit); 3962 #else 3963 is.setstate(::std::ios_base::failbit); 3964 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 3965 } 3966 } 3967 } 3968 else // read "(a,b" or "(a,c" (ambiguity resolution) 3969 { 3970 is.putback(ch); 3971 3972 is >> b; 3973 3974 if (!is.good()) goto finish; 3975 3976 is >> ch; // get the next lexeme 3977 3978 if (!is.good()) goto finish; 3979 3980 #ifdef BOOST_NO_STD_LOCALE 3981 cc = ch; 3982 #else 3983 cc = ct.narrow(ch, char()); 3984 #endif /* BOOST_NO_STD_LOCALE */ 3985 3986 if (cc == ')') // read "(a,b)" (ambiguity resolution) 3987 { 3988 o = octonion<T>(a,b); 3989 } 3990 else if (cc == ',') // read "(a,b," or "(a,c," 3991 { 3992 is >> ch; // get the next lexeme 3993 3994 if (!is.good()) goto finish; 3995 3996 #ifdef BOOST_NO_STD_LOCALE 3997 cc = ch; 3998 #else 3999 cc = ct.narrow(ch, char()); 4000 #endif /* BOOST_NO_STD_LOCALE */ 4001 4002 if (cc == '(') // read "(a,c,(" (ambiguity resolution) 4003 { 4004 u = ::std::complex<T>(a); 4005 4006 v = ::std::complex<T>(b); // "b" is actually "c" 4007 4008 is.putback(ch); // we backtrack 4009 4010 is >> x; // read "(a,c,x" 4011 4012 if (!is.good()) goto finish; 4013 4014 is >> ch; // get the next lexeme 4015 4016 if (!is.good()) goto finish; 4017 4018 #ifdef BOOST_NO_STD_LOCALE 4019 cc = ch; 4020 #else 4021 cc = ct.narrow(ch, char()); 4022 #endif /* BOOST_NO_STD_LOCALE */ 4023 4024 if (cc == ')') // read "(a,c,x)" 4025 { 4026 o = octonion<T>(u,v,x); 4027 } 4028 else if (cc == ',') // read "(a,c,x," 4029 { 4030 is >> y; // read "(a,c,x,y" // read "(a,c,x" 4031 4032 if (!is.good()) goto finish; 4033 4034 is >> ch; // get the next lexeme 4035 4036 if (!is.good()) goto finish; 4037 4038 #ifdef BOOST_NO_STD_LOCALE 4039 cc = ch; 4040 #else 4041 cc = ct.narrow(ch, char()); 4042 #endif /* BOOST_NO_STD_LOCALE */ 4043 4044 if (cc == ')') // read "(a,c,x,y)" 4045 { 4046 o = octonion<T>(u,v,x,y); 4047 } 4048 else // error 4049 { 4050 #if BOOST_WORKAROUND(__GNUC__, < 3) 4051 is.setstate(::std::ios::failbit); 4052 #else 4053 is.setstate(::std::ios_base::failbit); 4054 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4055 } 4056 } 4057 else // error 4058 { 4059 #if BOOST_WORKAROUND(__GNUC__, < 3) 4060 is.setstate(::std::ios::failbit); 4061 #else 4062 is.setstate(::std::ios_base::failbit); 4063 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4064 } 4065 } 4066 else // read "(a,b,c" or "(a,c,e" 4067 { 4068 is.putback(ch); 4069 4070 is >> c; 4071 4072 if (!is.good()) goto finish; 4073 4074 is >> ch; // get the next lexeme 4075 4076 if (!is.good()) goto finish; 4077 4078 #ifdef BOOST_NO_STD_LOCALE 4079 cc = ch; 4080 #else 4081 cc = ct.narrow(ch, char()); 4082 #endif /* BOOST_NO_STD_LOCALE */ 4083 4084 if (cc == ')') // read "(a,b,c)" (ambiguity resolution) 4085 { 4086 o = octonion<T>(a,b,c); 4087 } 4088 else if (cc == ',') // read "(a,b,c," or "(a,c,e," 4089 { 4090 is >> ch; // get the next lexeme 4091 4092 if (!is.good()) goto finish; 4093 4094 #ifdef BOOST_NO_STD_LOCALE 4095 cc = ch; 4096 #else 4097 cc = ct.narrow(ch, char()); 4098 #endif /* BOOST_NO_STD_LOCALE */ 4099 4100 if (cc == '(') // read "(a,c,e,(") (ambiguity resolution) 4101 { 4102 u = ::std::complex<T>(a); 4103 4104 v = ::std::complex<T>(b); // "b" is actually "c" 4105 4106 x = ::std::complex<T>(c); // "c" is actually "e" 4107 4108 is.putback(ch); // we backtrack 4109 4110 is >> y; // read "(a,c,e,y" 4111 4112 if (!is.good()) goto finish; 4113 4114 is >> ch; // get the next lexeme 4115 4116 if (!is.good()) goto finish; 4117 4118 #ifdef BOOST_NO_STD_LOCALE 4119 cc = ch; 4120 #else 4121 cc = ct.narrow(ch, char()); 4122 #endif /* BOOST_NO_STD_LOCALE */ 4123 4124 if (cc == ')') // read "(a,c,e,y)" 4125 { 4126 o = octonion<T>(u,v,x,y); 4127 } 4128 else // error 4129 { 4130 #if BOOST_WORKAROUND(__GNUC__, < 3) 4131 is.setstate(::std::ios::failbit); 4132 #else 4133 is.setstate(::std::ios_base::failbit); 4134 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4135 } 4136 } 4137 else // read "(a,b,c,d" (ambiguity resolution) 4138 { 4139 is.putback(ch); // we backtrack 4140 4141 is >> d; 4142 4143 if (!is.good()) goto finish; 4144 4145 is >> ch; // get the next lexeme 4146 4147 if (!is.good()) goto finish; 4148 4149 #ifdef BOOST_NO_STD_LOCALE 4150 cc = ch; 4151 #else 4152 cc = ct.narrow(ch, char()); 4153 #endif /* BOOST_NO_STD_LOCALE */ 4154 4155 if (cc == ')') // read "(a,b,c,d)" 4156 { 4157 o = octonion<T>(a,b,c,d); 4158 } 4159 else if (cc == ',') // read "(a,b,c,d," 4160 { 4161 is >> e; // read "(a,b,c,d,e" 4162 4163 if (!is.good()) goto finish; 4164 4165 is >> ch; // get the next lexeme 4166 4167 if (!is.good()) goto finish; 4168 4169 #ifdef BOOST_NO_STD_LOCALE 4170 cc = ch; 4171 #else 4172 cc = ct.narrow(ch, char()); 4173 #endif /* BOOST_NO_STD_LOCALE */ 4174 4175 if (cc == ')') // read "(a,b,c,d,e)" 4176 { 4177 o = octonion<T>(a,b,c,d,e); 4178 } 4179 else if (cc == ',') // read "(a,b,c,d,e," 4180 { 4181 is >> f; // read "(a,b,c,d,e,f" 4182 4183 if (!is.good()) goto finish; 4184 4185 is >> ch; // get the next lexeme 4186 4187 if (!is.good()) goto finish; 4188 4189 #ifdef BOOST_NO_STD_LOCALE 4190 cc = ch; 4191 #else 4192 cc = ct.narrow(ch, char()); 4193 #endif /* BOOST_NO_STD_LOCALE */ 4194 4195 if (cc == ')') // read "(a,b,c,d,e,f)" 4196 { 4197 o = octonion<T>(a,b,c,d,e,f); 4198 } 4199 else if (cc == ',') // read "(a,b,c,d,e,f," 4200 { 4201 is >> g; // read "(a,b,c,d,e,f,g" // read "(a,b,c,d,e,f" 4202 4203 if (!is.good()) goto finish; 4204 4205 is >> ch; // get the next lexeme 4206 4207 if (!is.good()) goto finish; 4208 4209 #ifdef BOOST_NO_STD_LOCALE 4210 cc = ch; 4211 #else 4212 cc = ct.narrow(ch, char()); 4213 #endif /* BOOST_NO_STD_LOCALE */ 4214 4215 if (cc == ')') // read "(a,b,c,d,e,f,g)" 4216 { 4217 o = octonion<T>(a,b,c,d,e,f,g); 4218 } 4219 else if (cc == ',') // read "(a,b,c,d,e,f,g," 4220 { 4221 is >> h; // read "(a,b,c,d,e,f,g,h" // read "(a,b,c,d,e,f,g" // read "(a,b,c,d,e,f" 4222 4223 if (!is.good()) goto finish; 4224 4225 is >> ch; // get the next lexeme 4226 4227 if (!is.good()) goto finish; 4228 4229 #ifdef BOOST_NO_STD_LOCALE 4230 cc = ch; 4231 #else 4232 cc = ct.narrow(ch, char()); 4233 #endif /* BOOST_NO_STD_LOCALE */ 4234 4235 if (cc == ')') // read "(a,b,c,d,e,f,g,h)" 4236 { 4237 o = octonion<T>(a,b,c,d,e,f,g,h); 4238 } 4239 else // error 4240 { 4241 #if BOOST_WORKAROUND(__GNUC__, < 3) 4242 is.setstate(::std::ios::failbit); 4243 #else 4244 is.setstate(::std::ios_base::failbit); 4245 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4246 } 4247 } 4248 else // error 4249 { 4250 #if BOOST_WORKAROUND(__GNUC__, < 3) 4251 is.setstate(::std::ios::failbit); 4252 #else 4253 is.setstate(::std::ios_base::failbit); 4254 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4255 } 4256 } 4257 else // error 4258 { 4259 #if BOOST_WORKAROUND(__GNUC__, < 3) 4260 is.setstate(::std::ios::failbit); 4261 #else 4262 is.setstate(::std::ios_base::failbit); 4263 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4264 } 4265 } 4266 else // error 4267 { 4268 #if BOOST_WORKAROUND(__GNUC__, < 3) 4269 is.setstate(::std::ios::failbit); 4270 #else 4271 is.setstate(::std::ios_base::failbit); 4272 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4273 } 4274 } 4275 else // error 4276 { 4277 #if BOOST_WORKAROUND(__GNUC__, < 3) 4278 is.setstate(::std::ios::failbit); 4279 #else 4280 is.setstate(::std::ios_base::failbit); 4281 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4282 } 4283 } 4284 } 4285 else // error 4286 { 4287 #if BOOST_WORKAROUND(__GNUC__, < 3) 4288 is.setstate(::std::ios::failbit); 4289 #else 4290 is.setstate(::std::ios_base::failbit); 4291 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4292 } 4293 } 4294 } 4295 else // error 4296 { 4297 #if BOOST_WORKAROUND(__GNUC__, < 3) 4298 is.setstate(::std::ios::failbit); 4299 #else 4300 is.setstate(::std::ios_base::failbit); 4301 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4302 } 4303 } 4304 } 4305 else // error 4306 { 4307 #if BOOST_WORKAROUND(__GNUC__, < 3) 4308 is.setstate(::std::ios::failbit); 4309 #else 4310 is.setstate(::std::ios_base::failbit); 4311 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4312 } 4313 } 4314 } 4315 else // format: a 4316 { 4317 is.putback(ch); 4318 4319 is >> a; // we extract the first component 4320 4321 if (!is.good()) goto finish; 4322 4323 o = octonion<T>(a); 4324 } 4325 4326 finish: 4327 return(is); 4328 } 4329 4330 4331 #if BOOST_WORKAROUND(__GNUC__, < 3) 4332 template<typename T> operator <<(::std::ostream & os,octonion<T> const & o)4333 ::std::ostream & operator << ( ::std::ostream & os, 4334 octonion<T> const & o) 4335 #else 4336 template<typename T, typename charT, class traits> 4337 ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os, 4338 octonion<T> const & o) 4339 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4340 { 4341 #if BOOST_WORKAROUND(__GNUC__, < 3) 4342 ::std::ostringstream s; 4343 #else 4344 ::std::basic_ostringstream<charT,traits> s; 4345 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4346 4347 s.flags(os.flags()); 4348 #ifdef BOOST_NO_STD_LOCALE 4349 #else 4350 s.imbue(os.getloc()); 4351 #endif /* BOOST_NO_STD_LOCALE */ 4352 s.precision(os.precision()); 4353 4354 s << '(' << o.R_component_1() << ',' 4355 << o.R_component_2() << ',' 4356 << o.R_component_3() << ',' 4357 << o.R_component_4() << ',' 4358 << o.R_component_5() << ',' 4359 << o.R_component_6() << ',' 4360 << o.R_component_7() << ',' 4361 << o.R_component_8() << ')'; 4362 4363 return os << s.str(); 4364 } 4365 4366 4367 // values 4368 4369 template<typename T> real(octonion<T> const & o)4370 inline T real(octonion<T> const & o) 4371 { 4372 return(o.real()); 4373 } 4374 4375 4376 template<typename T> unreal(octonion<T> const & o)4377 inline octonion<T> unreal(octonion<T> const & o) 4378 { 4379 return(o.unreal()); 4380 } 4381 4382 4383 #define BOOST_OCTONION_VALARRAY_LOADER \ 4384 using ::std::valarray; \ 4385 \ 4386 valarray<T> temp(8); \ 4387 \ 4388 temp[0] = o.R_component_1(); \ 4389 temp[1] = o.R_component_2(); \ 4390 temp[2] = o.R_component_3(); \ 4391 temp[3] = o.R_component_4(); \ 4392 temp[4] = o.R_component_5(); \ 4393 temp[5] = o.R_component_6(); \ 4394 temp[6] = o.R_component_7(); \ 4395 temp[7] = o.R_component_8(); 4396 4397 4398 template<typename T> sup(octonion<T> const & o)4399 inline T sup(octonion<T> const & o) 4400 { 4401 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP 4402 using ::std::abs; 4403 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ 4404 4405 BOOST_OCTONION_VALARRAY_LOADER 4406 4407 #if BOOST_WORKAROUND(__GNUC__, < 3) 4408 return((BOOST_GET_VALARRAY(T, abs(temp)).max)()); 4409 #else 4410 return((abs(temp).max)()); 4411 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4412 } 4413 4414 4415 template<typename T> l1(octonion<T> const & o)4416 inline T l1(octonion<T> const & o) 4417 { 4418 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP 4419 using ::std::abs; 4420 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ 4421 4422 BOOST_OCTONION_VALARRAY_LOADER 4423 4424 #if BOOST_WORKAROUND(__GNUC__, < 3) 4425 return(BOOST_GET_VALARRAY(T, abs(temp)).sum()); 4426 #else 4427 return(abs(temp).sum()); 4428 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4429 } 4430 4431 4432 template<typename T> abs(const octonion<T> & o)4433 inline T abs(const octonion<T> & o) 4434 { 4435 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP 4436 using ::std::abs; 4437 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */ 4438 4439 using ::std::sqrt; 4440 4441 BOOST_OCTONION_VALARRAY_LOADER 4442 4443 #if BOOST_WORKAROUND(__GNUC__, < 3) 4444 T maxim = (BOOST_GET_VALARRAY(T,abs(temp)).max)(); // overflow protection 4445 #else 4446 T maxim = (abs(temp).max)(); // overflow protection 4447 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4448 4449 if (maxim == static_cast<T>(0)) 4450 { 4451 return(maxim); 4452 } 4453 else 4454 { 4455 T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions 4456 4457 temp *= mixam; 4458 4459 temp *= temp; 4460 4461 return(maxim*sqrt(temp.sum())); 4462 } 4463 4464 //return(::std::sqrt(norm(o))); 4465 } 4466 4467 4468 #undef BOOST_OCTONION_VALARRAY_LOADER 4469 4470 4471 // Note: This is the Cayley norm, not the Euclidian norm... 4472 4473 template<typename T> norm(octonion<T> const & o)4474 inline T norm(octonion<T> const & o) 4475 { 4476 return(real(o*conj(o))); 4477 } 4478 4479 4480 template<typename T> conj(octonion<T> const & o)4481 inline octonion<T> conj(octonion<T> const & o) 4482 { 4483 return(octonion<T>( +o.R_component_1(), 4484 -o.R_component_2(), 4485 -o.R_component_3(), 4486 -o.R_component_4(), 4487 -o.R_component_5(), 4488 -o.R_component_6(), 4489 -o.R_component_7(), 4490 -o.R_component_8())); 4491 } 4492 4493 4494 // Note: There is little point, for the octonions, to introduce the equivalents 4495 // to the complex "arg" and the quaternionic "cylindropolar". 4496 4497 4498 template<typename T> spherical(T const & rho,T const & theta,T const & phi1,T const & phi2,T const & phi3,T const & phi4,T const & phi5,T const & phi6)4499 inline octonion<T> spherical(T const & rho, 4500 T const & theta, 4501 T const & phi1, 4502 T const & phi2, 4503 T const & phi3, 4504 T const & phi4, 4505 T const & phi5, 4506 T const & phi6) 4507 { 4508 using ::std::cos; 4509 using ::std::sin; 4510 4511 //T a = cos(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6); 4512 //T b = sin(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6); 4513 //T c = sin(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6); 4514 //T d = sin(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6); 4515 //T e = sin(phi3)*cos(phi4)*cos(phi5)*cos(phi6); 4516 //T f = sin(phi4)*cos(phi5)*cos(phi6); 4517 //T g = sin(phi5)*cos(phi6); 4518 //T h = sin(phi6); 4519 4520 T courrant = static_cast<T>(1); 4521 4522 T h = sin(phi6); 4523 4524 courrant *= cos(phi6); 4525 4526 T g = sin(phi5)*courrant; 4527 4528 courrant *= cos(phi5); 4529 4530 T f = sin(phi4)*courrant; 4531 4532 courrant *= cos(phi4); 4533 4534 T e = sin(phi3)*courrant; 4535 4536 courrant *= cos(phi3); 4537 4538 T d = sin(phi2)*courrant; 4539 4540 courrant *= cos(phi2); 4541 4542 T c = sin(phi1)*courrant; 4543 4544 courrant *= cos(phi1); 4545 4546 T b = sin(theta)*courrant; 4547 T a = cos(theta)*courrant; 4548 4549 return(rho*octonion<T>(a,b,c,d,e,f,g,h)); 4550 } 4551 4552 4553 template<typename T> multipolar(T const & rho1,T const & theta1,T const & rho2,T const & theta2,T const & rho3,T const & theta3,T const & rho4,T const & theta4)4554 inline octonion<T> multipolar(T const & rho1, 4555 T const & theta1, 4556 T const & rho2, 4557 T const & theta2, 4558 T const & rho3, 4559 T const & theta3, 4560 T const & rho4, 4561 T const & theta4) 4562 { 4563 using ::std::cos; 4564 using ::std::sin; 4565 4566 T a = rho1*cos(theta1); 4567 T b = rho1*sin(theta1); 4568 T c = rho2*cos(theta2); 4569 T d = rho2*sin(theta2); 4570 T e = rho3*cos(theta3); 4571 T f = rho3*sin(theta3); 4572 T g = rho4*cos(theta4); 4573 T h = rho4*sin(theta4); 4574 4575 return(octonion<T>(a,b,c,d,e,f,g,h)); 4576 } 4577 4578 4579 template<typename T> cylindrical(T const & r,T const & angle,T const & h1,T const & h2,T const & h3,T const & h4,T const & h5,T const & h6)4580 inline octonion<T> cylindrical(T const & r, 4581 T const & angle, 4582 T const & h1, 4583 T const & h2, 4584 T const & h3, 4585 T const & h4, 4586 T const & h5, 4587 T const & h6) 4588 { 4589 using ::std::cos; 4590 using ::std::sin; 4591 4592 T a = r*cos(angle); 4593 T b = r*sin(angle); 4594 4595 return(octonion<T>(a,b,h1,h2,h3,h4,h5,h6)); 4596 } 4597 4598 4599 template<typename T> exp(octonion<T> const & o)4600 inline octonion<T> exp(octonion<T> const & o) 4601 { 4602 using ::std::exp; 4603 using ::std::cos; 4604 4605 using ::boost::math::sinc_pi; 4606 4607 T u = exp(real(o)); 4608 4609 T z = abs(unreal(o)); 4610 4611 T w = sinc_pi(z); 4612 4613 return(u*octonion<T>(cos(z), 4614 w*o.R_component_2(), w*o.R_component_3(), 4615 w*o.R_component_4(), w*o.R_component_5(), 4616 w*o.R_component_6(), w*o.R_component_7(), 4617 w*o.R_component_8())); 4618 } 4619 4620 4621 template<typename T> cos(octonion<T> const & o)4622 inline octonion<T> cos(octonion<T> const & o) 4623 { 4624 using ::std::sin; 4625 using ::std::cos; 4626 using ::std::cosh; 4627 4628 using ::boost::math::sinhc_pi; 4629 4630 T z = abs(unreal(o)); 4631 4632 T w = -sin(o.real())*sinhc_pi(z); 4633 4634 return(octonion<T>(cos(o.real())*cosh(z), 4635 w*o.R_component_2(), w*o.R_component_3(), 4636 w*o.R_component_4(), w*o.R_component_5(), 4637 w*o.R_component_6(), w*o.R_component_7(), 4638 w*o.R_component_8())); 4639 } 4640 4641 4642 template<typename T> sin(octonion<T> const & o)4643 inline octonion<T> sin(octonion<T> const & o) 4644 { 4645 using ::std::sin; 4646 using ::std::cos; 4647 using ::std::cosh; 4648 4649 using ::boost::math::sinhc_pi; 4650 4651 T z = abs(unreal(o)); 4652 4653 T w = +cos(o.real())*sinhc_pi(z); 4654 4655 return(octonion<T>(sin(o.real())*cosh(z), 4656 w*o.R_component_2(), w*o.R_component_3(), 4657 w*o.R_component_4(), w*o.R_component_5(), 4658 w*o.R_component_6(), w*o.R_component_7(), 4659 w*o.R_component_8())); 4660 } 4661 4662 4663 template<typename T> tan(octonion<T> const & o)4664 inline octonion<T> tan(octonion<T> const & o) 4665 { 4666 return(sin(o)/cos(o)); 4667 } 4668 4669 4670 template<typename T> cosh(octonion<T> const & o)4671 inline octonion<T> cosh(octonion<T> const & o) 4672 { 4673 return((exp(+o)+exp(-o))/static_cast<T>(2)); 4674 } 4675 4676 4677 template<typename T> sinh(octonion<T> const & o)4678 inline octonion<T> sinh(octonion<T> const & o) 4679 { 4680 return((exp(+o)-exp(-o))/static_cast<T>(2)); 4681 } 4682 4683 4684 template<typename T> tanh(octonion<T> const & o)4685 inline octonion<T> tanh(octonion<T> const & o) 4686 { 4687 return(sinh(o)/cosh(o)); 4688 } 4689 4690 4691 template<typename T> pow(octonion<T> const & o,int n)4692 octonion<T> pow(octonion<T> const & o, 4693 int n) 4694 { 4695 if (n > 1) 4696 { 4697 int m = n>>1; 4698 4699 octonion<T> result = pow(o, m); 4700 4701 result *= result; 4702 4703 if (n != (m<<1)) 4704 { 4705 result *= o; // n odd 4706 } 4707 4708 return(result); 4709 } 4710 else if (n == 1) 4711 { 4712 return(o); 4713 } 4714 else if (n == 0) 4715 { 4716 return(octonion<T>(static_cast<T>(1))); 4717 } 4718 else /* n < 0 */ 4719 { 4720 return(pow(octonion<T>(static_cast<T>(1))/o,-n)); 4721 } 4722 } 4723 4724 4725 // helper templates for converting copy constructors (definition) 4726 4727 namespace detail 4728 { 4729 4730 template< typename T, 4731 typename U 4732 > octonion_type_converter(octonion<U> const & rhs)4733 octonion<T> octonion_type_converter(octonion<U> const & rhs) 4734 { 4735 return(octonion<T>( static_cast<T>(rhs.R_component_1()), 4736 static_cast<T>(rhs.R_component_2()), 4737 static_cast<T>(rhs.R_component_3()), 4738 static_cast<T>(rhs.R_component_4()), 4739 static_cast<T>(rhs.R_component_5()), 4740 static_cast<T>(rhs.R_component_6()), 4741 static_cast<T>(rhs.R_component_7()), 4742 static_cast<T>(rhs.R_component_8()))); 4743 } 4744 } 4745 } 4746 } 4747 4748 4749 #if BOOST_WORKAROUND(__GNUC__, < 3) 4750 #undef BOOST_GET_VALARRAY 4751 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */ 4752 4753 4754 #endif /* BOOST_OCTONION_HPP */ 4755