quaternion.hpp 89 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924
  1. // boost quaternion.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_QUATERNION_HPP
  8. #define BOOST_QUATERNION_HPP
  9. #include <complex>
  10. #include <iosfwd> // for the "<<" and ">>" operators
  11. #include <sstream> // for the "<<" operator
  12. #include <boost/config.hpp> // for BOOST_NO_STD_LOCALE
  13. #include <boost/detail/workaround.hpp>
  14. #ifndef BOOST_NO_STD_LOCALE
  15. #include <locale> // for the "<<" operator
  16. #endif /* BOOST_NO_STD_LOCALE */
  17. #include <valarray>
  18. #include <boost/math/special_functions/sinc.hpp> // for the Sinus cardinal
  19. #include <boost/math/special_functions/sinhc.hpp> // for the Hyperbolic Sinus cardinal
  20. namespace boost
  21. {
  22. namespace math
  23. {
  24. #if BOOST_WORKAROUND(__GNUC__, < 3)
  25. // gcc 2.95.x uses expression templates for valarray calculations, but
  26. // the result is not conforming. We need BOOST_GET_VALARRAY to get an
  27. // actual valarray result when we need to call a member function
  28. #define BOOST_GET_VALARRAY(T,x) ::std::valarray<T>(x)
  29. // gcc 2.95.x has an "std::ios" class that is similar to
  30. // "std::ios_base", so we just use a #define
  31. #define BOOST_IOS_BASE ::std::ios
  32. // gcc 2.x ignores function scope using declarations,
  33. // put them in the scope of the enclosing namespace instead:
  34. using ::std::valarray;
  35. using ::std::sqrt;
  36. using ::std::cos;
  37. using ::std::sin;
  38. using ::std::exp;
  39. using ::std::cosh;
  40. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  41. #define BOOST_QUATERNION_ACCESSOR_GENERATOR(type) \
  42. type real() const \
  43. { \
  44. return(a); \
  45. } \
  46. \
  47. quaternion<type> unreal() const \
  48. { \
  49. return(quaternion<type>(static_cast<type>(0),b,c,d)); \
  50. } \
  51. \
  52. type R_component_1() const \
  53. { \
  54. return(a); \
  55. } \
  56. \
  57. type R_component_2() const \
  58. { \
  59. return(b); \
  60. } \
  61. \
  62. type R_component_3() const \
  63. { \
  64. return(c); \
  65. } \
  66. \
  67. type R_component_4() const \
  68. { \
  69. return(d); \
  70. } \
  71. \
  72. ::std::complex<type> C_component_1() const \
  73. { \
  74. return(::std::complex<type>(a,b)); \
  75. } \
  76. \
  77. ::std::complex<type> C_component_2() const \
  78. { \
  79. return(::std::complex<type>(c,d)); \
  80. }
  81. #define BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(type) \
  82. template<typename X> \
  83. quaternion<type> & operator = (quaternion<X> const & a_affecter) \
  84. { \
  85. a = static_cast<type>(a_affecter.R_component_1()); \
  86. b = static_cast<type>(a_affecter.R_component_2()); \
  87. c = static_cast<type>(a_affecter.R_component_3()); \
  88. d = static_cast<type>(a_affecter.R_component_4()); \
  89. \
  90. return(*this); \
  91. } \
  92. \
  93. quaternion<type> & operator = (quaternion<type> const & a_affecter) \
  94. { \
  95. a = a_affecter.a; \
  96. b = a_affecter.b; \
  97. c = a_affecter.c; \
  98. d = a_affecter.d; \
  99. \
  100. return(*this); \
  101. } \
  102. \
  103. quaternion<type> & operator = (type const & a_affecter) \
  104. { \
  105. a = a_affecter; \
  106. \
  107. b = c = d = static_cast<type>(0); \
  108. \
  109. return(*this); \
  110. } \
  111. \
  112. quaternion<type> & operator = (::std::complex<type> const & a_affecter) \
  113. { \
  114. a = a_affecter.real(); \
  115. b = a_affecter.imag(); \
  116. \
  117. c = d = static_cast<type>(0); \
  118. \
  119. return(*this); \
  120. }
  121. #define BOOST_QUATERNION_MEMBER_DATA_GENERATOR(type) \
  122. type a; \
  123. type b; \
  124. type c; \
  125. type d;
  126. template<typename T>
  127. class quaternion
  128. {
  129. public:
  130. typedef T value_type;
  131. // constructor for H seen as R^4
  132. // (also default constructor)
  133. explicit quaternion( T const & requested_a = T(),
  134. T const & requested_b = T(),
  135. T const & requested_c = T(),
  136. T const & requested_d = T())
  137. : a(requested_a),
  138. b(requested_b),
  139. c(requested_c),
  140. d(requested_d)
  141. {
  142. // nothing to do!
  143. }
  144. // constructor for H seen as C^2
  145. explicit quaternion( ::std::complex<T> const & z0,
  146. ::std::complex<T> const & z1 = ::std::complex<T>())
  147. : a(z0.real()),
  148. b(z0.imag()),
  149. c(z1.real()),
  150. d(z1.imag())
  151. {
  152. // nothing to do!
  153. }
  154. // UNtemplated copy constructor
  155. // (this is taken care of by the compiler itself)
  156. // templated copy constructor
  157. template<typename X>
  158. explicit quaternion(quaternion<X> const & a_recopier)
  159. : a(static_cast<T>(a_recopier.R_component_1())),
  160. b(static_cast<T>(a_recopier.R_component_2())),
  161. c(static_cast<T>(a_recopier.R_component_3())),
  162. d(static_cast<T>(a_recopier.R_component_4()))
  163. {
  164. // nothing to do!
  165. }
  166. // destructor
  167. // (this is taken care of by the compiler itself)
  168. // accessors
  169. //
  170. // Note: Like complex number, quaternions do have a meaningful notion of "real part",
  171. // but unlike them there is no meaningful notion of "imaginary part".
  172. // Instead there is an "unreal part" which itself is a quaternion, and usually
  173. // nothing simpler (as opposed to the complex number case).
  174. // However, for practicallity, there are accessors for the other components
  175. // (these are necessary for the templated copy constructor, for instance).
  176. BOOST_QUATERNION_ACCESSOR_GENERATOR(T)
  177. // assignment operators
  178. BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(T)
  179. // other assignment-related operators
  180. //
  181. // NOTE: Quaternion multiplication is *NOT* commutative;
  182. // symbolically, "q *= rhs;" means "q = q * rhs;"
  183. // and "q /= rhs;" means "q = q * inverse_of(rhs);"
  184. quaternion<T> & operator += (T const & rhs)
  185. {
  186. T at = a + rhs; // exception guard
  187. a = at;
  188. return(*this);
  189. }
  190. quaternion<T> & operator += (::std::complex<T> const & rhs)
  191. {
  192. T at = a + rhs.real(); // exception guard
  193. T bt = b + rhs.imag(); // exception guard
  194. a = at;
  195. b = bt;
  196. return(*this);
  197. }
  198. template<typename X>
  199. quaternion<T> & operator += (quaternion<X> const & rhs)
  200. {
  201. T at = a + static_cast<T>(rhs.R_component_1()); // exception guard
  202. T bt = b + static_cast<T>(rhs.R_component_2()); // exception guard
  203. T ct = c + static_cast<T>(rhs.R_component_3()); // exception guard
  204. T dt = d + static_cast<T>(rhs.R_component_4()); // exception guard
  205. a = at;
  206. b = bt;
  207. c = ct;
  208. d = dt;
  209. return(*this);
  210. }
  211. quaternion<T> & operator -= (T const & rhs)
  212. {
  213. T at = a - rhs; // exception guard
  214. a = at;
  215. return(*this);
  216. }
  217. quaternion<T> & operator -= (::std::complex<T> const & rhs)
  218. {
  219. T at = a - rhs.real(); // exception guard
  220. T bt = b - rhs.imag(); // exception guard
  221. a = at;
  222. b = bt;
  223. return(*this);
  224. }
  225. template<typename X>
  226. quaternion<T> & operator -= (quaternion<X> const & rhs)
  227. {
  228. T at = a - static_cast<T>(rhs.R_component_1()); // exception guard
  229. T bt = b - static_cast<T>(rhs.R_component_2()); // exception guard
  230. T ct = c - static_cast<T>(rhs.R_component_3()); // exception guard
  231. T dt = d - static_cast<T>(rhs.R_component_4()); // exception guard
  232. a = at;
  233. b = bt;
  234. c = ct;
  235. d = dt;
  236. return(*this);
  237. }
  238. quaternion<T> & operator *= (T const & rhs)
  239. {
  240. T at = a * rhs; // exception guard
  241. T bt = b * rhs; // exception guard
  242. T ct = c * rhs; // exception guard
  243. T dt = d * rhs; // exception guard
  244. a = at;
  245. b = bt;
  246. c = ct;
  247. d = dt;
  248. return(*this);
  249. }
  250. quaternion<T> & operator *= (::std::complex<T> const & rhs)
  251. {
  252. T ar = rhs.real();
  253. T br = rhs.imag();
  254. T at = +a*ar-b*br;
  255. T bt = +a*br+b*ar;
  256. T ct = +c*ar+d*br;
  257. T dt = -c*br+d*ar;
  258. a = at;
  259. b = bt;
  260. c = ct;
  261. d = dt;
  262. return(*this);
  263. }
  264. template<typename X>
  265. quaternion<T> & operator *= (quaternion<X> const & rhs)
  266. {
  267. T ar = static_cast<T>(rhs.R_component_1());
  268. T br = static_cast<T>(rhs.R_component_2());
  269. T cr = static_cast<T>(rhs.R_component_3());
  270. T dr = static_cast<T>(rhs.R_component_4());
  271. T at = +a*ar-b*br-c*cr-d*dr;
  272. T bt = +a*br+b*ar+c*dr-d*cr; //(a*br+ar*b)+(c*dr-cr*d);
  273. T ct = +a*cr-b*dr+c*ar+d*br; //(a*cr+ar*c)+(d*br-dr*b);
  274. T dt = +a*dr+b*cr-c*br+d*ar; //(a*dr+ar*d)+(b*cr-br*c);
  275. a = at;
  276. b = bt;
  277. c = ct;
  278. d = dt;
  279. return(*this);
  280. }
  281. quaternion<T> & operator /= (T const & rhs)
  282. {
  283. T at = a / rhs; // exception guard
  284. T bt = b / rhs; // exception guard
  285. T ct = c / rhs; // exception guard
  286. T dt = d / rhs; // exception guard
  287. a = at;
  288. b = bt;
  289. c = ct;
  290. d = dt;
  291. return(*this);
  292. }
  293. quaternion<T> & operator /= (::std::complex<T> const & rhs)
  294. {
  295. T ar = rhs.real();
  296. T br = rhs.imag();
  297. T denominator = ar*ar+br*br;
  298. T at = (+a*ar+b*br)/denominator; //(a*ar+b*br)/denominator;
  299. T bt = (-a*br+b*ar)/denominator; //(ar*b-a*br)/denominator;
  300. T ct = (+c*ar-d*br)/denominator; //(ar*c-d*br)/denominator;
  301. T dt = (+c*br+d*ar)/denominator; //(ar*d+br*c)/denominator;
  302. a = at;
  303. b = bt;
  304. c = ct;
  305. d = dt;
  306. return(*this);
  307. }
  308. template<typename X>
  309. quaternion<T> & operator /= (quaternion<X> const & rhs)
  310. {
  311. T ar = static_cast<T>(rhs.R_component_1());
  312. T br = static_cast<T>(rhs.R_component_2());
  313. T cr = static_cast<T>(rhs.R_component_3());
  314. T dr = static_cast<T>(rhs.R_component_4());
  315. T denominator = ar*ar+br*br+cr*cr+dr*dr;
  316. T at = (+a*ar+b*br+c*cr+d*dr)/denominator; //(a*ar+b*br+c*cr+d*dr)/denominator;
  317. T bt = (-a*br+b*ar-c*dr+d*cr)/denominator; //((ar*b-a*br)+(cr*d-c*dr))/denominator;
  318. T ct = (-a*cr+b*dr+c*ar-d*br)/denominator; //((ar*c-a*cr)+(dr*b-d*br))/denominator;
  319. T dt = (-a*dr-b*cr+c*br+d*ar)/denominator; //((ar*d-a*dr)+(br*c-b*cr))/denominator;
  320. a = at;
  321. b = bt;
  322. c = ct;
  323. d = dt;
  324. return(*this);
  325. }
  326. protected:
  327. BOOST_QUATERNION_MEMBER_DATA_GENERATOR(T)
  328. private:
  329. };
  330. // declaration of quaternion specialization
  331. template<> class quaternion<float>;
  332. template<> class quaternion<double>;
  333. template<> class quaternion<long double>;
  334. // helper templates for converting copy constructors (declaration)
  335. namespace detail
  336. {
  337. template< typename T,
  338. typename U
  339. >
  340. quaternion<T> quaternion_type_converter(quaternion<U> const & rhs);
  341. }
  342. // implementation of quaternion specialization
  343. #define BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(type) \
  344. explicit quaternion( type const & requested_a = static_cast<type>(0), \
  345. type const & requested_b = static_cast<type>(0), \
  346. type const & requested_c = static_cast<type>(0), \
  347. type const & requested_d = static_cast<type>(0)) \
  348. : a(requested_a), \
  349. b(requested_b), \
  350. c(requested_c), \
  351. d(requested_d) \
  352. { \
  353. } \
  354. \
  355. explicit quaternion( ::std::complex<type> const & z0, \
  356. ::std::complex<type> const & z1 = ::std::complex<type>()) \
  357. : a(z0.real()), \
  358. b(z0.imag()), \
  359. c(z1.real()), \
  360. d(z1.imag()) \
  361. { \
  362. }
  363. #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
  364. quaternion<type> & operator += (type const & rhs) \
  365. { \
  366. a += rhs; \
  367. \
  368. return(*this); \
  369. }
  370. #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
  371. quaternion<type> & operator += (::std::complex<type> const & rhs) \
  372. { \
  373. a += rhs.real(); \
  374. b += rhs.imag(); \
  375. \
  376. return(*this); \
  377. }
  378. #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type) \
  379. template<typename X> \
  380. quaternion<type> & operator += (quaternion<X> const & rhs) \
  381. { \
  382. a += static_cast<type>(rhs.R_component_1()); \
  383. b += static_cast<type>(rhs.R_component_2()); \
  384. c += static_cast<type>(rhs.R_component_3()); \
  385. d += static_cast<type>(rhs.R_component_4()); \
  386. \
  387. return(*this); \
  388. }
  389. #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
  390. quaternion<type> & operator -= (type const & rhs) \
  391. { \
  392. a -= rhs; \
  393. \
  394. return(*this); \
  395. }
  396. #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
  397. quaternion<type> & operator -= (::std::complex<type> const & rhs) \
  398. { \
  399. a -= rhs.real(); \
  400. b -= rhs.imag(); \
  401. \
  402. return(*this); \
  403. }
  404. #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type) \
  405. template<typename X> \
  406. quaternion<type> & operator -= (quaternion<X> const & rhs) \
  407. { \
  408. a -= static_cast<type>(rhs.R_component_1()); \
  409. b -= static_cast<type>(rhs.R_component_2()); \
  410. c -= static_cast<type>(rhs.R_component_3()); \
  411. d -= static_cast<type>(rhs.R_component_4()); \
  412. \
  413. return(*this); \
  414. }
  415. #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
  416. quaternion<type> & operator *= (type const & rhs) \
  417. { \
  418. a *= rhs; \
  419. b *= rhs; \
  420. c *= rhs; \
  421. d *= rhs; \
  422. \
  423. return(*this); \
  424. }
  425. #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
  426. quaternion<type> & operator *= (::std::complex<type> const & rhs) \
  427. { \
  428. type ar = rhs.real(); \
  429. type br = rhs.imag(); \
  430. \
  431. type at = +a*ar-b*br; \
  432. type bt = +a*br+b*ar; \
  433. type ct = +c*ar+d*br; \
  434. type dt = -c*br+d*ar; \
  435. \
  436. a = at; \
  437. b = bt; \
  438. c = ct; \
  439. d = dt; \
  440. \
  441. return(*this); \
  442. }
  443. #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type) \
  444. template<typename X> \
  445. quaternion<type> & operator *= (quaternion<X> const & rhs) \
  446. { \
  447. type ar = static_cast<type>(rhs.R_component_1()); \
  448. type br = static_cast<type>(rhs.R_component_2()); \
  449. type cr = static_cast<type>(rhs.R_component_3()); \
  450. type dr = static_cast<type>(rhs.R_component_4()); \
  451. \
  452. type at = +a*ar-b*br-c*cr-d*dr; \
  453. type bt = +a*br+b*ar+c*dr-d*cr; \
  454. type ct = +a*cr-b*dr+c*ar+d*br; \
  455. type dt = +a*dr+b*cr-c*br+d*ar; \
  456. \
  457. a = at; \
  458. b = bt; \
  459. c = ct; \
  460. d = dt; \
  461. \
  462. return(*this); \
  463. }
  464. // There is quite a lot of repetition in the code below. This is intentional.
  465. // The last conditional block is the normal form, and the others merely
  466. // consist of workarounds for various compiler deficiencies. Hopefuly, when
  467. // more compilers are conformant and we can retire support for those that are
  468. // not, we will be able to remove the clutter. This is makes the situation
  469. // (painfully) explicit.
  470. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
  471. quaternion<type> & operator /= (type const & rhs) \
  472. { \
  473. a /= rhs; \
  474. b /= rhs; \
  475. c /= rhs; \
  476. d /= rhs; \
  477. \
  478. return(*this); \
  479. }
  480. #if defined(__GNUC__) && (__GNUC__ < 3)
  481. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
  482. quaternion<type> & operator /= (::std::complex<type> const & rhs) \
  483. { \
  484. using ::std::valarray; \
  485. \
  486. valarray<type> tr(2); \
  487. \
  488. tr[0] = rhs.real(); \
  489. tr[1] = rhs.imag(); \
  490. \
  491. type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
  492. \
  493. tr *= mixam; \
  494. \
  495. valarray<type> tt(4); \
  496. \
  497. tt[0] = +a*tr[0]+b*tr[1]; \
  498. tt[1] = -a*tr[1]+b*tr[0]; \
  499. tt[2] = +c*tr[0]-d*tr[1]; \
  500. tt[3] = +c*tr[1]+d*tr[0]; \
  501. \
  502. tr *= tr; \
  503. \
  504. tt *= (mixam/tr.sum()); \
  505. \
  506. a = tt[0]; \
  507. b = tt[1]; \
  508. c = tt[2]; \
  509. d = tt[3]; \
  510. \
  511. return(*this); \
  512. }
  513. #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  514. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
  515. quaternion<type> & operator /= (::std::complex<type> const & rhs) \
  516. { \
  517. using ::std::valarray; \
  518. using ::std::abs; \
  519. \
  520. valarray<type> tr(2); \
  521. \
  522. tr[0] = rhs.real(); \
  523. tr[1] = rhs.imag(); \
  524. \
  525. type mixam = static_cast<type>(1)/(abs(tr).max)(); \
  526. \
  527. tr *= mixam; \
  528. \
  529. valarray<type> tt(4); \
  530. \
  531. tt[0] = +a*tr[0]+b*tr[1]; \
  532. tt[1] = -a*tr[1]+b*tr[0]; \
  533. tt[2] = +c*tr[0]-d*tr[1]; \
  534. tt[3] = +c*tr[1]+d*tr[0]; \
  535. \
  536. tr *= tr; \
  537. \
  538. tt *= (mixam/tr.sum()); \
  539. \
  540. a = tt[0]; \
  541. b = tt[1]; \
  542. c = tt[2]; \
  543. d = tt[3]; \
  544. \
  545. return(*this); \
  546. }
  547. #else
  548. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
  549. quaternion<type> & operator /= (::std::complex<type> const & rhs) \
  550. { \
  551. using ::std::valarray; \
  552. \
  553. valarray<type> tr(2); \
  554. \
  555. tr[0] = rhs.real(); \
  556. tr[1] = rhs.imag(); \
  557. \
  558. type mixam = static_cast<type>(1)/(abs(tr).max)(); \
  559. \
  560. tr *= mixam; \
  561. \
  562. valarray<type> tt(4); \
  563. \
  564. tt[0] = +a*tr[0]+b*tr[1]; \
  565. tt[1] = -a*tr[1]+b*tr[0]; \
  566. tt[2] = +c*tr[0]-d*tr[1]; \
  567. tt[3] = +c*tr[1]+d*tr[0]; \
  568. \
  569. tr *= tr; \
  570. \
  571. tt *= (mixam/tr.sum()); \
  572. \
  573. a = tt[0]; \
  574. b = tt[1]; \
  575. c = tt[2]; \
  576. d = tt[3]; \
  577. \
  578. return(*this); \
  579. }
  580. #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
  581. #if defined(__GNUC__) && (__GNUC__ < 3)
  582. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
  583. template<typename X> \
  584. quaternion<type> & operator /= (quaternion<X> const & rhs) \
  585. { \
  586. using ::std::valarray; \
  587. \
  588. valarray<type> tr(4); \
  589. \
  590. tr[0] = static_cast<type>(rhs.R_component_1()); \
  591. tr[1] = static_cast<type>(rhs.R_component_2()); \
  592. tr[2] = static_cast<type>(rhs.R_component_3()); \
  593. tr[3] = static_cast<type>(rhs.R_component_4()); \
  594. \
  595. type mixam = (BOOST_GET_VALARRAY(type,static_cast<type>(1)/abs(tr)).max)(); \
  596. \
  597. tr *= mixam; \
  598. \
  599. valarray<type> tt(4); \
  600. \
  601. tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
  602. tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
  603. tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
  604. tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
  605. \
  606. tr *= tr; \
  607. \
  608. tt *= (mixam/tr.sum()); \
  609. \
  610. a = tt[0]; \
  611. b = tt[1]; \
  612. c = tt[2]; \
  613. d = tt[3]; \
  614. \
  615. return(*this); \
  616. }
  617. #elif defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
  618. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
  619. template<typename X> \
  620. quaternion<type> & operator /= (quaternion<X> const & rhs) \
  621. { \
  622. using ::std::valarray; \
  623. using ::std::abs; \
  624. \
  625. valarray<type> tr(4); \
  626. \
  627. tr[0] = static_cast<type>(rhs.R_component_1()); \
  628. tr[1] = static_cast<type>(rhs.R_component_2()); \
  629. tr[2] = static_cast<type>(rhs.R_component_3()); \
  630. tr[3] = static_cast<type>(rhs.R_component_4()); \
  631. \
  632. type mixam = static_cast<type>(1)/(abs(tr).max)(); \
  633. \
  634. tr *= mixam; \
  635. \
  636. valarray<type> tt(4); \
  637. \
  638. tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
  639. tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
  640. tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
  641. tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
  642. \
  643. tr *= tr; \
  644. \
  645. tt *= (mixam/tr.sum()); \
  646. \
  647. a = tt[0]; \
  648. b = tt[1]; \
  649. c = tt[2]; \
  650. d = tt[3]; \
  651. \
  652. return(*this); \
  653. }
  654. #else
  655. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type) \
  656. template<typename X> \
  657. quaternion<type> & operator /= (quaternion<X> const & rhs) \
  658. { \
  659. using ::std::valarray; \
  660. \
  661. valarray<type> tr(4); \
  662. \
  663. tr[0] = static_cast<type>(rhs.R_component_1()); \
  664. tr[1] = static_cast<type>(rhs.R_component_2()); \
  665. tr[2] = static_cast<type>(rhs.R_component_3()); \
  666. tr[3] = static_cast<type>(rhs.R_component_4()); \
  667. \
  668. type mixam = static_cast<type>(1)/(abs(tr).max)(); \
  669. \
  670. tr *= mixam; \
  671. \
  672. valarray<type> tt(4); \
  673. \
  674. tt[0] = +a*tr[0]+b*tr[1]+c*tr[2]+d*tr[3]; \
  675. tt[1] = -a*tr[1]+b*tr[0]-c*tr[3]+d*tr[2]; \
  676. tt[2] = -a*tr[2]+b*tr[3]+c*tr[0]-d*tr[1]; \
  677. tt[3] = -a*tr[3]-b*tr[2]+c*tr[1]+d*tr[0]; \
  678. \
  679. tr *= tr; \
  680. \
  681. tt *= (mixam/tr.sum()); \
  682. \
  683. a = tt[0]; \
  684. b = tt[1]; \
  685. c = tt[2]; \
  686. d = tt[3]; \
  687. \
  688. return(*this); \
  689. }
  690. #endif /* defined(__GNUC__) && (__GNUC__ < 3) */ /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
  691. #define BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
  692. BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1(type) \
  693. BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2(type) \
  694. BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3(type)
  695. #define BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
  696. BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1(type) \
  697. BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2(type) \
  698. BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3(type)
  699. #define BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
  700. BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1(type) \
  701. BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2(type) \
  702. BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3(type)
  703. #define BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type) \
  704. BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1(type) \
  705. BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2(type) \
  706. BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3(type)
  707. #define BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(type) \
  708. BOOST_QUATERNION_MEMBER_ADD_GENERATOR(type) \
  709. BOOST_QUATERNION_MEMBER_SUB_GENERATOR(type) \
  710. BOOST_QUATERNION_MEMBER_MUL_GENERATOR(type) \
  711. BOOST_QUATERNION_MEMBER_DIV_GENERATOR(type)
  712. template<>
  713. class quaternion<float>
  714. {
  715. public:
  716. typedef float value_type;
  717. BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(float)
  718. // UNtemplated copy constructor
  719. // (this is taken care of by the compiler itself)
  720. // explicit copy constructors (precision-loosing converters)
  721. explicit quaternion(quaternion<double> const & a_recopier)
  722. {
  723. *this = detail::quaternion_type_converter<float, double>(a_recopier);
  724. }
  725. explicit quaternion(quaternion<long double> const & a_recopier)
  726. {
  727. *this = detail::quaternion_type_converter<float, long double>(a_recopier);
  728. }
  729. // destructor
  730. // (this is taken care of by the compiler itself)
  731. // accessors
  732. //
  733. // Note: Like complex number, quaternions do have a meaningful notion of "real part",
  734. // but unlike them there is no meaningful notion of "imaginary part".
  735. // Instead there is an "unreal part" which itself is a quaternion, and usually
  736. // nothing simpler (as opposed to the complex number case).
  737. // However, for practicallity, there are accessors for the other components
  738. // (these are necessary for the templated copy constructor, for instance).
  739. BOOST_QUATERNION_ACCESSOR_GENERATOR(float)
  740. // assignment operators
  741. BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(float)
  742. // other assignment-related operators
  743. //
  744. // NOTE: Quaternion multiplication is *NOT* commutative;
  745. // symbolically, "q *= rhs;" means "q = q * rhs;"
  746. // and "q /= rhs;" means "q = q * inverse_of(rhs);"
  747. BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(float)
  748. protected:
  749. BOOST_QUATERNION_MEMBER_DATA_GENERATOR(float)
  750. private:
  751. };
  752. template<>
  753. class quaternion<double>
  754. {
  755. public:
  756. typedef double value_type;
  757. BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(double)
  758. // UNtemplated copy constructor
  759. // (this is taken care of by the compiler itself)
  760. // converting copy constructor
  761. explicit quaternion(quaternion<float> const & a_recopier)
  762. {
  763. *this = detail::quaternion_type_converter<double, float>(a_recopier);
  764. }
  765. // explicit copy constructors (precision-loosing converters)
  766. explicit quaternion(quaternion<long double> const & a_recopier)
  767. {
  768. *this = detail::quaternion_type_converter<double, long double>(a_recopier);
  769. }
  770. // destructor
  771. // (this is taken care of by the compiler itself)
  772. // accessors
  773. //
  774. // Note: Like complex number, quaternions do have a meaningful notion of "real part",
  775. // but unlike them there is no meaningful notion of "imaginary part".
  776. // Instead there is an "unreal part" which itself is a quaternion, and usually
  777. // nothing simpler (as opposed to the complex number case).
  778. // However, for practicallity, there are accessors for the other components
  779. // (these are necessary for the templated copy constructor, for instance).
  780. BOOST_QUATERNION_ACCESSOR_GENERATOR(double)
  781. // assignment operators
  782. BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(double)
  783. // other assignment-related operators
  784. //
  785. // NOTE: Quaternion multiplication is *NOT* commutative;
  786. // symbolically, "q *= rhs;" means "q = q * rhs;"
  787. // and "q /= rhs;" means "q = q * inverse_of(rhs);"
  788. BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(double)
  789. protected:
  790. BOOST_QUATERNION_MEMBER_DATA_GENERATOR(double)
  791. private:
  792. };
  793. template<>
  794. class quaternion<long double>
  795. {
  796. public:
  797. typedef long double value_type;
  798. BOOST_QUATERNION_CONSTRUCTOR_GENERATOR(long double)
  799. // UNtemplated copy constructor
  800. // (this is taken care of by the compiler itself)
  801. // converting copy constructors
  802. explicit quaternion(quaternion<float> const & a_recopier)
  803. {
  804. *this = detail::quaternion_type_converter<long double, float>(a_recopier);
  805. }
  806. explicit quaternion(quaternion<double> const & a_recopier)
  807. {
  808. *this = detail::quaternion_type_converter<long double, double>(a_recopier);
  809. }
  810. // destructor
  811. // (this is taken care of by the compiler itself)
  812. // accessors
  813. //
  814. // Note: Like complex number, quaternions do have a meaningful notion of "real part",
  815. // but unlike them there is no meaningful notion of "imaginary part".
  816. // Instead there is an "unreal part" which itself is a quaternion, and usually
  817. // nothing simpler (as opposed to the complex number case).
  818. // However, for practicallity, there are accessors for the other components
  819. // (these are necessary for the templated copy constructor, for instance).
  820. BOOST_QUATERNION_ACCESSOR_GENERATOR(long double)
  821. // assignment operators
  822. BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR(long double)
  823. // other assignment-related operators
  824. //
  825. // NOTE: Quaternion multiplication is *NOT* commutative;
  826. // symbolically, "q *= rhs;" means "q = q * rhs;"
  827. // and "q /= rhs;" means "q = q * inverse_of(rhs);"
  828. BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR(long double)
  829. protected:
  830. BOOST_QUATERNION_MEMBER_DATA_GENERATOR(long double)
  831. private:
  832. };
  833. #undef BOOST_QUATERNION_MEMBER_ALGEBRAIC_GENERATOR
  834. #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR
  835. #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR
  836. #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR
  837. #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR
  838. #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_1
  839. #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_2
  840. #undef BOOST_QUATERNION_MEMBER_ADD_GENERATOR_3
  841. #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_1
  842. #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_2
  843. #undef BOOST_QUATERNION_MEMBER_SUB_GENERATOR_3
  844. #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_1
  845. #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_2
  846. #undef BOOST_QUATERNION_MEMBER_MUL_GENERATOR_3
  847. #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_1
  848. #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_2
  849. #undef BOOST_QUATERNION_MEMBER_DIV_GENERATOR_3
  850. #undef BOOST_QUATERNION_CONSTRUCTOR_GENERATOR
  851. #undef BOOST_QUATERNION_MEMBER_ASSIGNMENT_GENERATOR
  852. #undef BOOST_QUATERNION_MEMBER_DATA_GENERATOR
  853. #undef BOOST_QUATERNION_ACCESSOR_GENERATOR
  854. // operators
  855. #define BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op) \
  856. { \
  857. quaternion<T> res(lhs); \
  858. res op##= rhs; \
  859. return(res); \
  860. }
  861. #define BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
  862. template<typename T> \
  863. inline quaternion<T> operator op (T const & lhs, quaternion<T> const & rhs) \
  864. BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
  865. #define BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
  866. template<typename T> \
  867. inline quaternion<T> operator op (quaternion<T> const & lhs, T const & rhs) \
  868. BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
  869. #define BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
  870. template<typename T> \
  871. inline quaternion<T> operator op (::std::complex<T> const & lhs, quaternion<T> const & rhs) \
  872. BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
  873. #define BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
  874. template<typename T> \
  875. inline quaternion<T> operator op (quaternion<T> const & lhs, ::std::complex<T> const & rhs) \
  876. BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
  877. #define BOOST_QUATERNION_OPERATOR_GENERATOR_3(op) \
  878. template<typename T> \
  879. inline quaternion<T> operator op (quaternion<T> const & lhs, quaternion<T> const & rhs) \
  880. BOOST_QUATERNION_OPERATOR_GENERATOR_BODY(op)
  881. #define BOOST_QUATERNION_OPERATOR_GENERATOR(op) \
  882. BOOST_QUATERNION_OPERATOR_GENERATOR_1_L(op) \
  883. BOOST_QUATERNION_OPERATOR_GENERATOR_1_R(op) \
  884. BOOST_QUATERNION_OPERATOR_GENERATOR_2_L(op) \
  885. BOOST_QUATERNION_OPERATOR_GENERATOR_2_R(op) \
  886. BOOST_QUATERNION_OPERATOR_GENERATOR_3(op)
  887. BOOST_QUATERNION_OPERATOR_GENERATOR(+)
  888. BOOST_QUATERNION_OPERATOR_GENERATOR(-)
  889. BOOST_QUATERNION_OPERATOR_GENERATOR(*)
  890. BOOST_QUATERNION_OPERATOR_GENERATOR(/)
  891. #undef BOOST_QUATERNION_OPERATOR_GENERATOR
  892. #undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_L
  893. #undef BOOST_QUATERNION_OPERATOR_GENERATOR_1_R
  894. #undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_L
  895. #undef BOOST_QUATERNION_OPERATOR_GENERATOR_2_R
  896. #undef BOOST_QUATERNION_OPERATOR_GENERATOR_3
  897. #undef BOOST_QUATERNION_OPERATOR_GENERATOR_BODY
  898. template<typename T>
  899. inline quaternion<T> operator + (quaternion<T> const & q)
  900. {
  901. return(q);
  902. }
  903. template<typename T>
  904. inline quaternion<T> operator - (quaternion<T> const & q)
  905. {
  906. return(quaternion<T>(-q.R_component_1(),-q.R_component_2(),-q.R_component_3(),-q.R_component_4()));
  907. }
  908. template<typename T>
  909. inline bool operator == (T const & lhs, quaternion<T> const & rhs)
  910. {
  911. return (
  912. (rhs.R_component_1() == lhs)&&
  913. (rhs.R_component_2() == static_cast<T>(0))&&
  914. (rhs.R_component_3() == static_cast<T>(0))&&
  915. (rhs.R_component_4() == static_cast<T>(0))
  916. );
  917. }
  918. template<typename T>
  919. inline bool operator == (quaternion<T> const & lhs, T const & rhs)
  920. {
  921. return (
  922. (lhs.R_component_1() == rhs)&&
  923. (lhs.R_component_2() == static_cast<T>(0))&&
  924. (lhs.R_component_3() == static_cast<T>(0))&&
  925. (lhs.R_component_4() == static_cast<T>(0))
  926. );
  927. }
  928. template<typename T>
  929. inline bool operator == (::std::complex<T> const & lhs, quaternion<T> const & rhs)
  930. {
  931. return (
  932. (rhs.R_component_1() == lhs.real())&&
  933. (rhs.R_component_2() == lhs.imag())&&
  934. (rhs.R_component_3() == static_cast<T>(0))&&
  935. (rhs.R_component_4() == static_cast<T>(0))
  936. );
  937. }
  938. template<typename T>
  939. inline bool operator == (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
  940. {
  941. return (
  942. (lhs.R_component_1() == rhs.real())&&
  943. (lhs.R_component_2() == rhs.imag())&&
  944. (lhs.R_component_3() == static_cast<T>(0))&&
  945. (lhs.R_component_4() == static_cast<T>(0))
  946. );
  947. }
  948. template<typename T>
  949. inline bool operator == (quaternion<T> const & lhs, quaternion<T> const & rhs)
  950. {
  951. return (
  952. (rhs.R_component_1() == lhs.R_component_1())&&
  953. (rhs.R_component_2() == lhs.R_component_2())&&
  954. (rhs.R_component_3() == lhs.R_component_3())&&
  955. (rhs.R_component_4() == lhs.R_component_4())
  956. );
  957. }
  958. #define BOOST_QUATERNION_NOT_EQUAL_GENERATOR \
  959. { \
  960. return(!(lhs == rhs)); \
  961. }
  962. template<typename T>
  963. inline bool operator != (T const & lhs, quaternion<T> const & rhs)
  964. BOOST_QUATERNION_NOT_EQUAL_GENERATOR
  965. template<typename T>
  966. inline bool operator != (quaternion<T> const & lhs, T const & rhs)
  967. BOOST_QUATERNION_NOT_EQUAL_GENERATOR
  968. template<typename T>
  969. inline bool operator != (::std::complex<T> const & lhs, quaternion<T> const & rhs)
  970. BOOST_QUATERNION_NOT_EQUAL_GENERATOR
  971. template<typename T>
  972. inline bool operator != (quaternion<T> const & lhs, ::std::complex<T> const & rhs)
  973. BOOST_QUATERNION_NOT_EQUAL_GENERATOR
  974. template<typename T>
  975. inline bool operator != (quaternion<T> const & lhs, quaternion<T> const & rhs)
  976. BOOST_QUATERNION_NOT_EQUAL_GENERATOR
  977. #undef BOOST_QUATERNION_NOT_EQUAL_GENERATOR
  978. // Note: we allow the following formats, whith a, b, c, and d reals
  979. // a
  980. // (a), (a,b), (a,b,c), (a,b,c,d)
  981. // (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b),(c,d))
  982. #if BOOST_WORKAROUND(__GNUC__, < 3)
  983. template<typename T>
  984. std::istream & operator >> ( ::std::istream & is,
  985. quaternion<T> & q)
  986. #else
  987. template<typename T, typename charT, class traits>
  988. ::std::basic_istream<charT,traits> & operator >> ( ::std::basic_istream<charT,traits> & is,
  989. quaternion<T> & q)
  990. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  991. {
  992. #if BOOST_WORKAROUND(__GNUC__, < 3)
  993. typedef char charT;
  994. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  995. #ifdef BOOST_NO_STD_LOCALE
  996. #else
  997. const ::std::ctype<charT> & ct = ::std::use_facet< ::std::ctype<charT> >(is.getloc());
  998. #endif /* BOOST_NO_STD_LOCALE */
  999. T a = T();
  1000. T b = T();
  1001. T c = T();
  1002. T d = T();
  1003. ::std::complex<T> u = ::std::complex<T>();
  1004. ::std::complex<T> v = ::std::complex<T>();
  1005. charT ch = charT();
  1006. char cc;
  1007. is >> ch; // get the first lexeme
  1008. if (!is.good()) goto finish;
  1009. #ifdef BOOST_NO_STD_LOCALE
  1010. cc = ch;
  1011. #else
  1012. cc = ct.narrow(ch, char());
  1013. #endif /* BOOST_NO_STD_LOCALE */
  1014. if (cc == '(') // read "(", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d)), ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
  1015. {
  1016. is >> ch; // get the second lexeme
  1017. if (!is.good()) goto finish;
  1018. #ifdef BOOST_NO_STD_LOCALE
  1019. cc = ch;
  1020. #else
  1021. cc = ct.narrow(ch, char());
  1022. #endif /* BOOST_NO_STD_LOCALE */
  1023. if (cc == '(') // read "((", possible: ((a)), ((a),c), ((a),(c)), ((a),(c,d)), ((a,b)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
  1024. {
  1025. is.putback(ch);
  1026. is >> u; // we extract the first and second components
  1027. a = u.real();
  1028. b = u.imag();
  1029. if (!is.good()) goto finish;
  1030. is >> ch; // get the next lexeme
  1031. if (!is.good()) goto finish;
  1032. #ifdef BOOST_NO_STD_LOCALE
  1033. cc = ch;
  1034. #else
  1035. cc = ct.narrow(ch, char());
  1036. #endif /* BOOST_NO_STD_LOCALE */
  1037. if (cc == ')') // format: ((a)) or ((a,b))
  1038. {
  1039. q = quaternion<T>(a,b);
  1040. }
  1041. else if (cc == ',') // read "((a)," or "((a,b),", possible: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)), ((a,b,),(c,d,))
  1042. {
  1043. is >> v; // we extract the third and fourth components
  1044. c = v.real();
  1045. d = v.imag();
  1046. if (!is.good()) goto finish;
  1047. is >> ch; // get the last lexeme
  1048. if (!is.good()) goto finish;
  1049. #ifdef BOOST_NO_STD_LOCALE
  1050. cc = ch;
  1051. #else
  1052. cc = ct.narrow(ch, char());
  1053. #endif /* BOOST_NO_STD_LOCALE */
  1054. if (cc == ')') // format: ((a),c), ((a),(c)), ((a),(c,d)), ((a,b),c), ((a,b),(c)) or ((a,b,),(c,d,))
  1055. {
  1056. q = quaternion<T>(a,b,c,d);
  1057. }
  1058. else // error
  1059. {
  1060. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1061. is.setstate(::std::ios::failbit);
  1062. #else
  1063. is.setstate(::std::ios_base::failbit);
  1064. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1065. }
  1066. }
  1067. else // error
  1068. {
  1069. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1070. is.setstate(::std::ios::failbit);
  1071. #else
  1072. is.setstate(::std::ios_base::failbit);
  1073. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1074. }
  1075. }
  1076. else // read "(a", possible: (a), (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
  1077. {
  1078. is.putback(ch);
  1079. is >> a; // we extract the first component
  1080. if (!is.good()) goto finish;
  1081. is >> ch; // get the third lexeme
  1082. if (!is.good()) goto finish;
  1083. #ifdef BOOST_NO_STD_LOCALE
  1084. cc = ch;
  1085. #else
  1086. cc = ct.narrow(ch, char());
  1087. #endif /* BOOST_NO_STD_LOCALE */
  1088. if (cc == ')') // format: (a)
  1089. {
  1090. q = quaternion<T>(a);
  1091. }
  1092. else if (cc == ',') // read "(a,", possible: (a,b), (a,b,c), (a,b,c,d), (a,(c)), (a,(c,d))
  1093. {
  1094. is >> ch; // get the fourth lexeme
  1095. if (!is.good()) goto finish;
  1096. #ifdef BOOST_NO_STD_LOCALE
  1097. cc = ch;
  1098. #else
  1099. cc = ct.narrow(ch, char());
  1100. #endif /* BOOST_NO_STD_LOCALE */
  1101. if (cc == '(') // read "(a,(", possible: (a,(c)), (a,(c,d))
  1102. {
  1103. is.putback(ch);
  1104. is >> v; // we extract the third and fourth component
  1105. c = v.real();
  1106. d = v.imag();
  1107. if (!is.good()) goto finish;
  1108. is >> ch; // get the ninth lexeme
  1109. if (!is.good()) goto finish;
  1110. #ifdef BOOST_NO_STD_LOCALE
  1111. cc = ch;
  1112. #else
  1113. cc = ct.narrow(ch, char());
  1114. #endif /* BOOST_NO_STD_LOCALE */
  1115. if (cc == ')') // format: (a,(c)) or (a,(c,d))
  1116. {
  1117. q = quaternion<T>(a,b,c,d);
  1118. }
  1119. else // error
  1120. {
  1121. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1122. is.setstate(::std::ios::failbit);
  1123. #else
  1124. is.setstate(::std::ios_base::failbit);
  1125. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1126. }
  1127. }
  1128. else // read "(a,b", possible: (a,b), (a,b,c), (a,b,c,d)
  1129. {
  1130. is.putback(ch);
  1131. is >> b; // we extract the second component
  1132. if (!is.good()) goto finish;
  1133. is >> ch; // get the fifth lexeme
  1134. if (!is.good()) goto finish;
  1135. #ifdef BOOST_NO_STD_LOCALE
  1136. cc = ch;
  1137. #else
  1138. cc = ct.narrow(ch, char());
  1139. #endif /* BOOST_NO_STD_LOCALE */
  1140. if (cc == ')') // format: (a,b)
  1141. {
  1142. q = quaternion<T>(a,b);
  1143. }
  1144. else if (cc == ',') // read "(a,b,", possible: (a,b,c), (a,b,c,d)
  1145. {
  1146. is >> c; // we extract the third component
  1147. if (!is.good()) goto finish;
  1148. is >> ch; // get the seventh lexeme
  1149. if (!is.good()) goto finish;
  1150. #ifdef BOOST_NO_STD_LOCALE
  1151. cc = ch;
  1152. #else
  1153. cc = ct.narrow(ch, char());
  1154. #endif /* BOOST_NO_STD_LOCALE */
  1155. if (cc == ')') // format: (a,b,c)
  1156. {
  1157. q = quaternion<T>(a,b,c);
  1158. }
  1159. else if (cc == ',') // read "(a,b,c,", possible: (a,b,c,d)
  1160. {
  1161. is >> d; // we extract the fourth component
  1162. if (!is.good()) goto finish;
  1163. is >> ch; // get the ninth lexeme
  1164. if (!is.good()) goto finish;
  1165. #ifdef BOOST_NO_STD_LOCALE
  1166. cc = ch;
  1167. #else
  1168. cc = ct.narrow(ch, char());
  1169. #endif /* BOOST_NO_STD_LOCALE */
  1170. if (cc == ')') // format: (a,b,c,d)
  1171. {
  1172. q = quaternion<T>(a,b,c,d);
  1173. }
  1174. else // error
  1175. {
  1176. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1177. is.setstate(::std::ios::failbit);
  1178. #else
  1179. is.setstate(::std::ios_base::failbit);
  1180. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1181. }
  1182. }
  1183. else // error
  1184. {
  1185. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1186. is.setstate(::std::ios::failbit);
  1187. #else
  1188. is.setstate(::std::ios_base::failbit);
  1189. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1190. }
  1191. }
  1192. else // error
  1193. {
  1194. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1195. is.setstate(::std::ios::failbit);
  1196. #else
  1197. is.setstate(::std::ios_base::failbit);
  1198. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1199. }
  1200. }
  1201. }
  1202. else // error
  1203. {
  1204. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1205. is.setstate(::std::ios::failbit);
  1206. #else
  1207. is.setstate(::std::ios_base::failbit);
  1208. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1209. }
  1210. }
  1211. }
  1212. else // format: a
  1213. {
  1214. is.putback(ch);
  1215. is >> a; // we extract the first component
  1216. if (!is.good()) goto finish;
  1217. q = quaternion<T>(a);
  1218. }
  1219. finish:
  1220. return(is);
  1221. }
  1222. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1223. template<typename T>
  1224. ::std::ostream & operator << ( ::std::ostream & os,
  1225. quaternion<T> const & q)
  1226. #else
  1227. template<typename T, typename charT, class traits>
  1228. ::std::basic_ostream<charT,traits> & operator << ( ::std::basic_ostream<charT,traits> & os,
  1229. quaternion<T> const & q)
  1230. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1231. {
  1232. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1233. ::std::ostringstream s;
  1234. #else
  1235. ::std::basic_ostringstream<charT,traits> s;
  1236. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1237. s.flags(os.flags());
  1238. #ifdef BOOST_NO_STD_LOCALE
  1239. #else
  1240. s.imbue(os.getloc());
  1241. #endif /* BOOST_NO_STD_LOCALE */
  1242. s.precision(os.precision());
  1243. s << '(' << q.R_component_1() << ','
  1244. << q.R_component_2() << ','
  1245. << q.R_component_3() << ','
  1246. << q.R_component_4() << ')';
  1247. return os << s.str();
  1248. }
  1249. // values
  1250. template<typename T>
  1251. inline T real(quaternion<T> const & q)
  1252. {
  1253. return(q.real());
  1254. }
  1255. template<typename T>
  1256. inline quaternion<T> unreal(quaternion<T> const & q)
  1257. {
  1258. return(q.unreal());
  1259. }
  1260. #define BOOST_QUATERNION_VALARRAY_LOADER \
  1261. using ::std::valarray; \
  1262. \
  1263. valarray<T> temp(4); \
  1264. \
  1265. temp[0] = q.R_component_1(); \
  1266. temp[1] = q.R_component_2(); \
  1267. temp[2] = q.R_component_3(); \
  1268. temp[3] = q.R_component_4();
  1269. template<typename T>
  1270. inline T sup(quaternion<T> const & q)
  1271. {
  1272. #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  1273. using ::std::abs;
  1274. #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
  1275. BOOST_QUATERNION_VALARRAY_LOADER
  1276. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1277. return((BOOST_GET_VALARRAY(T, abs(temp)).max)());
  1278. #else
  1279. return((abs(temp).max)());
  1280. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1281. }
  1282. template<typename T>
  1283. inline T l1(quaternion<T> const & q)
  1284. {
  1285. #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  1286. using ::std::abs;
  1287. #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
  1288. BOOST_QUATERNION_VALARRAY_LOADER
  1289. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1290. return(BOOST_GET_VALARRAY(T, abs(temp)).sum());
  1291. #else
  1292. return(abs(temp).sum());
  1293. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1294. }
  1295. template<typename T>
  1296. inline T abs(quaternion<T> const & q)
  1297. {
  1298. #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
  1299. using ::std::abs;
  1300. #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
  1301. using ::std::sqrt;
  1302. BOOST_QUATERNION_VALARRAY_LOADER
  1303. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1304. T maxim = (BOOST_GET_VALARRAY(T, abs(temp)).max)(); // overflow protection
  1305. #else
  1306. T maxim = (abs(temp).max)(); // overflow protection
  1307. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1308. if (maxim == static_cast<T>(0))
  1309. {
  1310. return(maxim);
  1311. }
  1312. else
  1313. {
  1314. T mixam = static_cast<T>(1)/maxim; // prefer multiplications over divisions
  1315. temp *= mixam;
  1316. temp *= temp;
  1317. return(maxim*sqrt(temp.sum()));
  1318. }
  1319. //return(sqrt(norm(q)));
  1320. }
  1321. #undef BOOST_QUATERNION_VALARRAY_LOADER
  1322. // Note: This is the Cayley norm, not the Euclidian norm...
  1323. template<typename T>
  1324. inline T norm(quaternion<T>const & q)
  1325. {
  1326. return(real(q*conj(q)));
  1327. }
  1328. template<typename T>
  1329. inline quaternion<T> conj(quaternion<T> const & q)
  1330. {
  1331. return(quaternion<T>( +q.R_component_1(),
  1332. -q.R_component_2(),
  1333. -q.R_component_3(),
  1334. -q.R_component_4()));
  1335. }
  1336. template<typename T>
  1337. inline quaternion<T> spherical( T const & rho,
  1338. T const & theta,
  1339. T const & phi1,
  1340. T const & phi2)
  1341. {
  1342. using ::std::cos;
  1343. using ::std::sin;
  1344. //T a = cos(theta)*cos(phi1)*cos(phi2);
  1345. //T b = sin(theta)*cos(phi1)*cos(phi2);
  1346. //T c = sin(phi1)*cos(phi2);
  1347. //T d = sin(phi2);
  1348. T courrant = static_cast<T>(1);
  1349. T d = sin(phi2);
  1350. courrant *= cos(phi2);
  1351. T c = sin(phi1)*courrant;
  1352. courrant *= cos(phi1);
  1353. T b = sin(theta)*courrant;
  1354. T a = cos(theta)*courrant;
  1355. return(rho*quaternion<T>(a,b,c,d));
  1356. }
  1357. template<typename T>
  1358. inline quaternion<T> semipolar( T const & rho,
  1359. T const & alpha,
  1360. T const & theta1,
  1361. T const & theta2)
  1362. {
  1363. using ::std::cos;
  1364. using ::std::sin;
  1365. T a = cos(alpha)*cos(theta1);
  1366. T b = cos(alpha)*sin(theta1);
  1367. T c = sin(alpha)*cos(theta2);
  1368. T d = sin(alpha)*sin(theta2);
  1369. return(rho*quaternion<T>(a,b,c,d));
  1370. }
  1371. template<typename T>
  1372. inline quaternion<T> multipolar( T const & rho1,
  1373. T const & theta1,
  1374. T const & rho2,
  1375. T const & theta2)
  1376. {
  1377. using ::std::cos;
  1378. using ::std::sin;
  1379. T a = rho1*cos(theta1);
  1380. T b = rho1*sin(theta1);
  1381. T c = rho2*cos(theta2);
  1382. T d = rho2*sin(theta2);
  1383. return(quaternion<T>(a,b,c,d));
  1384. }
  1385. template<typename T>
  1386. inline quaternion<T> cylindrospherical( T const & t,
  1387. T const & radius,
  1388. T const & longitude,
  1389. T const & latitude)
  1390. {
  1391. using ::std::cos;
  1392. using ::std::sin;
  1393. T b = radius*cos(longitude)*cos(latitude);
  1394. T c = radius*sin(longitude)*cos(latitude);
  1395. T d = radius*sin(latitude);
  1396. return(quaternion<T>(t,b,c,d));
  1397. }
  1398. template<typename T>
  1399. inline quaternion<T> cylindrical(T const & r,
  1400. T const & angle,
  1401. T const & h1,
  1402. T const & h2)
  1403. {
  1404. using ::std::cos;
  1405. using ::std::sin;
  1406. T a = r*cos(angle);
  1407. T b = r*sin(angle);
  1408. return(quaternion<T>(a,b,h1,h2));
  1409. }
  1410. // transcendentals
  1411. // (please see the documentation)
  1412. template<typename T>
  1413. inline quaternion<T> exp(quaternion<T> const & q)
  1414. {
  1415. using ::std::exp;
  1416. using ::std::cos;
  1417. using ::boost::math::sinc_pi;
  1418. T u = exp(real(q));
  1419. T z = abs(unreal(q));
  1420. T w = sinc_pi(z);
  1421. return(u*quaternion<T>(cos(z),
  1422. w*q.R_component_2(), w*q.R_component_3(),
  1423. w*q.R_component_4()));
  1424. }
  1425. template<typename T>
  1426. inline quaternion<T> cos(quaternion<T> const & q)
  1427. {
  1428. using ::std::sin;
  1429. using ::std::cos;
  1430. using ::std::cosh;
  1431. using ::boost::math::sinhc_pi;
  1432. T z = abs(unreal(q));
  1433. T w = -sin(q.real())*sinhc_pi(z);
  1434. return(quaternion<T>(cos(q.real())*cosh(z),
  1435. w*q.R_component_2(), w*q.R_component_3(),
  1436. w*q.R_component_4()));
  1437. }
  1438. template<typename T>
  1439. inline quaternion<T> sin(quaternion<T> const & q)
  1440. {
  1441. using ::std::sin;
  1442. using ::std::cos;
  1443. using ::std::cosh;
  1444. using ::boost::math::sinhc_pi;
  1445. T z = abs(unreal(q));
  1446. T w = +cos(q.real())*sinhc_pi(z);
  1447. return(quaternion<T>(sin(q.real())*cosh(z),
  1448. w*q.R_component_2(), w*q.R_component_3(),
  1449. w*q.R_component_4()));
  1450. }
  1451. template<typename T>
  1452. inline quaternion<T> tan(quaternion<T> const & q)
  1453. {
  1454. return(sin(q)/cos(q));
  1455. }
  1456. template<typename T>
  1457. inline quaternion<T> cosh(quaternion<T> const & q)
  1458. {
  1459. return((exp(+q)+exp(-q))/static_cast<T>(2));
  1460. }
  1461. template<typename T>
  1462. inline quaternion<T> sinh(quaternion<T> const & q)
  1463. {
  1464. return((exp(+q)-exp(-q))/static_cast<T>(2));
  1465. }
  1466. template<typename T>
  1467. inline quaternion<T> tanh(quaternion<T> const & q)
  1468. {
  1469. return(sinh(q)/cosh(q));
  1470. }
  1471. template<typename T>
  1472. quaternion<T> pow(quaternion<T> const & q,
  1473. int n)
  1474. {
  1475. if (n > 1)
  1476. {
  1477. int m = n>>1;
  1478. quaternion<T> result = pow(q, m);
  1479. result *= result;
  1480. if (n != (m<<1))
  1481. {
  1482. result *= q; // n odd
  1483. }
  1484. return(result);
  1485. }
  1486. else if (n == 1)
  1487. {
  1488. return(q);
  1489. }
  1490. else if (n == 0)
  1491. {
  1492. return(quaternion<T>(static_cast<T>(1)));
  1493. }
  1494. else /* n < 0 */
  1495. {
  1496. return(pow(quaternion<T>(static_cast<T>(1))/q,-n));
  1497. }
  1498. }
  1499. // helper templates for converting copy constructors (definition)
  1500. namespace detail
  1501. {
  1502. template< typename T,
  1503. typename U
  1504. >
  1505. quaternion<T> quaternion_type_converter(quaternion<U> const & rhs)
  1506. {
  1507. return(quaternion<T>( static_cast<T>(rhs.R_component_1()),
  1508. static_cast<T>(rhs.R_component_2()),
  1509. static_cast<T>(rhs.R_component_3()),
  1510. static_cast<T>(rhs.R_component_4())));
  1511. }
  1512. }
  1513. }
  1514. }
  1515. #if BOOST_WORKAROUND(__GNUC__, < 3)
  1516. #undef BOOST_GET_VALARRAY
  1517. #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
  1518. #endif /* BOOST_QUATERNION_HPP */