gold.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. //Copyright (c) 2008-2016 Emil Dotchevski and Reverge Studios, Inc.
  2. //Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #ifndef UUID_907229FCB3A711DE83C152F855D89593
  5. #define UUID_907229FCB3A711DE83C152F855D89593
  6. #include <limits>
  7. #include <math.h>
  8. #include <assert.h>
  9. #include <memory.h>
  10. #include <stdlib.h>
  11. namespace
  12. test_qvm
  13. {
  14. namespace
  15. detail
  16. {
  17. inline
  18. float
  19. sin( float a )
  20. {
  21. return ::sinf(a);
  22. }
  23. inline
  24. double
  25. sin( double a )
  26. {
  27. return ::sin(a);
  28. }
  29. inline
  30. float
  31. cos( float a )
  32. {
  33. return ::cosf(a);
  34. }
  35. inline
  36. double
  37. cos( double a )
  38. {
  39. return ::cos(a);
  40. }
  41. inline
  42. float
  43. abs( float a )
  44. {
  45. return ::fabsf(a);
  46. }
  47. inline
  48. double
  49. abs( double a )
  50. {
  51. return ::fabs(a);
  52. }
  53. inline
  54. float
  55. atan2( float a, float b )
  56. {
  57. return ::atan2f(a,b);
  58. }
  59. inline
  60. double
  61. atan2( double a, double b )
  62. {
  63. return ::atan2(a,b);
  64. }
  65. template <class T>
  66. T
  67. determinant( T * * a, int n )
  68. {
  69. int i,j,j1,j2;
  70. T det = 0;
  71. T * * m = 0;
  72. assert(n>=1);
  73. if( n==1 )
  74. det = a[0][0];
  75. else if( n==2 )
  76. det = a[0][0] * a[1][1] - a[1][0] * a[0][1];
  77. else
  78. {
  79. det = 0;
  80. for( j1=0; j1<n; j1++ )
  81. {
  82. m = static_cast<T * *>(malloc((n-1)*sizeof(T *)));
  83. for( i=0; i<n-1; i++ )
  84. m[i] = static_cast<T *>(malloc((n-1)*sizeof(T)));
  85. for( i=1; i<n; i++ )
  86. {
  87. j2 = 0;
  88. for( j=0; j<n; j++ )
  89. {
  90. if( j==j1 )
  91. continue;
  92. m[i-1][j2] = a[i][j];
  93. j2++;
  94. }
  95. }
  96. det += T(pow(-1.0,1.0+j1+1.0)) * a[0][j1] * determinant(m,n-1);
  97. for( i=0; i<n-1; i++ )
  98. free(m[i]);
  99. free(m);
  100. }
  101. }
  102. return(det);
  103. }
  104. template <class T,int N>
  105. void
  106. cofactor( T * * a, T (&b)[N][N] )
  107. {
  108. int i,j,ii,jj,i1,j1;
  109. T det;
  110. T * * c;
  111. c = static_cast<T * *>(malloc((N-1)*sizeof(T *)));
  112. for( i=0; i<N-1; i++ )
  113. c[i] = static_cast<T *>(malloc((N-1)*sizeof(T)));
  114. for( j=0; j<N; j++ )
  115. {
  116. for( i=0; i<N; i++ )
  117. {
  118. i1 = 0;
  119. for( ii=0; ii<N; ii++ )
  120. {
  121. if( ii==i )
  122. continue;
  123. j1 = 0;
  124. for( jj=0; jj<N; jj++ )
  125. {
  126. if( jj==j )
  127. continue;
  128. c[i1][j1] = a[ii][jj];
  129. j1++;
  130. }
  131. i1++;
  132. }
  133. det = determinant(c,N-1);
  134. b[i][j] = T(pow(-1.0,i+j+2.0)) * det;
  135. }
  136. }
  137. for( i=0; i<N-1; i++ )
  138. free(c[i]);
  139. free(c);
  140. }
  141. }
  142. template <class T,int D>
  143. T
  144. determinant( T (&in)[D][D] )
  145. {
  146. T * * m = static_cast<T * *>(malloc(D*sizeof(T *)));
  147. for( int i=0; i!=D; ++i )
  148. {
  149. m[i] = static_cast<T *>(malloc(D*sizeof(T)));
  150. for( int j=0; j!=D; ++j )
  151. m[i][j]=in[i][j];
  152. }
  153. T det=::test_qvm::detail::determinant(m,D);
  154. for( int i=0; i<D; ++i )
  155. free(m[i]);
  156. free(m);
  157. return det;
  158. }
  159. template <class T,int D>
  160. void
  161. inverse( T (&out)[D][D], T (&in)[D][D] )
  162. {
  163. T * * m = static_cast<T * *>(malloc(D*sizeof(T *)));
  164. for( int i=0; i!=D; ++i )
  165. {
  166. m[i] = static_cast<T *>(malloc(D*sizeof(T)));
  167. for( int j=0; j!=D; ++j )
  168. m[i][j]=in[i][j];
  169. }
  170. T det=::test_qvm::detail::determinant(m,D);
  171. assert(det!=T(0));
  172. T f=T(1)/det;
  173. T b[D][D];
  174. ::test_qvm::detail::cofactor(m,b);
  175. for( int i=0; i<D; ++i )
  176. free(m[i]);
  177. free(m);
  178. for( int i=0; i!=D; ++i )
  179. for( int j=0; j!=D; ++j )
  180. out[j][i]=b[i][j]*f;
  181. }
  182. template <class T,int M,int N>
  183. void
  184. init_m( T (&r)[M][N], T start=T(0), T step=T(0) )
  185. {
  186. for( int i=0; i<M; ++i )
  187. for( int j=0; j<N; ++j,start+=step )
  188. r[i][j] = start;
  189. }
  190. template <class T,int D>
  191. void
  192. init_v( T (&r)[D], T start=T(0), T step=T(0) )
  193. {
  194. for( int i=0; i<D; ++i,start+=step )
  195. r[i] = start;
  196. }
  197. template <class T,int M,int N>
  198. void
  199. zero_mat( T (&r)[M][N] )
  200. {
  201. for( int i=0; i<M; ++i )
  202. for( int j=0; j<N; ++j )
  203. r[i][j] = T(0);
  204. }
  205. template <class T,int D>
  206. void
  207. zero_vec( T (&r)[D] )
  208. {
  209. for( int i=0; i<D; ++i )
  210. r[i] = T(0);
  211. }
  212. template <class T,int D>
  213. void
  214. identity( T (&r)[D][D] )
  215. {
  216. for( int i=0; i<D; ++i )
  217. for( int j=0; j<D; ++j )
  218. r[i][j] = (i==j) ? T(1) : T(0);
  219. }
  220. template <class T,class U,class V,int M,int N>
  221. void
  222. add_m( T (&r)[M][N], U (&a)[M][N], V (&b)[M][N] )
  223. {
  224. for( int i=0; i<M; ++i )
  225. for( int j=0; j<N; ++j )
  226. r[i][j] = a[i][j] + b[i][j];
  227. }
  228. template <class T,class U,class V,int D>
  229. void
  230. add_v( T (&r)[D], U (&a)[D], V (&b)[D] )
  231. {
  232. for( int i=0; i<D; ++i )
  233. r[i] = a[i] + b[i];
  234. }
  235. template <class T,class U,class V,int M,int N>
  236. void
  237. subtract_m( T (&r)[M][N], U (&a)[M][N], V (&b)[M][N] )
  238. {
  239. for( int i=0; i<M; ++i )
  240. for( int j=0; j<N; ++j )
  241. r[i][j] = a[i][j] - b[i][j];
  242. }
  243. template <class T,class U,class V,int D>
  244. void
  245. subtract_v( T (&r)[D], U (&a)[D], V (&b)[D] )
  246. {
  247. for( int i=0; i<D; ++i )
  248. r[i] = a[i] - b[i];
  249. }
  250. template <class T,int D,class U>
  251. void
  252. rotation_x( T (&r)[D][D], U angle )
  253. {
  254. identity(r);
  255. T c=::test_qvm::detail::cos(angle);
  256. T s=::test_qvm::detail::sin(angle);
  257. r[1][1]=c;
  258. r[1][2]=-s;
  259. r[2][1]=s;
  260. r[2][2]=c;
  261. }
  262. template <class T,int D,class U>
  263. void
  264. rotation_y( T (&r)[D][D], U angle )
  265. {
  266. identity(r);
  267. T c=::test_qvm::detail::cos(angle);
  268. T s=::test_qvm::detail::sin(angle);
  269. r[0][0]=c;
  270. r[0][2]=s;
  271. r[2][0]=-s;
  272. r[2][2]=c;
  273. }
  274. template <class T,int D,class U>
  275. void
  276. rotation_z( T (&r)[D][D], U angle )
  277. {
  278. identity(r);
  279. T c=::test_qvm::detail::cos(angle);
  280. T s=::test_qvm::detail::sin(angle);
  281. r[0][0]=c;
  282. r[0][1]=-s;
  283. r[1][0]=s;
  284. r[1][1]=c;
  285. }
  286. template <class T,int D>
  287. void
  288. translation( T (&r)[D][D], T (&t)[D-1] )
  289. {
  290. identity(r);
  291. for( int i=0; i!=D-1; ++i )
  292. r[i][D-1]=t[i];
  293. }
  294. template <class R,class T,class U,int M,int N,int P>
  295. void
  296. multiply_m( R (&r)[M][P], T (&a)[M][N], U (&b)[N][P] )
  297. {
  298. for( int i=0; i<M; ++i )
  299. for( int j=0; j<P; ++j )
  300. {
  301. R x=0;
  302. for( int k=0; k<N; ++k )
  303. x += R(a[i][k])*R(b[k][j]);
  304. r[i][j] = x;
  305. }
  306. }
  307. template <class R,class T,class U,int M,int N>
  308. void
  309. multiply_mv( R (&r)[M], T (&a)[M][N], U (&b)[N] )
  310. {
  311. for( int i=0; i<M; ++i )
  312. {
  313. R x=0;
  314. for( int k=0; k<N; ++k )
  315. x += R(a[i][k])*R(b[k]);
  316. r[i] = x;
  317. }
  318. }
  319. template <class R,class T,class U,int N,int P>
  320. void
  321. multiply_vm( R (&r)[P], T (&a)[N], U (&b)[N][P] )
  322. {
  323. for( int j=0; j<P; ++j )
  324. {
  325. R x=0;
  326. for( int k=0; k<N; ++k )
  327. x += R(a[k])*R(b[k][j]);
  328. r[j] = x;
  329. }
  330. }
  331. template <class T,class U,int M,int N,class S>
  332. void
  333. scalar_multiply_m( T (&r)[M][N], U (&a)[M][N], S scalar )
  334. {
  335. for( int i=0; i<M; ++i )
  336. for( int j=0; j<N; ++j )
  337. r[i][j] = a[i][j]*scalar;
  338. }
  339. template <class T,class U,int D,class S>
  340. void
  341. scalar_multiply_v( T (&r)[D], U (&a)[D], S scalar )
  342. {
  343. for( int i=0; i<D; ++i )
  344. r[i] = a[i]*scalar;
  345. }
  346. template <class T,int M,int N>
  347. void
  348. transpose( T (&r)[M][N], T (&a)[N][M] )
  349. {
  350. for( int i=0; i<M; ++i )
  351. for( int j=0; j<N; ++j )
  352. r[i][j] = a[j][i];
  353. }
  354. template <class R,class T,class U,int D>
  355. R
  356. dot( T (&a)[D], U (&b)[D] )
  357. {
  358. R r=R(0);
  359. for( int i=0; i<D; ++i )
  360. r+=a[i]*b[i];
  361. return r;
  362. }
  363. template <class T,int M,int N>
  364. T
  365. norm_squared( T (&m)[M][N] )
  366. {
  367. T f=T(0);
  368. for( int i=0; i<M; ++i )
  369. for( int j=0; j<N; ++j )
  370. {
  371. T x=m[i][j];
  372. f+=x*x;
  373. }
  374. return f;
  375. }
  376. template <class T>
  377. inline
  378. void
  379. matrix_perspective_lh( T (&r)[4][4], T fov_y, T aspect_ratio, T zn, T zf )
  380. {
  381. T ys=T(1)/::tanf(fov_y/T(2));
  382. T xs=ys/aspect_ratio;
  383. zero_mat(r);
  384. r[0][0] = xs;
  385. r[1][1] = ys;
  386. r[2][2] = zf/(zf-zn);
  387. r[2][3] = -zn*zf/(zf-zn);
  388. r[3][2] = 1;
  389. }
  390. template <class T>
  391. inline
  392. void
  393. matrix_perspective_rh( T (&r)[4][4], T fov_y, T aspect_ratio, T zn, T zf )
  394. {
  395. matrix_perspective_lh(r,fov_y,aspect_ratio,zn,zf);
  396. r[2][2]=-r[2][2];
  397. r[3][2]=-r[3][2];
  398. }
  399. }
  400. #endif