mat_operations.hpp 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539
  1. #ifndef BOOST_QVM_MAT_OPERATIONS_HPP_INCLUDED
  2. #define BOOST_QVM_MAT_OPERATIONS_HPP_INCLUDED
  3. // Copyright 2008-2022 Emil Dotchevski and Reverge Studios, Inc.
  4. // Copyright 2019 agate-pris
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #include <boost/qvm/detail/mat_assign.hpp>
  8. #include <boost/qvm/mat_operations2.hpp>
  9. #include <boost/qvm/mat_operations3.hpp>
  10. #include <boost/qvm/mat_operations4.hpp>
  11. #include <boost/qvm/math.hpp>
  12. #include <boost/qvm/detail/determinant_impl.hpp>
  13. #include <boost/qvm/detail/cofactor_impl.hpp>
  14. #include <boost/qvm/detail/transp_impl.hpp>
  15. #include <boost/qvm/scalar_traits.hpp>
  16. #include <boost/qvm/to_string.hpp>
  17. namespace boost { namespace qvm {
  18. namespace
  19. qvm_detail
  20. {
  21. BOOST_QVM_INLINE_CRITICAL
  22. void const *
  23. get_valid_ptr_mat_operations()
  24. {
  25. static int const obj=0;
  26. return &obj;
  27. }
  28. }
  29. ////////////////////////////////////////////////
  30. namespace
  31. qvm_detail
  32. {
  33. template <int R,int C>
  34. struct
  35. to_string_m_defined
  36. {
  37. static bool const value=false;
  38. };
  39. template <int I,int SizeMinusOne>
  40. struct
  41. to_string_matrix_elements
  42. {
  43. template <class A>
  44. static
  45. std::string
  46. f( A const & a )
  47. {
  48. using namespace qvm_to_string_detail;
  49. return
  50. ( (I%mat_traits<A>::cols)==0 ? '(' : ',' ) +
  51. to_string(mat_traits<A>::template read_element<I/mat_traits<A>::cols,I%mat_traits<A>::cols>(a)) +
  52. ( (I%mat_traits<A>::cols)==mat_traits<A>::cols-1 ? ")" : "" ) +
  53. to_string_matrix_elements<I+1,SizeMinusOne>::f(a);
  54. }
  55. };
  56. template <int SizeMinusOne>
  57. struct
  58. to_string_matrix_elements<SizeMinusOne,SizeMinusOne>
  59. {
  60. template <class A>
  61. static
  62. std::string
  63. f( A const & a )
  64. {
  65. using namespace qvm_to_string_detail;
  66. return
  67. ( (SizeMinusOne%mat_traits<A>::cols)==0 ? '(' : ',' ) +
  68. to_string(mat_traits<A>::template read_element<SizeMinusOne/mat_traits<A>::cols,SizeMinusOne%mat_traits<A>::cols>(a)) +
  69. ')';
  70. }
  71. };
  72. }
  73. template <class A>
  74. inline
  75. typename enable_if_c<
  76. is_mat<A>::value &&
  77. !qvm_detail::to_string_m_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  78. std::string>::type
  79. to_string( A const & a )
  80. {
  81. return "("+qvm_detail::to_string_matrix_elements<0,mat_traits<A>::rows*mat_traits<A>::cols-1>::f(a)+')';
  82. }
  83. ////////////////////////////////////////////////
  84. template <class A,class B,class Cmp>
  85. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  86. typename enable_if_c<
  87. is_mat<A>::value && is_mat<B>::value &&
  88. mat_traits<A>::rows==mat_traits<B>::rows &&
  89. mat_traits<A>::cols==mat_traits<B>::cols,
  90. bool>::type
  91. cmp( A const & a, B const & b, Cmp f )
  92. {
  93. for( int i=0; i!=mat_traits<A>::rows; ++i )
  94. for( int j=0; j!=mat_traits<A>::cols; ++j )
  95. if( !f(
  96. mat_traits<A>::read_element_idx(i, j, a),
  97. mat_traits<B>::read_element_idx(i, j, b)) )
  98. return false;
  99. return true;
  100. }
  101. ////////////////////////////////////////////////
  102. namespace
  103. qvm_detail
  104. {
  105. template <int M,int N>
  106. struct
  107. convert_to_m_defined
  108. {
  109. static bool const value=false;
  110. };
  111. }
  112. template <class R,class A>
  113. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  114. typename enable_if_c<
  115. is_mat<R>::value && is_mat<A>::value &&
  116. mat_traits<R>::rows==mat_traits<A>::rows &&
  117. mat_traits<R>::cols==mat_traits<A>::cols &&
  118. !qvm_detail::convert_to_m_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  119. R>::type
  120. convert_to( A const & a )
  121. {
  122. R r; assign(r,a);
  123. return r;
  124. }
  125. ////////////////////////////////////////////////
  126. namespace
  127. qvm_detail
  128. {
  129. template <int D>
  130. struct
  131. determinant_defined
  132. {
  133. static bool const value=false;
  134. };
  135. }
  136. template <class A>
  137. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  138. typename enable_if_c<
  139. is_mat<A>::value &&
  140. mat_traits<A>::rows==mat_traits<A>::cols &&
  141. !qvm_detail::determinant_defined<mat_traits<A>::rows>::value,
  142. typename mat_traits<A>::scalar_type>::type
  143. determinant( A const & a )
  144. {
  145. return qvm_detail::determinant_impl(a);
  146. }
  147. ////////////////////////////////////////////////
  148. namespace
  149. qvm_detail
  150. {
  151. template <class T,int Dim>
  152. class
  153. identity_mat_
  154. {
  155. identity_mat_( identity_mat_ const & );
  156. identity_mat_ & operator=( identity_mat_ const & );
  157. ~identity_mat_();
  158. public:
  159. template <class R
  160. #if __cplusplus >= 201103L
  161. , class = typename enable_if<is_mat<R> >::type
  162. #endif
  163. >
  164. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  165. operator R() const
  166. {
  167. R r;
  168. assign(r,*this);
  169. return r;
  170. }
  171. };
  172. }
  173. template <class T,int Dim>
  174. struct
  175. mat_traits< qvm_detail::identity_mat_<T,Dim> >
  176. {
  177. typedef qvm_detail::identity_mat_<T,Dim> this_matrix;
  178. typedef T scalar_type;
  179. static int const rows=Dim;
  180. static int const cols=Dim;
  181. template <int Row,int Col>
  182. static
  183. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  184. scalar_type
  185. read_element( this_matrix const & /*x*/ )
  186. {
  187. BOOST_QVM_STATIC_ASSERT(Row>=0);
  188. BOOST_QVM_STATIC_ASSERT(Row<Dim);
  189. BOOST_QVM_STATIC_ASSERT(Col>=0);
  190. BOOST_QVM_STATIC_ASSERT(Col<Dim);
  191. return scalar_traits<scalar_type>::value(Row==Col);
  192. }
  193. static
  194. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  195. scalar_type
  196. read_element_idx( int row, int col, this_matrix const & /*x*/ )
  197. {
  198. BOOST_QVM_ASSERT(row>=0);
  199. BOOST_QVM_ASSERT(row<Dim);
  200. BOOST_QVM_ASSERT(col>=0);
  201. BOOST_QVM_ASSERT(col<Dim);
  202. return scalar_traits<scalar_type>::value(row==col);
  203. }
  204. };
  205. template <class T,int Dim>
  206. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  207. qvm_detail::identity_mat_<T,Dim> const &
  208. identity_mat()
  209. {
  210. return *(qvm_detail::identity_mat_<T,Dim> const *)qvm_detail::get_valid_ptr_mat_operations();
  211. }
  212. template <class A>
  213. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  214. typename enable_if_c<
  215. is_mat<A>::value &&
  216. mat_traits<A>::rows==mat_traits<A>::cols,
  217. void>::type
  218. set_identity( A & a )
  219. {
  220. assign(a,identity_mat<typename mat_traits<A>::scalar_type,mat_traits<A>::rows>());
  221. }
  222. ////////////////////////////////////////////////
  223. namespace
  224. qvm_detail
  225. {
  226. template <class T>
  227. struct
  228. projection_
  229. {
  230. T const _00;
  231. T const _11;
  232. T const _22;
  233. T const _23;
  234. T const _32;
  235. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  236. projection_( T _00, T _11, T _22, T _23, T _32 ):
  237. _00(_00),
  238. _11(_11),
  239. _22(_22),
  240. _23(_23),
  241. _32(_32)
  242. {
  243. }
  244. template <class R
  245. #if __cplusplus >= 201103L
  246. , class = typename enable_if<is_mat<R> >::type
  247. #endif
  248. >
  249. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  250. operator R() const
  251. {
  252. R r;
  253. assign(r,*this);
  254. return r;
  255. }
  256. };
  257. template <int Row,int Col>
  258. struct
  259. projection_get
  260. {
  261. template <class T>
  262. static
  263. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  264. T
  265. get( projection_<T> const & )
  266. {
  267. return scalar_traits<T>::value(0);
  268. }
  269. };
  270. template <> struct projection_get<0,0> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._00; } };
  271. template <> struct projection_get<1,1> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._11; } };
  272. template <> struct projection_get<2,2> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._22; } };
  273. template <> struct projection_get<2,3> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._23; } };
  274. template <> struct projection_get<3,2> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( projection_<T> const & m ) { return m._32; } };
  275. }
  276. template <class T>
  277. struct
  278. mat_traits< qvm_detail::projection_<T> >
  279. {
  280. typedef qvm_detail::projection_<T> this_matrix;
  281. typedef T scalar_type;
  282. static int const rows=4;
  283. static int const cols=4;
  284. template <int Row,int Col>
  285. static
  286. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  287. scalar_type
  288. read_element( this_matrix const & x )
  289. {
  290. BOOST_QVM_STATIC_ASSERT(Row>=0);
  291. BOOST_QVM_STATIC_ASSERT(Row<rows);
  292. BOOST_QVM_STATIC_ASSERT(Col>=0);
  293. BOOST_QVM_STATIC_ASSERT(Col<cols);
  294. return qvm_detail::projection_get<Row,Col>::get(x);
  295. }
  296. };
  297. template <class T>
  298. qvm_detail::projection_<T>
  299. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  300. perspective_lh( T fov_y, T aspect_ratio, T z_near, T z_far )
  301. {
  302. T const one = scalar_traits<T>::value(1);
  303. T const ys = one/tan(fov_y/scalar_traits<T>::value(2));
  304. T const xs = ys/aspect_ratio;
  305. T const zd = z_far-z_near;
  306. T const z1 = z_far/zd;
  307. T const z2 = -z_near*z1;
  308. return qvm_detail::projection_<T>(xs,ys,z1,z2,one);
  309. }
  310. template <class T>
  311. qvm_detail::projection_<T>
  312. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  313. perspective_rh( T fov_y, T aspect_ratio, T z_near, T z_far )
  314. {
  315. T const one = scalar_traits<T>::value(1);
  316. T const ys = one/tan(fov_y/scalar_traits<T>::value(2));
  317. T const xs = ys/aspect_ratio;
  318. T const zd = z_near-z_far;
  319. T const z1 = z_far/zd;
  320. T const z2 = z_near*z1;
  321. return qvm_detail::projection_<T>(xs,ys,z1,z2,-one);
  322. }
  323. ////////////////////////////////////////////////
  324. namespace
  325. qvm_detail
  326. {
  327. template <class OriginalType,class Scalar>
  328. class
  329. matrix_scalar_cast_
  330. {
  331. matrix_scalar_cast_( matrix_scalar_cast_ const & );
  332. matrix_scalar_cast_ & operator=( matrix_scalar_cast_ const & );
  333. ~matrix_scalar_cast_();
  334. public:
  335. template <class T>
  336. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  337. matrix_scalar_cast_ &
  338. operator=( T const & x )
  339. {
  340. assign(*this,x);
  341. return *this;
  342. }
  343. template <class R
  344. #if __cplusplus >= 201103L
  345. , class = typename enable_if<is_mat<R> >::type
  346. #endif
  347. >
  348. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  349. operator R() const
  350. {
  351. R r;
  352. assign(r,*this);
  353. return r;
  354. }
  355. };
  356. template <bool> struct scalar_cast_matrix_filter { };
  357. template <> struct scalar_cast_matrix_filter<true> { typedef int type; };
  358. }
  359. template <class OriginalType,class Scalar>
  360. struct
  361. mat_traits< qvm_detail::matrix_scalar_cast_<OriginalType,Scalar> >
  362. {
  363. typedef Scalar scalar_type;
  364. typedef qvm_detail::matrix_scalar_cast_<OriginalType,Scalar> this_matrix;
  365. static int const rows=mat_traits<OriginalType>::rows;
  366. static int const cols=mat_traits<OriginalType>::cols;
  367. template <int Row,int Col>
  368. static
  369. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  370. scalar_type
  371. read_element( this_matrix const & x )
  372. {
  373. BOOST_QVM_STATIC_ASSERT(Row>=0);
  374. BOOST_QVM_STATIC_ASSERT(Row<rows);
  375. BOOST_QVM_STATIC_ASSERT(Col>=0);
  376. BOOST_QVM_STATIC_ASSERT(Col<cols);
  377. return scalar_type(mat_traits<OriginalType>::template read_element<Row,Col>(reinterpret_cast<OriginalType const &>(x)));
  378. }
  379. static
  380. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  381. scalar_type
  382. read_element_idx( int row, int col, this_matrix const & x )
  383. {
  384. BOOST_QVM_ASSERT(row>=0);
  385. BOOST_QVM_ASSERT(row<rows);
  386. BOOST_QVM_ASSERT(col>=0);
  387. BOOST_QVM_ASSERT(col<cols);
  388. return scalar_type(mat_traits<OriginalType>::read_element_idx(col,row,reinterpret_cast<OriginalType const &>(x)));
  389. }
  390. };
  391. template <class OriginalType,class Scalar,int R,int C>
  392. struct
  393. deduce_mat<qvm_detail::matrix_scalar_cast_<OriginalType,Scalar>,R,C>
  394. {
  395. typedef mat<Scalar,R,C> type;
  396. };
  397. template <class Scalar,class T>
  398. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  399. qvm_detail::matrix_scalar_cast_<T,Scalar> const &
  400. scalar_cast( T const & x, typename qvm_detail::scalar_cast_matrix_filter<is_mat<T>::value>::type=0 )
  401. {
  402. return reinterpret_cast<qvm_detail::matrix_scalar_cast_<T,Scalar> const &>(x);
  403. }
  404. ////////////////////////////////////////////////
  405. namespace
  406. qvm_detail
  407. {
  408. template <int M,int N>
  409. struct
  410. div_eq_ms_defined
  411. {
  412. static bool const value=false;
  413. };
  414. }
  415. template <class A,class B>
  416. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  417. typename enable_if_c<
  418. is_mat<A>::value && is_scalar<B>::value &&
  419. !qvm_detail::div_eq_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  420. A &>::type
  421. operator/=( A & a, B b )
  422. {
  423. for( int i=0; i!=mat_traits<A>::rows; ++i )
  424. for( int j=0; j!=mat_traits<A>::cols; ++j )
  425. write_mat_element_idx(i,j,a,mat_traits<A>::read_element_idx(i,j,a)/b);
  426. return a;
  427. }
  428. ////////////////////////////////////////////////
  429. namespace
  430. qvm_detail
  431. {
  432. template <int M,int N>
  433. struct
  434. div_ms_defined
  435. {
  436. static bool const value=false;
  437. };
  438. }
  439. template <class A,class B>
  440. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  441. typename lazy_enable_if_c<
  442. is_mat<A>::value && is_scalar<B>::value &&
  443. !qvm_detail::div_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  444. deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
  445. operator/( A const & a, B b )
  446. {
  447. typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
  448. R r;
  449. for( int i=0; i!=mat_traits<A>::rows; ++i )
  450. for( int j=0; j!=mat_traits<A>::cols; ++j )
  451. write_mat_element_idx(i,j,r,mat_traits<A>::read_element_idx(i,j,a)/b);
  452. return r;
  453. }
  454. ////////////////////////////////////////////////
  455. namespace
  456. qvm_detail
  457. {
  458. template <int M,int N>
  459. struct
  460. eq_mm_defined
  461. {
  462. static bool const value=false;
  463. };
  464. }
  465. template <class A,class B>
  466. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  467. typename enable_if_c<
  468. is_mat<A>::value && is_mat<B>::value &&
  469. mat_traits<A>::rows==mat_traits<B>::rows &&
  470. mat_traits<A>::cols==mat_traits<B>::cols &&
  471. !qvm_detail::eq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  472. bool>::type
  473. operator==( A const & a, B const & b )
  474. {
  475. for( int i=0; i!=mat_traits<A>::rows; ++i )
  476. for( int j=0; j!=mat_traits<A>::cols; ++j )
  477. if( mat_traits<A>::read_element_idx(i,j,a)!=mat_traits<B>::read_element_idx(i,j,b) )
  478. return false;
  479. return true;
  480. }
  481. ////////////////////////////////////////////////
  482. namespace
  483. qvm_detail
  484. {
  485. template <int M,int N>
  486. struct
  487. minus_eq_mm_defined
  488. {
  489. static bool const value=false;
  490. };
  491. }
  492. template <class A,class B>
  493. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  494. typename enable_if_c<
  495. is_mat<A>::value && is_mat<B>::value &&
  496. mat_traits<A>::rows==mat_traits<B>::rows &&
  497. mat_traits<A>::cols==mat_traits<B>::cols &&
  498. !qvm_detail::minus_eq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  499. A &>::type
  500. operator-=( A & a, B const & b )
  501. {
  502. for( int i=0; i!=mat_traits<A>::rows; ++i )
  503. for( int j=0; j!=mat_traits<A>::cols; ++j )
  504. write_mat_element_idx(i,j,a,mat_traits<A>::read_element_idx(i,j,a)-mat_traits<B>::read_element_idx(i,j,b));
  505. return a;
  506. }
  507. ////////////////////////////////////////////////
  508. namespace
  509. qvm_detail
  510. {
  511. template <int M,int N>
  512. struct
  513. minus_m_defined
  514. {
  515. static bool const value=false;
  516. };
  517. }
  518. template <class A>
  519. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  520. typename lazy_enable_if_c<
  521. is_mat<A>::value &&
  522. !qvm_detail::minus_m_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  523. deduce_mat<A> >::type
  524. operator-( A const & a )
  525. {
  526. typedef typename deduce_mat<A>::type R;
  527. R r;
  528. for( int i=0; i!=mat_traits<A>::rows; ++i )
  529. for( int j=0; j!=mat_traits<A>::cols; ++j )
  530. write_mat_element_idx(i,j,r,-mat_traits<A>::read_element_idx(i,j,a));
  531. return r;
  532. }
  533. ////////////////////////////////////////////////
  534. namespace
  535. qvm_detail
  536. {
  537. template <int M,int N>
  538. struct
  539. minus_mm_defined
  540. {
  541. static bool const value=false;
  542. };
  543. }
  544. template <class A,class B>
  545. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  546. typename lazy_enable_if_c<
  547. is_mat<A>::value && is_mat<B>::value &&
  548. mat_traits<A>::rows==mat_traits<B>::rows &&
  549. mat_traits<A>::cols==mat_traits<B>::cols &&
  550. !qvm_detail::minus_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  551. deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
  552. operator-( A const & a, B const & b )
  553. {
  554. typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
  555. R r;
  556. for( int i=0; i!=mat_traits<A>::rows; ++i )
  557. for( int j=0; j!=mat_traits<A>::cols; ++j )
  558. write_mat_element_idx(i,j,r,mat_traits<A>::read_element_idx(i,j,a)-mat_traits<B>::read_element_idx(i,j,b));
  559. return r;
  560. }
  561. ////////////////////////////////////////////////
  562. namespace
  563. qvm_detail
  564. {
  565. template <int D>
  566. struct
  567. mul_eq_mm_defined
  568. {
  569. static bool const value=false;
  570. };
  571. }
  572. template <class A,class B>
  573. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  574. typename enable_if_c<
  575. is_mat<A>::value &&
  576. is_mat<B>::value &&
  577. mat_traits<A>::rows==mat_traits<A>::cols &&
  578. mat_traits<A>::rows==mat_traits<B>::rows &&
  579. mat_traits<A>::cols==mat_traits<B>::cols &&
  580. !qvm_detail::mul_eq_mm_defined<mat_traits<A>::rows>::value,
  581. A &>::type
  582. operator*=( A & r, B const & b )
  583. {
  584. typedef typename mat_traits<A>::scalar_type Ta;
  585. Ta a[mat_traits<A>::rows][mat_traits<A>::cols];
  586. for( int i=0; i<mat_traits<A>::rows; ++i )
  587. for( int j=0; j<mat_traits<B>::cols; ++j )
  588. a[i][j]=mat_traits<A>::read_element_idx(i,j,r);
  589. for( int i=0; i<mat_traits<A>::rows; ++i )
  590. for( int j=0; j<mat_traits<B>::cols; ++j )
  591. {
  592. Ta x(scalar_traits<Ta>::value(0));
  593. for( int k=0; k<mat_traits<A>::cols; ++k )
  594. x += a[i][k]*mat_traits<B>::read_element_idx(k,j,b);
  595. write_mat_element_idx(i,j,r,x);
  596. }
  597. return r;
  598. }
  599. ////////////////////////////////////////////////
  600. namespace
  601. qvm_detail
  602. {
  603. template <int M,int N>
  604. struct
  605. mul_eq_ms_defined
  606. {
  607. static bool const value=false;
  608. };
  609. }
  610. template <class A,class B>
  611. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  612. typename enable_if_c<
  613. is_mat<A>::value && is_scalar<B>::value &&
  614. !qvm_detail::mul_eq_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  615. A &>::type
  616. operator*=( A & a, B b )
  617. {
  618. for( int i=0; i!=mat_traits<A>::rows; ++i )
  619. for( int j=0; j!=mat_traits<A>::cols; ++j )
  620. write_mat_element_idx(i,j,a,mat_traits<A>::read_element_idx(i,j,a)*b);
  621. return a;
  622. }
  623. ////////////////////////////////////////////////
  624. namespace
  625. qvm_detail
  626. {
  627. template <int R,int /*CR*/,int C>
  628. struct
  629. mul_mm_defined
  630. {
  631. static bool const value=false;
  632. };
  633. }
  634. template <class A,class B>
  635. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  636. typename lazy_enable_if_c<
  637. is_mat<A>::value && is_mat<B>::value &&
  638. mat_traits<A>::cols==mat_traits<B>::rows &&
  639. !qvm_detail::mul_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols,mat_traits<B>::cols>::value,
  640. deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<B>::cols> >::type
  641. operator*( A const & a, B const & b )
  642. {
  643. typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<B>::cols>::type R;
  644. R r;
  645. for( int i=0; i<mat_traits<A>::rows; ++i )
  646. for( int j=0; j<mat_traits<B>::cols; ++j )
  647. {
  648. typedef typename mat_traits<A>::scalar_type Ta;
  649. Ta x(scalar_traits<Ta>::value(0));
  650. for( int k=0; k<mat_traits<A>::cols; ++k )
  651. x += mat_traits<A>::read_element_idx(i,k,a)*mat_traits<B>::read_element_idx(k,j,b);
  652. write_mat_element_idx(i,j,r,x);
  653. }
  654. return r;
  655. }
  656. ////////////////////////////////////////////////
  657. namespace
  658. qvm_detail
  659. {
  660. template <int M,int N>
  661. struct
  662. mul_ms_defined
  663. {
  664. static bool const value=false;
  665. };
  666. }
  667. template <class A,class B>
  668. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  669. typename lazy_enable_if_c<
  670. is_mat<A>::value && is_scalar<B>::value &&
  671. !qvm_detail::mul_ms_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  672. deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
  673. operator*( A const & a, B b )
  674. {
  675. typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
  676. R r;
  677. for( int i=0; i!=mat_traits<A>::rows; ++i )
  678. for( int j=0; j!=mat_traits<A>::cols; ++j )
  679. write_mat_element_idx(i,j,r,mat_traits<A>::read_element_idx(i,j,a)*b);
  680. return r;
  681. }
  682. ////////////////////////////////////////////////
  683. namespace
  684. qvm_detail
  685. {
  686. template <int M,int N>
  687. struct
  688. mul_sm_defined
  689. {
  690. static bool const value=false;
  691. };
  692. }
  693. template <class A,class B>
  694. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  695. typename lazy_enable_if_c<
  696. is_scalar<A>::value && is_mat<B>::value &&
  697. !qvm_detail::mul_sm_defined<mat_traits<B>::rows,mat_traits<B>::cols>::value,
  698. deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols> >::type
  699. operator*( A a, B const & b )
  700. {
  701. typedef typename deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols>::type R;
  702. R r;
  703. for( int i=0; i!=mat_traits<B>::rows; ++i )
  704. for( int j=0; j!=mat_traits<B>::cols; ++j )
  705. write_mat_element_idx(i,j,r,a*mat_traits<B>::read_element_idx(i,j,b));
  706. return r;
  707. }
  708. ////////////////////////////////////////////////
  709. namespace
  710. qvm_detail
  711. {
  712. template <int M,int N>
  713. struct
  714. neq_mm_defined
  715. {
  716. static bool const value=false;
  717. };
  718. }
  719. template <class A,class B>
  720. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  721. typename enable_if_c<
  722. is_mat<A>::value && is_mat<B>::value &&
  723. mat_traits<A>::rows==mat_traits<B>::rows &&
  724. mat_traits<A>::cols==mat_traits<B>::cols &&
  725. !qvm_detail::neq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  726. bool>::type
  727. operator!=( A const & a, B const & b )
  728. {
  729. for( int i=0; i!=mat_traits<A>::rows; ++i )
  730. for( int j=0; j!=mat_traits<A>::cols; ++j )
  731. if( mat_traits<A>::read_element_idx(i,j,a)!=mat_traits<B>::read_element_idx(i,j,b) )
  732. return true;
  733. return false;
  734. }
  735. ////////////////////////////////////////////////
  736. namespace
  737. qvm_detail
  738. {
  739. template <int M,int N>
  740. struct
  741. plus_eq_mm_defined
  742. {
  743. static bool const value=false;
  744. };
  745. }
  746. template <class A,class B>
  747. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  748. typename enable_if_c<
  749. is_mat<A>::value && is_mat<B>::value &&
  750. mat_traits<A>::rows==mat_traits<B>::rows &&
  751. mat_traits<A>::cols==mat_traits<B>::cols &&
  752. !qvm_detail::plus_eq_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  753. A &>::type
  754. operator+=( A & a, B const & b )
  755. {
  756. for( int i=0; i!=mat_traits<A>::rows; ++i )
  757. for( int j=0; j!=mat_traits<A>::cols; ++j )
  758. write_mat_element_idx(i,j,a,mat_traits<A>::read_element_idx(i,j,a)+mat_traits<B>::read_element_idx(i,j,b));
  759. return a;
  760. }
  761. ////////////////////////////////////////////////
  762. namespace
  763. qvm_detail
  764. {
  765. template <int M,int N>
  766. struct
  767. plus_mm_defined
  768. {
  769. static bool const value=false;
  770. };
  771. }
  772. template <class A,class B>
  773. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  774. typename lazy_enable_if_c<
  775. is_mat<A>::value && is_mat<B>::value &&
  776. mat_traits<A>::rows==mat_traits<B>::rows &&
  777. mat_traits<A>::cols==mat_traits<B>::cols &&
  778. !qvm_detail::plus_mm_defined<mat_traits<A>::rows,mat_traits<A>::cols>::value,
  779. deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
  780. operator+( A const & a, B const & b )
  781. {
  782. typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
  783. R r;
  784. for( int i=0; i!=mat_traits<A>::rows; ++i )
  785. for( int j=0; j!=mat_traits<A>::cols; ++j )
  786. write_mat_element_idx(i,j,r,mat_traits<A>::read_element_idx(i,j,a)+mat_traits<B>::read_element_idx(i,j,b));
  787. return r;
  788. }
  789. ////////////////////////////////////////////////
  790. namespace
  791. qvm_detail
  792. {
  793. template <class T>
  794. class
  795. mref_
  796. {
  797. mref_( mref_ const & );
  798. mref_ & operator=( mref_ const & );
  799. ~mref_();
  800. public:
  801. template <class R>
  802. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  803. mref_ &
  804. operator=( R const & x )
  805. {
  806. assign(*this,x);
  807. return *this;
  808. }
  809. template <class R
  810. #if __cplusplus >= 201103L
  811. , class = typename enable_if<is_mat<R> >::type
  812. #endif
  813. >
  814. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  815. operator R() const
  816. {
  817. R r;
  818. assign(r,*this);
  819. return r;
  820. }
  821. };
  822. template <class M,bool WriteElementRef=mat_write_element_ref<M>::value>
  823. struct mref_write_traits;
  824. template <class M>
  825. struct
  826. mref_write_traits<M,true>
  827. {
  828. typedef typename mat_traits<M>::scalar_type scalar_type;
  829. typedef qvm_detail::mref_<M> this_matrix;
  830. static int const rows=mat_traits<M>::rows;
  831. static int const cols=mat_traits<M>::cols;
  832. template <int Row,int Col>
  833. static
  834. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  835. scalar_type &
  836. write_element( this_matrix & x )
  837. {
  838. BOOST_QVM_STATIC_ASSERT(Row>=0);
  839. BOOST_QVM_STATIC_ASSERT(Row<rows);
  840. BOOST_QVM_STATIC_ASSERT(Col>=0);
  841. BOOST_QVM_STATIC_ASSERT(Col<cols);
  842. return mat_traits<M>::template write_element<Row,Col>(reinterpret_cast<M &>(x));
  843. }
  844. static
  845. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  846. scalar_type &
  847. write_element_idx( int row, int col, this_matrix & x )
  848. {
  849. BOOST_QVM_ASSERT(row>=0);
  850. BOOST_QVM_ASSERT(row<rows);
  851. BOOST_QVM_ASSERT(col>=0);
  852. BOOST_QVM_ASSERT(col<cols);
  853. return mat_traits<M>::write_element_idx(row,col,reinterpret_cast<M &>(x));
  854. }
  855. };
  856. template <class M>
  857. struct
  858. mref_write_traits<M,false>
  859. {
  860. typedef typename mat_traits<M>::scalar_type scalar_type;
  861. typedef qvm_detail::mref_<M> this_matrix;
  862. static int const rows=mat_traits<M>::rows;
  863. static int const cols=mat_traits<M>::cols;
  864. template <int Row,int Col>
  865. static
  866. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  867. void
  868. write_element( this_matrix & x, scalar_type s )
  869. {
  870. BOOST_QVM_STATIC_ASSERT(Row>=0);
  871. BOOST_QVM_STATIC_ASSERT(Row<rows);
  872. BOOST_QVM_STATIC_ASSERT(Col>=0);
  873. BOOST_QVM_STATIC_ASSERT(Col<cols);
  874. mat_traits<M>::template write_element<Row,Col>(reinterpret_cast<M &>(x), s);
  875. }
  876. static
  877. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  878. void
  879. write_element_idx( int row, int col, this_matrix & x, scalar_type s )
  880. {
  881. BOOST_QVM_ASSERT(row>=0);
  882. BOOST_QVM_ASSERT(row<rows);
  883. BOOST_QVM_ASSERT(col>=0);
  884. BOOST_QVM_ASSERT(col<cols);
  885. mat_traits<M>::write_element_idx(row,col,reinterpret_cast<M &>(x), s);
  886. }
  887. };
  888. }
  889. template <class M>
  890. struct
  891. mat_traits< qvm_detail::mref_<M> >:
  892. qvm_detail::mref_write_traits<M>
  893. {
  894. typedef typename mat_traits<M>::scalar_type scalar_type;
  895. typedef qvm_detail::mref_<M> this_matrix;
  896. static int const rows=mat_traits<M>::rows;
  897. static int const cols=mat_traits<M>::cols;
  898. template <int Row,int Col>
  899. static
  900. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  901. scalar_type
  902. read_element( this_matrix const & x )
  903. {
  904. BOOST_QVM_STATIC_ASSERT(Row>=0);
  905. BOOST_QVM_STATIC_ASSERT(Row<rows);
  906. BOOST_QVM_STATIC_ASSERT(Col>=0);
  907. BOOST_QVM_STATIC_ASSERT(Col<cols);
  908. return mat_traits<M>::template read_element<Row,Col>(reinterpret_cast<M const &>(x));
  909. }
  910. static
  911. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  912. scalar_type
  913. read_element_idx( int row, int col, this_matrix const & x )
  914. {
  915. BOOST_QVM_ASSERT(row>=0);
  916. BOOST_QVM_ASSERT(row<rows);
  917. BOOST_QVM_ASSERT(col>=0);
  918. BOOST_QVM_ASSERT(col<cols);
  919. return mat_traits<M>::read_element_idx(row,col,reinterpret_cast<M const &>(x));
  920. }
  921. };
  922. template <class M,int R,int C>
  923. struct
  924. deduce_mat<qvm_detail::mref_<M>,R,C>
  925. {
  926. typedef mat<typename mat_traits<M>::scalar_type,R,C> type;
  927. };
  928. template <class M>
  929. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  930. typename enable_if_c<
  931. is_mat<M>::value,
  932. qvm_detail::mref_<M> const &>::type
  933. mref( M const & a )
  934. {
  935. return reinterpret_cast<qvm_detail::mref_<M> const &>(a);
  936. }
  937. template <class M>
  938. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  939. typename enable_if_c<
  940. is_mat<M>::value,
  941. qvm_detail::mref_<M> &>::type
  942. mref( M & a )
  943. {
  944. return reinterpret_cast<qvm_detail::mref_<M> &>(a);
  945. }
  946. ////////////////////////////////////////////////
  947. namespace
  948. qvm_detail
  949. {
  950. template <class T,int Rows,int Cols>
  951. class
  952. zero_mat_
  953. {
  954. zero_mat_( zero_mat_ const & );
  955. zero_mat_ & operator=( zero_mat_ const & );
  956. ~zero_mat_();
  957. public:
  958. template <class R
  959. #if __cplusplus >= 201103L
  960. , class = typename enable_if<is_mat<R> >::type
  961. #endif
  962. >
  963. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  964. operator R() const
  965. {
  966. R r;
  967. assign(r,*this);
  968. return r;
  969. }
  970. };
  971. }
  972. template <class T,int Rows,int Cols>
  973. struct
  974. mat_traits< qvm_detail::zero_mat_<T,Rows,Cols> >
  975. {
  976. typedef qvm_detail::zero_mat_<T,Rows,Cols> this_matrix;
  977. typedef T scalar_type;
  978. static int const rows=Rows;
  979. static int const cols=Cols;
  980. template <int Row,int Col>
  981. static
  982. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  983. scalar_type
  984. read_element( this_matrix const & )
  985. {
  986. BOOST_QVM_STATIC_ASSERT(Row>=0);
  987. BOOST_QVM_STATIC_ASSERT(Row<rows);
  988. BOOST_QVM_STATIC_ASSERT(Col>=0);
  989. BOOST_QVM_STATIC_ASSERT(Col<cols);
  990. return scalar_traits<scalar_type>::value(0);
  991. }
  992. static
  993. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  994. scalar_type
  995. read_element_idx( int row, int col, this_matrix const & )
  996. {
  997. BOOST_QVM_ASSERT(row>=0);
  998. BOOST_QVM_ASSERT(row<rows);
  999. BOOST_QVM_ASSERT(col>=0);
  1000. BOOST_QVM_ASSERT(col<cols);
  1001. return scalar_traits<scalar_type>::value(0);
  1002. }
  1003. };
  1004. template <class T,int Rows,int Cols,int R,int C>
  1005. struct
  1006. deduce_mat<qvm_detail::zero_mat_<T,Rows,Cols>,R,C>
  1007. {
  1008. typedef mat<T,R,C> type;
  1009. };
  1010. template <class T,int Rows,int Cols>
  1011. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1012. qvm_detail::zero_mat_<T,Rows,Cols> const &
  1013. zero_mat()
  1014. {
  1015. return *(qvm_detail::zero_mat_<T,Rows,Cols> const *)qvm_detail::get_valid_ptr_mat_operations();
  1016. }
  1017. template <class T,int Dim>
  1018. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1019. qvm_detail::zero_mat_<T,Dim,Dim> const &
  1020. zero_mat()
  1021. {
  1022. return *(qvm_detail::zero_mat_<T,Dim,Dim> const *)qvm_detail::get_valid_ptr_mat_operations();
  1023. }
  1024. template <class A>
  1025. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1026. typename enable_if_c<
  1027. is_mat<A>::value,
  1028. void>::type
  1029. set_zero( A & a )
  1030. {
  1031. assign(a,zero_mat<typename mat_traits<A>::scalar_type,mat_traits<A>::rows,mat_traits<A>::cols>());
  1032. }
  1033. ////////////////////////////////////////////////
  1034. namespace
  1035. qvm_detail
  1036. {
  1037. template <int D,class S>
  1038. struct
  1039. rot_mat_
  1040. {
  1041. typedef S scalar_type;
  1042. scalar_type a[3][3];
  1043. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1044. rot_mat_(
  1045. scalar_type a00, scalar_type a01, scalar_type a02,
  1046. scalar_type a10, scalar_type a11, scalar_type a12,
  1047. scalar_type a20, scalar_type a21, scalar_type a22 )
  1048. {
  1049. a[0][0] = a00;
  1050. a[0][1] = a01;
  1051. a[0][2] = a02;
  1052. a[1][0] = a10;
  1053. a[1][1] = a11;
  1054. a[1][2] = a12;
  1055. a[2][0] = a20;
  1056. a[2][1] = a21;
  1057. a[2][2] = a22;
  1058. }
  1059. template <class R
  1060. #if __cplusplus >= 201103L
  1061. , class = typename enable_if<is_mat<R> >::type
  1062. #endif
  1063. >
  1064. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1065. operator R() const
  1066. {
  1067. R r;
  1068. assign(r,*this);
  1069. return r;
  1070. }
  1071. };
  1072. template <int Row,int Col>
  1073. struct
  1074. rot_m_get
  1075. {
  1076. template <class T>
  1077. static
  1078. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1079. T
  1080. get( T const (&)[3][3] )
  1081. {
  1082. return scalar_traits<T>::value(Row==Col);
  1083. }
  1084. };
  1085. template <> struct rot_m_get<0,0> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[0][0]; } };
  1086. template <> struct rot_m_get<0,1> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[0][1]; } };
  1087. template <> struct rot_m_get<0,2> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[0][2]; } };
  1088. template <> struct rot_m_get<1,0> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[1][0]; } };
  1089. template <> struct rot_m_get<1,1> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[1][1]; } };
  1090. template <> struct rot_m_get<1,2> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[1][2]; } };
  1091. template <> struct rot_m_get<2,0> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[2][0]; } };
  1092. template <> struct rot_m_get<2,1> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[2][1]; } };
  1093. template <> struct rot_m_get<2,2> { template <class T> static BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL T get( T const (&a)[3][3] ) { return a[2][2]; } };
  1094. }
  1095. template <class M>
  1096. struct mat_traits;
  1097. template <int D,class S>
  1098. struct
  1099. mat_traits< qvm_detail::rot_mat_<D,S> >
  1100. {
  1101. typedef qvm_detail::rot_mat_<D,S> this_matrix;
  1102. typedef typename this_matrix::scalar_type scalar_type;
  1103. static int const rows=D;
  1104. static int const cols=D;
  1105. template <int Row,int Col>
  1106. static
  1107. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1108. scalar_type
  1109. read_element( this_matrix const & x )
  1110. {
  1111. BOOST_QVM_STATIC_ASSERT(Row>=0);
  1112. BOOST_QVM_STATIC_ASSERT(Row<D);
  1113. BOOST_QVM_STATIC_ASSERT(Col>=0);
  1114. BOOST_QVM_STATIC_ASSERT(Col<D);
  1115. return qvm_detail::rot_m_get<Row,Col>::get(x.a);
  1116. }
  1117. static
  1118. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1119. scalar_type
  1120. read_element_idx( int row, int col, this_matrix const & x )
  1121. {
  1122. BOOST_QVM_ASSERT(row>=0);
  1123. BOOST_QVM_ASSERT(row<D);
  1124. BOOST_QVM_ASSERT(col>=0);
  1125. BOOST_QVM_ASSERT(col<D);
  1126. return row<3 && col<3?
  1127. x.a[row][col] :
  1128. scalar_traits<scalar_type>::value(row==col);
  1129. }
  1130. };
  1131. template <int Dim,class V,class Angle>
  1132. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1133. typename enable_if_c<
  1134. is_vec<V>::value && vec_traits<V>::dim==3,
  1135. qvm_detail::rot_mat_<Dim,Angle> >::type
  1136. rot_mat( V const & axis, Angle angle )
  1137. {
  1138. typedef Angle scalar_type;
  1139. scalar_type const x=vec_traits<V>::template read_element<0>(axis);
  1140. scalar_type const y=vec_traits<V>::template read_element<1>(axis);
  1141. scalar_type const z=vec_traits<V>::template read_element<2>(axis);
  1142. scalar_type const m2=x*x+y*y+z*z;
  1143. if( m2==scalar_traits<scalar_type>::value(0) )
  1144. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  1145. scalar_type const s = sin(angle);
  1146. scalar_type const c = cos(angle);
  1147. scalar_type const x2 = x*x;
  1148. scalar_type const y2 = y*y;
  1149. scalar_type const z2 = z*z;
  1150. scalar_type const xy = x*y;
  1151. scalar_type const xz = x*z;
  1152. scalar_type const yz = y*z;
  1153. scalar_type const xs = x*s;
  1154. scalar_type const ys = y*s;
  1155. scalar_type const zs = z*s;
  1156. scalar_type const one = scalar_traits<scalar_type>::value(1);
  1157. scalar_type const c1 = one-c;
  1158. return qvm_detail::rot_mat_<Dim,Angle>(
  1159. x2+(one-x2)*c, xy*c1-zs, xz*(one-c)+ys,
  1160. xy*c1+zs, y2+(one-y2)*c, yz*c1-xs,
  1161. xz*c1-ys, yz*c1+xs, z2+(one-z2)*c );
  1162. }
  1163. template <class A,class B,class Angle>
  1164. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1165. typename enable_if_c<
  1166. is_mat<A>::value &&
  1167. mat_traits<A>::rows==mat_traits<A>::cols &&
  1168. mat_traits<A>::rows>=3 &&
  1169. is_vec<B>::value && vec_traits<B>::dim==3,
  1170. void>::type
  1171. set_rot( A & a, B const & axis, Angle angle )
  1172. {
  1173. assign(a,rot_mat<mat_traits<A>::rows>(axis,angle));
  1174. }
  1175. template <class A,class B,class Angle>
  1176. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1177. typename enable_if_c<
  1178. is_mat<A>::value &&
  1179. mat_traits<A>::rows==mat_traits<A>::cols &&
  1180. mat_traits<A>::rows>=3 &&
  1181. is_vec<B>::value && vec_traits<B>::dim==3,
  1182. void>::type
  1183. rotate( A & a, B const & axis, Angle angle )
  1184. {
  1185. a *= rot_mat<mat_traits<A>::rows>(axis,angle);
  1186. }
  1187. ////////////////////////////////////////////////
  1188. template <int Dim,class Angle>
  1189. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1190. qvm_detail::rot_mat_<Dim,Angle>
  1191. rot_mat_xzy( Angle x1, Angle z2, Angle y3 )
  1192. {
  1193. typedef Angle scalar_type;
  1194. scalar_type const c1 = cos(x1);
  1195. scalar_type const s1 = sin(x1);
  1196. scalar_type const c2 = cos(z2);
  1197. scalar_type const s2 = sin(z2);
  1198. scalar_type const c3 = cos(y3);
  1199. scalar_type const s3 = sin(y3);
  1200. return qvm_detail::rot_mat_<Dim,Angle>(
  1201. c2*c3, -s2, c2*s3,
  1202. s1*s3 + c1*c3*s2, c1*c2, c1*s2*s3 - c3*s1,
  1203. c3*s1*s2 - c1*s3, c2*s1, c1*c3 + s1*s2*s3 );
  1204. }
  1205. template <class A,class Angle>
  1206. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1207. typename enable_if_c<
  1208. is_mat<A>::value &&
  1209. mat_traits<A>::rows==mat_traits<A>::cols &&
  1210. mat_traits<A>::rows>=3,
  1211. void>::type
  1212. set_rot_xzy( A & a, Angle x1, Angle z2, Angle y3 )
  1213. {
  1214. assign(a,rot_mat_xzy<mat_traits<A>::rows>(x1,z2,y3));
  1215. }
  1216. template <class A,class Angle>
  1217. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1218. typename enable_if_c<
  1219. is_mat<A>::value &&
  1220. mat_traits<A>::rows==mat_traits<A>::cols &&
  1221. mat_traits<A>::rows>=3,
  1222. void>::type
  1223. rotate_xzy( A & a, Angle x1, Angle z2, Angle y3 )
  1224. {
  1225. a *= rot_mat_xzy<mat_traits<A>::rows>(x1,z2,y3);
  1226. }
  1227. ////////////////////////////////////////////////
  1228. template <int Dim,class Angle>
  1229. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1230. qvm_detail::rot_mat_<Dim,Angle>
  1231. rot_mat_xyz( Angle x1, Angle y2, Angle z3 )
  1232. {
  1233. typedef Angle scalar_type;
  1234. scalar_type const c1 = cos(x1);
  1235. scalar_type const s1 = sin(x1);
  1236. scalar_type const c2 = cos(y2);
  1237. scalar_type const s2 = sin(y2);
  1238. scalar_type const c3 = cos(z3);
  1239. scalar_type const s3 = sin(z3);
  1240. return qvm_detail::rot_mat_<Dim,Angle>(
  1241. c2*c3, -c2*s3, s2,
  1242. c1*s3 + c3*s1*s2, c1*c3 - s1*s2*s3, -c2*s1,
  1243. s1*s3 - c1*c3*s2, c3*s1 + c1*s2*s3, c1*c2 );
  1244. }
  1245. template <class A,class Angle>
  1246. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1247. typename enable_if_c<
  1248. is_mat<A>::value &&
  1249. mat_traits<A>::rows==mat_traits<A>::cols &&
  1250. mat_traits<A>::rows>=3,
  1251. void>::type
  1252. set_rot_xyz( A & a, Angle x1, Angle y2, Angle z3 )
  1253. {
  1254. assign(a,rot_mat_xyz<mat_traits<A>::rows>(x1,y2,z3));
  1255. }
  1256. template <class A,class Angle>
  1257. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1258. typename enable_if_c<
  1259. is_mat<A>::value &&
  1260. mat_traits<A>::rows==mat_traits<A>::cols &&
  1261. mat_traits<A>::rows>=3,
  1262. void>::type
  1263. rotate_xyz( A & a, Angle x1, Angle y2, Angle z3 )
  1264. {
  1265. a *= rot_mat_xyz<mat_traits<A>::rows>(x1,y2,z3);
  1266. }
  1267. ////////////////////////////////////////////////
  1268. template <int Dim,class Angle>
  1269. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1270. qvm_detail::rot_mat_<Dim,Angle>
  1271. rot_mat_yxz( Angle y1, Angle x2, Angle z3 )
  1272. {
  1273. typedef Angle scalar_type;
  1274. scalar_type const c1 = cos(y1);
  1275. scalar_type const s1 = sin(y1);
  1276. scalar_type const c2 = cos(x2);
  1277. scalar_type const s2 = sin(x2);
  1278. scalar_type const c3 = cos(z3);
  1279. scalar_type const s3 = sin(z3);
  1280. return qvm_detail::rot_mat_<Dim,Angle>(
  1281. c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3, c2*s1,
  1282. c2*s3, c2*c3, -s2,
  1283. c1*s2*s3 - c3*s1, c1*c3*s2 + s1*s3, c1*c2 );
  1284. }
  1285. template <class A,class Angle>
  1286. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1287. typename enable_if_c<
  1288. is_mat<A>::value &&
  1289. mat_traits<A>::rows==mat_traits<A>::cols &&
  1290. mat_traits<A>::rows>=3,
  1291. void>::type
  1292. set_rot_yxz( A & a, Angle y1, Angle x2, Angle z3 )
  1293. {
  1294. assign(a,rot_mat_yxz<mat_traits<A>::rows>(y1,x2,z3));
  1295. }
  1296. template <class A,class Angle>
  1297. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1298. typename enable_if_c<
  1299. is_mat<A>::value &&
  1300. mat_traits<A>::rows==mat_traits<A>::cols &&
  1301. mat_traits<A>::rows>=3,
  1302. void>::type
  1303. rotate_yxz( A & a, Angle y1, Angle x2, Angle z3 )
  1304. {
  1305. a *= rot_mat_yxz<mat_traits<A>::rows>(y1,x2,z3);
  1306. }
  1307. ////////////////////////////////////////////////
  1308. template <int Dim,class Angle>
  1309. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1310. qvm_detail::rot_mat_<Dim,Angle>
  1311. rot_mat_yzx( Angle y1, Angle z2, Angle x3 )
  1312. {
  1313. typedef Angle scalar_type;
  1314. scalar_type const c1 = cos(y1);
  1315. scalar_type const s1 = sin(y1);
  1316. scalar_type const c2 = cos(z2);
  1317. scalar_type const s2 = sin(z2);
  1318. scalar_type const c3 = cos(x3);
  1319. scalar_type const s3 = sin(x3);
  1320. return qvm_detail::rot_mat_<Dim,Angle>(
  1321. c1*c2, s1*s3 - c1*c3*s2, c3*s1 + c1*s2*s3,
  1322. s2, c2*c3, -c2*s3,
  1323. -c2*s1, c1*s3 + c3*s1*s2, c1*c3 - s1*s2*s3 );
  1324. }
  1325. template <class A,class Angle>
  1326. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1327. typename enable_if_c<
  1328. is_mat<A>::value &&
  1329. mat_traits<A>::rows==mat_traits<A>::cols &&
  1330. mat_traits<A>::rows>=3,
  1331. void>::type
  1332. set_rot_yzx( A & a, Angle y1, Angle z2, Angle x3 )
  1333. {
  1334. assign(a,rot_mat_yzx<mat_traits<A>::rows>(y1,z2,x3));
  1335. }
  1336. template <class A,class Angle>
  1337. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1338. typename enable_if_c<
  1339. is_mat<A>::value &&
  1340. mat_traits<A>::rows==mat_traits<A>::cols &&
  1341. mat_traits<A>::rows>=3,
  1342. void>::type
  1343. rotate_yzx( A & a, Angle y1, Angle z2, Angle x3 )
  1344. {
  1345. a *= rot_mat_yzx<mat_traits<A>::rows>(y1,z2,x3);
  1346. }
  1347. ////////////////////////////////////////////////
  1348. template <int Dim,class Angle>
  1349. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1350. qvm_detail::rot_mat_<Dim,Angle>
  1351. rot_mat_zyx( Angle z1, Angle y2, Angle x3 )
  1352. {
  1353. typedef Angle scalar_type;
  1354. scalar_type const c1 = cos(z1);
  1355. scalar_type const s1 = sin(z1);
  1356. scalar_type const c2 = cos(y2);
  1357. scalar_type const s2 = sin(y2);
  1358. scalar_type const c3 = cos(x3);
  1359. scalar_type const s3 = sin(x3);
  1360. return qvm_detail::rot_mat_<Dim,Angle>(
  1361. c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2,
  1362. c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3,
  1363. -s2, c2*s3, c2*c3 );
  1364. }
  1365. template <class A,class Angle>
  1366. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1367. typename enable_if_c<
  1368. is_mat<A>::value &&
  1369. mat_traits<A>::rows==mat_traits<A>::cols &&
  1370. mat_traits<A>::rows>=3,
  1371. void>::type
  1372. set_rot_zyx( A & a, Angle z1, Angle y2, Angle x3 )
  1373. {
  1374. assign(a,rot_mat_zyx<mat_traits<A>::rows>(z1,y2,x3));
  1375. }
  1376. template <class A,class Angle>
  1377. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1378. typename enable_if_c<
  1379. is_mat<A>::value &&
  1380. mat_traits<A>::rows==mat_traits<A>::cols &&
  1381. mat_traits<A>::rows>=3,
  1382. void>::type
  1383. rotate_zyx( A & a, Angle z1, Angle y2, Angle x3 )
  1384. {
  1385. a *= rot_mat_zyx<mat_traits<A>::rows>(z1,y2,x3);
  1386. }
  1387. ////////////////////////////////////////////////
  1388. template <int Dim,class Angle>
  1389. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1390. qvm_detail::rot_mat_<Dim,Angle>
  1391. rot_mat_zxy( Angle z1, Angle x2, Angle y3 )
  1392. {
  1393. typedef Angle scalar_type;
  1394. scalar_type const c1 = cos(z1);
  1395. scalar_type const s1 = sin(z1);
  1396. scalar_type const c2 = cos(x2);
  1397. scalar_type const s2 = sin(x2);
  1398. scalar_type const c3 = cos(y3);
  1399. scalar_type const s3 = sin(y3);
  1400. return qvm_detail::rot_mat_<Dim,Angle>(
  1401. c1*c3 - s1*s2*s3, -c2*s1, c1*s3 + c3*s1*s2,
  1402. c3*s1 + c1*s2*s3, c1*c2, s1*s3 - c1*c3*s2,
  1403. -c2*s3, s2, c2*c3 );
  1404. }
  1405. template <class A,class Angle>
  1406. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1407. typename enable_if_c<
  1408. is_mat<A>::value &&
  1409. mat_traits<A>::rows==mat_traits<A>::cols &&
  1410. mat_traits<A>::rows>=3,
  1411. void>::type
  1412. set_rot_zxy( A & a, Angle z1, Angle x2, Angle y3 )
  1413. {
  1414. assign(a,rot_mat_zxy<mat_traits<A>::rows>(z1,x2,y3));
  1415. }
  1416. template <class A,class Angle>
  1417. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1418. typename enable_if_c<
  1419. is_mat<A>::value &&
  1420. mat_traits<A>::rows==mat_traits<A>::cols &&
  1421. mat_traits<A>::rows>=3,
  1422. void>::type
  1423. rotate_zxy( A & a, Angle z1, Angle x2, Angle y3 )
  1424. {
  1425. a *= rot_mat_zxy<mat_traits<A>::rows>(z1,x2,y3);
  1426. }
  1427. ////////////////////////////////////////////////
  1428. template <int Dim,class Angle>
  1429. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1430. qvm_detail::rot_mat_<Dim,Angle>
  1431. rot_mat_xzx( Angle x1, Angle z2, Angle x3 )
  1432. {
  1433. typedef Angle scalar_type;
  1434. scalar_type const c1 = cos(x1);
  1435. scalar_type const s1 = sin(x1);
  1436. scalar_type const c2 = cos(z2);
  1437. scalar_type const s2 = sin(z2);
  1438. scalar_type const c3 = cos(x3);
  1439. scalar_type const s3 = sin(x3);
  1440. return qvm_detail::rot_mat_<Dim,Angle>(
  1441. c2, -c3*s2, s2*s3,
  1442. c1*s2, c1*c2*c3 - s1*s3, -c3*s1 - c1*c2*s3,
  1443. s1*s2, c1*s3 + c2*c3*s1, c1*c3 - c2*s1*s3 );
  1444. }
  1445. template <class A,class Angle>
  1446. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1447. typename enable_if_c<
  1448. is_mat<A>::value &&
  1449. mat_traits<A>::rows==mat_traits<A>::cols &&
  1450. mat_traits<A>::rows>=3,
  1451. void>::type
  1452. set_rot_xzx( A & a, Angle x1, Angle z2, Angle x3 )
  1453. {
  1454. assign(a,rot_mat_xzx<mat_traits<A>::rows>(x1,z2,x3));
  1455. }
  1456. template <class A,class Angle>
  1457. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1458. typename enable_if_c<
  1459. is_mat<A>::value &&
  1460. mat_traits<A>::rows==mat_traits<A>::cols &&
  1461. mat_traits<A>::rows>=3,
  1462. void>::type
  1463. rotate_xzx( A & a, Angle x1, Angle z2, Angle x3 )
  1464. {
  1465. a *= rot_mat_xzx<mat_traits<A>::rows>(x1,z2,x3);
  1466. }
  1467. ////////////////////////////////////////////////
  1468. template <int Dim,class Angle>
  1469. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1470. qvm_detail::rot_mat_<Dim,Angle>
  1471. rot_mat_xyx( Angle x1, Angle y2, Angle x3 )
  1472. {
  1473. typedef Angle scalar_type;
  1474. scalar_type const c1 = cos(x1);
  1475. scalar_type const s1 = sin(x1);
  1476. scalar_type const c2 = cos(y2);
  1477. scalar_type const s2 = sin(y2);
  1478. scalar_type const c3 = cos(x3);
  1479. scalar_type const s3 = sin(x3);
  1480. return qvm_detail::rot_mat_<Dim,Angle>(
  1481. c2, s2*s3, c3*s2,
  1482. s1*s2, c1*c3 - c2*s1*s3, -c1*s3 - c2*c3*s1,
  1483. -c1*s2, c3*s1 + c1*c2*s3, c1*c2*c3 - s1*s3 );
  1484. }
  1485. template <class A,class Angle>
  1486. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1487. typename enable_if_c<
  1488. is_mat<A>::value &&
  1489. mat_traits<A>::rows==mat_traits<A>::cols &&
  1490. mat_traits<A>::rows>=3,
  1491. void>::type
  1492. set_rot_xyx( A & a, Angle x1, Angle y2, Angle x3 )
  1493. {
  1494. assign(a,rot_mat_xyx<mat_traits<A>::rows>(x1,y2,x3));
  1495. }
  1496. template <class A,class Angle>
  1497. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1498. typename enable_if_c<
  1499. is_mat<A>::value &&
  1500. mat_traits<A>::rows==mat_traits<A>::cols &&
  1501. mat_traits<A>::rows>=3,
  1502. void>::type
  1503. rotate_xyx( A & a, Angle x1, Angle y2, Angle x3 )
  1504. {
  1505. a *= rot_mat_xyx<mat_traits<A>::rows>(x1,y2,x3);
  1506. }
  1507. ////////////////////////////////////////////////
  1508. template <int Dim,class Angle>
  1509. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1510. qvm_detail::rot_mat_<Dim,Angle>
  1511. rot_mat_yxy( Angle y1, Angle x2, Angle y3 )
  1512. {
  1513. typedef Angle scalar_type;
  1514. scalar_type const c1 = cos(y1);
  1515. scalar_type const s1 = sin(y1);
  1516. scalar_type const c2 = cos(x2);
  1517. scalar_type const s2 = sin(x2);
  1518. scalar_type const c3 = cos(y3);
  1519. scalar_type const s3 = sin(y3);
  1520. return qvm_detail::rot_mat_<Dim,Angle>(
  1521. c1*c3 - c2*s1*s3, s1*s2, c1*s3 + c2*c3*s1,
  1522. s2*s3, c2, -c3*s2,
  1523. -c3*s1 - c1*c2*s3, c1*s2, c1*c2*c3 - s1*s3 );
  1524. }
  1525. template <class A,class Angle>
  1526. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1527. typename enable_if_c<
  1528. is_mat<A>::value &&
  1529. mat_traits<A>::rows==mat_traits<A>::cols &&
  1530. mat_traits<A>::rows>=3,
  1531. void>::type
  1532. set_rot_yxy( A & a, Angle y1, Angle x2, Angle y3 )
  1533. {
  1534. assign(a,rot_mat_yxy<mat_traits<A>::rows>(y1,x2,y3));
  1535. }
  1536. template <class A,class Angle>
  1537. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1538. typename enable_if_c<
  1539. is_mat<A>::value &&
  1540. mat_traits<A>::rows==mat_traits<A>::cols &&
  1541. mat_traits<A>::rows>=3,
  1542. void>::type
  1543. rotate_yxy( A & a, Angle y1, Angle x2, Angle y3 )
  1544. {
  1545. a *= rot_mat_yxy<mat_traits<A>::rows>(y1,x2,y3);
  1546. }
  1547. ////////////////////////////////////////////////
  1548. template <int Dim,class Angle>
  1549. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1550. qvm_detail::rot_mat_<Dim,Angle>
  1551. rot_mat_yzy( Angle y1, Angle z2, Angle y3 )
  1552. {
  1553. typedef Angle scalar_type;
  1554. scalar_type const c1 = cos(y1);
  1555. scalar_type const s1 = sin(y1);
  1556. scalar_type const c2 = cos(z2);
  1557. scalar_type const s2 = sin(z2);
  1558. scalar_type const c3 = cos(y3);
  1559. scalar_type const s3 = sin(y3);
  1560. return qvm_detail::rot_mat_<Dim,Angle>(
  1561. c1*c2*c3 - s1*s3, -c1*s2, c3*s1 + c1*c2*s3,
  1562. c3*s2, c2, s2*s3,
  1563. -c1*s3 - c2*c3*s1, s1*s2, c1*c3 - c2*s1*s3 );
  1564. }
  1565. template <class A,class Angle>
  1566. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1567. typename enable_if_c<
  1568. is_mat<A>::value &&
  1569. mat_traits<A>::rows==mat_traits<A>::cols &&
  1570. mat_traits<A>::rows>=3,
  1571. void>::type
  1572. set_rot_yzy( A & a, Angle y1, Angle z2, Angle y3 )
  1573. {
  1574. assign(a,rot_mat_yzy<mat_traits<A>::rows>(y1,z2,y3));
  1575. }
  1576. template <class A,class Angle>
  1577. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1578. typename enable_if_c<
  1579. is_mat<A>::value &&
  1580. mat_traits<A>::rows==mat_traits<A>::cols &&
  1581. mat_traits<A>::rows>=3,
  1582. void>::type
  1583. rotate_yzy( A & a, Angle y1, Angle z2, Angle y3 )
  1584. {
  1585. a *= rot_mat_yzy<mat_traits<A>::rows>(y1,z2,y3);
  1586. }
  1587. ////////////////////////////////////////////////
  1588. template <int Dim,class Angle>
  1589. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1590. qvm_detail::rot_mat_<Dim,Angle>
  1591. rot_mat_zyz( Angle z1, Angle y2, Angle z3 )
  1592. {
  1593. typedef Angle scalar_type;
  1594. scalar_type const c1 = cos(z1);
  1595. scalar_type const s1 = sin(z1);
  1596. scalar_type const c2 = cos(y2);
  1597. scalar_type const s2 = sin(y2);
  1598. scalar_type const c3 = cos(z3);
  1599. scalar_type const s3 = sin(z3);
  1600. return qvm_detail::rot_mat_<Dim,Angle>(
  1601. c1*c2*c3 - s1*s3, -c3*s1 - c1*c2*s3, c1*s2,
  1602. c1*s3 + c2*c3*s1, c1*c3 - c2*s1*s3, s1*s2,
  1603. -c3*s2, s2*s3, c2 );
  1604. }
  1605. template <class A,class Angle>
  1606. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1607. typename enable_if_c<
  1608. is_mat<A>::value &&
  1609. mat_traits<A>::rows==mat_traits<A>::cols &&
  1610. mat_traits<A>::rows>=3,
  1611. void>::type
  1612. set_rot_zyz( A & a, Angle z1, Angle y2, Angle z3 )
  1613. {
  1614. assign(a,rot_mat_zyz<mat_traits<A>::rows>(z1,y2,z3));
  1615. }
  1616. template <class A,class Angle>
  1617. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1618. typename enable_if_c<
  1619. is_mat<A>::value &&
  1620. mat_traits<A>::rows==mat_traits<A>::cols &&
  1621. mat_traits<A>::rows>=3,
  1622. void>::type
  1623. rotate_zyz( A & a, Angle z1, Angle y2, Angle z3 )
  1624. {
  1625. a *= rot_mat_zyz<mat_traits<A>::rows>(z1,y2,z3);
  1626. }
  1627. ////////////////////////////////////////////////
  1628. template <int Dim,class Angle>
  1629. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
  1630. qvm_detail::rot_mat_<Dim,Angle>
  1631. rot_mat_zxz( Angle z1, Angle x2, Angle z3 )
  1632. {
  1633. typedef Angle scalar_type;
  1634. scalar_type const c1 = cos(z1);
  1635. scalar_type const s1 = sin(z1);
  1636. scalar_type const c2 = cos(x2);
  1637. scalar_type const s2 = sin(x2);
  1638. scalar_type const c3 = cos(z3);
  1639. scalar_type const s3 = sin(z3);
  1640. return qvm_detail::rot_mat_<Dim,Angle>(
  1641. c1*c3 - c2*s1*s3, -c1*s3 - c2*c3*s1, s1*s2,
  1642. c3*s1 + c1*c2*s3, c1*c2*c3 - s1*s3, -c1*s2,
  1643. s2*s3, c3*s2, c2 );
  1644. }
  1645. template <class A,class Angle>
  1646. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1647. typename enable_if_c<
  1648. is_mat<A>::value &&
  1649. mat_traits<A>::rows==mat_traits<A>::cols &&
  1650. mat_traits<A>::rows>=3,
  1651. void>::type
  1652. set_rot_zxz( A & a, Angle z1, Angle x2, Angle z3 )
  1653. {
  1654. assign(a,rot_mat_zxz<mat_traits<A>::rows>(z1,x2,z3));
  1655. }
  1656. template <class A,class Angle>
  1657. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1658. typename enable_if_c<
  1659. is_mat<A>::value &&
  1660. mat_traits<A>::rows==mat_traits<A>::cols &&
  1661. mat_traits<A>::rows>=3,
  1662. void>::type
  1663. rotate_zxz( A & a, Angle z1, Angle x2, Angle z3 )
  1664. {
  1665. a *= rot_mat_zxz<mat_traits<A>::rows>(z1,x2,z3);
  1666. }
  1667. ////////////////////////////////////////////////
  1668. namespace
  1669. qvm_detail
  1670. {
  1671. template <int Dim,class Angle>
  1672. struct
  1673. rotx_mat_
  1674. {
  1675. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1676. rotx_mat_()
  1677. {
  1678. }
  1679. template <class R
  1680. #if __cplusplus >= 201103L
  1681. , class = typename enable_if<is_mat<R> >::type
  1682. #endif
  1683. >
  1684. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1685. operator R() const
  1686. {
  1687. R r;
  1688. assign(r,*this);
  1689. return r;
  1690. }
  1691. private:
  1692. rotx_mat_( rotx_mat_ const & );
  1693. rotx_mat_ & operator=( rotx_mat_ const & );
  1694. ~rotx_mat_();
  1695. };
  1696. template <int Row,int Col>
  1697. struct
  1698. rotx_m_get
  1699. {
  1700. template <class T>
  1701. static
  1702. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1703. T
  1704. get( T const & )
  1705. {
  1706. return scalar_traits<T>::value(Row==Col);
  1707. }
  1708. };
  1709. template <>
  1710. struct
  1711. rotx_m_get<1,1>
  1712. {
  1713. template <class T>
  1714. static
  1715. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1716. T
  1717. get( T const & angle )
  1718. {
  1719. return cos(angle);
  1720. }
  1721. };
  1722. template <>
  1723. struct
  1724. rotx_m_get<1,2>
  1725. {
  1726. template <class T>
  1727. static
  1728. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1729. T
  1730. get( T const & angle )
  1731. {
  1732. return -sin(angle);
  1733. }
  1734. };
  1735. template <>
  1736. struct
  1737. rotx_m_get<2,1>
  1738. {
  1739. template <class T>
  1740. static
  1741. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1742. T
  1743. get( T const & angle )
  1744. {
  1745. return sin(angle);
  1746. }
  1747. };
  1748. template <>
  1749. struct
  1750. rotx_m_get<2,2>
  1751. {
  1752. template <class T>
  1753. static
  1754. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1755. T
  1756. get( T const & angle )
  1757. {
  1758. return cos(angle);
  1759. }
  1760. };
  1761. }
  1762. template <int Dim,class Angle>
  1763. struct
  1764. mat_traits< qvm_detail::rotx_mat_<Dim,Angle> >
  1765. {
  1766. typedef qvm_detail::rotx_mat_<Dim,Angle> this_matrix;
  1767. typedef Angle scalar_type;
  1768. static int const rows=Dim;
  1769. static int const cols=Dim;
  1770. template <int Row,int Col>
  1771. static
  1772. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1773. scalar_type
  1774. read_element( this_matrix const & x )
  1775. {
  1776. BOOST_QVM_STATIC_ASSERT(Row>=0);
  1777. BOOST_QVM_STATIC_ASSERT(Col>=0);
  1778. BOOST_QVM_STATIC_ASSERT(Row<Dim);
  1779. BOOST_QVM_STATIC_ASSERT(Col<Dim);
  1780. return qvm_detail::rotx_m_get<Row,Col>::get(reinterpret_cast<Angle const &>(x));
  1781. }
  1782. static
  1783. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1784. scalar_type
  1785. read_element_idx( int row, int col, this_matrix const & x )
  1786. {
  1787. BOOST_QVM_ASSERT(row>=0);
  1788. BOOST_QVM_ASSERT(col>=0);
  1789. BOOST_QVM_ASSERT(row<Dim);
  1790. BOOST_QVM_ASSERT(col<Dim);
  1791. Angle const & a=reinterpret_cast<Angle const &>(x);
  1792. if( row==1 )
  1793. {
  1794. if( col==1 )
  1795. return cos(a);
  1796. if( col==2 )
  1797. return -sin(a);
  1798. }
  1799. if( row==2 )
  1800. {
  1801. if( col==1 )
  1802. return sin(a);
  1803. if( col==2 )
  1804. return cos(a);
  1805. }
  1806. return scalar_traits<scalar_type>::value(row==col);
  1807. }
  1808. };
  1809. template <int Dim,class Angle>
  1810. struct
  1811. deduce_mat<qvm_detail::rotx_mat_<Dim,Angle>,Dim,Dim>
  1812. {
  1813. typedef mat<Angle,Dim,Dim> type;
  1814. };
  1815. template <int Dim,class Angle>
  1816. struct
  1817. deduce_mat2<qvm_detail::rotx_mat_<Dim,Angle>,qvm_detail::rotx_mat_<Dim,Angle>,Dim,Dim>
  1818. {
  1819. typedef mat<Angle,Dim,Dim> type;
  1820. };
  1821. template <int Dim,class Angle>
  1822. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1823. qvm_detail::rotx_mat_<Dim,Angle> const &
  1824. rotx_mat( Angle const & angle )
  1825. {
  1826. BOOST_QVM_STATIC_ASSERT(Dim>=3);
  1827. return reinterpret_cast<qvm_detail::rotx_mat_<Dim,Angle> const &>(angle);
  1828. }
  1829. template <class A,class Angle>
  1830. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1831. typename enable_if_c<
  1832. is_mat<A>::value &&
  1833. mat_traits<A>::rows>=3 &&
  1834. mat_traits<A>::rows==mat_traits<A>::cols,
  1835. void>::type
  1836. set_rotx( A & a, Angle angle )
  1837. {
  1838. assign(a,rotx_mat<mat_traits<A>::rows>(angle));
  1839. }
  1840. template <class A,class Angle>
  1841. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  1842. typename enable_if_c<
  1843. is_mat<A>::value &&
  1844. mat_traits<A>::rows>=3 &&
  1845. mat_traits<A>::rows==mat_traits<A>::cols,
  1846. void>::type
  1847. rotate_x( A & a, Angle angle )
  1848. {
  1849. a *= rotx_mat<mat_traits<A>::rows>(angle);
  1850. }
  1851. ////////////////////////////////////////////////
  1852. namespace
  1853. qvm_detail
  1854. {
  1855. template <int Dim,class Angle>
  1856. struct
  1857. roty_mat_
  1858. {
  1859. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1860. roty_mat_()
  1861. {
  1862. }
  1863. template <class R
  1864. #if __cplusplus >= 201103L
  1865. , class = typename enable_if<is_mat<R> >::type
  1866. #endif
  1867. >
  1868. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  1869. operator R() const
  1870. {
  1871. R r;
  1872. assign(r,*this);
  1873. return r;
  1874. }
  1875. private:
  1876. roty_mat_( roty_mat_ const & );
  1877. roty_mat_ & operator=( roty_mat_ const & );
  1878. ~roty_mat_();
  1879. };
  1880. template <int Row,int Col>
  1881. struct
  1882. roty_m_get
  1883. {
  1884. template <class T>
  1885. static
  1886. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1887. T
  1888. get( T const & )
  1889. {
  1890. return scalar_traits<T>::value(Row==Col);
  1891. }
  1892. };
  1893. template <>
  1894. struct
  1895. roty_m_get<0,0>
  1896. {
  1897. template <class T>
  1898. static
  1899. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1900. T
  1901. get( T const & angle )
  1902. {
  1903. return cos(angle);
  1904. }
  1905. };
  1906. template <>
  1907. struct
  1908. roty_m_get<0,2>
  1909. {
  1910. template <class T>
  1911. static
  1912. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1913. T
  1914. get( T const & angle )
  1915. {
  1916. return sin(angle);
  1917. }
  1918. };
  1919. template <>
  1920. struct
  1921. roty_m_get<2,0>
  1922. {
  1923. template <class T>
  1924. static
  1925. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1926. T
  1927. get( T const & angle )
  1928. {
  1929. return -sin(angle);
  1930. }
  1931. };
  1932. template <>
  1933. struct
  1934. roty_m_get<2,2>
  1935. {
  1936. template <class T>
  1937. static
  1938. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1939. T
  1940. get( T const & angle )
  1941. {
  1942. return cos(angle);
  1943. }
  1944. };
  1945. }
  1946. template <int Dim,class Angle>
  1947. struct
  1948. mat_traits< qvm_detail::roty_mat_<Dim,Angle> >
  1949. {
  1950. typedef qvm_detail::roty_mat_<Dim,Angle> this_matrix;
  1951. typedef Angle scalar_type;
  1952. static int const rows=Dim;
  1953. static int const cols=Dim;
  1954. template <int Row,int Col>
  1955. static
  1956. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1957. scalar_type
  1958. read_element( this_matrix const & x )
  1959. {
  1960. BOOST_QVM_STATIC_ASSERT(Row>=0);
  1961. BOOST_QVM_STATIC_ASSERT(Col>=0);
  1962. BOOST_QVM_STATIC_ASSERT(Row<Dim);
  1963. BOOST_QVM_STATIC_ASSERT(Col<Dim);
  1964. return qvm_detail::roty_m_get<Row,Col>::get(reinterpret_cast<Angle const &>(x));
  1965. }
  1966. static
  1967. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  1968. scalar_type
  1969. read_element_idx( int row, int col, this_matrix const & x )
  1970. {
  1971. BOOST_QVM_ASSERT(row>=0);
  1972. BOOST_QVM_ASSERT(col>=0);
  1973. BOOST_QVM_ASSERT(row<Dim);
  1974. BOOST_QVM_ASSERT(col<Dim);
  1975. Angle const & a=reinterpret_cast<Angle const &>(x);
  1976. if( row==0 )
  1977. {
  1978. if( col==0 )
  1979. return cos(a);
  1980. if( col==2 )
  1981. return sin(a);
  1982. }
  1983. if( row==2 )
  1984. {
  1985. if( col==0 )
  1986. return -sin(a);
  1987. if( col==2 )
  1988. return cos(a);
  1989. }
  1990. return scalar_traits<scalar_type>::value(row==col);
  1991. }
  1992. };
  1993. template <int Dim,class Angle>
  1994. struct
  1995. deduce_mat<qvm_detail::roty_mat_<Dim,Angle>,Dim,Dim>
  1996. {
  1997. typedef mat<Angle,Dim,Dim> type;
  1998. };
  1999. template <int Dim,class Angle>
  2000. struct
  2001. deduce_mat2<qvm_detail::roty_mat_<Dim,Angle>,qvm_detail::roty_mat_<Dim,Angle>,Dim,Dim>
  2002. {
  2003. typedef mat<Angle,Dim,Dim> type;
  2004. };
  2005. template <int Dim,class Angle>
  2006. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  2007. qvm_detail::roty_mat_<Dim,Angle> const &
  2008. roty_mat( Angle const & angle )
  2009. {
  2010. BOOST_QVM_STATIC_ASSERT(Dim>=3);
  2011. return reinterpret_cast<qvm_detail::roty_mat_<Dim,Angle> const &>(angle);
  2012. }
  2013. template <class A,class Angle>
  2014. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  2015. typename enable_if_c<
  2016. is_mat<A>::value &&
  2017. mat_traits<A>::rows>=2 &&
  2018. mat_traits<A>::rows==mat_traits<A>::cols,
  2019. void>::type
  2020. set_roty( A & a, Angle angle )
  2021. {
  2022. assign(a,roty_mat<mat_traits<A>::rows>(angle));
  2023. }
  2024. template <class A,class Angle>
  2025. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  2026. typename enable_if_c<
  2027. is_mat<A>::value &&
  2028. mat_traits<A>::rows>=3 &&
  2029. mat_traits<A>::rows==mat_traits<A>::cols,
  2030. void>::type
  2031. rotate_y( A & a, Angle angle )
  2032. {
  2033. a *= roty_mat<mat_traits<A>::rows>(angle);
  2034. }
  2035. ////////////////////////////////////////////////
  2036. namespace
  2037. qvm_detail
  2038. {
  2039. template <int Dim,class Angle>
  2040. struct
  2041. rotz_mat_
  2042. {
  2043. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  2044. rotz_mat_()
  2045. {
  2046. }
  2047. template <class R
  2048. #if __cplusplus >= 201103L
  2049. , class = typename enable_if<is_mat<R> >::type
  2050. #endif
  2051. >
  2052. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  2053. operator R() const
  2054. {
  2055. R r;
  2056. assign(r,*this);
  2057. return r;
  2058. }
  2059. private:
  2060. rotz_mat_( rotz_mat_ const & );
  2061. rotz_mat_ & operator=( rotz_mat_ const & );
  2062. ~rotz_mat_();
  2063. };
  2064. template <int Row,int Col>
  2065. struct
  2066. rotz_m_get
  2067. {
  2068. template <class T>
  2069. static
  2070. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  2071. T
  2072. get( T const & )
  2073. {
  2074. return scalar_traits<T>::value(Row==Col);
  2075. }
  2076. };
  2077. template <>
  2078. struct
  2079. rotz_m_get<0,0>
  2080. {
  2081. template <class T>
  2082. static
  2083. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  2084. T
  2085. get( T const & angle )
  2086. {
  2087. return cos(angle);
  2088. }
  2089. };
  2090. template <>
  2091. struct
  2092. rotz_m_get<0,1>
  2093. {
  2094. template <class T>
  2095. static
  2096. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  2097. T
  2098. get( T const & angle )
  2099. {
  2100. return -sin(angle);
  2101. }
  2102. };
  2103. template <>
  2104. struct
  2105. rotz_m_get<1,0>
  2106. {
  2107. template <class T>
  2108. static
  2109. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  2110. T
  2111. get( T const & angle )
  2112. {
  2113. return sin(angle);
  2114. }
  2115. };
  2116. template <>
  2117. struct
  2118. rotz_m_get<1,1>
  2119. {
  2120. template <class T>
  2121. static
  2122. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  2123. T
  2124. get( T const & angle )
  2125. {
  2126. return cos(angle);
  2127. }
  2128. };
  2129. }
  2130. template <int Dim,class Angle>
  2131. struct
  2132. mat_traits< qvm_detail::rotz_mat_<Dim,Angle> >
  2133. {
  2134. typedef qvm_detail::rotz_mat_<Dim,Angle> this_matrix;
  2135. typedef Angle scalar_type;
  2136. static int const rows=Dim;
  2137. static int const cols=Dim;
  2138. template <int Row,int Col>
  2139. static
  2140. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  2141. scalar_type
  2142. read_element( this_matrix const & x )
  2143. {
  2144. BOOST_QVM_STATIC_ASSERT(Row>=0);
  2145. BOOST_QVM_STATIC_ASSERT(Col>=0);
  2146. BOOST_QVM_STATIC_ASSERT(Row<Dim);
  2147. BOOST_QVM_STATIC_ASSERT(Col<Dim);
  2148. return qvm_detail::rotz_m_get<Row,Col>::get(reinterpret_cast<Angle const &>(x));
  2149. }
  2150. static
  2151. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_CRITICAL
  2152. scalar_type
  2153. read_element_idx( int row, int col, this_matrix const & x )
  2154. {
  2155. BOOST_QVM_ASSERT(row>=0);
  2156. BOOST_QVM_ASSERT(col>=0);
  2157. BOOST_QVM_ASSERT(row<Dim);
  2158. BOOST_QVM_ASSERT(col<Dim);
  2159. Angle const & a=reinterpret_cast<Angle const &>(x);
  2160. if( row==0 )
  2161. {
  2162. if( col==0 )
  2163. return cos(a);
  2164. if( col==1 )
  2165. return -sin(a);
  2166. }
  2167. if( row==1 )
  2168. {
  2169. if( col==0 )
  2170. return sin(a);
  2171. if( col==1 )
  2172. return cos(a);
  2173. }
  2174. return scalar_traits<scalar_type>::value(row==col);
  2175. }
  2176. };
  2177. template <int Dim,class Angle>
  2178. struct
  2179. deduce_mat<qvm_detail::rotz_mat_<Dim,Angle>,Dim,Dim>
  2180. {
  2181. typedef mat<Angle,Dim,Dim> type;
  2182. };
  2183. template <int Dim,class Angle,int R,int C>
  2184. struct
  2185. deduce_mat2<qvm_detail::rotz_mat_<Dim,Angle>,qvm_detail::rotz_mat_<Dim,Angle>,R,C>
  2186. {
  2187. typedef mat<Angle,R,C> type;
  2188. };
  2189. template <int Dim,class Angle>
  2190. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  2191. qvm_detail::rotz_mat_<Dim,Angle> const &
  2192. rotz_mat( Angle const & angle )
  2193. {
  2194. BOOST_QVM_STATIC_ASSERT(Dim>=2);
  2195. return reinterpret_cast<qvm_detail::rotz_mat_<Dim,Angle> const &>(angle);
  2196. }
  2197. template <class A,class Angle>
  2198. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  2199. typename enable_if_c<
  2200. is_mat<A>::value &&
  2201. mat_traits<A>::rows>=2 &&
  2202. mat_traits<A>::rows==mat_traits<A>::cols,
  2203. void>::type
  2204. set_rotz( A & a, Angle angle )
  2205. {
  2206. assign(a,rotz_mat<mat_traits<A>::rows>(angle));
  2207. }
  2208. template <class A,class Angle>
  2209. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
  2210. typename enable_if_c<
  2211. is_mat<A>::value &&
  2212. mat_traits<A>::rows>=2 &&
  2213. mat_traits<A>::rows==mat_traits<A>::cols,
  2214. void>::type
  2215. rotate_z( A & a, Angle angle )
  2216. {
  2217. a *= rotz_mat<mat_traits<A>::rows>(angle);
  2218. }
  2219. ////////////////////////////////////////////////
  2220. namespace
  2221. qvm_detail
  2222. {
  2223. template <int D>
  2224. struct
  2225. inverse_m_defined
  2226. {
  2227. static bool const value=false;
  2228. };
  2229. }
  2230. template <class A,class B>
  2231. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  2232. typename lazy_enable_if_c<
  2233. is_mat<A>::value && is_scalar<B>::value &&
  2234. mat_traits<A>::rows==mat_traits<A>::cols &&
  2235. !qvm_detail::inverse_m_defined<mat_traits<A>::rows>::value,
  2236. deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
  2237. inverse( A const & a, B det )
  2238. {
  2239. typedef typename mat_traits<A>::scalar_type T;
  2240. BOOST_QVM_ASSERT(det!=scalar_traits<T>::value(0));
  2241. T f=scalar_traits<T>::value(1)/det;
  2242. typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type cofactor_return_type;
  2243. cofactor_return_type c=qvm_detail::cofactor_impl(a);
  2244. return reinterpret_cast<qvm_detail::transposed_<cofactor_return_type> const &>(c) * f;
  2245. }
  2246. template <class A>
  2247. BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_TRIVIAL
  2248. typename lazy_enable_if_c<
  2249. is_mat<A>::value &&
  2250. mat_traits<A>::rows==mat_traits<A>::cols &&
  2251. !qvm_detail::inverse_m_defined<mat_traits<A>::rows>::value,
  2252. deduce_mat<A> >::type
  2253. inverse( A const & a )
  2254. {
  2255. typedef typename mat_traits<A>::scalar_type T;
  2256. T det=determinant(a);
  2257. if( det==scalar_traits<T>::value(0) )
  2258. BOOST_QVM_THROW_EXCEPTION(zero_determinant_error());
  2259. return inverse(a,det);
  2260. }
  2261. ////////////////////////////////////////////////
  2262. namespace
  2263. sfinae
  2264. {
  2265. using ::boost::qvm::to_string;
  2266. using ::boost::qvm::assign;
  2267. using ::boost::qvm::determinant;
  2268. using ::boost::qvm::cmp;
  2269. using ::boost::qvm::convert_to;
  2270. using ::boost::qvm::set_identity;
  2271. using ::boost::qvm::set_zero;
  2272. using ::boost::qvm::scalar_cast;
  2273. using ::boost::qvm::operator/=;
  2274. using ::boost::qvm::operator/;
  2275. using ::boost::qvm::operator==;
  2276. using ::boost::qvm::operator-=;
  2277. using ::boost::qvm::operator-;
  2278. using ::boost::qvm::operator*=;
  2279. using ::boost::qvm::operator*;
  2280. using ::boost::qvm::operator!=;
  2281. using ::boost::qvm::operator+=;
  2282. using ::boost::qvm::operator+;
  2283. using ::boost::qvm::mref;
  2284. using ::boost::qvm::rot_mat;
  2285. using ::boost::qvm::set_rot;
  2286. using ::boost::qvm::rotate;
  2287. using ::boost::qvm::set_rotx;
  2288. using ::boost::qvm::rotate_x;
  2289. using ::boost::qvm::set_roty;
  2290. using ::boost::qvm::rotate_y;
  2291. using ::boost::qvm::set_rotz;
  2292. using ::boost::qvm::rotate_z;
  2293. using ::boost::qvm::inverse;
  2294. }
  2295. } }
  2296. #endif