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