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