mat_operations.hpp 65 KB

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