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;
494 // GLSL-style naming \note CxR.
495 typedef Matrix2f Mat2;
496 typedef Matrix<float, 3, 2> Mat2x3;
497 typedef Matrix<float, 4, 2> Mat2x4;
498 typedef Matrix<float, 2, 3> Mat3x2;
499 typedef Matrix3f Mat3;
500 typedef Matrix<float, 4, 3> Mat3x4;
501 typedef Matrix<float, 2, 4> Mat4x2;
502 typedef Matrix<float, 3, 4> Mat4x3;
503 typedef Matrix4f Mat4;
506 // Common typedefs 16Bit.
507 typedef Matrix<deUint16, 2, 2> Matrix2f16b;
508 typedef Matrix<deUint16, 3, 3> Matrix3f16b;
509 typedef Matrix<deUint16, 4, 4> Matrix4f16b;
511 // GLSL-style naming \note CxR.
512 typedef Matrix2f16b Mat2_16b;
513 typedef Matrix<deUint16, 3, 2> Mat2x3_16b;
514 typedef Matrix<deUint16, 4, 2> Mat2x4_16b;
515 typedef Matrix<deUint16, 2, 3> Mat3x2_16b;
516 typedef Matrix3f16b Mat3_16b;
517 typedef Matrix<deUint16, 4, 3> Mat3x4_16b;
518 typedef Matrix<deUint16, 2, 4> Mat4x2_16b;
519 typedef Matrix<deUint16, 3, 4> Mat4x3_16b;
520 typedef Matrix4f16b Mat4_16b;
523 typedef Matrix<double, 2, 2> Matrix2d;
524 typedef Matrix<double, 3, 3> Matrix3d;
525 typedef Matrix<double, 4, 4> Matrix4d;
527 // GLSL-style naming \note CxR.
528 typedef Matrix2d Mat2d;
529 typedef Matrix<double, 3, 2> Mat2x3d;
530 typedef Matrix<double, 4, 2> Mat2x4d;
531 typedef Matrix<double, 2, 3> Mat3x2d;
532 typedef Matrix3d Mat3d;
533 typedef Matrix<double, 4, 3> Mat3x4d;
534 typedef Matrix<double, 2, 4> Mat4x2d;
535 typedef Matrix<double, 3, 4> Mat4x3d;
536 typedef Matrix4d Mat4d;
538 // Matrix-scalar operators.
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 template <typename T, int Rows, int Cols>
551 Matrix<T, Rows, Cols> operator- (const Matrix<T, Rows, Cols>& mtx, T scalar)
553 Matrix<T, Rows, Cols> res;
554 for (int col = 0; col < Cols; col++)
555 for (int row = 0; row < Rows; row++)
556 res(row, col) = mtx(row, col) - scalar;
560 template <typename T, int Rows, int Cols>
561 Matrix<T, Rows, Cols> operator* (const Matrix<T, Rows, Cols>& mtx, T scalar)
563 Matrix<T, Rows, Cols> res;
564 for (int col = 0; col < Cols; col++)
565 for (int row = 0; row < Rows; row++)
566 res(row, col) = mtx(row, col) * scalar;
570 template <typename T, int Rows, int Cols>
571 Matrix<T, Rows, Cols> operator/ (const Matrix<T, Rows, Cols>& mtx, T scalar)
573 Matrix<T, Rows, Cols> res;
574 for (int col = 0; col < Cols; col++)
575 for (int row = 0; row < Rows; row++)
576 res(row, col) = mtx(row, col) / scalar;
580 // Matrix-matrix component-wise operators.
582 template <typename T, int Rows, int Cols>
583 Matrix<T, Rows, Cols> operator+ (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
585 Matrix<T, Rows, Cols> res;
586 for (int col = 0; col < Cols; col++)
587 for (int row = 0; row < Rows; row++)
588 res(row, col) = a(row, col) + b(row, col);
592 template <typename T, int Rows, int Cols>
593 Matrix<T, Rows, Cols> operator- (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
595 Matrix<T, Rows, Cols> res;
596 for (int col = 0; col < Cols; col++)
597 for (int row = 0; row < Rows; row++)
598 res(row, col) = a(row, col) - b(row, col);
602 template <typename T, int Rows, int Cols>
603 Matrix<T, Rows, Cols> operator/ (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
605 Matrix<T, Rows, Cols> res;
606 for (int col = 0; col < Cols; col++)
607 for (int row = 0; row < Rows; row++)
608 res(row, col) = a(row, col) / b(row, col);
612 template <typename T, int Rows, int Cols>
613 bool operator== (const Matrix<T, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs)
615 for (int row = 0; row < Rows; row++)
616 for (int col = 0; col < Cols; col++)
617 if (lhs(row, col) != rhs(row, col))
622 template <typename T, int Rows, int Cols>
623 bool operator!= (const Matrix<T, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs)
625 return !(lhs == rhs);
630 #endif // _TCUMATRIX_HPP