4251 lines · plain
1// boost octonion.hpp header file2 3// (C) Copyright Hubert Holin 2001.4// Distributed under the Boost Software License, Version 1.0. (See5// accompanying file LICENSE_1_0.txt or copy at6// 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_HPP12#define BOOST_OCTONION_HPP13 14#include <boost/math/quaternion.hpp>15#include <valarray>16 17 18namespace boost19{20 namespace math21 {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 // LCOV_EXCL_START178 // No code coverage for the generic case, like std::complex,179 // the The behavior of octonion is unspecified if T is not180 // one of float, double or long double.181 182 template<typename T>183 class octonion184 {185 public:186 187 using value_type = T;188 189 // constructor for O seen as R^8190 // (also default constructor)191 192 explicit octonion( T const & requested_a = T(),193 T const & requested_b = T(),194 T const & requested_c = T(),195 T const & requested_d = T(),196 T const & requested_e = T(),197 T const & requested_f = T(),198 T const & requested_g = T(),199 T const & requested_h = T())200 : a(requested_a),201 b(requested_b),202 c(requested_c),203 d(requested_d),204 e(requested_e),205 f(requested_f),206 g(requested_g),207 h(requested_h)208 {209 // nothing to do!210 }211 212 213 // constructor for H seen as C^4214 215 explicit octonion( ::std::complex<T> const & z0,216 ::std::complex<T> const & z1 = ::std::complex<T>(),217 ::std::complex<T> const & z2 = ::std::complex<T>(),218 ::std::complex<T> const & z3 = ::std::complex<T>())219 : a(z0.real()),220 b(z0.imag()),221 c(z1.real()),222 d(z1.imag()),223 e(z2.real()),224 f(z2.imag()),225 g(z3.real()),226 h(z3.imag())227 {228 // nothing to do!229 }230 231 232 // constructor for O seen as H^2233 234 explicit octonion( ::boost::math::quaternion<T> const & q0,235 ::boost::math::quaternion<T> const & q1 = ::boost::math::quaternion<T>())236 : a(q0.R_component_1()),237 b(q0.R_component_2()),238 c(q0.R_component_3()),239 d(q0.R_component_4()),240 e(q1.R_component_1()),241 f(q1.R_component_2()),242 g(q1.R_component_3()),243 h(q1.R_component_4())244 {245 // nothing to do!246 }247 248 249 // UNtemplated copy constructor250 octonion(const octonion&) = default;251 252 253 // templated copy constructor254 255 template<typename X>256 explicit octonion(octonion<X> const & a_recopier)257 : a(static_cast<T>(a_recopier.R_component_1())),258 b(static_cast<T>(a_recopier.R_component_2())),259 c(static_cast<T>(a_recopier.R_component_3())),260 d(static_cast<T>(a_recopier.R_component_4())),261 e(static_cast<T>(a_recopier.R_component_5())),262 f(static_cast<T>(a_recopier.R_component_6())),263 g(static_cast<T>(a_recopier.R_component_7())),264 h(static_cast<T>(a_recopier.R_component_8()))265 {266 // nothing to do!267 }268 269 270 // destructor271 ~octonion() = default;272 273 274 // accessors275 //276 // Note: Like complex number, octonions do have a meaningful notion of "real part",277 // but unlike them there is no meaningful notion of "imaginary part".278 // Instead there is an "unreal part" which itself is an octonion, and usually279 // nothing simpler (as opposed to the complex number case).280 // However, for practicality, there are accessors for the other components281 // (these are necessary for the templated copy constructor, for instance).282 283 BOOST_OCTONION_ACCESSOR_GENERATOR(T)284 285 // assignment operators286 287 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(T)288 289 // other assignment-related operators290 //291 // NOTE: Octonion multiplication is *NOT* commutative;292 // symbolically, "q *= rhs;" means "q = q * rhs;"293 // and "q /= rhs;" means "q = q * inverse_of(rhs);";294 // octonion multiplication is also *NOT* associative295 296 octonion<T> & operator += (T const & rhs)297 {298 T at = a + rhs; // exception guard299 300 a = at;301 302 return(*this);303 }304 305 306 octonion<T> & operator += (::std::complex<T> const & rhs)307 {308 T at = a + rhs.real(); // exception guard309 T bt = b + rhs.imag(); // exception guard310 311 a = at;312 b = bt;313 314 return(*this);315 }316 317 318 octonion<T> & operator += (::boost::math::quaternion<T> const & rhs)319 {320 T at = a + rhs.R_component_1(); // exception guard321 T bt = b + rhs.R_component_2(); // exception guard322 T ct = c + rhs.R_component_3(); // exception guard323 T dt = d + rhs.R_component_4(); // exception guard324 325 a = at;326 b = bt;327 c = ct;328 d = dt;329 330 return(*this);331 }332 333 334 template<typename X>335 octonion<T> & operator += (octonion<X> const & rhs)336 {337 T at = a + static_cast<T>(rhs.R_component_1()); // exception guard338 T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard339 T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard340 T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard341 T et = e + static_cast<T>(rhs.R_component_5()); // exception guard342 T ft = f + static_cast<T>(rhs.R_component_6()); // exception guard343 T gt = g + static_cast<T>(rhs.R_component_7()); // exception guard344 T ht = h + static_cast<T>(rhs.R_component_8()); // exception guard345 346 a = at;347 b = bt;348 c = ct;349 d = dt;350 e = et;351 f = ft;352 g = gt;353 h = ht;354 355 return(*this);356 }357 358 359 360 octonion<T> & operator -= (T const & rhs)361 {362 T at = a - rhs; // exception guard363 364 a = at;365 366 return(*this);367 }368 369 370 octonion<T> & operator -= (::std::complex<T> const & rhs)371 {372 T at = a - rhs.real(); // exception guard373 T bt = b - rhs.imag(); // exception guard374 375 a = at;376 b = bt;377 378 return(*this);379 }380 381 382 octonion<T> & operator -= (::boost::math::quaternion<T> const & rhs)383 {384 T at = a - rhs.R_component_1(); // exception guard385 T bt = b - rhs.R_component_2(); // exception guard386 T ct = c - rhs.R_component_3(); // exception guard387 T dt = d - rhs.R_component_4(); // exception guard388 389 a = at;390 b = bt;391 c = ct;392 d = dt;393 394 return(*this);395 }396 397 398 template<typename X>399 octonion<T> & operator -= (octonion<X> const & rhs)400 {401 T at = a - static_cast<T>(rhs.R_component_1()); // exception guard402 T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard403 T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard404 T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard405 T et = e - static_cast<T>(rhs.R_component_5()); // exception guard406 T ft = f - static_cast<T>(rhs.R_component_6()); // exception guard407 T gt = g - static_cast<T>(rhs.R_component_7()); // exception guard408 T ht = h - static_cast<T>(rhs.R_component_8()); // exception guard409 410 a = at;411 b = bt;412 c = ct;413 d = dt;414 e = et;415 f = ft;416 g = gt;417 h = ht;418 419 return(*this);420 }421 422 423 octonion<T> & operator *= (T const & rhs)424 {425 T at = a * rhs; // exception guard426 T bt = b * rhs; // exception guard427 T ct = c * rhs; // exception guard428 T dt = d * rhs; // exception guard429 T et = e * rhs; // exception guard430 T ft = f * rhs; // exception guard431 T gt = g * rhs; // exception guard432 T ht = h * rhs; // exception guard433 434 a = at;435 b = bt;436 c = ct;437 d = dt;438 e = et;439 f = ft;440 g = gt;441 h = ht;442 443 return(*this);444 }445 446 447 octonion<T> & operator *= (::std::complex<T> const & rhs)448 {449 T ar = rhs.real();450 T br = rhs.imag();451 452 T at = +a*ar-b*br;453 T bt = +a*br+b*ar;454 T ct = +c*ar+d*br;455 T dt = -c*br+d*ar;456 T et = +e*ar+f*br;457 T ft = -e*br+f*ar;458 T gt = +g*ar-h*br;459 T ht = +g*br+h*ar;460 461 a = at;462 b = bt;463 c = ct;464 d = dt;465 e = et;466 f = ft;467 g = gt;468 h = ht;469 470 return(*this);471 }472 473 474 octonion<T> & operator *= (::boost::math::quaternion<T> const & rhs)475 {476 T ar = rhs.R_component_1();477 T br = rhs.R_component_2();478 T cr = rhs.R_component_2();479 T dr = rhs.R_component_2();480 481 T at = +a*ar-b*br-c*cr-d*dr;482 T bt = +a*br+b*ar+c*dr-d*cr;483 T ct = +a*cr-b*dr+c*ar+d*br;484 T dt = +a*dr+b*cr-c*br+d*ar;485 T et = +e*ar+f*br+g*cr+h*dr;486 T ft = -e*br+f*ar-g*dr+h*cr;487 T gt = -e*cr+f*dr+g*ar-h*br;488 T ht = -e*dr-f*cr+g*br+h*ar;489 490 a = at;491 b = bt;492 c = ct;493 d = dt;494 e = et;495 f = ft;496 g = gt;497 h = ht;498 499 return(*this);500 }501 502 503 template<typename X>504 octonion<T> & operator *= (octonion<X> const & rhs)505 {506 T ar = static_cast<T>(rhs.R_component_1());507 T br = static_cast<T>(rhs.R_component_2());508 T cr = static_cast<T>(rhs.R_component_3());509 T dr = static_cast<T>(rhs.R_component_4());510 T er = static_cast<T>(rhs.R_component_5());511 T fr = static_cast<T>(rhs.R_component_6());512 T gr = static_cast<T>(rhs.R_component_7());513 T hr = static_cast<T>(rhs.R_component_8());514 515 T at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr;516 T bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr;517 T ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr;518 T dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er;519 T et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr;520 T ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr;521 T gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br;522 T ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar;523 524 a = at;525 b = bt;526 c = ct;527 d = dt;528 e = et;529 f = ft;530 g = gt;531 h = ht;532 533 return(*this);534 }535 536 537 octonion<T> & operator /= (T const & rhs)538 {539 T at = a / rhs; // exception guard540 T bt = b / rhs; // exception guard541 T ct = c / rhs; // exception guard542 T dt = d / rhs; // exception guard543 T et = e / rhs; // exception guard544 T ft = f / rhs; // exception guard545 T gt = g / rhs; // exception guard546 T ht = h / rhs; // exception guard547 548 a = at;549 b = bt;550 c = ct;551 d = dt;552 e = et;553 f = ft;554 g = gt;555 h = ht;556 557 return(*this);558 }559 560 561 octonion<T> & operator /= (::std::complex<T> const & rhs)562 {563 T ar = rhs.real();564 T br = rhs.imag();565 566 T denominator = ar*ar+br*br;567 568 T at = (+a*ar-b*br)/denominator;569 T bt = (-a*br+b*ar)/denominator;570 T ct = (+c*ar-d*br)/denominator;571 T dt = (+c*br+d*ar)/denominator;572 T et = (+e*ar-f*br)/denominator;573 T ft = (+e*br+f*ar)/denominator;574 T gt = (+g*ar+h*br)/denominator;575 T ht = (+g*br+h*ar)/denominator;576 577 a = at;578 b = bt;579 c = ct;580 d = dt;581 e = et;582 f = ft;583 g = gt;584 h = ht;585 586 return(*this);587 }588 589 590 octonion<T> & operator /= (::boost::math::quaternion<T> const & rhs)591 {592 T ar = rhs.R_component_1();593 T br = rhs.R_component_2();594 T cr = rhs.R_component_2();595 T dr = rhs.R_component_2();596 597 T denominator = ar*ar+br*br+cr*cr+dr*dr;598 599 T at = (+a*ar+b*br+c*cr+d*dr)/denominator;600 T bt = (-a*br+b*ar-c*dr+d*cr)/denominator;601 T ct = (-a*cr+b*dr+c*ar-d*br)/denominator;602 T dt = (-a*dr-b*cr+c*br+d*ar)/denominator;603 T et = (+e*ar-f*br-g*cr-h*dr)/denominator;604 T ft = (+e*br+f*ar+g*dr-h*cr)/denominator;605 T gt = (+e*cr-f*dr+g*ar+h*br)/denominator;606 T ht = (+e*dr+f*cr-g*br+h*ar)/denominator;607 608 a = at;609 b = bt;610 c = ct;611 d = dt;612 e = et;613 f = ft;614 g = gt;615 h = ht;616 617 return(*this);618 }619 620 621 template<typename X>622 octonion<T> & operator /= (octonion<X> const & rhs)623 {624 T ar = static_cast<T>(rhs.R_component_1());625 T br = static_cast<T>(rhs.R_component_2());626 T cr = static_cast<T>(rhs.R_component_3());627 T dr = static_cast<T>(rhs.R_component_4());628 T er = static_cast<T>(rhs.R_component_5());629 T fr = static_cast<T>(rhs.R_component_6());630 T gr = static_cast<T>(rhs.R_component_7());631 T hr = static_cast<T>(rhs.R_component_8());632 633 T denominator = ar*ar+br*br+cr*cr+dr*dr+er*er+fr*fr+gr*gr+hr*hr;634 635 T at = (+a*ar+b*br+c*cr+d*dr+e*er+f*fr+g*gr+h*hr)/denominator;636 T bt = (-a*br+b*ar-c*dr+d*cr-e*fr+f*er+g*hr-h*gr)/denominator;637 T ct = (-a*cr+b*dr+c*ar-d*br-e*gr-f*hr+g*er+h*fr)/denominator;638 T dt = (-a*dr-b*cr+c*br+d*ar-e*hr+f*gr-g*fr+h*er)/denominator;639 T et = (-a*er+b*fr+c*gr+d*hr+e*ar-f*br-g*cr-h*dr)/denominator;640 T ft = (-a*fr-b*er+c*hr-d*gr+e*br+f*ar+g*dr-h*cr)/denominator;641 T gt = (-a*gr-b*hr-c*er+d*fr+e*cr-f*dr+g*ar+h*br)/denominator;642 T ht = (-a*hr+b*gr-c*fr-d*er+e*dr+f*cr-g*br+h*ar)/denominator;643 644 a = at;645 b = bt;646 c = ct;647 d = dt;648 e = et;649 f = ft;650 g = gt;651 h = ht;652 653 return(*this);654 }655 656 657 protected:658 659 BOOST_OCTONION_MEMBER_DATA_GENERATOR(T)660 661 662 private:663 664 };665 // LCOV_EXCL_STOP666 667 // declaration of octonion specialization668 669 template<> class octonion<float>;670 template<> class octonion<double>;671 template<> class octonion<long double>;672 673 674 // helper templates for converting copy constructors (declaration)675 676 namespace detail677 {678 679 template< typename T,680 typename U681 >682 octonion<T> octonion_type_converter(octonion<U> const & rhs);683 }684 685 686 // implementation of octonion specialization687 688 689#define BOOST_OCTONION_CONSTRUCTOR_GENERATOR(type) \690 explicit octonion( type const & requested_a = static_cast<type>(0), \691 type const & requested_b = static_cast<type>(0), \692 type const & requested_c = static_cast<type>(0), \693 type const & requested_d = static_cast<type>(0), \694 type const & requested_e = static_cast<type>(0), \695 type const & requested_f = static_cast<type>(0), \696 type const & requested_g = static_cast<type>(0), \697 type const & requested_h = static_cast<type>(0)) \698 : a(requested_a), \699 b(requested_b), \700 c(requested_c), \701 d(requested_d), \702 e(requested_e), \703 f(requested_f), \704 g(requested_g), \705 h(requested_h) \706 { \707 } \708 \709 explicit octonion( ::std::complex<type> const & z0, \710 ::std::complex<type> const & z1 = ::std::complex<type>(), \711 ::std::complex<type> const & z2 = ::std::complex<type>(), \712 ::std::complex<type> const & z3 = ::std::complex<type>()) \713 : a(z0.real()), \714 b(z0.imag()), \715 c(z1.real()), \716 d(z1.imag()), \717 e(z2.real()), \718 f(z2.imag()), \719 g(z3.real()), \720 h(z3.imag()) \721 { \722 } \723 \724 explicit octonion( ::boost::math::quaternion<type> const & q0, \725 ::boost::math::quaternion<type> const & q1 = ::boost::math::quaternion<type>()) \726 : a(q0.R_component_1()), \727 b(q0.R_component_2()), \728 c(q0.R_component_3()), \729 d(q0.R_component_4()), \730 e(q1.R_component_1()), \731 f(q1.R_component_2()), \732 g(q1.R_component_3()), \733 h(q1.R_component_4()) \734 { \735 }736 737 738#define BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \739 octonion<type> & operator += (type const & rhs) \740 { \741 a += rhs; \742 \743 return(*this); \744 }745 746#define BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \747 octonion<type> & operator += (::std::complex<type> const & rhs) \748 { \749 a += rhs.real(); \750 b += rhs.imag(); \751 \752 return(*this); \753 }754 755#define BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \756 octonion<type> & operator += (::boost::math::quaternion<type> const & rhs) \757 { \758 a += rhs.R_component_1(); \759 b += rhs.R_component_2(); \760 c += rhs.R_component_3(); \761 d += rhs.R_component_4(); \762 \763 return(*this); \764 }765 766#define BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type) \767 template<typename X> \768 octonion<type> & operator += (octonion<X> const & rhs) \769 { \770 a += static_cast<type>(rhs.R_component_1()); \771 b += static_cast<type>(rhs.R_component_2()); \772 c += static_cast<type>(rhs.R_component_3()); \773 d += static_cast<type>(rhs.R_component_4()); \774 e += static_cast<type>(rhs.R_component_5()); \775 f += static_cast<type>(rhs.R_component_6()); \776 g += static_cast<type>(rhs.R_component_7()); \777 h += static_cast<type>(rhs.R_component_8()); \778 \779 return(*this); \780 }781 782#define BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \783 octonion<type> & operator -= (type const & rhs) \784 { \785 a -= rhs; \786 \787 return(*this); \788 }789 790#define BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \791 octonion<type> & operator -= (::std::complex<type> const & rhs) \792 { \793 a -= rhs.real(); \794 b -= rhs.imag(); \795 \796 return(*this); \797 }798 799#define BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \800 octonion<type> & operator -= (::boost::math::quaternion<type> const & rhs) \801 { \802 a -= rhs.R_component_1(); \803 b -= rhs.R_component_2(); \804 c -= rhs.R_component_3(); \805 d -= rhs.R_component_4(); \806 \807 return(*this); \808 }809 810#define BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type) \811 template<typename X> \812 octonion<type> & operator -= (octonion<X> const & rhs) \813 { \814 a -= static_cast<type>(rhs.R_component_1()); \815 b -= static_cast<type>(rhs.R_component_2()); \816 c -= static_cast<type>(rhs.R_component_3()); \817 d -= static_cast<type>(rhs.R_component_4()); \818 e -= static_cast<type>(rhs.R_component_5()); \819 f -= static_cast<type>(rhs.R_component_6()); \820 g -= static_cast<type>(rhs.R_component_7()); \821 h -= static_cast<type>(rhs.R_component_8()); \822 \823 return(*this); \824 }825 826#define BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \827 octonion<type> & operator *= (type const & rhs) \828 { \829 a *= rhs; \830 b *= rhs; \831 c *= rhs; \832 d *= rhs; \833 e *= rhs; \834 f *= rhs; \835 g *= rhs; \836 h *= rhs; \837 \838 return(*this); \839 }840 841#define BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \842 octonion<type> & operator *= (::std::complex<type> const & rhs) \843 { \844 type ar = rhs.real(); \845 type br = rhs.imag(); \846 \847 type at = +a*ar-b*br; \848 type bt = +a*br+b*ar; \849 type ct = +c*ar+d*br; \850 type dt = -c*br+d*ar; \851 type et = +e*ar+f*br; \852 type ft = -e*br+f*ar; \853 type gt = +g*ar-h*br; \854 type ht = +g*br+h*ar; \855 \856 a = at; \857 b = bt; \858 c = ct; \859 d = dt; \860 e = et; \861 f = ft; \862 g = gt; \863 h = ht; \864 \865 return(*this); \866 }867 868#define BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \869 octonion<type> & operator *= (::boost::math::quaternion<type> const & rhs) \870 { \871 type ar = rhs.R_component_1(); \872 type br = rhs.R_component_2(); \873 type cr = rhs.R_component_2(); \874 type dr = rhs.R_component_2(); \875 \876 type at = +a*ar-b*br-c*cr-d*dr; \877 type bt = +a*br+b*ar+c*dr-d*cr; \878 type ct = +a*cr-b*dr+c*ar+d*br; \879 type dt = +a*dr+b*cr-c*br+d*ar; \880 type et = +e*ar+f*br+g*cr+h*dr; \881 type ft = -e*br+f*ar-g*dr+h*cr; \882 type gt = -e*cr+f*dr+g*ar-h*br; \883 type ht = -e*dr-f*cr+g*br+h*ar; \884 \885 a = at; \886 b = bt; \887 c = ct; \888 d = dt; \889 e = et; \890 f = ft; \891 g = gt; \892 h = ht; \893 \894 return(*this); \895 }896 897#define BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type) \898 template<typename X> \899 octonion<type> & operator *= (octonion<X> const & rhs) \900 { \901 type ar = static_cast<type>(rhs.R_component_1()); \902 type br = static_cast<type>(rhs.R_component_2()); \903 type cr = static_cast<type>(rhs.R_component_3()); \904 type dr = static_cast<type>(rhs.R_component_4()); \905 type er = static_cast<type>(rhs.R_component_5()); \906 type fr = static_cast<type>(rhs.R_component_6()); \907 type gr = static_cast<type>(rhs.R_component_7()); \908 type hr = static_cast<type>(rhs.R_component_8()); \909 \910 type at = +a*ar-b*br-c*cr-d*dr-e*er-f*fr-g*gr-h*hr; \911 type bt = +a*br+b*ar+c*dr-d*cr+e*fr-f*er-g*hr+h*gr; \912 type ct = +a*cr-b*dr+c*ar+d*br+e*gr+f*hr-g*er-h*fr; \913 type dt = +a*dr+b*cr-c*br+d*ar+e*hr-f*gr+g*fr-h*er; \914 type et = +a*er-b*fr-c*gr-d*hr+e*ar+f*br+g*cr+h*dr; \915 type ft = +a*fr+b*er-c*hr+d*gr-e*br+f*ar-g*dr+h*cr; \916 type gt = +a*gr+b*hr+c*er-d*fr-e*cr+f*dr+g*ar-h*br; \917 type ht = +a*hr-b*gr+c*fr+d*er-e*dr-f*cr+g*br+h*ar; \918 \919 a = at; \920 b = bt; \921 c = ct; \922 d = dt; \923 e = et; \924 f = ft; \925 g = gt; \926 h = ht; \927 \928 return(*this); \929 }930 931// There is quite a lot of repetition in the code below. This is intentional.932// The last conditional block is the normal form, and the others merely933// consist of workarounds for various compiler deficiencies. Hopefully, when934// more compilers are conformant and we can retire support for those that are935// not, we will be able to remove the clutter. This is makes the situation936// (painfully) explicit.937 938#define BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \939 octonion<type> & operator /= (type const & rhs) \940 { \941 a /= rhs; \942 b /= rhs; \943 c /= rhs; \944 d /= rhs; \945 \946 return(*this); \947 }948 949#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)950 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \951 octonion<type> & operator /= (::std::complex<type> const & rhs) \952 { \953 using ::std::valarray; \954 using ::std::abs; \955 \956 valarray<type> tr(2); \957 \958 tr[0] = rhs.real(); \959 tr[1] = rhs.imag(); \960 \961 type mixam = static_cast<type>(1)/(abs(tr).max)(); \962 \963 tr *= mixam; \964 \965 valarray<type> tt(8); \966 \967 tt[0] = +a*tr[0]-b*tr[1]; \968 tt[1] = -a*tr[1]+b*tr[0]; \969 tt[2] = +c*tr[0]-d*tr[1]; \970 tt[3] = +c*tr[1]+d*tr[0]; \971 tt[4] = +e*tr[0]-f*tr[1]; \972 tt[5] = +e*tr[1]+f*tr[0]; \973 tt[6] = +g*tr[0]+h*tr[1]; \974 tt[7] = +g*tr[1]+h*tr[0]; \975 \976 tr *= tr; \977 \978 tt *= (mixam/tr.sum()); \979 \980 a = tt[0]; \981 b = tt[1]; \982 c = tt[2]; \983 d = tt[3]; \984 e = tt[4]; \985 f = tt[5]; \986 g = tt[6]; \987 h = tt[7]; \988 \989 return(*this); \990 }991#else992 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \993 octonion<type> & operator /= (::std::complex<type> const & rhs) \994 { \995 using ::std::valarray; \996 \997 valarray<type> tr(2); \998 \999 tr[0] = rhs.real(); \1000 tr[1] = rhs.imag(); \1001 \1002 type mixam = static_cast<type>(1)/(abs(tr).max)(); \1003 \1004 tr *= mixam; \1005 \1006 valarray<type> tt(8); \1007 \1008 tt[0] = +a*tr[0]-b*tr[1]; \1009 tt[1] = -a*tr[1]+b*tr[0]; \1010 tt[2] = +c*tr[0]-d*tr[1]; \1011 tt[3] = +c*tr[1]+d*tr[0]; \1012 tt[4] = +e*tr[0]-f*tr[1]; \1013 tt[5] = +e*tr[1]+f*tr[0]; \1014 tt[6] = +g*tr[0]+h*tr[1]; \1015 tt[7] = +g*tr[1]+h*tr[0]; \1016 \1017 tr *= tr; \1018 \1019 tt *= (mixam/tr.sum()); \1020 \1021 a = tt[0]; \1022 b = tt[1]; \1023 c = tt[2]; \1024 d = tt[3]; \1025 e = tt[4]; \1026 f = tt[5]; \1027 g = tt[6]; \1028 h = tt[7]; \1029 \1030 return(*this); \1031 }1032#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */1033 1034#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)1035 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \1036 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \1037 { \1038 using ::std::valarray; \1039 using ::std::abs; \1040 \1041 valarray<type> tr(4); \1042 \1043 tr[0] = static_cast<type>(rhs.R_component_1()); \1044 tr[1] = static_cast<type>(rhs.R_component_2()); \1045 tr[2] = static_cast<type>(rhs.R_component_3()); \1046 tr[3] = static_cast<type>(rhs.R_component_4()); \1047 \1048 type mixam = static_cast<type>(1)/(abs(tr).max)(); \1049 \1050 tr *= mixam; \1051 \1052 valarray<type> tt(8); \1053 \1054 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \1055 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \1056 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \1057 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \1058 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \1059 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \1060 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \1061 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \1062 \1063 tr *= tr; \1064 \1065 tt *= (mixam/tr.sum()); \1066 \1067 a = tt[0]; \1068 b = tt[1]; \1069 c = tt[2]; \1070 d = tt[3]; \1071 e = tt[4]; \1072 f = tt[5]; \1073 g = tt[6]; \1074 h = tt[7]; \1075 \1076 return(*this); \1077 }1078#else1079 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \1080 octonion<type> & operator /= (::boost::math::quaternion<type> const & rhs) \1081 { \1082 using ::std::valarray; \1083 \1084 valarray<type> tr(4); \1085 \1086 tr[0] = static_cast<type>(rhs.R_component_1()); \1087 tr[1] = static_cast<type>(rhs.R_component_2()); \1088 tr[2] = static_cast<type>(rhs.R_component_3()); \1089 tr[3] = static_cast<type>(rhs.R_component_4()); \1090 \1091 type mixam = static_cast<type>(1)/(abs(tr).max)(); \1092 \1093 tr *= mixam; \1094 \1095 valarray<type> tt(8); \1096 \1097 tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \1098 tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \1099 tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \1100 tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \1101 tt[4] = +e*tr[0]-f*tr[1]-g*tr[2]-h*tr[3]; \1102 tt[5] = +e*tr[1]+f*tr[0]+g*tr[3]-h*tr[2]; \1103 tt[6] = +e*tr[2]-f*tr[3]+g*tr[0]+h*tr[1]; \1104 tt[7] = +e*tr[3]+f*tr[2]-g*tr[1]+h*tr[0]; \1105 \1106 tr *= tr; \1107 \1108 tt *= (mixam/tr.sum()); \1109 \1110 a = tt[0]; \1111 b = tt[1]; \1112 c = tt[2]; \1113 d = tt[3]; \1114 e = tt[4]; \1115 f = tt[5]; \1116 g = tt[6]; \1117 h = tt[7]; \1118 \1119 return(*this); \1120 }1121#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */1122 1123#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)1124 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \1125 template<typename X> \1126 octonion<type> & operator /= (octonion<X> const & rhs) \1127 { \1128 using ::std::valarray; \1129 using ::std::abs; \1130 \1131 valarray<type> tr(8); \1132 \1133 tr[0] = static_cast<type>(rhs.R_component_1()); \1134 tr[1] = static_cast<type>(rhs.R_component_2()); \1135 tr[2] = static_cast<type>(rhs.R_component_3()); \1136 tr[3] = static_cast<type>(rhs.R_component_4()); \1137 tr[4] = static_cast<type>(rhs.R_component_5()); \1138 tr[5] = static_cast<type>(rhs.R_component_6()); \1139 tr[6] = static_cast<type>(rhs.R_component_7()); \1140 tr[7] = static_cast<type>(rhs.R_component_8()); \1141 \1142 type mixam = static_cast<type>(1)/(abs(tr).max)(); \1143 \1144 tr *= mixam; \1145 \1146 valarray<type> tt(8); \1147 \1148 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]; \1149 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]; \1150 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]; \1151 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]; \1152 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]; \1153 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]; \1154 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]; \1155 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]; \1156 \1157 tr *= tr; \1158 \1159 tt *= (mixam/tr.sum()); \1160 \1161 a = tt[0]; \1162 b = tt[1]; \1163 c = tt[2]; \1164 d = tt[3]; \1165 e = tt[4]; \1166 f = tt[5]; \1167 g = tt[6]; \1168 h = tt[7]; \1169 \1170 return(*this); \1171 }1172#else1173 #define BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type) \1174 template<typename X> \1175 octonion<type> & operator /= (octonion<X> const & rhs) \1176 { \1177 using ::std::valarray; \1178 \1179 valarray<type> tr(8); \1180 \1181 tr[0] = static_cast<type>(rhs.R_component_1()); \1182 tr[1] = static_cast<type>(rhs.R_component_2()); \1183 tr[2] = static_cast<type>(rhs.R_component_3()); \1184 tr[3] = static_cast<type>(rhs.R_component_4()); \1185 tr[4] = static_cast<type>(rhs.R_component_5()); \1186 tr[5] = static_cast<type>(rhs.R_component_6()); \1187 tr[6] = static_cast<type>(rhs.R_component_7()); \1188 tr[7] = static_cast<type>(rhs.R_component_8()); \1189 \1190 type mixam = static_cast<type>(1)/(abs(tr).max)(); \1191 \1192 tr *= mixam; \1193 \1194 valarray<type> tt(8); \1195 \1196 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]; \1197 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]; \1198 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]; \1199 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]; \1200 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]; \1201 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]; \1202 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]; \1203 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]; \1204 \1205 tr *= tr; \1206 \1207 tt *= (mixam/tr.sum()); \1208 \1209 a = tt[0]; \1210 b = tt[1]; \1211 c = tt[2]; \1212 d = tt[3]; \1213 e = tt[4]; \1214 f = tt[5]; \1215 g = tt[6]; \1216 h = tt[7]; \1217 \1218 return(*this); \1219 }1220#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */1221 1222 1223#define BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \1224 BOOST_OCTONION_MEMBER_ADD_GENERATOR_1(type) \1225 BOOST_OCTONION_MEMBER_ADD_GENERATOR_2(type) \1226 BOOST_OCTONION_MEMBER_ADD_GENERATOR_3(type) \1227 BOOST_OCTONION_MEMBER_ADD_GENERATOR_4(type)1228 1229#define BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \1230 BOOST_OCTONION_MEMBER_SUB_GENERATOR_1(type) \1231 BOOST_OCTONION_MEMBER_SUB_GENERATOR_2(type) \1232 BOOST_OCTONION_MEMBER_SUB_GENERATOR_3(type) \1233 BOOST_OCTONION_MEMBER_SUB_GENERATOR_4(type)1234 1235#define BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \1236 BOOST_OCTONION_MEMBER_MUL_GENERATOR_1(type) \1237 BOOST_OCTONION_MEMBER_MUL_GENERATOR_2(type) \1238 BOOST_OCTONION_MEMBER_MUL_GENERATOR_3(type) \1239 BOOST_OCTONION_MEMBER_MUL_GENERATOR_4(type)1240 1241#define BOOST_OCTONION_MEMBER_DIV_GENERATOR(type) \1242 BOOST_OCTONION_MEMBER_DIV_GENERATOR_1(type) \1243 BOOST_OCTONION_MEMBER_DIV_GENERATOR_2(type) \1244 BOOST_OCTONION_MEMBER_DIV_GENERATOR_3(type) \1245 BOOST_OCTONION_MEMBER_DIV_GENERATOR_4(type)1246 1247#define BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(type) \1248 BOOST_OCTONION_MEMBER_ADD_GENERATOR(type) \1249 BOOST_OCTONION_MEMBER_SUB_GENERATOR(type) \1250 BOOST_OCTONION_MEMBER_MUL_GENERATOR(type) \1251 BOOST_OCTONION_MEMBER_DIV_GENERATOR(type)1252 1253 1254 template<>1255 class octonion<float>1256 {1257 public:1258 1259 using value_type = float;1260 1261 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(float)1262 1263 // UNtemplated copy constructor1264 octonion(const octonion&) = default;1265 1266 // explicit copy constructors (precision-losing converters)1267 1268 explicit octonion(octonion<double> const & a_recopier)1269 {1270 *this = detail::octonion_type_converter<float, double>(a_recopier);1271 }1272 1273 explicit octonion(octonion<long double> const & a_recopier)1274 {1275 *this = detail::octonion_type_converter<float, long double>(a_recopier);1276 }1277 1278 // destructor1279 ~octonion() = default;1280 1281 // accessors1282 //1283 // Note: Like complex number, octonions do have a meaningful notion of "real part",1284 // but unlike them there is no meaningful notion of "imaginary part".1285 // Instead there is an "unreal part" which itself is an octonion, and usually1286 // nothing simpler (as opposed to the complex number case).1287 // However, for practicality, there are accessors for the other components1288 // (these are necessary for the templated copy constructor, for instance).1289 1290 BOOST_OCTONION_ACCESSOR_GENERATOR(float)1291 1292 // assignment operators1293 1294 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(float)1295 1296 // other assignment-related operators1297 //1298 // NOTE: Octonion multiplication is *NOT* commutative;1299 // symbolically, "q *= rhs;" means "q = q * rhs;"1300 // and "q /= rhs;" means "q = q * inverse_of(rhs);";1301 // octonion multiplication is also *NOT* associative1302 1303 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(float)1304 1305 1306 protected:1307 1308 BOOST_OCTONION_MEMBER_DATA_GENERATOR(float)1309 };1310 1311 1312 template<>1313 class octonion<double>1314 {1315 public:1316 1317 using value_type = double;1318 1319 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(double)1320 1321 // Untemplated copy constructor1322 octonion(const octonion&) = default;1323 1324 // converting copy constructor1325 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 1333 explicit octonion(octonion<long double> const & a_recopier)1334 {1335 *this = detail::octonion_type_converter<double, long double>(a_recopier);1336 }1337 1338 // destructor1339 // (this is taken care of by the compiler itself)1340 1341 // accessors1342 //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 usually1346 // nothing simpler (as opposed to the complex number case).1347 // However, for practicality, there are accessors for the other components1348 // (these are necessary for the templated copy constructor, for instance).1349 1350 BOOST_OCTONION_ACCESSOR_GENERATOR(double)1351 1352 // assignment operators1353 1354 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(double)1355 1356 // other assignment-related operators1357 //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* associative1362 1363 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(double)1364 1365 1366 protected:1367 1368 BOOST_OCTONION_MEMBER_DATA_GENERATOR(double)1369 };1370 1371 1372 template<>1373 class octonion<long double>1374 {1375 public:1376 1377 using value_type = long double;1378 1379 BOOST_OCTONION_CONSTRUCTOR_GENERATOR(long double)1380 1381 // UNtemplated copy constructor1382 octonion(const octonion&) = default;1383 1384 // converting copy constructor1385 1386 explicit octonion(octonion<float> const & a_recopier)1387 {1388 *this = detail::octonion_type_converter<long double, float>(a_recopier);1389 }1390 1391 1392 explicit octonion(octonion<double> const & a_recopier)1393 {1394 *this = detail::octonion_type_converter<long double, double>(a_recopier);1395 }1396 1397 1398 // destructor1399 // (this is taken care of by the compiler itself)1400 1401 // accessors1402 //1403 // Note: Like complex number, octonions do have a meaningful notion of "real part",1404 // but unlike them there is no meaningful notion of "imaginary part".1405 // Instead there is an "unreal part" which itself is an octonion, and usually1406 // nothing simpler (as opposed to the complex number case).1407 // However, for practicality, there are accessors for the other components1408 // (these are necessary for the templated copy constructor, for instance).1409 1410 BOOST_OCTONION_ACCESSOR_GENERATOR(long double)1411 1412 // assignment operators1413 1414 BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR(long double)1415 1416 // other assignment-related operators1417 //1418 // NOTE: Octonion multiplication is *NOT* commutative;1419 // symbolically, "q *= rhs;" means "q = q * rhs;"1420 // and "q /= rhs;" means "q = q * inverse_of(rhs);";1421 // octonion multiplication is also *NOT* associative1422 1423 BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR(long double)1424 1425 1426 protected:1427 1428 BOOST_OCTONION_MEMBER_DATA_GENERATOR(long double)1429 1430 1431 private:1432 1433 };1434 1435 1436#undef BOOST_OCTONION_CONSTRUCTOR_GENERATOR1437 1438#undef BOOST_OCTONION_MEMBER_ALGEBRAIC_GENERATOR1439 1440#undef BOOST_OCTONION_MEMBER_ADD_GENERATOR1441#undef BOOST_OCTONION_MEMBER_SUB_GENERATOR1442#undef BOOST_OCTONION_MEMBER_MUL_GENERATOR1443#undef BOOST_OCTONION_MEMBER_DIV_GENERATOR1444 1445#undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_11446#undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_21447#undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_31448#undef BOOST_OCTONION_MEMBER_ADD_GENERATOR_41449#undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_11450#undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_21451#undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_31452#undef BOOST_OCTONION_MEMBER_SUB_GENERATOR_41453#undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_11454#undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_21455#undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_31456#undef BOOST_OCTONION_MEMBER_MUL_GENERATOR_41457#undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_11458#undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_21459#undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_31460#undef BOOST_OCTONION_MEMBER_DIV_GENERATOR_41461 1462 1463#undef BOOST_OCTONION_MEMBER_DATA_GENERATOR1464 1465#undef BOOST_OCTONION_MEMBER_ASSIGNMENT_GENERATOR1466 1467#undef BOOST_OCTONION_ACCESSOR_GENERATOR1468 1469 1470 // operators1471 1472#define BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op) \1473 { \1474 octonion<T> res(lhs); \1475 res op##= rhs; \1476 return(res); \1477 }1478 1479#define BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \1480 template<typename T> \1481 inline octonion<T> operator op (T const & lhs, octonion<T> const & rhs) \1482 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)1483 1484#define BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \1485 template<typename T> \1486 inline octonion<T> operator op (octonion<T> const & lhs, T const & rhs) \1487 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)1488 1489#define BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \1490 template<typename T> \1491 inline octonion<T> operator op (::std::complex<T> const & lhs, octonion<T> const & rhs) \1492 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)1493 1494#define BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \1495 template<typename T> \1496 inline octonion<T> operator op (octonion<T> const & lhs, ::std::complex<T> const & rhs) \1497 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)1498 1499#define BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \1500 template<typename T> \1501 inline octonion<T> operator op (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs) \1502 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)1503 1504#define BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \1505 template<typename T> \1506 inline octonion<T> operator op (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs) \1507 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)1508 1509#define BOOST_OCTONION_OPERATOR_GENERATOR_4(op) \1510 template<typename T> \1511 inline octonion<T> operator op (octonion<T> const & lhs, octonion<T> const & rhs) \1512 BOOST_OCTONION_OPERATOR_GENERATOR_BODY(op)1513 1514#define BOOST_OCTONION_OPERATOR_GENERATOR(op) \1515 BOOST_OCTONION_OPERATOR_GENERATOR_1_L(op) \1516 BOOST_OCTONION_OPERATOR_GENERATOR_1_R(op) \1517 BOOST_OCTONION_OPERATOR_GENERATOR_2_L(op) \1518 BOOST_OCTONION_OPERATOR_GENERATOR_2_R(op) \1519 BOOST_OCTONION_OPERATOR_GENERATOR_3_L(op) \1520 BOOST_OCTONION_OPERATOR_GENERATOR_3_R(op) \1521 BOOST_OCTONION_OPERATOR_GENERATOR_4(op)1522 1523 1524 BOOST_OCTONION_OPERATOR_GENERATOR(+)1525 BOOST_OCTONION_OPERATOR_GENERATOR(-)1526 BOOST_OCTONION_OPERATOR_GENERATOR(*)1527 BOOST_OCTONION_OPERATOR_GENERATOR(/)1528 1529 1530#undef BOOST_OCTONION_OPERATOR_GENERATOR1531 1532#undef BOOST_OCTONION_OPERATOR_GENERATOR_1_L1533#undef BOOST_OCTONION_OPERATOR_GENERATOR_1_R1534#undef BOOST_OCTONION_OPERATOR_GENERATOR_2_L1535#undef BOOST_OCTONION_OPERATOR_GENERATOR_2_R1536#undef BOOST_OCTONION_OPERATOR_GENERATOR_3_L1537#undef BOOST_OCTONION_OPERATOR_GENERATOR_3_R1538#undef BOOST_OCTONION_OPERATOR_GENERATOR_41539 1540#undef BOOST_OCTONION_OPERATOR_GENERATOR_BODY1541 1542 1543 template<typename T>1544 inline octonion<T> operator + (octonion<T> const & o)1545 {1546 return(o);1547 }1548 1549 1550 template<typename T>1551 inline octonion<T> operator - (octonion<T> const & o)1552 {1553 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()));1554 }1555 1556 1557 template<typename T>1558 inline bool operator == (T const & lhs, octonion<T> const & rhs)1559 {1560 return(1561 (rhs.R_component_1() == lhs)&&1562 (rhs.R_component_2() == static_cast<T>(0))&&1563 (rhs.R_component_3() == static_cast<T>(0))&&1564 (rhs.R_component_4() == static_cast<T>(0))&&1565 (rhs.R_component_5() == static_cast<T>(0))&&1566 (rhs.R_component_6() == static_cast<T>(0))&&1567 (rhs.R_component_7() == static_cast<T>(0))&&1568 (rhs.R_component_8() == static_cast<T>(0))1569 );1570 }1571 1572 1573 template<typename T>1574 inline bool operator == (octonion<T> const & lhs, T const & rhs)1575 {1576 return(1577 (lhs.R_component_1() == rhs)&&1578 (lhs.R_component_2() == static_cast<T>(0))&&1579 (lhs.R_component_3() == static_cast<T>(0))&&1580 (lhs.R_component_4() == static_cast<T>(0))&&1581 (lhs.R_component_5() == static_cast<T>(0))&&1582 (lhs.R_component_6() == static_cast<T>(0))&&1583 (lhs.R_component_7() == static_cast<T>(0))&&1584 (lhs.R_component_8() == static_cast<T>(0))1585 );1586 }1587 1588 1589 template<typename T>1590 inline bool operator == (::std::complex<T> const & lhs, octonion<T> const & rhs)1591 {1592 return(1593 (rhs.R_component_1() == lhs.real())&&1594 (rhs.R_component_2() == lhs.imag())&&1595 (rhs.R_component_3() == static_cast<T>(0))&&1596 (rhs.R_component_4() == static_cast<T>(0))&&1597 (rhs.R_component_5() == static_cast<T>(0))&&1598 (rhs.R_component_6() == static_cast<T>(0))&&1599 (rhs.R_component_7() == static_cast<T>(0))&&1600 (rhs.R_component_8() == static_cast<T>(0))1601 );1602 }1603 1604 1605 template<typename T>1606 inline bool operator == (octonion<T> const & lhs, ::std::complex<T> const & rhs)1607 {1608 return(1609 (lhs.R_component_1() == rhs.real())&&1610 (lhs.R_component_2() == rhs.imag())&&1611 (lhs.R_component_3() == static_cast<T>(0))&&1612 (lhs.R_component_4() == static_cast<T>(0))&&1613 (lhs.R_component_5() == static_cast<T>(0))&&1614 (lhs.R_component_6() == static_cast<T>(0))&&1615 (lhs.R_component_7() == static_cast<T>(0))&&1616 (lhs.R_component_8() == static_cast<T>(0))1617 );1618 }1619 1620 1621 template<typename T>1622 inline bool operator == (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)1623 {1624 return(1625 (rhs.R_component_1() == lhs.R_component_1())&&1626 (rhs.R_component_2() == lhs.R_component_2())&&1627 (rhs.R_component_3() == lhs.R_component_3())&&1628 (rhs.R_component_4() == lhs.R_component_4())&&1629 (rhs.R_component_5() == static_cast<T>(0))&&1630 (rhs.R_component_6() == static_cast<T>(0))&&1631 (rhs.R_component_7() == static_cast<T>(0))&&1632 (rhs.R_component_8() == static_cast<T>(0))1633 );1634 }1635 1636 1637 template<typename T>1638 inline bool operator == (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)1639 {1640 return(1641 (lhs.R_component_1() == rhs.R_component_1())&&1642 (lhs.R_component_2() == rhs.R_component_2())&&1643 (lhs.R_component_3() == rhs.R_component_3())&&1644 (lhs.R_component_4() == rhs.R_component_4())&&1645 (lhs.R_component_5() == static_cast<T>(0))&&1646 (lhs.R_component_6() == static_cast<T>(0))&&1647 (lhs.R_component_7() == static_cast<T>(0))&&1648 (lhs.R_component_8() == static_cast<T>(0))1649 );1650 }1651 1652 1653 template<typename T>1654 inline bool operator == (octonion<T> const & lhs, octonion<T> const & rhs)1655 {1656 return(1657 (rhs.R_component_1() == lhs.R_component_1())&&1658 (rhs.R_component_2() == lhs.R_component_2())&&1659 (rhs.R_component_3() == lhs.R_component_3())&&1660 (rhs.R_component_4() == lhs.R_component_4())&&1661 (rhs.R_component_5() == lhs.R_component_5())&&1662 (rhs.R_component_6() == lhs.R_component_6())&&1663 (rhs.R_component_7() == lhs.R_component_7())&&1664 (rhs.R_component_8() == lhs.R_component_8())1665 );1666 }1667 1668 1669#define BOOST_OCTONION_NOT_EQUAL_GENERATOR \1670 { \1671 return(!(lhs == rhs)); \1672 }1673 1674 template<typename T>1675 inline bool operator != (T const & lhs, octonion<T> const & rhs)1676 BOOST_OCTONION_NOT_EQUAL_GENERATOR1677 1678 template<typename T>1679 inline bool operator != (octonion<T> const & lhs, T const & rhs)1680 BOOST_OCTONION_NOT_EQUAL_GENERATOR1681 1682 template<typename T>1683 inline bool operator != (::std::complex<T> const & lhs, octonion<T> const & rhs)1684 BOOST_OCTONION_NOT_EQUAL_GENERATOR1685 1686 template<typename T>1687 inline bool operator != (octonion<T> const & lhs, ::std::complex<T> const & rhs)1688 BOOST_OCTONION_NOT_EQUAL_GENERATOR1689 1690 template<typename T>1691 inline bool operator != (::boost::math::quaternion<T> const & lhs, octonion<T> const & rhs)1692 BOOST_OCTONION_NOT_EQUAL_GENERATOR1693 1694 template<typename T>1695 inline bool operator != (octonion<T> const & lhs, ::boost::math::quaternion<T> const & rhs)1696 BOOST_OCTONION_NOT_EQUAL_GENERATOR1697 1698 template<typename T>1699 inline bool operator != (octonion<T> const & lhs, octonion<T> const & rhs)1700 BOOST_OCTONION_NOT_EQUAL_GENERATOR1701 1702 #undef BOOST_OCTONION_NOT_EQUAL_GENERATOR1703 1704 // LCOV_EXCL_START1705 // Something like 2,100 lines of input-streaming up to line 3,800 and beyond.1706 1707 // Note: the default values in the constructors of the complex and quaternions make for1708 // a very complex and ambiguous situation; we have made choices to disambiguate.1709 template<typename T, typename charT, class traits>1710 ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,1711 octonion<T> & o)1712 {1713#ifdef BOOST_NO_STD_LOCALE1714#else1715 const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());1716#endif /* BOOST_NO_STD_LOCALE */1717 1718 T a = T();1719 T b = T();1720 T c = T();1721 T d = T();1722 T e = T();1723 T f = T();1724 T g = T();1725 T h = T();1726 1727 ::std::complex<T> u = ::std::complex<T>();1728 ::std::complex<T> v = ::std::complex<T>();1729 ::std::complex<T> x = ::std::complex<T>();1730 ::std::complex<T> y = ::std::complex<T>();1731 1732 ::boost::math::quaternion<T> p = ::boost::math::quaternion<T>();1733 ::boost::math::quaternion<T> q = ::boost::math::quaternion<T>();1734 1735 charT ch = charT();1736 char cc;1737 1738 is >> ch; // get the first lexeme1739 1740 if (!is.good()) goto finish;1741 1742#ifdef BOOST_NO_STD_LOCALE1743 cc = ch;1744#else1745 cc = ct.narrow(ch, char());1746#endif /* BOOST_NO_STD_LOCALE */1747 1748 if (cc == '(') // read "("1749 {1750 is >> ch; // get the second lexeme1751 1752 if (!is.good()) goto finish;1753 1754#ifdef BOOST_NO_STD_LOCALE1755 cc = ch;1756#else1757 cc = ct.narrow(ch, char());1758#endif /* BOOST_NO_STD_LOCALE */1759 1760 if (cc == '(') // read "(("1761 {1762 is >> ch; // get the third lexeme1763 1764 if (!is.good()) goto finish;1765 1766#ifdef BOOST_NO_STD_LOCALE1767 cc = ch;1768#else1769 cc = ct.narrow(ch, char());1770#endif /* BOOST_NO_STD_LOCALE */1771 1772 if (cc == '(') // read "((("1773 {1774 is.putback(ch);1775 1776 is >> u; // read "((u"1777 1778 if (!is.good()) goto finish;1779 1780 is >> ch; // get the next lexeme1781 1782 if (!is.good()) goto finish;1783 1784#ifdef BOOST_NO_STD_LOCALE1785 cc = ch;1786#else1787 cc = ct.narrow(ch, char());1788#endif /* BOOST_NO_STD_LOCALE */1789 1790 if (cc == ')') // read "((u)"1791 {1792 is >> ch; // get the next lexeme1793 1794 if (!is.good()) goto finish;1795 1796#ifdef BOOST_NO_STD_LOCALE1797 cc = ch;1798#else1799 cc = ct.narrow(ch, char());1800#endif /* BOOST_NO_STD_LOCALE */1801 1802 if (cc == ')') // format: (((a))), (((a,b)))1803 {1804 o = octonion<T>(u);1805 }1806 else if (cc == ',') // read "((u),"1807 {1808 p = ::boost::math::quaternion<T>(u);1809 1810 is >> q; // read "((u),q"1811 1812 if (!is.good()) goto finish;1813 1814 is >> ch; // get the next lexeme1815 1816 if (!is.good()) goto finish;1817 1818#ifdef BOOST_NO_STD_LOCALE1819 cc = ch;1820#else1821 cc = ct.narrow(ch, char());1822#endif /* BOOST_NO_STD_LOCALE */1823 1824 if (cc == ')') // format: (((a)),q), (((a,b)),q)1825 {1826 o = octonion<T>(p,q);1827 }1828 else // error1829 {1830 is.setstate(::std::ios_base::failbit);1831 }1832 }1833 else // error1834 {1835 is.setstate(::std::ios_base::failbit);1836 }1837 }1838 else if (cc ==',') // read "((u,"1839 {1840 is >> v; // read "((u,v"1841 1842 if (!is.good()) goto finish;1843 1844 is >> ch; // get the next lexeme1845 1846 if (!is.good()) goto finish;1847 1848#ifdef BOOST_NO_STD_LOCALE1849 cc = ch;1850#else1851 cc = ct.narrow(ch, char());1852#endif /* BOOST_NO_STD_LOCALE */1853 1854 if (cc == ')') // read "((u,v)"1855 {1856 p = ::boost::math::quaternion<T>(u,v);1857 1858 is >> ch; // get the next lexeme1859 1860 if (!is.good()) goto finish;1861 1862#ifdef BOOST_NO_STD_LOCALE1863 cc = ch;1864#else1865 cc = ct.narrow(ch, char());1866#endif /* BOOST_NO_STD_LOCALE */1867 1868 if (cc == ')') // format: (((a),v)), (((a,b),v))1869 {1870 o = octonion<T>(p);1871 }1872 else if (cc == ',') // read "((u,v),"1873 {1874 is >> q; // read "(p,q"1875 1876 if (!is.good()) goto finish;1877 1878 is >> ch; // get the next lexeme1879 1880 if (!is.good()) goto finish;1881 1882#ifdef BOOST_NO_STD_LOCALE1883 cc = ch;1884#else1885 cc = ct.narrow(ch, char());1886#endif /* BOOST_NO_STD_LOCALE */1887 1888 if (cc == ')') // format: (((a),v),q), (((a,b),v),q)1889 {1890 o = octonion<T>(p,q);1891 }1892 else // error1893 {1894 is.setstate(::std::ios_base::failbit);1895 }1896 }1897 else // error1898 {1899 is.setstate(::std::ios_base::failbit);1900 }1901 }1902 else // error1903 {1904 is.setstate(::std::ios_base::failbit);1905 }1906 }1907 else // error1908 {1909 is.setstate(::std::ios_base::failbit);1910 }1911 }1912 else // read "((a"1913 {1914 is.putback(ch);1915 1916 is >> a; // we extract the first component1917 1918 if (!is.good()) goto finish;1919 1920 is >> ch; // get the next lexeme1921 1922 if (!is.good()) goto finish;1923 1924#ifdef BOOST_NO_STD_LOCALE1925 cc = ch;1926#else1927 cc = ct.narrow(ch, char());1928#endif /* BOOST_NO_STD_LOCALE */1929 1930 if (cc == ')') // read "((a)"1931 {1932 is >> ch; // get the next lexeme1933 1934 if (!is.good()) goto finish;1935 1936#ifdef BOOST_NO_STD_LOCALE1937 cc = ch;1938#else1939 cc = ct.narrow(ch, char());1940#endif /* BOOST_NO_STD_LOCALE */1941 1942 if (cc == ')') // read "((a))"1943 {1944 o = octonion<T>(a);1945 }1946 else if (cc == ',') // read "((a),"1947 {1948 is >> ch; // get the next lexeme1949 1950 if (!is.good()) goto finish;1951 1952#ifdef BOOST_NO_STD_LOCALE1953 cc = ch;1954#else1955 cc = ct.narrow(ch, char());1956#endif /* BOOST_NO_STD_LOCALE */1957 1958 if (cc == '(') // read "((a),("1959 {1960 is >> ch; // get the next lexeme1961 1962 if (!is.good()) goto finish;1963 1964#ifdef BOOST_NO_STD_LOCALE1965 cc = ch;1966#else1967 cc = ct.narrow(ch, char());1968#endif /* BOOST_NO_STD_LOCALE */1969 1970 if (cc == '(') // read "((a),(("1971 {1972 is.putback(ch);1973 1974 is.putback(ch); // we backtrack twice, with the same value!1975 1976 is >> q; // read "((a),q"1977 1978 if (!is.good()) goto finish;1979 1980 is >> ch; // get the next lexeme1981 1982 if (!is.good()) goto finish;1983 1984#ifdef BOOST_NO_STD_LOCALE1985 cc = ch;1986#else1987 cc = ct.narrow(ch, char());1988#endif /* BOOST_NO_STD_LOCALE */1989 1990 if (cc == ')') // read "((a),q)"1991 {1992 p = ::boost::math::quaternion<T>(a);1993 1994 o = octonion<T>(p,q);1995 }1996 else // error1997 {1998 is.setstate(::std::ios_base::failbit);1999 }2000 }2001 else // read "((a),(c" or "((a),(e"2002 {2003 is.putback(ch);2004 2005 is >> c;2006 2007 if (!is.good()) goto finish;2008 2009 is >> ch; // get the next lexeme2010 2011 if (!is.good()) goto finish;2012 2013#ifdef BOOST_NO_STD_LOCALE2014 cc = ch;2015#else2016 cc = ct.narrow(ch, char());2017#endif /* BOOST_NO_STD_LOCALE */2018 2019 if (cc == ')') // read "((a),(c)" (ambiguity resolution)2020 {2021 is >> ch; // get the next lexeme2022 2023 if (!is.good()) goto finish;2024 2025#ifdef BOOST_NO_STD_LOCALE2026 cc = ch;2027#else2028 cc = ct.narrow(ch, char());2029#endif /* BOOST_NO_STD_LOCALE */2030 2031 if (cc == ')') // read "((a),(c))"2032 {2033 o = octonion<T>(a,b,c);2034 }2035 else if (cc == ',') // read "((a),(c),"2036 {2037 u = ::std::complex<T>(a);2038 2039 v = ::std::complex<T>(c);2040 2041 is >> x; // read "((a),(c),x"2042 2043 if (!is.good()) goto finish;2044 2045 is >> ch; // get the next lexeme2046 2047 if (!is.good()) goto finish;2048 2049#ifdef BOOST_NO_STD_LOCALE2050 cc = ch;2051#else2052 cc = ct.narrow(ch, char());2053#endif /* BOOST_NO_STD_LOCALE */2054 2055 if (cc == ')') // read "((a),(c),x)"2056 {2057 o = octonion<T>(u,v,x);2058 }2059 else if (cc == ',') // read "((a),(c),x,"2060 {2061 is >> y; // read "((a),(c),x,y"2062 2063 if (!is.good()) goto finish;2064 2065 is >> ch; // get the next lexeme2066 2067 if (!is.good()) goto finish;2068 2069#ifdef BOOST_NO_STD_LOCALE2070 cc = ch;2071#else2072 cc = ct.narrow(ch, char());2073#endif /* BOOST_NO_STD_LOCALE */2074 2075 if (cc == ')') // read "((a),(c),x,y)"2076 {2077 o = octonion<T>(u,v,x,y);2078 }2079 else // error2080 {2081 is.setstate(::std::ios_base::failbit);2082 }2083 }2084 else // error2085 {2086 is.setstate(::std::ios_base::failbit);2087 }2088 }2089 else // error2090 {2091 is.setstate(::std::ios_base::failbit);2092 }2093 }2094 else if (cc == ',') // read "((a),(c," or "((a),(e,"2095 {2096 is >> ch; // get the next lexeme2097 2098 if (!is.good()) goto finish;2099 2100#ifdef BOOST_NO_STD_LOCALE2101 cc = ch;2102#else2103 cc = ct.narrow(ch, char());2104#endif /* BOOST_NO_STD_LOCALE */2105 2106 if (cc == '(') // read "((a),(e,(" (ambiguity resolution)2107 {2108 p = ::boost::math::quaternion<T>(a);2109 2110 x = ::std::complex<T>(c); // "c" was actually "e"2111 2112 is.putback(ch); // we can only backtrace once2113 2114 is >> y; // read "((a),(e,y"2115 2116 if (!is.good()) goto finish;2117 2118 is >> ch; // get the next lexeme2119 2120#ifdef BOOST_NO_STD_LOCALE2121 cc = ch;2122#else2123 cc = ct.narrow(ch, char());2124#endif /* BOOST_NO_STD_LOCALE */2125 2126 if (cc == ')') // read "((a),(e,y)"2127 {2128 q = ::boost::math::quaternion<T>(x,y);2129 2130 is >> ch; // get the next lexeme2131 2132#ifdef BOOST_NO_STD_LOCALE2133 cc = ch;2134#else2135 cc = ct.narrow(ch, char());2136#endif /* BOOST_NO_STD_LOCALE */2137 2138 if (cc == ')') // read "((a),(e,y))"2139 {2140 o = octonion<T>(p,q);2141 }2142 else // error2143 {2144 is.setstate(::std::ios_base::failbit);2145 }2146 }2147 else // error2148 {2149 is.setstate(::std::ios_base::failbit);2150 }2151 }2152 else // read "((a),(c,d" or "((a),(e,f"2153 {2154 is.putback(ch);2155 2156 is >> d;2157 2158 if (!is.good()) goto finish;2159 2160 is >> ch; // get the next lexeme2161 2162 if (!is.good()) goto finish;2163 2164#ifdef BOOST_NO_STD_LOCALE2165 cc = ch;2166#else2167 cc = ct.narrow(ch, char());2168#endif /* BOOST_NO_STD_LOCALE */2169 2170 if (cc == ')') // read "((a),(c,d)" (ambiguity resolution)2171 {2172 is >> ch; // get the next lexeme2173 2174 if (!is.good()) goto finish;2175 2176#ifdef BOOST_NO_STD_LOCALE2177 cc = ch;2178#else2179 cc = ct.narrow(ch, char());2180#endif /* BOOST_NO_STD_LOCALE */2181 2182 if (cc == ')') // read "((a),(c,d))"2183 {2184 o = octonion<T>(a,b,c,d);2185 }2186 else if (cc == ',') // read "((a),(c,d),"2187 {2188 u = ::std::complex<T>(a);2189 2190 v = ::std::complex<T>(c,d);2191 2192 is >> x; // read "((a),(c,d),x"2193 2194 if (!is.good()) goto finish;2195 2196 is >> ch; // get the next lexeme2197 2198 if (!is.good()) goto finish;2199 2200#ifdef BOOST_NO_STD_LOCALE2201 cc = ch;2202#else2203 cc = ct.narrow(ch, char());2204#endif /* BOOST_NO_STD_LOCALE */2205 2206 if (cc == ')') // read "((a),(c,d),x)"2207 {2208 o = octonion<T>(u,v,x);2209 }2210 else if (cc == ',') // read "((a),(c,d),x,"2211 {2212 is >> y; // read "((a),(c,d),x,y"2213 2214 if (!is.good()) goto finish;2215 2216 is >> ch; // get the next lexeme2217 2218 if (!is.good()) goto finish;2219 2220#ifdef BOOST_NO_STD_LOCALE2221 cc = ch;2222#else2223 cc = ct.narrow(ch, char());2224#endif /* BOOST_NO_STD_LOCALE */2225 2226 if (cc == ')') // read "((a),(c,d),x,y)"2227 {2228 o = octonion<T>(u,v,x,y);2229 }2230 else // error2231 {2232 is.setstate(::std::ios_base::failbit);2233 }2234 }2235 else // error2236 {2237 is.setstate(::std::ios_base::failbit);2238 }2239 }2240 else // error2241 {2242 is.setstate(::std::ios_base::failbit);2243 }2244 }2245 else if (cc == ',') // read "((a),(e,f," (ambiguity resolution)2246 {2247 p = ::boost::math::quaternion<T>(a);2248 2249 is >> g; // read "((a),(e,f,g" (too late to backtrack)2250 2251 if (!is.good()) goto finish;2252 2253 is >> ch; // get the next lexeme2254 2255 if (!is.good()) goto finish;2256 2257#ifdef BOOST_NO_STD_LOCALE2258 cc = ch;2259#else2260 cc = ct.narrow(ch, char());2261#endif /* BOOST_NO_STD_LOCALE */2262 2263 if (cc == ')') // read "((a),(e,f,g)"2264 {2265 q = ::boost::math::quaternion<T>(c,d,g); // "c" was actually "e", and "d" was actually "f"2266 2267 is >> ch; // get the next lexeme2268 2269 if (!is.good()) goto finish;2270 2271#ifdef BOOST_NO_STD_LOCALE2272 cc = ch;2273#else2274 cc = ct.narrow(ch, char());2275#endif /* BOOST_NO_STD_LOCALE */2276 2277 if (cc == ')') // read "((a),(e,f,g))"2278 {2279 o = octonion<T>(p,q);2280 }2281 else // error2282 {2283 is.setstate(::std::ios_base::failbit);2284 }2285 }2286 else if (cc == ',') // read "((a),(e,f,g,"2287 {2288 is >> h; // read "((a),(e,f,g,h"2289 2290 if (!is.good()) goto finish;2291 2292 is >> ch; // get the next lexeme2293 2294 if (!is.good()) goto finish;2295 2296#ifdef BOOST_NO_STD_LOCALE2297 cc = ch;2298#else2299 cc = ct.narrow(ch, char());2300#endif /* BOOST_NO_STD_LOCALE */2301 2302 if (cc == ')') // read "((a),(e,f,g,h)"2303 {2304 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" was actually "e", and "d" was actually "f"2305 2306 is >> ch; // get the next lexeme2307 2308 if (!is.good()) goto finish;2309 2310#ifdef BOOST_NO_STD_LOCALE2311 cc = ch;2312#else2313 cc = ct.narrow(ch, char());2314#endif /* BOOST_NO_STD_LOCALE */2315 2316 if (cc == ')') // read "((a),(e,f,g,h))"2317 {2318 o = octonion<T>(p,q);2319 }2320 else // error2321 {2322 is.setstate(::std::ios_base::failbit);2323 }2324 }2325 else // error2326 {2327 is.setstate(::std::ios_base::failbit);2328 }2329 }2330 else // error2331 {2332 is.setstate(::std::ios_base::failbit);2333 }2334 }2335 else // error2336 {2337 is.setstate(::std::ios_base::failbit);2338 }2339 }2340 }2341 else // error2342 {2343 is.setstate(::std::ios_base::failbit);2344 }2345 }2346 }2347 else // read "((a),c" (ambiguity resolution)2348 {2349 is.putback(ch);2350 2351 is >> c; // we extract the third component2352 2353 if (!is.good()) goto finish;2354 2355 is >> ch; // get the next lexeme2356 2357 if (!is.good()) goto finish;2358 2359#ifdef BOOST_NO_STD_LOCALE2360 cc = ch;2361#else2362 cc = ct.narrow(ch, char());2363#endif /* BOOST_NO_STD_LOCALE */2364 2365 if (cc == ')') // read "((a),c)"2366 {2367 o = octonion<T>(a,b,c);2368 }2369 else if (cc == ',') // read "((a),c,"2370 {2371 is >> x; // read "((a),c,x"2372 2373 if (!is.good()) goto finish;2374 2375 is >> ch; // get the next lexeme2376 2377 if (!is.good()) goto finish;2378 2379#ifdef BOOST_NO_STD_LOCALE2380 cc = ch;2381#else2382 cc = ct.narrow(ch, char());2383#endif /* BOOST_NO_STD_LOCALE */2384 2385 if (cc == ')') // read "((a),c,x)"2386 {2387 o = octonion<T>(a,b,c,d,x.real(),x.imag());2388 }2389 else if (cc == ',') // read "((a),c,x,"2390 {2391 is >> y;if (!is.good()) goto finish; // read "((a),c,x,y"2392 2393 is >> ch; // get the next lexeme2394 2395 if (!is.good()) goto finish;2396 2397#ifdef BOOST_NO_STD_LOCALE2398 cc = ch;2399#else2400 cc = ct.narrow(ch, char());2401#endif /* BOOST_NO_STD_LOCALE */2402 2403 if (cc == ')') // read "((a),c,x,y)"2404 {2405 o = octonion<T>(a,b,c,d,x.real(),x.imag(),y.real(),y.imag());2406 }2407 else // error2408 {2409 is.setstate(::std::ios_base::failbit);2410 }2411 }2412 else // error2413 {2414 is.setstate(::std::ios_base::failbit);2415 }2416 }2417 else // error2418 {2419 is.setstate(::std::ios_base::failbit);2420 }2421 }2422 }2423 else // error2424 {2425 is.setstate(::std::ios_base::failbit);2426 }2427 }2428 else if (cc ==',') // read "((a,"2429 {2430 is >> ch; // get the next lexeme2431 2432 if (!is.good()) goto finish;2433 2434#ifdef BOOST_NO_STD_LOCALE2435 cc = ch;2436#else2437 cc = ct.narrow(ch, char());2438#endif /* BOOST_NO_STD_LOCALE */2439 2440 if (cc == '(') // read "((a,("2441 {2442 u = ::std::complex<T>(a);2443 2444 is.putback(ch); // can only backtrack so much2445 2446 is >> v; // read "((a,v"2447 2448 if (!is.good()) goto finish;2449 2450 is >> ch; // get the next lexeme2451 2452 if (!is.good()) goto finish;2453 2454#ifdef BOOST_NO_STD_LOCALE2455 cc = ch;2456#else2457 cc = ct.narrow(ch, char());2458#endif /* BOOST_NO_STD_LOCALE */2459 2460 if (cc == ')') // read "((a,v)"2461 {2462 is >> ch; // get the next lexeme2463 2464 if (!is.good()) goto finish;2465 2466#ifdef BOOST_NO_STD_LOCALE2467 cc = ch;2468#else2469 cc = ct.narrow(ch, char());2470#endif /* BOOST_NO_STD_LOCALE */2471 2472 if (cc == ')') // read "((a,v))"2473 {2474 o = octonion<T>(u,v);2475 }2476 else if (cc == ',') // read "((a,v),"2477 {2478 p = ::boost::math::quaternion<T>(u,v);2479 2480 is >> q; // read "((a,v),q"2481 2482 if (!is.good()) goto finish;2483 2484 is >> ch; // get the next lexeme2485 2486 if (!is.good()) goto finish;2487 2488#ifdef BOOST_NO_STD_LOCALE2489 cc = ch;2490#else2491 cc = ct.narrow(ch, char());2492#endif /* BOOST_NO_STD_LOCALE */2493 2494 if (cc == ')') // read "((a,v),q)"2495 {2496 o = octonion<T>(p,q);2497 }2498 else // error2499 {2500 is.setstate(::std::ios_base::failbit);2501 }2502 }2503 else // error2504 {2505 is.setstate(::std::ios_base::failbit);2506 }2507 }2508 else // error2509 {2510 is.setstate(::std::ios_base::failbit);2511 }2512 }2513 else2514 {2515 is.putback(ch);2516 2517 is >> b; // read "((a,b"2518 2519 if (!is.good()) goto finish;2520 2521 is >> ch; // get the next lexeme2522 2523 if (!is.good()) goto finish;2524 2525#ifdef BOOST_NO_STD_LOCALE2526 cc = ch;2527#else2528 cc = ct.narrow(ch, char());2529#endif /* BOOST_NO_STD_LOCALE */2530 2531 if (cc == ')') // read "((a,b)"2532 {2533 is >> ch; // get the next lexeme2534 2535 if (!is.good()) goto finish;2536 2537#ifdef BOOST_NO_STD_LOCALE2538 cc = ch;2539#else2540 cc = ct.narrow(ch, char());2541#endif /* BOOST_NO_STD_LOCALE */2542 2543 if (cc == ')') // read "((a,b))"2544 {2545 o = octonion<T>(a,b);2546 }2547 else if (cc == ',') // read "((a,b),"2548 {2549 is >> ch; // get the next lexeme2550 2551 if (!is.good()) goto finish;2552 2553#ifdef BOOST_NO_STD_LOCALE2554 cc = ch;2555#else2556 cc = ct.narrow(ch, char());2557#endif /* BOOST_NO_STD_LOCALE */2558 2559 if (cc == '(') // read "((a,b),("2560 {2561 is >> ch; // get the next lexeme2562 2563 if (!is.good()) goto finish;2564 2565#ifdef BOOST_NO_STD_LOCALE2566 cc = ch;2567#else2568 cc = ct.narrow(ch, char());2569#endif /* BOOST_NO_STD_LOCALE */2570 2571 if (cc == '(') // read "((a,b),(("2572 {2573 p = ::boost::math::quaternion<T>(a,b);2574 2575 is.putback(ch);2576 2577 is.putback(ch); // we backtrack twice, with the same value2578 2579 is >> q; // read "((a,b),q"2580 2581 if (!is.good()) goto finish;2582 2583 is >> ch; // get the next lexeme2584 2585 if (!is.good()) goto finish;2586 2587#ifdef BOOST_NO_STD_LOCALE2588 cc = ch;2589#else2590 cc = ct.narrow(ch, char());2591#endif /* BOOST_NO_STD_LOCALE */2592 2593 if (cc == ')') // read "((a,b),q)"2594 {2595 o = octonion<T>(p,q);2596 }2597 else // error2598 {2599 is.setstate(::std::ios_base::failbit);2600 }2601 }2602 else // read "((a,b),(c" or "((a,b),(e"2603 {2604 is.putback(ch);2605 2606 is >> c;2607 2608 if (!is.good()) goto finish;2609 2610 is >> ch; // get the next lexeme2611 2612 if (!is.good()) goto finish;2613 2614#ifdef BOOST_NO_STD_LOCALE2615 cc = ch;2616#else2617 cc = ct.narrow(ch, char());2618#endif /* BOOST_NO_STD_LOCALE */2619 2620 if (cc == ')') // read "((a,b),(c)" (ambiguity resolution)2621 {2622 is >> ch; // get the next lexeme2623 2624 if (!is.good()) goto finish;2625 2626#ifdef BOOST_NO_STD_LOCALE2627 cc = ch;2628#else2629 cc = ct.narrow(ch, char());2630#endif /* BOOST_NO_STD_LOCALE */2631 2632 if (cc == ')') // read "((a,b),(c))"2633 {2634 o = octonion<T>(a,b,c);2635 }2636 else if (cc == ',') // read "((a,b),(c),"2637 {2638 u = ::std::complex<T>(a,b);2639 2640 v = ::std::complex<T>(c);2641 2642 is >> x; // read "((a,b),(c),x"2643 2644 if (!is.good()) goto finish;2645 2646 is >> ch; // get the next lexeme2647 2648 if (!is.good()) goto finish;2649 2650#ifdef BOOST_NO_STD_LOCALE2651 cc = ch;2652#else2653 cc = ct.narrow(ch, char());2654#endif /* BOOST_NO_STD_LOCALE */2655 2656 if (cc == ')') // read "((a,b),(c),x)"2657 {2658 o = octonion<T>(u,v,x);2659 }2660 else if (cc == ',') // read "((a,b),(c),x,"2661 {2662 is >> y; // read "((a,b),(c),x,y"2663 2664 if (!is.good()) goto finish;2665 2666 is >> ch; // get the next lexeme2667 2668 if (!is.good()) goto finish;2669 2670#ifdef BOOST_NO_STD_LOCALE2671 cc = ch;2672#else2673 cc = ct.narrow(ch, char());2674#endif /* BOOST_NO_STD_LOCALE */2675 2676 if (cc == ')') // read "((a,b),(c),x,y)"2677 {2678 o = octonion<T>(u,v,x,y);2679 }2680 else // error2681 {2682 is.setstate(::std::ios_base::failbit);2683 }2684 }2685 else // error2686 {2687 is.setstate(::std::ios_base::failbit);2688 }2689 }2690 else // error2691 {2692 is.setstate(::std::ios_base::failbit);2693 }2694 }2695 else if (cc == ',') // read "((a,b),(c," or "((a,b),(e,"2696 {2697 is >> ch; // get the next lexeme2698 2699 if (!is.good()) goto finish;2700 2701#ifdef BOOST_NO_STD_LOCALE2702 cc = ch;2703#else2704 cc = ct.narrow(ch, char());2705#endif /* BOOST_NO_STD_LOCALE */2706 2707 if (cc == '(') // read "((a,b),(e,(" (ambiguity resolution)2708 {2709 u = ::std::complex<T>(a,b);2710 2711 x = ::std::complex<T>(c); // "c" is actually "e"2712 2713 is.putback(ch);2714 2715 is >> y; // read "((a,b),(e,y"2716 2717 if (!is.good()) goto finish;2718 2719 is >> ch; // get the next lexeme2720 2721 if (!is.good()) goto finish;2722 2723#ifdef BOOST_NO_STD_LOCALE2724 cc = ch;2725#else2726 cc = ct.narrow(ch, char());2727#endif /* BOOST_NO_STD_LOCALE */2728 2729 if (cc == ')') // read "((a,b),(e,y)"2730 {2731 is >> ch; // get the next lexeme2732 2733 if (!is.good()) goto finish;2734 2735#ifdef BOOST_NO_STD_LOCALE2736 cc = ch;2737#else2738 cc = ct.narrow(ch, char());2739#endif /* BOOST_NO_STD_LOCALE */2740 2741 if (cc == ')') // read "((a,b),(e,y))"2742 {2743 o = octonion<T>(u,v,x,y);2744 }2745 else // error2746 {2747 is.setstate(::std::ios_base::failbit);2748 }2749 }2750 else // error2751 {2752 is.setstate(::std::ios_base::failbit);2753 }2754 }2755 else // read "((a,b),(c,d" or "((a,b),(e,f"2756 {2757 is.putback(ch);2758 2759 is >> d;2760 2761 if (!is.good()) goto finish;2762 2763 is >> ch; // get the next lexeme2764 2765 if (!is.good()) goto finish;2766 2767#ifdef BOOST_NO_STD_LOCALE2768 cc = ch;2769#else2770 cc = ct.narrow(ch, char());2771#endif /* BOOST_NO_STD_LOCALE */2772 2773 if (cc == ')') // read "((a,b),(c,d)" (ambiguity resolution)2774 {2775 u = ::std::complex<T>(a,b);2776 2777 v = ::std::complex<T>(c,d);2778 2779 is >> ch; // get the next lexeme2780 2781 if (!is.good()) goto finish;2782 2783#ifdef BOOST_NO_STD_LOCALE2784 cc = ch;2785#else2786 cc = ct.narrow(ch, char());2787#endif /* BOOST_NO_STD_LOCALE */2788 2789 if (cc == ')') // read "((a,b),(c,d))"2790 {2791 o = octonion<T>(u,v);2792 }2793 else if (cc == ',') // read "((a,b),(c,d),"2794 {2795 is >> x; // read "((a,b),(c,d),x2796 2797 if (!is.good()) goto finish;2798 2799 is >> ch; // get the next lexeme2800 2801 if (!is.good()) goto finish;2802 2803#ifdef BOOST_NO_STD_LOCALE2804 cc = ch;2805#else2806 cc = ct.narrow(ch, char());2807#endif /* BOOST_NO_STD_LOCALE */2808 2809 if (cc == ')') // read "((a,b),(c,d),x)"2810 {2811 o = octonion<T>(u,v,x);2812 }2813 else if (cc == ',') // read "((a,b),(c,d),x,"2814 {2815 is >> y; // read "((a,b),(c,d),x,y"2816 2817 if (!is.good()) goto finish;2818 2819 is >> ch; // get the next lexeme2820 2821 if (!is.good()) goto finish;2822 2823#ifdef BOOST_NO_STD_LOCALE2824 cc = ch;2825#else2826 cc = ct.narrow(ch, char());2827#endif /* BOOST_NO_STD_LOCALE */2828 2829 if (cc == ')') // read "((a,b),(c,d),x,y)"2830 {2831 o = octonion<T>(u,v,x,y);2832 }2833 else // error2834 {2835 is.setstate(::std::ios_base::failbit);2836 }2837 }2838 else // error2839 {2840 is.setstate(::std::ios_base::failbit);2841 }2842 }2843 else // error2844 {2845 is.setstate(::std::ios_base::failbit);2846 }2847 }2848 else if (cc == ',') // read "((a,b),(e,f," (ambiguity resolution)2849 {2850 p = ::boost::math::quaternion<T>(a,b); // too late to backtrack2851 2852 is >> g; // read "((a,b),(e,f,g"2853 2854 if (!is.good()) goto finish;2855 2856 is >> ch; // get the next lexeme2857 2858 if (!is.good()) goto finish;2859 2860#ifdef BOOST_NO_STD_LOCALE2861 cc = ch;2862#else2863 cc = ct.narrow(ch, char());2864#endif /* BOOST_NO_STD_LOCALE */2865 2866 if (cc == ')') // read "((a,b),(e,f,g)"2867 {2868 is >> ch; // get the next lexeme2869 2870 if (!is.good()) goto finish;2871 2872#ifdef BOOST_NO_STD_LOCALE2873 cc = ch;2874#else2875 cc = ct.narrow(ch, char());2876#endif /* BOOST_NO_STD_LOCALE */2877 2878 if (cc == ')') // read "((a,b),(e,f,g))"2879 {2880 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f"2881 2882 o = octonion<T>(p,q);2883 }2884 else // error2885 {2886 is.setstate(::std::ios_base::failbit);2887 }2888 }2889 else if (cc == ',') // read "((a,b),(e,f,g,"2890 {2891 is >> h; // read "((a,b),(e,f,g,h"2892 2893 if (!is.good()) goto finish;2894 2895 is >> ch; // get the next lexeme2896 2897 if (!is.good()) goto finish;2898 2899#ifdef BOOST_NO_STD_LOCALE2900 cc = ch;2901#else2902 cc = ct.narrow(ch, char());2903#endif /* BOOST_NO_STD_LOCALE */2904 2905 if (cc == ')') // read "((a,b),(e,f,g,h)"2906 {2907 is >> ch; // get the next lexeme2908 2909 if (!is.good()) goto finish;2910 2911#ifdef BOOST_NO_STD_LOCALE2912 cc = ch;2913#else2914 cc = ct.narrow(ch, char());2915#endif /* BOOST_NO_STD_LOCALE */2916 2917 if (cc == ')') // read ((a,b),(e,f,g,h))"2918 {2919 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f"2920 2921 o = octonion<T>(p,q);2922 }2923 else // error2924 {2925 is.setstate(::std::ios_base::failbit);2926 }2927 }2928 else // error2929 {2930 is.setstate(::std::ios_base::failbit);2931 }2932 }2933 else // error2934 {2935 is.setstate(::std::ios_base::failbit);2936 }2937 }2938 else // error2939 {2940 is.setstate(::std::ios_base::failbit);2941 }2942 }2943 }2944 else // error2945 {2946 is.setstate(::std::ios_base::failbit);2947 }2948 }2949 }2950 else // error2951 {2952 is.setstate(::std::ios_base::failbit);2953 }2954 }2955 else // error2956 {2957 is.setstate(::std::ios_base::failbit);2958 }2959 }2960 else if (cc == ',') // read "((a,b,"2961 {2962 is >> c; // read "((a,b,c"2963 2964 if (!is.good()) goto finish;2965 2966 is >> ch; // get the next lexeme2967 2968 if (!is.good()) goto finish;2969 2970#ifdef BOOST_NO_STD_LOCALE2971 cc = ch;2972#else2973 cc = ct.narrow(ch, char());2974#endif /* BOOST_NO_STD_LOCALE */2975 2976 if (cc == ')') // read "((a,b,c)"2977 {2978 is >> ch; // get the next lexeme2979 2980 if (!is.good()) goto finish;2981 2982#ifdef BOOST_NO_STD_LOCALE2983 cc = ch;2984#else2985 cc = ct.narrow(ch, char());2986#endif /* BOOST_NO_STD_LOCALE */2987 2988 if (cc == ')') // read "((a,b,c))"2989 {2990 o = octonion<T>(a,b,c);2991 }2992 else if (cc == ',') // read "((a,b,c),"2993 {2994 p = ::boost::math::quaternion<T>(a,b,c);2995 2996 is >> q; // read "((a,b,c),q"2997 2998 if (!is.good()) goto finish;2999 3000 is >> ch; // get the next lexeme3001 3002 if (!is.good()) goto finish;3003 3004#ifdef BOOST_NO_STD_LOCALE3005 cc = ch;3006#else3007 cc = ct.narrow(ch, char());3008#endif /* BOOST_NO_STD_LOCALE */3009 3010 if (cc == ')') // read "((a,b,c),q)"3011 {3012 o = octonion<T>(p,q);3013 }3014 else // error3015 {3016 is.setstate(::std::ios_base::failbit);3017 }3018 }3019 else // error3020 {3021 is.setstate(::std::ios_base::failbit);3022 }3023 }3024 else if (cc == ',') // read "((a,b,c,"3025 {3026 is >> d; // read "((a,b,c,d"3027 3028 if (!is.good()) goto finish;3029 3030 is >> ch; // get the next lexeme3031 3032 if (!is.good()) goto finish;3033 3034#ifdef BOOST_NO_STD_LOCALE3035 cc = ch;3036#else3037 cc = ct.narrow(ch, char());3038#endif /* BOOST_NO_STD_LOCALE */3039 3040 if (cc == ')') // read "((a,b,c,d)"3041 {3042 is >> ch; // get the next lexeme3043 3044 if (!is.good()) goto finish;3045 3046#ifdef BOOST_NO_STD_LOCALE3047 cc = ch;3048#else3049 cc = ct.narrow(ch, char());3050#endif /* BOOST_NO_STD_LOCALE */3051 3052 if (cc == ')') // read "((a,b,c,d))"3053 {3054 o = octonion<T>(a,b,c,d);3055 }3056 else if (cc == ',') // read "((a,b,c,d),"3057 {3058 p = ::boost::math::quaternion<T>(a,b,c,d);3059 3060 is >> q; // read "((a,b,c,d),q"3061 3062 if (!is.good()) goto finish;3063 3064 is >> ch; // get the next lexeme3065 3066 if (!is.good()) goto finish;3067 3068#ifdef BOOST_NO_STD_LOCALE3069 cc = ch;3070#else3071 cc = ct.narrow(ch, char());3072#endif /* BOOST_NO_STD_LOCALE */3073 3074 if (cc == ')') // read "((a,b,c,d),q)"3075 {3076 o = octonion<T>(p,q);3077 }3078 else // error3079 {3080 is.setstate(::std::ios_base::failbit);3081 }3082 }3083 else // error3084 {3085 is.setstate(::std::ios_base::failbit);3086 }3087 }3088 else // error3089 {3090 is.setstate(::std::ios_base::failbit);3091 }3092 }3093 else // error3094 {3095 is.setstate(::std::ios_base::failbit);3096 }3097 }3098 else // error3099 {3100 is.setstate(::std::ios_base::failbit);3101 }3102 }3103 }3104 else // error3105 {3106 is.setstate(::std::ios_base::failbit);3107 }3108 }3109 }3110 else // read "(a"3111 {3112 is.putback(ch);3113 3114 is >> a; // we extract the first component3115 3116 if (!is.good()) goto finish;3117 3118 is >> ch; // get the next lexeme3119 3120 if (!is.good()) goto finish;3121 3122#ifdef BOOST_NO_STD_LOCALE3123 cc = ch;3124#else3125 cc = ct.narrow(ch, char());3126#endif /* BOOST_NO_STD_LOCALE */3127 3128 if (cc == ')') // read "(a)"3129 {3130 o = octonion<T>(a);3131 }3132 else if (cc == ',') // read "(a,"3133 {3134 is >> ch; // get the next lexeme3135 3136 if (!is.good()) goto finish;3137 3138#ifdef BOOST_NO_STD_LOCALE3139 cc = ch;3140#else3141 cc = ct.narrow(ch, char());3142#endif /* BOOST_NO_STD_LOCALE */3143 3144 if (cc == '(') // read "(a,("3145 {3146 is >> ch; // get the next lexeme3147 3148 if (!is.good()) goto finish;3149 3150#ifdef BOOST_NO_STD_LOCALE3151 cc = ch;3152#else3153 cc = ct.narrow(ch, char());3154#endif /* BOOST_NO_STD_LOCALE */3155 3156 if (cc == '(') // read "(a,(("3157 {3158 p = ::boost::math::quaternion<T>(a);3159 3160 is.putback(ch);3161 3162 is.putback(ch); // we backtrack twice, with the same value3163 3164 is >> q; // read "(a,q"3165 3166 if (!is.good()) goto finish;3167 3168 is >> ch; // get the next lexeme3169 3170 if (!is.good()) goto finish;3171 3172#ifdef BOOST_NO_STD_LOCALE3173 cc = ch;3174#else3175 cc = ct.narrow(ch, char());3176#endif /* BOOST_NO_STD_LOCALE */3177 3178 if (cc == ')') // read "(a,q)"3179 {3180 o = octonion<T>(p,q);3181 }3182 else // error3183 {3184 is.setstate(::std::ios_base::failbit);3185 }3186 }3187 else // read "(a,(c" or "(a,(e"3188 {3189 is.putback(ch);3190 3191 is >> c;3192 3193 if (!is.good()) goto finish;3194 3195 is >> ch; // get the next lexeme3196 3197 if (!is.good()) goto finish;3198 3199#ifdef BOOST_NO_STD_LOCALE3200 cc = ch;3201#else3202 cc = ct.narrow(ch, char());3203#endif /* BOOST_NO_STD_LOCALE */3204 3205 if (cc == ')') // read "(a,(c)" (ambiguity resolution)3206 {3207 is >> ch; // get the next lexeme3208 3209 if (!is.good()) goto finish;3210 3211#ifdef BOOST_NO_STD_LOCALE3212 cc = ch;3213#else3214 cc = ct.narrow(ch, char());3215#endif /* BOOST_NO_STD_LOCALE */3216 3217 if (cc == ')') // read "(a,(c))"3218 {3219 o = octonion<T>(a,b,c);3220 }3221 else if (cc == ',') // read "(a,(c),"3222 {3223 u = ::std::complex<T>(a);3224 3225 v = ::std::complex<T>(c);3226 3227 is >> x; // read "(a,(c),x"3228 3229 if (!is.good()) goto finish;3230 3231 is >> ch; // get the next lexeme3232 3233 if (!is.good()) goto finish;3234 3235#ifdef BOOST_NO_STD_LOCALE3236 cc = ch;3237#else3238 cc = ct.narrow(ch, char());3239#endif /* BOOST_NO_STD_LOCALE */3240 3241 if (cc == ')') // read "(a,(c),x)"3242 {3243 o = octonion<T>(u,v,x);3244 }3245 else if (cc == ',') // read "(a,(c),x,"3246 {3247 is >> y; // read "(a,(c),x,y"3248 3249 if (!is.good()) goto finish;3250 3251 is >> ch; // get the next lexeme3252 3253 if (!is.good()) goto finish;3254 3255#ifdef BOOST_NO_STD_LOCALE3256 cc = ch;3257#else3258 cc = ct.narrow(ch, char());3259#endif /* BOOST_NO_STD_LOCALE */3260 3261 if (cc == ')') // read "(a,(c),x,y)"3262 {3263 o = octonion<T>(u,v,x,y);3264 }3265 else // error3266 {3267 is.setstate(::std::ios_base::failbit);3268 }3269 }3270 else // error3271 {3272 is.setstate(::std::ios_base::failbit);3273 }3274 }3275 else // error3276 {3277 is.setstate(::std::ios_base::failbit);3278 }3279 }3280 else if (cc == ',') // read "(a,(c," or "(a,(e,"3281 {3282 is >> ch; // get the next lexeme3283 3284 if (!is.good()) goto finish;3285 3286#ifdef BOOST_NO_STD_LOCALE3287 cc = ch;3288#else3289 cc = ct.narrow(ch, char());3290#endif /* BOOST_NO_STD_LOCALE */3291 3292 if (cc == '(') // read "(a,(e,(" (ambiguity resolution)3293 {3294 u = ::std::complex<T>(a);3295 3296 x = ::std::complex<T>(c); // "c" is actually "e"3297 3298 is.putback(ch); // we backtrack3299 3300 is >> y; // read "(a,(e,y"3301 3302 if (!is.good()) goto finish;3303 3304 is >> ch; // get the next lexeme3305 3306 if (!is.good()) goto finish;3307 3308#ifdef BOOST_NO_STD_LOCALE3309 cc = ch;3310#else3311 cc = ct.narrow(ch, char());3312#endif /* BOOST_NO_STD_LOCALE */3313 3314 if (cc == ')') // read "(a,(e,y)"3315 {3316 is >> ch; // get the next lexeme3317 3318 if (!is.good()) goto finish;3319 3320#ifdef BOOST_NO_STD_LOCALE3321 cc = ch;3322#else3323 cc = ct.narrow(ch, char());3324#endif /* BOOST_NO_STD_LOCALE */3325 3326 if (cc == ')') // read "(a,(e,y))"3327 {3328 o = octonion<T>(u,v,x,y);3329 }3330 else // error3331 {3332 is.setstate(::std::ios_base::failbit);3333 }3334 }3335 else // error3336 {3337 is.setstate(::std::ios_base::failbit);3338 }3339 }3340 else // read "(a,(c,d" or "(a,(e,f"3341 {3342 is.putback(ch);3343 3344 is >> d;3345 3346 if (!is.good()) goto finish;3347 3348 is >> ch; // get the next lexeme3349 3350 if (!is.good()) goto finish;3351 3352#ifdef BOOST_NO_STD_LOCALE3353 cc = ch;3354#else3355 cc = ct.narrow(ch, char());3356#endif /* BOOST_NO_STD_LOCALE */3357 3358 if (cc == ')') // read "(a,(c,d)" (ambiguity resolution)3359 {3360 is >> ch; // get the next lexeme3361 3362 if (!is.good()) goto finish;3363 3364#ifdef BOOST_NO_STD_LOCALE3365 cc = ch;3366#else3367 cc = ct.narrow(ch, char());3368#endif /* BOOST_NO_STD_LOCALE */3369 3370 if (cc == ')') // read "(a,(c,d))"3371 {3372 o = octonion<T>(a,b,c,d);3373 }3374 else if (cc == ',') // read "(a,(c,d),"3375 {3376 u = ::std::complex<T>(a);3377 3378 v = ::std::complex<T>(c,d);3379 3380 is >> x; // read "(a,(c,d),x"3381 3382 if (!is.good()) goto finish;3383 3384 is >> ch; // get the next lexeme3385 3386 if (!is.good()) goto finish;3387 3388#ifdef BOOST_NO_STD_LOCALE3389 cc = ch;3390#else3391 cc = ct.narrow(ch, char());3392#endif /* BOOST_NO_STD_LOCALE */3393 3394 if (cc == ')') // read "(a,(c,d),x)"3395 {3396 o = octonion<T>(u,v,x);3397 }3398 else if (cc == ',') // read "(a,(c,d),x,"3399 {3400 is >> y; // read "(a,(c,d),x,y"3401 3402 if (!is.good()) goto finish;3403 3404 is >> ch; // get the next lexeme3405 3406 if (!is.good()) goto finish;3407 3408#ifdef BOOST_NO_STD_LOCALE3409 cc = ch;3410#else3411 cc = ct.narrow(ch, char());3412#endif /* BOOST_NO_STD_LOCALE */3413 3414 if (cc == ')') // read "(a,(c,d),x,y)"3415 {3416 o = octonion<T>(u,v,x,y);3417 }3418 else // error3419 {3420 is.setstate(::std::ios_base::failbit);3421 }3422 }3423 else // error3424 {3425 is.setstate(::std::ios_base::failbit);3426 }3427 }3428 else // error3429 {3430 is.setstate(::std::ios_base::failbit);3431 }3432 }3433 else if (cc == ',') // read "(a,(e,f," (ambiguity resolution)3434 {3435 p = ::boost::math::quaternion<T>(a);3436 3437 is >> g; // read "(a,(e,f,g"3438 3439 if (!is.good()) goto finish;3440 3441 is >> ch; // get the next lexeme3442 3443 if (!is.good()) goto finish;3444 3445#ifdef BOOST_NO_STD_LOCALE3446 cc = ch;3447#else3448 cc = ct.narrow(ch, char());3449#endif /* BOOST_NO_STD_LOCALE */3450 3451 if (cc == ')') // read "(a,(e,f,g)"3452 {3453 is >> ch; // get the next lexeme3454 3455 if (!is.good()) goto finish;3456 3457#ifdef BOOST_NO_STD_LOCALE3458 cc = ch;3459#else3460 cc = ct.narrow(ch, char());3461#endif /* BOOST_NO_STD_LOCALE */3462 3463 if (cc == ')') // read "(a,(e,f,g))"3464 {3465 q = ::boost::math::quaternion<T>(c,d,g); // "c" is actually "e" and "d" is actually "f"3466 3467 o = octonion<T>(p,q);3468 }3469 else // error3470 {3471 is.setstate(::std::ios_base::failbit);3472 }3473 }3474 else if (cc == ',') // read "(a,(e,f,g,"3475 {3476 is >> h; // read "(a,(e,f,g,h"3477 3478 if (!is.good()) goto finish;3479 3480 is >> ch; // get the next lexeme3481 3482 if (!is.good()) goto finish;3483 3484#ifdef BOOST_NO_STD_LOCALE3485 cc = ch;3486#else3487 cc = ct.narrow(ch, char());3488#endif /* BOOST_NO_STD_LOCALE */3489 3490 if (cc == ')') // read "(a,(e,f,g,h)"3491 {3492 is >> ch; // get the next lexeme3493 3494 if (!is.good()) goto finish;3495 3496#ifdef BOOST_NO_STD_LOCALE3497 cc = ch;3498#else3499 cc = ct.narrow(ch, char());3500#endif /* BOOST_NO_STD_LOCALE */3501 3502 if (cc == ')') // read "(a,(e,f,g,h))"3503 {3504 q = ::boost::math::quaternion<T>(c,d,g,h); // "c" is actually "e" and "d" is actually "f"3505 3506 o = octonion<T>(p,q);3507 }3508 else // error3509 {3510 is.setstate(::std::ios_base::failbit);3511 }3512 }3513 else // error3514 {3515 is.setstate(::std::ios_base::failbit);3516 }3517 }3518 else // error3519 {3520 is.setstate(::std::ios_base::failbit);3521 }3522 }3523 else // error3524 {3525 is.setstate(::std::ios_base::failbit);3526 }3527 }3528 }3529 else // error3530 {3531 is.setstate(::std::ios_base::failbit);3532 }3533 }3534 }3535 else // read "(a,b" or "(a,c" (ambiguity resolution)3536 {3537 is.putback(ch);3538 3539 is >> b;3540 3541 if (!is.good()) goto finish;3542 3543 is >> ch; // get the next lexeme3544 3545 if (!is.good()) goto finish;3546 3547#ifdef BOOST_NO_STD_LOCALE3548 cc = ch;3549#else3550 cc = ct.narrow(ch, char());3551#endif /* BOOST_NO_STD_LOCALE */3552 3553 if (cc == ')') // read "(a,b)" (ambiguity resolution)3554 {3555 o = octonion<T>(a,b);3556 }3557 else if (cc == ',') // read "(a,b," or "(a,c,"3558 {3559 is >> ch; // get the next lexeme3560 3561 if (!is.good()) goto finish;3562 3563#ifdef BOOST_NO_STD_LOCALE3564 cc = ch;3565#else3566 cc = ct.narrow(ch, char());3567#endif /* BOOST_NO_STD_LOCALE */3568 3569 if (cc == '(') // read "(a,c,(" (ambiguity resolution)3570 {3571 u = ::std::complex<T>(a);3572 3573 v = ::std::complex<T>(b); // "b" is actually "c"3574 3575 is.putback(ch); // we backtrack3576 3577 is >> x; // read "(a,c,x"3578 3579 if (!is.good()) goto finish;3580 3581 is >> ch; // get the next lexeme3582 3583 if (!is.good()) goto finish;3584 3585#ifdef BOOST_NO_STD_LOCALE3586 cc = ch;3587#else3588 cc = ct.narrow(ch, char());3589#endif /* BOOST_NO_STD_LOCALE */3590 3591 if (cc == ')') // read "(a,c,x)"3592 {3593 o = octonion<T>(u,v,x);3594 }3595 else if (cc == ',') // read "(a,c,x,"3596 {3597 is >> y; // read "(a,c,x,y" // read "(a,c,x"3598 3599 if (!is.good()) goto finish;3600 3601 is >> ch; // get the next lexeme3602 3603 if (!is.good()) goto finish;3604 3605#ifdef BOOST_NO_STD_LOCALE3606 cc = ch;3607#else3608 cc = ct.narrow(ch, char());3609#endif /* BOOST_NO_STD_LOCALE */3610 3611 if (cc == ')') // read "(a,c,x,y)"3612 {3613 o = octonion<T>(u,v,x,y);3614 }3615 else // error3616 {3617 is.setstate(::std::ios_base::failbit);3618 }3619 }3620 else // error3621 {3622 is.setstate(::std::ios_base::failbit);3623 }3624 }3625 else // read "(a,b,c" or "(a,c,e"3626 {3627 is.putback(ch);3628 3629 is >> c;3630 3631 if (!is.good()) goto finish;3632 3633 is >> ch; // get the next lexeme3634 3635 if (!is.good()) goto finish;3636 3637#ifdef BOOST_NO_STD_LOCALE3638 cc = ch;3639#else3640 cc = ct.narrow(ch, char());3641#endif /* BOOST_NO_STD_LOCALE */3642 3643 if (cc == ')') // read "(a,b,c)" (ambiguity resolution)3644 {3645 o = octonion<T>(a,b,c);3646 }3647 else if (cc == ',') // read "(a,b,c," or "(a,c,e,"3648 {3649 is >> ch; // get the next lexeme3650 3651 if (!is.good()) goto finish;3652 3653#ifdef BOOST_NO_STD_LOCALE3654 cc = ch;3655#else3656 cc = ct.narrow(ch, char());3657#endif /* BOOST_NO_STD_LOCALE */3658 3659 if (cc == '(') // read "(a,c,e,(") (ambiguity resolution)3660 {3661 u = ::std::complex<T>(a);3662 3663 v = ::std::complex<T>(b); // "b" is actually "c"3664 3665 x = ::std::complex<T>(c); // "c" is actually "e"3666 3667 is.putback(ch); // we backtrack3668 3669 is >> y; // read "(a,c,e,y"3670 3671 if (!is.good()) goto finish;3672 3673 is >> ch; // get the next lexeme3674 3675 if (!is.good()) goto finish;3676 3677#ifdef BOOST_NO_STD_LOCALE3678 cc = ch;3679#else3680 cc = ct.narrow(ch, char());3681#endif /* BOOST_NO_STD_LOCALE */3682 3683 if (cc == ')') // read "(a,c,e,y)"3684 {3685 o = octonion<T>(u,v,x,y);3686 }3687 else // error3688 {3689 is.setstate(::std::ios_base::failbit);3690 }3691 }3692 else // read "(a,b,c,d" (ambiguity resolution)3693 {3694 is.putback(ch); // we backtrack3695 3696 is >> d;3697 3698 if (!is.good()) goto finish;3699 3700 is >> ch; // get the next lexeme3701 3702 if (!is.good()) goto finish;3703 3704#ifdef BOOST_NO_STD_LOCALE3705 cc = ch;3706#else3707 cc = ct.narrow(ch, char());3708#endif /* BOOST_NO_STD_LOCALE */3709 3710 if (cc == ')') // read "(a,b,c,d)"3711 {3712 o = octonion<T>(a,b,c,d);3713 }3714 else if (cc == ',') // read "(a,b,c,d,"3715 {3716 is >> e; // read "(a,b,c,d,e"3717 3718 if (!is.good()) goto finish;3719 3720 is >> ch; // get the next lexeme3721 3722 if (!is.good()) goto finish;3723 3724#ifdef BOOST_NO_STD_LOCALE3725 cc = ch;3726#else3727 cc = ct.narrow(ch, char());3728#endif /* BOOST_NO_STD_LOCALE */3729 3730 if (cc == ')') // read "(a,b,c,d,e)"3731 {3732 o = octonion<T>(a,b,c,d,e);3733 }3734 else if (cc == ',') // read "(a,b,c,d,e,"3735 {3736 is >> f; // read "(a,b,c,d,e,f"3737 3738 if (!is.good()) goto finish;3739 3740 is >> ch; // get the next lexeme3741 3742 if (!is.good()) goto finish;3743 3744#ifdef BOOST_NO_STD_LOCALE3745 cc = ch;3746#else3747 cc = ct.narrow(ch, char());3748#endif /* BOOST_NO_STD_LOCALE */3749 3750 if (cc == ')') // read "(a,b,c,d,e,f)"3751 {3752 o = octonion<T>(a,b,c,d,e,f);3753 }3754 else if (cc == ',') // read "(a,b,c,d,e,f,"3755 {3756 is >> g; // read "(a,b,c,d,e,f,g" // read "(a,b,c,d,e,f"3757 3758 if (!is.good()) goto finish;3759 3760 is >> ch; // get the next lexeme3761 3762 if (!is.good()) goto finish;3763 3764#ifdef BOOST_NO_STD_LOCALE3765 cc = ch;3766#else3767 cc = ct.narrow(ch, char());3768#endif /* BOOST_NO_STD_LOCALE */3769 3770 if (cc == ')') // read "(a,b,c,d,e,f,g)"3771 {3772 o = octonion<T>(a,b,c,d,e,f,g);3773 }3774 else if (cc == ',') // read "(a,b,c,d,e,f,g,"3775 {3776 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"3777 3778 if (!is.good()) goto finish;3779 3780 is >> ch; // get the next lexeme3781 3782 if (!is.good()) goto finish;3783 3784#ifdef BOOST_NO_STD_LOCALE3785 cc = ch;3786#else3787 cc = ct.narrow(ch, char());3788#endif /* BOOST_NO_STD_LOCALE */3789 3790 if (cc == ')') // read "(a,b,c,d,e,f,g,h)"3791 {3792 o = octonion<T>(a,b,c,d,e,f,g,h);3793 }3794 else // error3795 {3796 is.setstate(::std::ios_base::failbit);3797 }3798 }3799 else // error3800 {3801 is.setstate(::std::ios_base::failbit);3802 }3803 }3804 else // error3805 {3806 is.setstate(::std::ios_base::failbit);3807 }3808 }3809 else // error3810 {3811 is.setstate(::std::ios_base::failbit);3812 }3813 }3814 else // error3815 {3816 is.setstate(::std::ios_base::failbit);3817 }3818 }3819 }3820 else // error3821 {3822 is.setstate(::std::ios_base::failbit);3823 }3824 }3825 }3826 else // error3827 {3828 is.setstate(::std::ios_base::failbit);3829 }3830 }3831 }3832 else // error3833 {3834 is.setstate(::std::ios_base::failbit);3835 }3836 }3837 }3838 else // format: a3839 {3840 is.putback(ch);3841 3842 is >> a; // we extract the first component3843 3844 if (!is.good()) goto finish;3845 3846 o = octonion<T>(a);3847 }3848 3849 finish:3850 return(is);3851 }3852 // LCOV_EXCL_STOP3853 3854 3855 template<typename T, typename charT, class traits>3856 ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,3857 octonion<T> const & o)3858 {3859 ::std::basic_ostringstream<charT,traits> s;3860 3861 s.flags(os.flags());3862#ifdef BOOST_NO_STD_LOCALE3863#else3864 s.imbue(os.getloc());3865#endif /* BOOST_NO_STD_LOCALE */3866 s.precision(os.precision());3867 3868 s << '(' << o.R_component_1() << ','3869 << o.R_component_2() << ','3870 << o.R_component_3() << ','3871 << o.R_component_4() << ','3872 << o.R_component_5() << ','3873 << o.R_component_6() << ','3874 << o.R_component_7() << ','3875 << o.R_component_8() << ')';3876 3877 return os << s.str();3878 }3879 3880 3881 // values3882 3883 template<typename T>3884 inline T real(octonion<T> const & o)3885 {3886 return(o.real());3887 }3888 3889 3890 template<typename T>3891 inline octonion<T> unreal(octonion<T> const & o)3892 {3893 return(o.unreal());3894 }3895 3896 3897#define BOOST_OCTONION_VALARRAY_LOADER \3898 using ::std::valarray; \3899 \3900 valarray<T> temp(8); \3901 \3902 temp[0] = o.R_component_1(); \3903 temp[1] = o.R_component_2(); \3904 temp[2] = o.R_component_3(); \3905 temp[3] = o.R_component_4(); \3906 temp[4] = o.R_component_5(); \3907 temp[5] = o.R_component_6(); \3908 temp[6] = o.R_component_7(); \3909 temp[7] = o.R_component_8();3910 3911 3912 template<typename T>3913 inline T sup(octonion<T> const & o)3914 {3915#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP3916 using ::std::abs;3917#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */3918 3919 BOOST_OCTONION_VALARRAY_LOADER3920 3921 return((abs(temp).max)());3922 }3923 3924 3925 template<typename T>3926 inline T l1(octonion<T> const & o)3927 {3928#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP3929 using ::std::abs;3930#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */3931 3932 BOOST_OCTONION_VALARRAY_LOADER3933 3934 return(abs(temp).sum());3935 }3936 3937 3938 template<typename T>3939 inline T abs(const octonion<T> & o)3940 {3941#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP3942 using ::std::abs;3943#endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */3944 3945 using ::std::sqrt;3946 3947 BOOST_OCTONION_VALARRAY_LOADER3948 3949 T maxim = (abs(temp).max)(); // overflow protection3950 3951 if (maxim == static_cast<T>(0))3952 {3953 return(maxim);3954 }3955 else3956 {3957 T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions3958 3959 temp *= mixam;3960 3961 temp *= temp;3962 3963 return(maxim*sqrt(temp.sum()));3964 }3965 3966 //return(::std::sqrt(norm(o)));3967 }3968 3969 3970#undef BOOST_OCTONION_VALARRAY_LOADER3971 3972 3973 // Note: This is the Cayley norm, not the Euclidean norm...3974 3975 template<typename T>3976 inline T norm(octonion<T> const & o)3977 {3978 return(real(o*conj(o)));3979 }3980 3981 3982 template<typename T>3983 inline octonion<T> conj(octonion<T> const & o)3984 {3985 return(octonion<T>( +o.R_component_1(),3986 -o.R_component_2(),3987 -o.R_component_3(),3988 -o.R_component_4(),3989 -o.R_component_5(),3990 -o.R_component_6(),3991 -o.R_component_7(),3992 -o.R_component_8()));3993 }3994 3995 3996 // Note: There is little point, for the octonions, to introduce the equivalents3997 // to the complex "arg" and the quaternionic "cylindropolar".3998 3999 4000 template<typename T>4001 inline octonion<T> spherical(T const & rho,4002 T const & theta,4003 T const & phi1,4004 T const & phi2,4005 T const & phi3,4006 T const & phi4,4007 T const & phi5,4008 T const & phi6)4009 {4010 using ::std::cos;4011 using ::std::sin;4012 4013 //T a = cos(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);4014 //T b = sin(theta)*cos(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);4015 //T c = sin(phi1)*cos(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);4016 //T d = sin(phi2)*cos(phi3)*cos(phi4)*cos(phi5)*cos(phi6);4017 //T e = sin(phi3)*cos(phi4)*cos(phi5)*cos(phi6);4018 //T f = sin(phi4)*cos(phi5)*cos(phi6);4019 //T g = sin(phi5)*cos(phi6);4020 //T h = sin(phi6);4021 4022 T courrant = static_cast<T>(1);4023 4024 T h = sin(phi6);4025 4026 courrant *= cos(phi6);4027 4028 T g = sin(phi5)*courrant;4029 4030 courrant *= cos(phi5);4031 4032 T f = sin(phi4)*courrant;4033 4034 courrant *= cos(phi4);4035 4036 T e = sin(phi3)*courrant;4037 4038 courrant *= cos(phi3);4039 4040 T d = sin(phi2)*courrant;4041 4042 courrant *= cos(phi2);4043 4044 T c = sin(phi1)*courrant;4045 4046 courrant *= cos(phi1);4047 4048 T b = sin(theta)*courrant;4049 T a = cos(theta)*courrant;4050 4051 return(rho*octonion<T>(a,b,c,d,e,f,g,h));4052 }4053 4054 4055 template<typename T>4056 inline octonion<T> multipolar(T const & rho1,4057 T const & theta1,4058 T const & rho2,4059 T const & theta2,4060 T const & rho3,4061 T const & theta3,4062 T const & rho4,4063 T const & theta4)4064 {4065 using ::std::cos;4066 using ::std::sin;4067 4068 T a = rho1*cos(theta1);4069 T b = rho1*sin(theta1);4070 T c = rho2*cos(theta2);4071 T d = rho2*sin(theta2);4072 T e = rho3*cos(theta3);4073 T f = rho3*sin(theta3);4074 T g = rho4*cos(theta4);4075 T h = rho4*sin(theta4);4076 4077 return(octonion<T>(a,b,c,d,e,f,g,h));4078 }4079 4080 4081 template<typename T>4082 inline octonion<T> cylindrical(T const & r,4083 T const & angle,4084 T const & h1,4085 T const & h2,4086 T const & h3,4087 T const & h4,4088 T const & h5,4089 T const & h6)4090 {4091 using ::std::cos;4092 using ::std::sin;4093 4094 T a = r*cos(angle);4095 T b = r*sin(angle);4096 4097 return(octonion<T>(a,b,h1,h2,h3,h4,h5,h6));4098 }4099 4100 4101 template<typename T>4102 inline octonion<T> exp(octonion<T> const & o)4103 {4104 using ::std::exp;4105 using ::std::cos;4106 4107 using ::boost::math::sinc_pi;4108 4109 T u = exp(real(o));4110 4111 T z = abs(unreal(o));4112 4113 T w = sinc_pi(z);4114 4115 return(u*octonion<T>(cos(z),4116 w*o.R_component_2(), w*o.R_component_3(),4117 w*o.R_component_4(), w*o.R_component_5(),4118 w*o.R_component_6(), w*o.R_component_7(),4119 w*o.R_component_8()));4120 }4121 4122 4123 template<typename T>4124 inline octonion<T> cos(octonion<T> const & o)4125 {4126 using ::std::sin;4127 using ::std::cos;4128 using ::std::cosh;4129 4130 using ::boost::math::sinhc_pi;4131 4132 T z = abs(unreal(o));4133 4134 T w = -sin(o.real())*sinhc_pi(z);4135 4136 return(octonion<T>(cos(o.real())*cosh(z),4137 w*o.R_component_2(), w*o.R_component_3(),4138 w*o.R_component_4(), w*o.R_component_5(),4139 w*o.R_component_6(), w*o.R_component_7(),4140 w*o.R_component_8()));4141 }4142 4143 4144 template<typename T>4145 inline octonion<T> sin(octonion<T> const & o)4146 {4147 using ::std::sin;4148 using ::std::cos;4149 using ::std::cosh;4150 4151 using ::boost::math::sinhc_pi;4152 4153 T z = abs(unreal(o));4154 4155 T w = +cos(o.real())*sinhc_pi(z);4156 4157 return(octonion<T>(sin(o.real())*cosh(z),4158 w*o.R_component_2(), w*o.R_component_3(),4159 w*o.R_component_4(), w*o.R_component_5(),4160 w*o.R_component_6(), w*o.R_component_7(),4161 w*o.R_component_8()));4162 }4163 4164 4165 template<typename T>4166 inline octonion<T> tan(octonion<T> const & o)4167 {4168 return(sin(o)/cos(o));4169 }4170 4171 4172 template<typename T>4173 inline octonion<T> cosh(octonion<T> const & o)4174 {4175 return((exp(+o)+exp(-o))/static_cast<T>(2));4176 }4177 4178 4179 template<typename T>4180 inline octonion<T> sinh(octonion<T> const & o)4181 {4182 return((exp(+o)-exp(-o))/static_cast<T>(2));4183 }4184 4185 4186 template<typename T>4187 inline octonion<T> tanh(octonion<T> const & o)4188 {4189 return(sinh(o)/cosh(o));4190 }4191 4192 4193 template<typename T>4194 octonion<T> pow(octonion<T> const & o,4195 int n)4196 {4197 if (n > 1)4198 {4199 int m = n>>1;4200 4201 octonion<T> result = pow(o, m);4202 4203 result *= result;4204 4205 if (n != (m<<1))4206 {4207 result *= o; // n odd4208 }4209 4210 return(result);4211 }4212 else if (n == 1)4213 {4214 return(o);4215 }4216 else if (n == 0)4217 {4218 return(octonion<T>(static_cast<T>(1)));4219 }4220 else /* n < 0 */4221 {4222 return(pow(octonion<T>(static_cast<T>(1))/o,-n));4223 }4224 }4225 4226 4227 // helper templates for converting copy constructors (definition)4228 4229 namespace detail4230 {4231 4232 template< typename T,4233 typename U4234 >4235 octonion<T> octonion_type_converter(octonion<U> const & rhs)4236 {4237 return(octonion<T>( static_cast<T>(rhs.R_component_1()),4238 static_cast<T>(rhs.R_component_2()),4239 static_cast<T>(rhs.R_component_3()),4240 static_cast<T>(rhs.R_component_4()),4241 static_cast<T>(rhs.R_component_5()),4242 static_cast<T>(rhs.R_component_6()),4243 static_cast<T>(rhs.R_component_7()),4244 static_cast<T>(rhs.R_component_8())));4245 }4246 }4247 }4248}4249 4250#endif /* BOOST_OCTONION_HPP */4251