3 /*-------------------------------------------------------------------------
4 * drawElements Quality Program Tester Core
5 * ----------------------------------------
7 * Copyright 2014 The Android Open Source Project
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * \brief Templatized matrix class.
24 *//*--------------------------------------------------------------------*/
26 #include "tcuDefs.hpp"
27 #include "tcuVector.hpp"
28 #include "tcuArray.hpp"
33 // Templated matrix class.
34 template <typename T, int Rows, int Cols>
38 typedef Vector<T, Rows> Element;
49 explicit Matrix (const T& src);
50 explicit Matrix (const T src[Rows*Cols]);
51 Matrix (const Vector<T, Rows>& src);
52 Matrix (const Matrix<T, Rows, Cols>& src);
55 Matrix<T, Rows, Cols>& operator= (const Matrix<T, Rows, Cols>& src);
56 Matrix<T, Rows, Cols>& operator*= (const Matrix<T, Rows, Cols>& src);
58 void setRow (int rowNdx, const Vector<T, Cols>& vec);
59 void setColumn (int colNdx, const Vector<T, Rows>& vec);
61 Vector<T, Cols> getRow (int ndx) const;
62 Vector<T, Rows>& getColumn (int ndx);
63 const Vector<T, Rows>& getColumn (int ndx) const;
65 Vector<T, Rows>& operator[] (int ndx) { return getColumn(ndx); }
66 const Vector<T, Rows>& operator[] (int ndx) const { return getColumn(ndx); }
68 inline const T& operator() (int row, int col) const { return m_data[col][row]; }
69 inline T& operator() (int row, int col) { return m_data[col][row]; }
71 Array<T, Rows*Cols> getRowMajorData (void) const;
72 Array<T, Rows*Cols> getColumnMajorData (void) const;
75 Vector<Vector<T, Rows>, Cols> m_data;
76 } DE_WARN_UNUSED_TYPE;
81 template <typename T, int Rows0, int Cols0, int Rows1, int Cols1>
82 Matrix<T, Rows0, Cols1> operator* (const Matrix<T, Rows0, Cols0>& a, const Matrix<T, Rows1, Cols1>& b);
84 // Mat * Vec (column vector).
85 template <typename T, int Rows, int Cols>
86 Vector<T, Rows> operator* (const Matrix<T, Rows, Cols>& mtx, const Vector<T, Cols>& vec);
88 // Vec * Mat (row vector).
89 template <typename T, int Rows, int Cols>
90 Vector<T, Cols> operator* (const Vector<T, Rows>& vec, const Matrix<T, Rows, Cols>& mtx);
92 template <typename T, int Rows, int Cols>
93 bool operator== (const Matrix<T, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs);
95 template <typename T, int Rows, int Cols>
96 bool operator!= (const Matrix<T, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs);
100 template <typename T, int Size>
101 struct SquareMatrixOps
103 static T doDeterminant (const Matrix<T, Size, Size>& mat);
104 static Matrix<T, Size, Size> doInverse (const Matrix<T, Size, Size>& mat);
107 template <typename T>
108 struct SquareMatrixOps<T, 2>
110 static T doDeterminant (const Matrix<T, 2, 2>& mat);
111 static Matrix<T, 2, 2> doInverse (const Matrix<T, 2, 2>& mat);
114 template <typename T>
115 struct SquareMatrixOps<T, 3>
117 static T doDeterminant (const Matrix<T, 3, 3>& mat);
118 static Matrix<T, 3, 3> doInverse (const Matrix<T, 3, 3>& mat);
121 template <typename T>
122 struct SquareMatrixOps<T, 4>
124 static T doDeterminant (const Matrix<T, 4, 4>& mat);
125 static Matrix<T, 4, 4> doInverse (const Matrix<T, 4, 4>& mat);
131 template <typename T, int Size>
132 T determinant (const Matrix<T, Size, Size>& mat)
134 return SquareMatrixOps<T, Size>::doDeterminant(mat);
137 template <typename T, int Size>
138 Matrix<T, Size, Size> inverse (const Matrix<T, Size, Size>& mat)
140 return SquareMatrixOps<T, Size>::doInverse(mat);
145 // Template implementations.
147 template <typename T>
148 T SquareMatrixOps<T, 2>::doDeterminant (const Matrix<T, 2, 2>& mat)
150 return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1);
153 template <typename T>
154 T SquareMatrixOps<T, 3>::doDeterminant (const Matrix<T, 3, 3>& mat)
156 return + mat(0,0) * mat(1,1) * mat(2,2)
157 + mat(0,1) * mat(1,2) * mat(2,0)
158 + mat(0,2) * mat(1,0) * mat(2,1)
159 - mat(0,0) * mat(1,2) * mat(2,1)
160 - mat(0,1) * mat(1,0) * mat(2,2)
161 - mat(0,2) * mat(1,1) * mat(2,0);
164 template <typename T>
165 T SquareMatrixOps<T, 4>::doDeterminant (const Matrix<T, 4, 4>& mat)
167 using matrix::determinant;
169 const T minorMatrices[4][3*3] =
172 mat(1,1), mat(2,1), mat(3,1),
173 mat(1,2), mat(2,2), mat(3,2),
174 mat(1,3), mat(2,3), mat(3,3),
177 mat(1,0), mat(2,0), mat(3,0),
178 mat(1,2), mat(2,2), mat(3,2),
179 mat(1,3), mat(2,3), mat(3,3),
182 mat(1,0), mat(2,0), mat(3,0),
183 mat(1,1), mat(2,1), mat(3,1),
184 mat(1,3), mat(2,3), mat(3,3),
187 mat(1,0), mat(2,0), mat(3,0),
188 mat(1,1), mat(2,1), mat(3,1),
189 mat(1,2), mat(2,2), mat(3,2),
193 return + mat(0,0) * determinant(Matrix<T, 3, 3>(minorMatrices[0]))
194 - mat(0,1) * determinant(Matrix<T, 3, 3>(minorMatrices[1]))
195 + mat(0,2) * determinant(Matrix<T, 3, 3>(minorMatrices[2]))
196 - mat(0,3) * determinant(Matrix<T, 3, 3>(minorMatrices[3]));
199 template <typename T>
200 Matrix<T, 2, 2> SquareMatrixOps<T, 2>::doInverse (const Matrix<T, 2, 2>& mat)
202 using matrix::determinant;
204 const T det = determinant(mat);
205 Matrix<T, 2, 2> retVal;
207 retVal(0, 0) = mat(1, 1) / det;
208 retVal(0, 1) = -mat(0, 1) / det;
209 retVal(1, 0) = -mat(1, 0) / det;
210 retVal(1, 1) = mat(0, 0) / det;
215 template <typename T>
216 Matrix<T, 3, 3> SquareMatrixOps<T, 3>::doInverse (const Matrix<T, 3, 3>& mat)
218 // Blockwise inversion
219 using matrix::inverse;
239 const T nullField[4] = { T(0.0f) };
241 const Matrix<T, 2, 2> invA = inverse(Matrix<T, 2, 2>(areaA));
242 const Matrix<T, 2, 1> matB = Matrix<T, 2, 1>(areaB);
243 const Matrix<T, 1, 2> matC = Matrix<T, 1, 2>(areaC);
244 const Matrix<T, 1, 1> matD = Matrix<T, 1, 1>(areaD);
246 const T schurComplement = T(1.0f) / (matD - matC*invA*matB)(0,0);
247 const Matrix<T, 2, 2> zeroMat = Matrix<T, 2, 2>(nullField);
249 const Matrix<T, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
250 const Matrix<T, 2, 1> blockB = (zeroMat-invA)*matB*schurComplement;
251 const Matrix<T, 1, 2> blockC = matC*invA*(-schurComplement);
252 const T blockD = schurComplement;
254 const T result[3*3] =
256 blockA(0,0), blockA(0,1), blockB(0,0),
257 blockA(1,0), blockA(1,1), blockB(1,0),
258 blockC(0,0), blockC(0,1), blockD,
261 return Matrix<T, 3, 3>(result);
264 template <typename T>
265 Matrix<T, 4, 4> SquareMatrixOps<T, 4>::doInverse (const Matrix<T, 4, 4>& mat)
267 // Blockwise inversion
268 using matrix::inverse;
290 const T nullField[4] = { T(0.0f) };
292 const Matrix<T, 2, 2> invA = inverse(Matrix<T, 2, 2>(areaA));
293 const Matrix<T, 2, 2> matB = Matrix<T, 2, 2>(areaB);
294 const Matrix<T, 2, 2> matC = Matrix<T, 2, 2>(areaC);
295 const Matrix<T, 2, 2> matD = Matrix<T, 2, 2>(areaD);
297 const Matrix<T, 2, 2> schurComplement = inverse(matD - matC*invA*matB);
298 const Matrix<T, 2, 2> zeroMat = Matrix<T, 2, 2>(nullField);
300 const Matrix<T, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
301 const Matrix<T, 2, 2> blockB = (zeroMat-invA)*matB*schurComplement;
302 const Matrix<T, 2, 2> blockC = (zeroMat-schurComplement)*matC*invA;
303 const Matrix<T, 2, 2> blockD = schurComplement;
305 const T result[4*4] =
307 blockA(0,0), blockA(0,1), blockB(0,0), blockB(0,1),
308 blockA(1,0), blockA(1,1), blockB(1,0), blockB(1,1),
309 blockC(0,0), blockC(0,1), blockD(0,0), blockD(0,1),
310 blockC(1,0), blockC(1,1), blockD(1,0), blockD(1,1),
313 return Matrix<T, 4, 4>(result);
316 // Initialize to identity.
317 template <typename T, int Rows, int Cols>
318 Matrix<T, Rows, Cols>::Matrix (void)
320 for (int row = 0; row < Rows; row++)
321 for (int col = 0; col < Cols; col++)
322 (*this)(row, col) = (row == col) ? T(1) : T(0);
325 // Initialize to diagonal matrix.
326 template <typename T, int Rows, int Cols>
327 Matrix<T, Rows, Cols>::Matrix (const T& src)
329 for (int row = 0; row < Rows; row++)
330 for (int col = 0; col < Cols; col++)
331 (*this)(row, col) = (row == col) ? src : T(0);
334 // Initialize from data array.
335 template <typename T, int Rows, int Cols>
336 Matrix<T, Rows, Cols>::Matrix (const T src[Rows*Cols])
338 for (int row = 0; row < Rows; row++)
339 for (int col = 0; col < Cols; col++)
340 (*this)(row, col) = src[row*Cols + col];
343 // Initialize to diagonal matrix.
344 template <typename T, int Rows, int Cols>
345 Matrix<T, Rows, Cols>::Matrix (const Vector<T, Rows>& src)
347 DE_STATIC_ASSERT(Rows == Cols);
348 for (int row = 0; row < Rows; row++)
349 for (int col = 0; col < Cols; col++)
350 (*this)(row, col) = (row == col) ? src.m_data[row] : T(0);
354 template <typename T, int Rows, int Cols>
355 Matrix<T, Rows, Cols>::Matrix (const Matrix<T, Rows, Cols>& src)
361 template <typename T, int Rows, int Cols>
362 Matrix<T, Rows, Cols>::~Matrix (void)
366 // Assignment operator.
367 template <typename T, int Rows, int Cols>
368 Matrix<T, Rows, Cols>& Matrix<T, Rows, Cols>::operator= (const Matrix<T, Rows, Cols>& src)
370 for (int row = 0; row < Rows; row++)
371 for (int col = 0; col < Cols; col++)
372 (*this)(row, col) = src(row, col);
376 // Multipy and assign op
377 template <typename T, int Rows, int Cols>
378 Matrix<T, Rows, Cols>& Matrix<T, Rows, Cols>::operator*= (const Matrix<T, Rows, Cols>& src)
384 template <typename T, int Rows, int Cols>
385 void Matrix<T, Rows, Cols>::setRow (int rowNdx, const Vector<T, Cols>& vec)
387 for (int col = 0; col < Cols; col++)
388 (*this)(rowNdx, col) = vec.m_data[col];
391 template <typename T, int Rows, int Cols>
392 void Matrix<T, Rows, Cols>::setColumn (int colNdx, const Vector<T, Rows>& vec)
394 m_data[colNdx] = vec;
397 template <typename T, int Rows, int Cols>
398 Vector<T, Cols> Matrix<T, Rows, Cols>::getRow (int rowNdx) const
401 for (int col = 0; col < Cols; col++)
402 res[col] = (*this)(rowNdx, col);
406 template <typename T, int Rows, int Cols>
407 Vector<T, Rows>& Matrix<T, Rows, Cols>::getColumn (int colNdx)
409 return m_data[colNdx];
412 template <typename T, int Rows, int Cols>
413 const Vector<T, Rows>& Matrix<T, Rows, Cols>::getColumn (int colNdx) const
415 return m_data[colNdx];
418 template <typename T, int Rows, int Cols>
419 Array<T, Rows*Cols> Matrix<T, Rows, Cols>::getColumnMajorData (void) const
421 Array<T, Rows*Cols> a;
423 for (int col = 0; col < Cols; col++)
424 for (int row = 0; row < Rows; row++)
425 *dst++ = (*this)(row, col);
429 template <typename T, int Rows, int Cols>
430 Array<T, Rows*Cols> Matrix<T, Rows, Cols>::getRowMajorData (void) const
432 Array<T, Rows*Cols> a;
434 for (int row = 0; row < Rows; row++)
435 for (int col = 0; col < Cols; col++)
436 *dst++ = (*this)(row, col);
440 // Multiplication of two matrices.
441 template <typename T, int Rows0, int Cols0, int Rows1, int Cols1>
442 Matrix<T, Rows0, Cols1> operator* (const Matrix<T, Rows0, Cols0>& a, const Matrix<T, Rows1, Cols1>& b)
444 DE_STATIC_ASSERT(Cols0 == Rows1);
445 Matrix<T, Rows0, Cols1> res;
446 for (int row = 0; row < Rows0; row++)
448 for (int col = 0; col < Cols1; col++)
451 for (int ndx = 0; ndx < Cols0; ndx++)
452 v += a(row,ndx) * b(ndx,col);
459 // Multiply of matrix with column vector.
460 template <typename T, int Rows, int Cols>
461 Vector<T, Rows> operator* (const Matrix<T, Rows, Cols>& mtx, const Vector<T, Cols>& vec)
464 for (int row = 0; row < Rows; row++)
467 for (int col = 0; col < Cols; col++)
468 v += mtx(row,col) * vec.m_data[col];
474 // Multiply of matrix with row vector.
475 template <typename T, int Rows, int Cols>
476 Vector<T, Cols> operator* (const Vector<T, Rows>& vec, const Matrix<T, Rows, Cols>& mtx)
479 for (int col = 0; col < Cols; col++)
482 for (int row = 0; row < Rows; row++)
483 v += mtx(row,col) * vec.m_data[row];
490 typedef Matrix<float, 2, 2> Matrix2f;
491 typedef Matrix<float, 3, 3> Matrix3f;
492 typedef Matrix<float, 4, 4> Matrix4f;
493 typedef Matrix<double, 2, 2> Matrix2d;
494 typedef Matrix<double, 3, 3> Matrix3d;
495 typedef Matrix<double, 4, 4> Matrix4d;
497 // GLSL-style naming \note CxR.
498 typedef Matrix2f Mat2;
499 typedef Matrix<float, 3, 2> Mat2x3;
500 typedef Matrix<float, 4, 2> Mat2x4;
501 typedef Matrix<float, 2, 3> Mat3x2;
502 typedef Matrix3f Mat3;
503 typedef Matrix<float, 4, 3> Mat3x4;
504 typedef Matrix<float, 2, 4> Mat4x2;
505 typedef Matrix<float, 3, 4> Mat4x3;
506 typedef Matrix4f Mat4;
508 // Matrix-scalar operators.
510 template <typename T, int Rows, int Cols>
511 Matrix<T, Rows, Cols> operator+ (const Matrix<T, Rows, Cols>& mtx, T scalar)
513 Matrix<T, Rows, Cols> res;
514 for (int col = 0; col < Cols; col++)
515 for (int row = 0; row < Rows; row++)
516 res(row, col) = mtx(row, col) + scalar;
520 template <typename T, int Rows, int Cols>
521 Matrix<T, Rows, Cols> operator- (const Matrix<T, Rows, Cols>& mtx, T scalar)
523 Matrix<T, Rows, Cols> res;
524 for (int col = 0; col < Cols; col++)
525 for (int row = 0; row < Rows; row++)
526 res(row, col) = mtx(row, col) - scalar;
530 template <typename T, int Rows, int Cols>
531 Matrix<T, Rows, Cols> operator* (const Matrix<T, Rows, Cols>& mtx, T scalar)
533 Matrix<T, Rows, Cols> res;
534 for (int col = 0; col < Cols; col++)
535 for (int row = 0; row < Rows; row++)
536 res(row, col) = mtx(row, col) * scalar;
540 template <typename T, int Rows, int Cols>
541 Matrix<T, Rows, Cols> operator/ (const Matrix<T, Rows, Cols>& mtx, T scalar)
543 Matrix<T, Rows, Cols> res;
544 for (int col = 0; col < Cols; col++)
545 for (int row = 0; row < Rows; row++)
546 res(row, col) = mtx(row, col) / scalar;
550 // Matrix-matrix component-wise operators.
552 template <typename T, int Rows, int Cols>
553 Matrix<T, Rows, Cols> operator+ (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
555 Matrix<T, Rows, Cols> res;
556 for (int col = 0; col < Cols; col++)
557 for (int row = 0; row < Rows; row++)
558 res(row, col) = a(row, col) + b(row, col);
562 template <typename T, int Rows, int Cols>
563 Matrix<T, Rows, Cols> operator- (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
565 Matrix<T, Rows, Cols> res;
566 for (int col = 0; col < Cols; col++)
567 for (int row = 0; row < Rows; row++)
568 res(row, col) = a(row, col) - b(row, col);
572 template <typename T, int Rows, int Cols>
573 Matrix<T, Rows, Cols> operator/ (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
575 Matrix<T, Rows, Cols> res;
576 for (int col = 0; col < Cols; col++)
577 for (int row = 0; row < Rows; row++)
578 res(row, col) = a(row, col) / b(row, col);
582 template <typename T, int Rows, int Cols>
583 bool operator== (const Matrix<T, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs)
585 for (int row = 0; row < Rows; row++)
586 for (int col = 0; col < Cols; col++)
587 if (lhs(row, col) != rhs(row, col))
592 template <typename T, int Rows, int Cols>
593 bool operator!= (const Matrix<T, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs)
595 return !(lhs == rhs);
600 #endif // _TCUMATRIX_HPP