1/// @ref core 2/// @file glm/detail/func_matrix.inl 3 4#include "../geometric.hpp" 5#include <limits> 6 7namespace glm{ 8namespace detail 9{ 10 template <template <typename, precision> class matType, typename T, precision P, bool Aligned> 11 struct compute_matrixCompMult 12 { 13 GLM_FUNC_QUALIFIER static matType<T, P> call(matType<T, P> const& x, matType<T, P> const& y) 14 { 15 matType<T, P> result(uninitialize); 16 for(length_t i = 0; i < result.length(); ++i) 17 result[i] = x[i] * y[i]; 18 return result; 19 } 20 }; 21 22 template <template <class, precision> class matType, typename T, precision P, bool Aligned> 23 struct compute_transpose{}; 24 25 template <typename T, precision P, bool Aligned> 26 struct compute_transpose<tmat2x2, T, P, Aligned> 27 { 28 GLM_FUNC_QUALIFIER static tmat2x2<T, P> call(tmat2x2<T, P> const & m) 29 { 30 tmat2x2<T, P> result(uninitialize); 31 result[0][0] = m[0][0]; 32 result[0][1] = m[1][0]; 33 result[1][0] = m[0][1]; 34 result[1][1] = m[1][1]; 35 return result; 36 } 37 }; 38 39 template <typename T, precision P, bool Aligned> 40 struct compute_transpose<tmat2x3, T, P, Aligned> 41 { 42 GLM_FUNC_QUALIFIER static tmat3x2<T, P> call(tmat2x3<T, P> const & m) 43 { 44 tmat3x2<T, P> result(uninitialize); 45 result[0][0] = m[0][0]; 46 result[0][1] = m[1][0]; 47 result[1][0] = m[0][1]; 48 result[1][1] = m[1][1]; 49 result[2][0] = m[0][2]; 50 result[2][1] = m[1][2]; 51 return result; 52 } 53 }; 54 55 template <typename T, precision P, bool Aligned> 56 struct compute_transpose<tmat2x4, T, P, Aligned> 57 { 58 GLM_FUNC_QUALIFIER static tmat4x2<T, P> call(tmat2x4<T, P> const & m) 59 { 60 tmat4x2<T, P> result(uninitialize); 61 result[0][0] = m[0][0]; 62 result[0][1] = m[1][0]; 63 result[1][0] = m[0][1]; 64 result[1][1] = m[1][1]; 65 result[2][0] = m[0][2]; 66 result[2][1] = m[1][2]; 67 result[3][0] = m[0][3]; 68 result[3][1] = m[1][3]; 69 return result; 70 } 71 }; 72 73 template <typename T, precision P, bool Aligned> 74 struct compute_transpose<tmat3x2, T, P, Aligned> 75 { 76 GLM_FUNC_QUALIFIER static tmat2x3<T, P> call(tmat3x2<T, P> const & m) 77 { 78 tmat2x3<T, P> result(uninitialize); 79 result[0][0] = m[0][0]; 80 result[0][1] = m[1][0]; 81 result[0][2] = m[2][0]; 82 result[1][0] = m[0][1]; 83 result[1][1] = m[1][1]; 84 result[1][2] = m[2][1]; 85 return result; 86 } 87 }; 88 89 template <typename T, precision P, bool Aligned> 90 struct compute_transpose<tmat3x3, T, P, Aligned> 91 { 92 GLM_FUNC_QUALIFIER static tmat3x3<T, P> call(tmat3x3<T, P> const & m) 93 { 94 tmat3x3<T, P> result(uninitialize); 95 result[0][0] = m[0][0]; 96 result[0][1] = m[1][0]; 97 result[0][2] = m[2][0]; 98 99 result[1][0] = m[0][1]; 100 result[1][1] = m[1][1]; 101 result[1][2] = m[2][1]; 102 103 result[2][0] = m[0][2]; 104 result[2][1] = m[1][2]; 105 result[2][2] = m[2][2]; 106 return result; 107 } 108 }; 109 110 template <typename T, precision P, bool Aligned> 111 struct compute_transpose<tmat3x4, T, P, Aligned> 112 { 113 GLM_FUNC_QUALIFIER static tmat4x3<T, P> call(tmat3x4<T, P> const & m) 114 { 115 tmat4x3<T, P> result(uninitialize); 116 result[0][0] = m[0][0]; 117 result[0][1] = m[1][0]; 118 result[0][2] = m[2][0]; 119 result[1][0] = m[0][1]; 120 result[1][1] = m[1][1]; 121 result[1][2] = m[2][1]; 122 result[2][0] = m[0][2]; 123 result[2][1] = m[1][2]; 124 result[2][2] = m[2][2]; 125 result[3][0] = m[0][3]; 126 result[3][1] = m[1][3]; 127 result[3][2] = m[2][3]; 128 return result; 129 } 130 }; 131 132 template <typename T, precision P, bool Aligned> 133 struct compute_transpose<tmat4x2, T, P, Aligned> 134 { 135 GLM_FUNC_QUALIFIER static tmat2x4<T, P> call(tmat4x2<T, P> const & m) 136 { 137 tmat2x4<T, P> result(uninitialize); 138 result[0][0] = m[0][0]; 139 result[0][1] = m[1][0]; 140 result[0][2] = m[2][0]; 141 result[0][3] = m[3][0]; 142 result[1][0] = m[0][1]; 143 result[1][1] = m[1][1]; 144 result[1][2] = m[2][1]; 145 result[1][3] = m[3][1]; 146 return result; 147 } 148 }; 149 150 template <typename T, precision P, bool Aligned> 151 struct compute_transpose<tmat4x3, T, P, Aligned> 152 { 153 GLM_FUNC_QUALIFIER static tmat3x4<T, P> call(tmat4x3<T, P> const & m) 154 { 155 tmat3x4<T, P> result(uninitialize); 156 result[0][0] = m[0][0]; 157 result[0][1] = m[1][0]; 158 result[0][2] = m[2][0]; 159 result[0][3] = m[3][0]; 160 result[1][0] = m[0][1]; 161 result[1][1] = m[1][1]; 162 result[1][2] = m[2][1]; 163 result[1][3] = m[3][1]; 164 result[2][0] = m[0][2]; 165 result[2][1] = m[1][2]; 166 result[2][2] = m[2][2]; 167 result[2][3] = m[3][2]; 168 return result; 169 } 170 }; 171 172 template <typename T, precision P, bool Aligned> 173 struct compute_transpose<tmat4x4, T, P, Aligned> 174 { 175 GLM_FUNC_QUALIFIER static tmat4x4<T, P> call(tmat4x4<T, P> const & m) 176 { 177 tmat4x4<T, P> result(uninitialize); 178 result[0][0] = m[0][0]; 179 result[0][1] = m[1][0]; 180 result[0][2] = m[2][0]; 181 result[0][3] = m[3][0]; 182 183 result[1][0] = m[0][1]; 184 result[1][1] = m[1][1]; 185 result[1][2] = m[2][1]; 186 result[1][3] = m[3][1]; 187 188 result[2][0] = m[0][2]; 189 result[2][1] = m[1][2]; 190 result[2][2] = m[2][2]; 191 result[2][3] = m[3][2]; 192 193 result[3][0] = m[0][3]; 194 result[3][1] = m[1][3]; 195 result[3][2] = m[2][3]; 196 result[3][3] = m[3][3]; 197 return result; 198 } 199 }; 200 201 template <template <typename, precision> class matType, typename T, precision P, bool Aligned> 202 struct compute_determinant{}; 203 204 template <typename T, precision P, bool Aligned> 205 struct compute_determinant<tmat2x2, T, P, Aligned> 206 { 207 GLM_FUNC_QUALIFIER static T call(tmat2x2<T, P> const & m) 208 { 209 return m[0][0] * m[1][1] - m[1][0] * m[0][1]; 210 } 211 }; 212 213 template <typename T, precision P, bool Aligned> 214 struct compute_determinant<tmat3x3, T, P, Aligned> 215 { 216 GLM_FUNC_QUALIFIER static T call(tmat3x3<T, P> const & m) 217 { 218 return 219 + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) 220 - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) 221 + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); 222 } 223 }; 224 225 template <typename T, precision P, bool Aligned> 226 struct compute_determinant<tmat4x4, T, P, Aligned> 227 { 228 GLM_FUNC_QUALIFIER static T call(tmat4x4<T, P> const & m) 229 { 230 T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; 231 T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; 232 T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; 233 T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; 234 T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; 235 T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; 236 237 tvec4<T, P> DetCof( 238 + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), 239 - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), 240 + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), 241 - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); 242 243 return 244 m[0][0] * DetCof[0] + m[0][1] * DetCof[1] + 245 m[0][2] * DetCof[2] + m[0][3] * DetCof[3]; 246 } 247 }; 248 249 template <template <typename, precision> class matType, typename T, precision P, bool Aligned> 250 struct compute_inverse{}; 251 252 template <typename T, precision P, bool Aligned> 253 struct compute_inverse<tmat2x2, T, P, Aligned> 254 { 255 GLM_FUNC_QUALIFIER static tmat2x2<T, P> call(tmat2x2<T, P> const& m) 256 { 257 T OneOverDeterminant = static_cast<T>(1) / ( 258 + m[0][0] * m[1][1] 259 - m[1][0] * m[0][1]); 260 261 tmat2x2<T, P> Inverse( 262 + m[1][1] * OneOverDeterminant, 263 - m[0][1] * OneOverDeterminant, 264 - m[1][0] * OneOverDeterminant, 265 + m[0][0] * OneOverDeterminant); 266 267 return Inverse; 268 } 269 }; 270 271 template <typename T, precision P, bool Aligned> 272 struct compute_inverse<tmat3x3, T, P, Aligned> 273 { 274 GLM_FUNC_QUALIFIER static tmat3x3<T, P> call(tmat3x3<T, P> const& m) 275 { 276 T OneOverDeterminant = static_cast<T>(1) / ( 277 + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) 278 - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) 279 + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2])); 280 281 tmat3x3<T, P> Inverse(uninitialize); 282 Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant; 283 Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant; 284 Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant; 285 Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant; 286 Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant; 287 Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant; 288 Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant; 289 Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant; 290 Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant; 291 292 return Inverse; 293 } 294 }; 295 296 template <typename T, precision P, bool Aligned> 297 struct compute_inverse<tmat4x4, T, P, Aligned> 298 { 299 GLM_FUNC_QUALIFIER static tmat4x4<T, P> call(tmat4x4<T, P> const& m) 300 { 301 T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; 302 T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; 303 T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; 304 305 T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; 306 T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; 307 T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; 308 309 T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; 310 T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; 311 T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; 312 313 T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; 314 T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; 315 T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; 316 317 T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; 318 T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; 319 T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; 320 321 T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; 322 T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; 323 T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; 324 325 tvec4<T, P> Fac0(Coef00, Coef00, Coef02, Coef03); 326 tvec4<T, P> Fac1(Coef04, Coef04, Coef06, Coef07); 327 tvec4<T, P> Fac2(Coef08, Coef08, Coef10, Coef11); 328 tvec4<T, P> Fac3(Coef12, Coef12, Coef14, Coef15); 329 tvec4<T, P> Fac4(Coef16, Coef16, Coef18, Coef19); 330 tvec4<T, P> Fac5(Coef20, Coef20, Coef22, Coef23); 331 332 tvec4<T, P> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]); 333 tvec4<T, P> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]); 334 tvec4<T, P> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]); 335 tvec4<T, P> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]); 336 337 tvec4<T, P> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2); 338 tvec4<T, P> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4); 339 tvec4<T, P> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5); 340 tvec4<T, P> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5); 341 342 tvec4<T, P> SignA(+1, -1, +1, -1); 343 tvec4<T, P> SignB(-1, +1, -1, +1); 344 tmat4x4<T, P> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB); 345 346 tvec4<T, P> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]); 347 348 tvec4<T, P> Dot0(m[0] * Row0); 349 T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w); 350 351 T OneOverDeterminant = static_cast<T>(1) / Dot1; 352 353 return Inverse * OneOverDeterminant; 354 } 355 }; 356}//namespace detail 357 358 template <typename T, precision P, template <typename, precision> class matType> 359 GLM_FUNC_QUALIFIER matType<T, P> matrixCompMult(matType<T, P> const & x, matType<T, P> const & y) 360 { 361 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'matrixCompMult' only accept floating-point inputs"); 362 return detail::compute_matrixCompMult<matType, T, P, detail::is_aligned<P>::value>::call(x, y); 363 } 364 365 template<typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB> 366 GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r) 367 { 368 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'outerProduct' only accept floating-point inputs"); 369 370 typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type m(uninitialize); 371 for(length_t i = 0; i < m.length(); ++i) 372 m[i] = c * r[i]; 373 return m; 374 } 375 376 template <typename T, precision P, template <typename, precision> class matType> 377 GLM_FUNC_QUALIFIER typename matType<T, P>::transpose_type transpose(matType<T, P> const & m) 378 { 379 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'transpose' only accept floating-point inputs"); 380 return detail::compute_transpose<matType, T, P, detail::is_aligned<P>::value>::call(m); 381 } 382 383 template <typename T, precision P, template <typename, precision> class matType> 384 GLM_FUNC_QUALIFIER T determinant(matType<T, P> const & m) 385 { 386 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'determinant' only accept floating-point inputs"); 387 return detail::compute_determinant<matType, T, P, detail::is_aligned<P>::value>::call(m); 388 } 389 390 template <typename T, precision P, template <typename, precision> class matType> 391 GLM_FUNC_QUALIFIER matType<T, P> inverse(matType<T, P> const & m) 392 { 393 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'inverse' only accept floating-point inputs"); 394 return detail::compute_inverse<matType, T, P, detail::is_aligned<P>::value>::call(m); 395 } 396}//namespace glm 397 398#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS 399# include "func_matrix_simd.inl" 400#endif 401 402