octonion.hpp 241 KB

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