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);
94 template <typename T, int Size>
95 struct SquareMatrixOps
97 static T doDeterminant (const Matrix<T, Size, Size>& mat);
98 static Matrix<T, Size, Size> doInverse (const Matrix<T, Size, Size>& mat);
101 template <typename T>
102 struct SquareMatrixOps<T, 2>
104 static T doDeterminant (const Matrix<T, 2, 2>& mat);
105 static Matrix<T, 2, 2> doInverse (const Matrix<T, 2, 2>& mat);
108 template <typename T>
109 struct SquareMatrixOps<T, 3>
111 static T doDeterminant (const Matrix<T, 3, 3>& mat);
112 static Matrix<T, 3, 3> doInverse (const Matrix<T, 3, 3>& mat);
115 template <typename T>
116 struct SquareMatrixOps<T, 4>
118 static T doDeterminant (const Matrix<T, 4, 4>& mat);
119 static Matrix<T, 4, 4> doInverse (const Matrix<T, 4, 4>& mat);
125 template <typename T, int Size>
126 T determinant (const Matrix<T, Size, Size>& mat)
128 return SquareMatrixOps<T, Size>::doDeterminant(mat);
131 template <typename T, int Size>
132 Matrix<T, Size, Size> inverse (const Matrix<T, Size, Size>& mat)
134 return SquareMatrixOps<T, Size>::doInverse(mat);
139 // Template implementations.
141 template <typename T>
142 T SquareMatrixOps<T, 2>::doDeterminant (const Matrix<T, 2, 2>& mat)
144 return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1);
147 template <typename T>
148 T SquareMatrixOps<T, 3>::doDeterminant (const Matrix<T, 3, 3>& mat)
150 return + mat(0,0) * mat(1,1) * mat(2,2)
151 + mat(0,1) * mat(1,2) * mat(2,0)
152 + mat(0,2) * mat(1,0) * mat(2,1)
153 - mat(0,0) * mat(1,2) * mat(2,1)
154 - mat(0,1) * mat(1,0) * mat(2,2)
155 - mat(0,2) * mat(1,1) * mat(2,0);
158 template <typename T>
159 T SquareMatrixOps<T, 4>::doDeterminant (const Matrix<T, 4, 4>& mat)
161 using matrix::determinant;
163 const T minorMatrices[4][3*3] =
166 mat(1,1), mat(2,1), mat(3,1),
167 mat(1,2), mat(2,2), mat(3,2),
168 mat(1,3), mat(2,3), mat(3,3),
171 mat(1,0), mat(2,0), mat(3,0),
172 mat(1,2), mat(2,2), mat(3,2),
173 mat(1,3), mat(2,3), mat(3,3),
176 mat(1,0), mat(2,0), mat(3,0),
177 mat(1,1), mat(2,1), mat(3,1),
178 mat(1,3), mat(2,3), mat(3,3),
181 mat(1,0), mat(2,0), mat(3,0),
182 mat(1,1), mat(2,1), mat(3,1),
183 mat(1,2), mat(2,2), mat(3,2),
187 return + mat(0,0) * determinant(Matrix<T, 3, 3>(minorMatrices[0]))
188 - mat(0,1) * determinant(Matrix<T, 3, 3>(minorMatrices[1]))
189 + mat(0,2) * determinant(Matrix<T, 3, 3>(minorMatrices[2]))
190 - mat(0,3) * determinant(Matrix<T, 3, 3>(minorMatrices[3]));
193 template <typename T>
194 Matrix<T, 2, 2> SquareMatrixOps<T, 2>::doInverse (const Matrix<T, 2, 2>& mat)
196 using matrix::determinant;
198 const T det = determinant(mat);
199 Matrix<T, 2, 2> retVal;
201 retVal(0, 0) = mat(1, 1) / det;
202 retVal(0, 1) = -mat(0, 1) / det;
203 retVal(1, 0) = -mat(1, 0) / det;
204 retVal(1, 1) = mat(0, 0) / det;
209 template <typename T>
210 Matrix<T, 3, 3> SquareMatrixOps<T, 3>::doInverse (const Matrix<T, 3, 3>& mat)
212 // Blockwise inversion
213 using matrix::inverse;
233 const T nullField[4] = { T(0.0f) };
235 const Matrix<T, 2, 2> invA = inverse(Matrix<T, 2, 2>(areaA));
236 const Matrix<T, 2, 1> matB = Matrix<T, 2, 1>(areaB);
237 const Matrix<T, 1, 2> matC = Matrix<T, 1, 2>(areaC);
238 const Matrix<T, 1, 1> matD = Matrix<T, 1, 1>(areaD);
240 const T schurComplement = T(1.0f) / (matD - matC*invA*matB)(0,0);
241 const Matrix<T, 2, 2> zeroMat = Matrix<T, 2, 2>(nullField);
243 const Matrix<T, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
244 const Matrix<T, 2, 1> blockB = (zeroMat-invA)*matB*schurComplement;
245 const Matrix<T, 1, 2> blockC = matC*invA*(-schurComplement);
246 const T blockD = schurComplement;
248 const T result[3*3] =
250 blockA(0,0), blockA(0,1), blockB(0,0),
251 blockA(1,0), blockA(1,1), blockB(1,0),
252 blockC(0,0), blockC(0,1), blockD,
255 return Matrix<T, 3, 3>(result);
258 template <typename T>
259 Matrix<T, 4, 4> SquareMatrixOps<T, 4>::doInverse (const Matrix<T, 4, 4>& mat)
261 // Blockwise inversion
262 using matrix::inverse;
284 const T nullField[4] = { T(0.0f) };
286 const Matrix<T, 2, 2> invA = inverse(Matrix<T, 2, 2>(areaA));
287 const Matrix<T, 2, 2> matB = Matrix<T, 2, 2>(areaB);
288 const Matrix<T, 2, 2> matC = Matrix<T, 2, 2>(areaC);
289 const Matrix<T, 2, 2> matD = Matrix<T, 2, 2>(areaD);
291 const Matrix<T, 2, 2> schurComplement = inverse(matD - matC*invA*matB);
292 const Matrix<T, 2, 2> zeroMat = Matrix<T, 2, 2>(nullField);
294 const Matrix<T, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
295 const Matrix<T, 2, 2> blockB = (zeroMat-invA)*matB*schurComplement;
296 const Matrix<T, 2, 2> blockC = (zeroMat-schurComplement)*matC*invA;
297 const Matrix<T, 2, 2> blockD = schurComplement;
299 const T result[4*4] =
301 blockA(0,0), blockA(0,1), blockB(0,0), blockB(0,1),
302 blockA(1,0), blockA(1,1), blockB(1,0), blockB(1,1),
303 blockC(0,0), blockC(0,1), blockD(0,0), blockD(0,1),
304 blockC(1,0), blockC(1,1), blockD(1,0), blockD(1,1),
307 return Matrix<T, 4, 4>(result);
310 // Initialize to identity.
311 template <typename T, int Rows, int Cols>
312 Matrix<T, Rows, Cols>::Matrix (void)
314 for (int row = 0; row < Rows; row++)
315 for (int col = 0; col < Cols; col++)
316 (*this)(row, col) = (row == col) ? T(1) : T(0);
319 // Initialize to diagonal matrix.
320 template <typename T, int Rows, int Cols>
321 Matrix<T, Rows, Cols>::Matrix (const T& src)
323 for (int row = 0; row < Rows; row++)
324 for (int col = 0; col < Cols; col++)
325 (*this)(row, col) = (row == col) ? src : T(0);
328 // Initialize from data array.
329 template <typename T, int Rows, int Cols>
330 Matrix<T, Rows, Cols>::Matrix (const T src[Rows*Cols])
332 for (int row = 0; row < Rows; row++)
333 for (int col = 0; col < Cols; col++)
334 (*this)(row, col) = src[row*Cols + col];
337 // Initialize to diagonal matrix.
338 template <typename T, int Rows, int Cols>
339 Matrix<T, Rows, Cols>::Matrix (const Vector<T, Rows>& src)
341 DE_STATIC_ASSERT(Rows == Cols);
342 for (int row = 0; row < Rows; row++)
343 for (int col = 0; col < Cols; col++)
344 (*this)(row, col) = (row == col) ? src.m_data[row] : T(0);
348 template <typename T, int Rows, int Cols>
349 Matrix<T, Rows, Cols>::Matrix (const Matrix<T, Rows, Cols>& src)
355 template <typename T, int Rows, int Cols>
356 Matrix<T, Rows, Cols>::~Matrix (void)
360 // Assignment operator.
361 template <typename T, int Rows, int Cols>
362 Matrix<T, Rows, Cols>& Matrix<T, Rows, Cols>::operator= (const Matrix<T, Rows, Cols>& src)
364 for (int row = 0; row < Rows; row++)
365 for (int col = 0; col < Cols; col++)
366 (*this)(row, col) = src(row, col);
370 // Multipy and assign op
371 template <typename T, int Rows, int Cols>
372 Matrix<T, Rows, Cols>& Matrix<T, Rows, Cols>::operator*= (const Matrix<T, Rows, Cols>& src)
378 template <typename T, int Rows, int Cols>
379 void Matrix<T, Rows, Cols>::setRow (int rowNdx, const Vector<T, Cols>& vec)
381 for (int col = 0; col < Cols; col++)
382 (*this)(rowNdx, col) = vec.m_data[col];
385 template <typename T, int Rows, int Cols>
386 void Matrix<T, Rows, Cols>::setColumn (int colNdx, const Vector<T, Rows>& vec)
388 m_data[colNdx] = vec;
391 template <typename T, int Rows, int Cols>
392 Vector<T, Cols> Matrix<T, Rows, Cols>::getRow (int rowNdx) const
395 for (int col = 0; col < Cols; col++)
396 res[col] = (*this)(rowNdx, col);
400 template <typename T, int Rows, int Cols>
401 Vector<T, Rows>& Matrix<T, Rows, Cols>::getColumn (int colNdx)
403 return m_data[colNdx];
406 template <typename T, int Rows, int Cols>
407 const Vector<T, Rows>& Matrix<T, Rows, Cols>::getColumn (int colNdx) const
409 return m_data[colNdx];
412 template <typename T, int Rows, int Cols>
413 Array<T, Rows*Cols> Matrix<T, Rows, Cols>::getColumnMajorData (void) const
415 Array<T, Rows*Cols> a;
417 for (int col = 0; col < Cols; col++)
418 for (int row = 0; row < Rows; row++)
419 *dst++ = (*this)(row, col);
423 template <typename T, int Rows, int Cols>
424 Array<T, Rows*Cols> Matrix<T, Rows, Cols>::getRowMajorData (void) const
426 Array<T, Rows*Cols> a;
428 for (int row = 0; row < Rows; row++)
429 for (int col = 0; col < Cols; col++)
430 *dst++ = (*this)(row, col);
434 // Multiplication of two matrices.
435 template <typename T, int Rows0, int Cols0, int Rows1, int Cols1>
436 Matrix<T, Rows0, Cols1> operator* (const Matrix<T, Rows0, Cols0>& a, const Matrix<T, Rows1, Cols1>& b)
438 DE_STATIC_ASSERT(Cols0 == Rows1);
439 Matrix<T, Rows0, Cols1> res;
440 for (int row = 0; row < Rows0; row++)
442 for (int col = 0; col < Cols1; col++)
445 for (int ndx = 0; ndx < Cols0; ndx++)
446 v += a(row,ndx) * b(ndx,col);
453 // Multiply of matrix with column vector.
454 template <typename T, int Rows, int Cols>
455 Vector<T, Rows> operator* (const Matrix<T, Rows, Cols>& mtx, const Vector<T, Cols>& vec)
458 for (int row = 0; row < Rows; row++)
461 for (int col = 0; col < Cols; col++)
462 v += mtx(row,col) * vec.m_data[col];
468 // Multiply of matrix with row vector.
469 template <typename T, int Rows, int Cols>
470 Vector<T, Cols> operator* (const Vector<T, Rows>& vec, const Matrix<T, Rows, Cols>& mtx)
473 for (int col = 0; col < Cols; col++)
476 for (int row = 0; row < Rows; row++)
477 v += mtx(row,col) * vec.m_data[row];
484 typedef Matrix<float, 2, 2> Matrix2f;
485 typedef Matrix<float, 3, 3> Matrix3f;
486 typedef Matrix<float, 4, 4> Matrix4f;
487 typedef Matrix<double, 2, 2> Matrix2d;
488 typedef Matrix<double, 3, 3> Matrix3d;
489 typedef Matrix<double, 4, 4> Matrix4d;
491 // GLSL-style naming \note CxR.
492 typedef Matrix2f Mat2;
493 typedef Matrix<float, 3, 2> Mat2x3;
494 typedef Matrix<float, 4, 2> Mat2x4;
495 typedef Matrix<float, 2, 3> Mat3x2;
496 typedef Matrix3f Mat3;
497 typedef Matrix<float, 4, 3> Mat3x4;
498 typedef Matrix<float, 2, 4> Mat4x2;
499 typedef Matrix<float, 3, 4> Mat4x3;
500 typedef Matrix4f Mat4;
502 // Matrix-scalar operators.
504 template <typename T, int Rows, int Cols>
505 Matrix<T, Rows, Cols> operator+ (const Matrix<T, Rows, Cols>& mtx, T scalar)
507 Matrix<T, Rows, Cols> res;
508 for (int col = 0; col < Cols; col++)
509 for (int row = 0; row < Rows; row++)
510 res(row, col) = mtx(row, col) + scalar;
514 template <typename T, int Rows, int Cols>
515 Matrix<T, Rows, Cols> operator- (const Matrix<T, Rows, Cols>& mtx, T scalar)
517 Matrix<T, Rows, Cols> res;
518 for (int col = 0; col < Cols; col++)
519 for (int row = 0; row < Rows; row++)
520 res(row, col) = mtx(row, col) - scalar;
524 template <typename T, int Rows, int Cols>
525 Matrix<T, Rows, Cols> operator* (const Matrix<T, Rows, Cols>& mtx, T scalar)
527 Matrix<T, Rows, Cols> res;
528 for (int col = 0; col < Cols; col++)
529 for (int row = 0; row < Rows; row++)
530 res(row, col) = mtx(row, col) * scalar;
534 template <typename T, int Rows, int Cols>
535 Matrix<T, Rows, Cols> operator/ (const Matrix<T, Rows, Cols>& mtx, T scalar)
537 Matrix<T, Rows, Cols> res;
538 for (int col = 0; col < Cols; col++)
539 for (int row = 0; row < Rows; row++)
540 res(row, col) = mtx(row, col) / scalar;
544 // Matrix-matrix component-wise operators.
546 template <typename T, int Rows, int Cols>
547 Matrix<T, Rows, Cols> operator+ (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
549 Matrix<T, Rows, Cols> res;
550 for (int col = 0; col < Cols; col++)
551 for (int row = 0; row < Rows; row++)
552 res(row, col) = a(row, col) + b(row, col);
556 template <typename T, int Rows, int Cols>
557 Matrix<T, Rows, Cols> operator- (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
559 Matrix<T, Rows, Cols> res;
560 for (int col = 0; col < Cols; col++)
561 for (int row = 0; row < Rows; row++)
562 res(row, col) = a(row, col) - b(row, col);
566 template <typename T, int Rows, int Cols>
567 Matrix<T, Rows, Cols> operator/ (const Matrix<T, Rows, Cols>& a, const Matrix<T, Rows, Cols>& b)
569 Matrix<T, Rows, Cols> res;
570 for (int col = 0; col < Cols; col++)
571 for (int row = 0; row < Rows; row++)
572 res(row, col) = a(row, col) / b(row, col);
578 #endif // _TCUMATRIX_HPP