1
0

mat2.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. * Copyright (c), Recep Aslantas.
  3. *
  4. * MIT License (MIT), http://opensource.org/licenses/MIT
  5. * Full license can be found in the LICENSE file
  6. */
  7. /*
  8. Macros:
  9. GLM_MAT2_IDENTITY_INIT
  10. GLM_MAT2_ZERO_INIT
  11. GLM_MAT2_IDENTITY
  12. GLM_MAT2_ZERO
  13. Functions:
  14. CGLM_INLINE void glm_mat2_copy(mat2 mat, mat2 dest)
  15. CGLM_INLINE void glm_mat2_identity(mat2 mat)
  16. CGLM_INLINE void glm_mat2_identity_array(mat2 * restrict mat, size_t count)
  17. CGLM_INLINE void glm_mat2_zero(mat2 mat)
  18. CGLM_INLINE void glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest)
  19. CGLM_INLINE void glm_mat2_transpose_to(mat2 m, mat2 dest)
  20. CGLM_INLINE void glm_mat2_transpose(mat2 m)
  21. CGLM_INLINE void glm_mat2_mulv(mat2 m, vec2 v, vec2 dest)
  22. CGLM_INLINE float glm_mat2_trace(mat2 m)
  23. CGLM_INLINE void glm_mat2_scale(mat2 m, float s)
  24. CGLM_INLINE float glm_mat2_det(mat2 mat)
  25. CGLM_INLINE void glm_mat2_inv(mat2 mat, mat2 dest)
  26. CGLM_INLINE void glm_mat2_swap_col(mat2 mat, int col1, int col2)
  27. CGLM_INLINE void glm_mat2_swap_row(mat2 mat, int row1, int row2)
  28. CGLM_INLINE float glm_mat2_rmc(vec2 r, mat2 m, vec2 c)
  29. CGLM_INLINE void glm_mat2_make(float * restrict src, mat2 dest)
  30. */
  31. #ifndef cglm_mat2_h
  32. #define cglm_mat2_h
  33. #include "common.h"
  34. #include "vec2.h"
  35. #ifdef CGLM_SSE_FP
  36. # include "simd/sse2/mat2.h"
  37. #endif
  38. #ifdef CGLM_NEON_FP
  39. # include "simd/neon/mat2.h"
  40. #endif
  41. #ifdef CGLM_SIMD_WASM
  42. # include "simd/wasm/mat2.h"
  43. #endif
  44. #define GLM_MAT2_IDENTITY_INIT {{1.0f, 0.0f}, {0.0f, 1.0f}}
  45. #define GLM_MAT2_ZERO_INIT {{0.0f, 0.0f}, {0.0f, 0.0f}}
  46. /* for C only */
  47. #define GLM_MAT2_IDENTITY ((mat2)GLM_MAT2_IDENTITY_INIT)
  48. #define GLM_MAT2_ZERO ((mat2)GLM_MAT2_ZERO_INIT)
  49. /*!
  50. * @brief copy all members of [mat] to [dest]
  51. *
  52. * @param[in] mat source
  53. * @param[out] dest destination
  54. */
  55. CGLM_INLINE
  56. void
  57. glm_mat2_copy(mat2 mat, mat2 dest) {
  58. glm_vec4_ucopy(mat[0], dest[0]);
  59. }
  60. /*!
  61. * @brief make given matrix identity. It is identical with below,
  62. * but it is more easy to do that with this func especially for members
  63. * e.g. glm_mat2_identity(aStruct->aMatrix);
  64. *
  65. * @code
  66. * glm_mat2_copy(GLM_MAT2_IDENTITY, mat); // C only
  67. *
  68. * // or
  69. * mat2 mat = GLM_MAT2_IDENTITY_INIT;
  70. * @endcode
  71. *
  72. * @param[in, out] mat destination
  73. */
  74. CGLM_INLINE
  75. void
  76. glm_mat2_identity(mat2 mat) {
  77. CGLM_ALIGN_MAT mat2 t = GLM_MAT2_IDENTITY_INIT;
  78. glm_mat2_copy(t, mat);
  79. }
  80. /*!
  81. * @brief make given matrix array's each element identity matrix
  82. *
  83. * @param[in, out] mat matrix array (must be aligned (16)
  84. * if alignment is not disabled)
  85. *
  86. * @param[in] count count of matrices
  87. */
  88. CGLM_INLINE
  89. void
  90. glm_mat2_identity_array(mat2 * __restrict mat, size_t count) {
  91. CGLM_ALIGN_MAT mat2 t = GLM_MAT2_IDENTITY_INIT;
  92. size_t i;
  93. for (i = 0; i < count; i++) {
  94. glm_mat2_copy(t, mat[i]);
  95. }
  96. }
  97. /*!
  98. * @brief make given matrix zero.
  99. *
  100. * @param[in, out] mat matrix
  101. */
  102. CGLM_INLINE
  103. void
  104. glm_mat2_zero(mat2 mat) {
  105. CGLM_ALIGN_MAT mat2 t = GLM_MAT2_ZERO_INIT;
  106. glm_mat2_copy(t, mat);
  107. }
  108. /*!
  109. * @brief multiply m1 and m2 to dest
  110. *
  111. * m1, m2 and dest matrices can be same matrix, it is possible to write this:
  112. *
  113. * @code
  114. * mat2 m = GLM_MAT2_IDENTITY_INIT;
  115. * glm_mat2_mul(m, m, m);
  116. * @endcode
  117. *
  118. * @param[in] m1 left matrix
  119. * @param[in] m2 right matrix
  120. * @param[out] dest destination matrix
  121. */
  122. CGLM_INLINE
  123. void
  124. glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest) {
  125. #if defined(__wasm__) && defined(__wasm_simd128__)
  126. glm_mat2_mul_wasm(m1, m2, dest);
  127. #elif defined( __SSE__ ) || defined( __SSE2__ )
  128. glm_mat2_mul_sse2(m1, m2, dest);
  129. #elif defined(CGLM_NEON_FP)
  130. glm_mat2_mul_neon(m1, m2, dest);
  131. #else
  132. float a00 = m1[0][0], a01 = m1[0][1],
  133. a10 = m1[1][0], a11 = m1[1][1],
  134. b00 = m2[0][0], b01 = m2[0][1],
  135. b10 = m2[1][0], b11 = m2[1][1];
  136. dest[0][0] = a00 * b00 + a10 * b01;
  137. dest[0][1] = a01 * b00 + a11 * b01;
  138. dest[1][0] = a00 * b10 + a10 * b11;
  139. dest[1][1] = a01 * b10 + a11 * b11;
  140. #endif
  141. }
  142. /*!
  143. * @brief transpose mat2 and store in dest
  144. *
  145. * source matrix will not be transposed unless dest is m
  146. *
  147. * @param[in] m matrix
  148. * @param[out] dest result
  149. */
  150. CGLM_INLINE
  151. void
  152. glm_mat2_transpose_to(mat2 m, mat2 dest) {
  153. #if defined(__wasm__) && defined(__wasm_simd128__)
  154. glm_mat2_transp_wasm(m, dest);
  155. #elif defined( __SSE__ ) || defined( __SSE2__ )
  156. glm_mat2_transp_sse2(m, dest);
  157. #else
  158. dest[0][0] = m[0][0];
  159. dest[0][1] = m[1][0];
  160. dest[1][0] = m[0][1];
  161. dest[1][1] = m[1][1];
  162. #endif
  163. }
  164. /*!
  165. * @brief transpose mat2 and store result in same matrix
  166. *
  167. * @param[in, out] m source and dest
  168. */
  169. CGLM_INLINE
  170. void
  171. glm_mat2_transpose(mat2 m) {
  172. float tmp;
  173. tmp = m[0][1];
  174. m[0][1] = m[1][0];
  175. m[1][0] = tmp;
  176. }
  177. /*!
  178. * @brief multiply mat2 with vec2 (column vector) and store in dest vector
  179. *
  180. * @param[in] m mat2 (left)
  181. * @param[in] v vec2 (right, column vector)
  182. * @param[out] dest vec2 (result, column vector)
  183. */
  184. CGLM_INLINE
  185. void
  186. glm_mat2_mulv(mat2 m, vec2 v, vec2 dest) {
  187. dest[0] = m[0][0] * v[0] + m[1][0] * v[1];
  188. dest[1] = m[0][1] * v[0] + m[1][1] * v[1];
  189. }
  190. /*!
  191. * @brief trace of matrix
  192. *
  193. * sum of the elements on the main diagonal from upper left to the lower right
  194. *
  195. * @param[in] m matrix
  196. */
  197. CGLM_INLINE
  198. float
  199. glm_mat2_trace(mat2 m) {
  200. return m[0][0] + m[1][1];
  201. }
  202. /*!
  203. * @brief scale (multiply with scalar) matrix
  204. *
  205. * multiply matrix with scalar
  206. *
  207. * @param[in, out] m matrix
  208. * @param[in] s scalar
  209. */
  210. CGLM_INLINE
  211. void
  212. glm_mat2_scale(mat2 m, float s) {
  213. #if defined(__wasm__) && defined(__wasm_simd128__)
  214. glmm_store(m[0], wasm_f32x4_mul(wasm_v128_load(m[0]),
  215. wasm_f32x4_splat(s)));
  216. #elif defined( __SSE__ ) || defined( __SSE2__ )
  217. glmm_store(m[0], _mm_mul_ps(_mm_loadu_ps(m[0]), glmm_set1(s)));
  218. #elif defined(CGLM_NEON_FP)
  219. vst1q_f32(m[0], vmulq_f32(vld1q_f32(m[0]), vdupq_n_f32(s)));
  220. #else
  221. m[0][0] = m[0][0] * s;
  222. m[0][1] = m[0][1] * s;
  223. m[1][0] = m[1][0] * s;
  224. m[1][1] = m[1][1] * s;
  225. #endif
  226. }
  227. /*!
  228. * @brief mat2 determinant
  229. *
  230. * @param[in] mat matrix
  231. *
  232. * @return determinant
  233. */
  234. CGLM_INLINE
  235. float
  236. glm_mat2_det(mat2 mat) {
  237. return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
  238. }
  239. /*!
  240. * @brief inverse mat2 and store in dest
  241. *
  242. * @param[in] mat matrix
  243. * @param[out] dest inverse matrix
  244. */
  245. CGLM_INLINE
  246. void
  247. glm_mat2_inv(mat2 mat, mat2 dest) {
  248. float det;
  249. float a = mat[0][0], b = mat[0][1],
  250. c = mat[1][0], d = mat[1][1];
  251. det = 1.0f / (a * d - b * c);
  252. dest[0][0] = d * det;
  253. dest[0][1] = -b * det;
  254. dest[1][0] = -c * det;
  255. dest[1][1] = a * det;
  256. }
  257. /*!
  258. * @brief swap two matrix columns
  259. *
  260. * @param[in,out] mat matrix
  261. * @param[in] col1 col1
  262. * @param[in] col2 col2
  263. */
  264. CGLM_INLINE
  265. void
  266. glm_mat2_swap_col(mat2 mat, int col1, int col2) {
  267. float a, b;
  268. a = mat[col1][0];
  269. b = mat[col1][1];
  270. mat[col1][0] = mat[col2][0];
  271. mat[col1][1] = mat[col2][1];
  272. mat[col2][0] = a;
  273. mat[col2][1] = b;
  274. }
  275. /*!
  276. * @brief swap two matrix rows
  277. *
  278. * @param[in,out] mat matrix
  279. * @param[in] row1 row1
  280. * @param[in] row2 row2
  281. */
  282. CGLM_INLINE
  283. void
  284. glm_mat2_swap_row(mat2 mat, int row1, int row2) {
  285. float a, b;
  286. a = mat[0][row1];
  287. b = mat[1][row1];
  288. mat[0][row1] = mat[0][row2];
  289. mat[1][row1] = mat[1][row2];
  290. mat[0][row2] = a;
  291. mat[1][row2] = b;
  292. }
  293. /*!
  294. * @brief helper for R (row vector) * M (matrix) * C (column vector)
  295. *
  296. * rmc stands for Row * Matrix * Column
  297. *
  298. * the result is scalar because R * M = Matrix1x2 (row vector),
  299. * then Matrix1x2 * Vec2 (column vector) = Matrix1x1 (Scalar)
  300. *
  301. * @param[in] r row vector or matrix1x2
  302. * @param[in] m matrix2x2
  303. * @param[in] c column vector or matrix2x1
  304. *
  305. * @return scalar value e.g. Matrix1x1
  306. */
  307. CGLM_INLINE
  308. float
  309. glm_mat2_rmc(vec2 r, mat2 m, vec2 c) {
  310. vec2 tmp;
  311. glm_mat2_mulv(m, c, tmp);
  312. return glm_vec2_dot(r, tmp);
  313. }
  314. /*!
  315. * @brief Create mat2 matrix from pointer
  316. *
  317. * @param[in] src pointer to an array of floats
  318. * @param[out] dest matrix
  319. */
  320. CGLM_INLINE
  321. void
  322. glm_mat2_make(const float * __restrict src, mat2 dest) {
  323. dest[0][0] = src[0];
  324. dest[0][1] = src[1];
  325. dest[1][0] = src[2];
  326. dest[1][1] = src[3];
  327. }
  328. #endif /* cglm_mat2_h */