Merge upstream-vulkan-cts-1.0-dev into master
[platform/upstream/VK-GL-CTS.git] / framework / common / tcuMatrix.hpp
1 #ifndef _TCUMATRIX_HPP
2 #define _TCUMATRIX_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program Tester Core
5  * ----------------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
21  *//*!
22  * \file
23  * \brief Templatized matrix class.
24  *//*--------------------------------------------------------------------*/
25
26 #include "tcuDefs.hpp"
27 #include "tcuVector.hpp"
28 #include "tcuArray.hpp"
29
30 namespace tcu
31 {
32
33 // Templated matrix class.
34 template <typename T, int Rows, int Cols>
35 class Matrix
36 {
37 public:
38         typedef Vector<T, Rows>                 Element;
39         typedef T                                               Scalar;
40
41         enum
42         {
43                 SIZE = Cols,
44                 ROWS = Rows,
45                 COLS = Cols,
46         };
47
48                                                                         Matrix                          (void);
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);
53                                                                         ~Matrix                         (void);
54
55         Matrix<T, Rows, Cols>&                  operator=                       (const Matrix<T, Rows, Cols>& src);
56         Matrix<T, Rows, Cols>&                  operator*=                      (const Matrix<T, Rows, Cols>& src);
57
58         void                                                    setRow                          (int rowNdx, const Vector<T, Cols>& vec);
59         void                                                    setColumn                       (int colNdx, const Vector<T, Rows>& vec);
60
61         Vector<T, Cols>                                 getRow                          (int ndx) const;
62         Vector<T, Rows>&                                getColumn                       (int ndx);
63         const Vector<T, Rows>&                  getColumn                       (int ndx) const;
64
65         Vector<T, Rows>&                                operator[]                      (int ndx)                                       { return getColumn(ndx);        }
66         const Vector<T, Rows>&                  operator[]                      (int ndx) const                         { return getColumn(ndx);        }
67
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];      }
70
71         Array<T, Rows*Cols>                             getRowMajorData         (void) const;
72         Array<T, Rows*Cols>                             getColumnMajorData      (void) const;
73
74 private:
75         Vector<Vector<T, Rows>, Cols>   m_data;
76 } DE_WARN_UNUSED_TYPE;
77
78 // Operators.
79
80 // Mat * Mat.
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);
83
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);
87
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);
91
92 // Further operations
93
94 template <typename T, int Size>
95 struct SquareMatrixOps
96 {
97         static T                                                doDeterminant   (const Matrix<T, Size, Size>& mat);
98         static Matrix<T, Size, Size>    doInverse               (const Matrix<T, Size, Size>& mat);
99 };
100
101 template <typename T>
102 struct SquareMatrixOps<T, 2>
103 {
104         static T                                                doDeterminant   (const Matrix<T, 2, 2>& mat);
105         static Matrix<T, 2, 2>                  doInverse               (const Matrix<T, 2, 2>& mat);
106 };
107
108 template <typename T>
109 struct SquareMatrixOps<T, 3>
110 {
111         static T                                                doDeterminant   (const Matrix<T, 3, 3>& mat);
112         static Matrix<T, 3, 3>                  doInverse               (const Matrix<T, 3, 3>& mat);
113 };
114
115 template <typename T>
116 struct SquareMatrixOps<T, 4>
117 {
118         static T                                                doDeterminant   (const Matrix<T, 4, 4>& mat);
119         static Matrix<T, 4, 4>                  doInverse               (const Matrix<T, 4, 4>& mat);
120 };
121
122 namespace matrix
123 {
124
125 template <typename T, int Size>
126 T determinant (const Matrix<T, Size, Size>& mat)
127 {
128         return SquareMatrixOps<T, Size>::doDeterminant(mat);
129 }
130
131 template <typename T, int Size>
132 Matrix<T, Size, Size> inverse (const Matrix<T, Size, Size>& mat)
133 {
134         return SquareMatrixOps<T, Size>::doInverse(mat);
135 }
136
137 } // matrix
138
139 // Template implementations.
140
141 template <typename T>
142 T SquareMatrixOps<T, 2>::doDeterminant (const Matrix<T, 2, 2>& mat)
143 {
144         return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1);
145 }
146
147 template <typename T>
148 T SquareMatrixOps<T, 3>::doDeterminant (const Matrix<T, 3, 3>& mat)
149 {
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);
156 }
157
158 template <typename T>
159 T SquareMatrixOps<T, 4>::doDeterminant (const Matrix<T, 4, 4>& mat)
160 {
161         using matrix::determinant;
162
163         const T minorMatrices[4][3*3] =
164         {
165                 {
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),
169                 },
170                 {
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),
174                 },
175                 {
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),
179                 },
180                 {
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),
184                 }
185         };
186
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]));
191 }
192
193 template <typename T>
194 Matrix<T, 2, 2> SquareMatrixOps<T, 2>::doInverse (const Matrix<T, 2, 2>& mat)
195 {
196         using matrix::determinant;
197
198         const T                 det             = determinant(mat);
199         Matrix<T, 2, 2> retVal;
200
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;
205
206         return retVal;
207 }
208
209 template <typename T>
210 Matrix<T, 3, 3> SquareMatrixOps<T, 3>::doInverse (const Matrix<T, 3, 3>& mat)
211 {
212         // Blockwise inversion
213         using matrix::inverse;
214
215         const T areaA[2*2] =
216         {
217                 mat(0,0),       mat(0,1),
218                 mat(1,0),       mat(1,1)
219         };
220         const T areaB[2] =
221         {
222                 mat(0,2),
223                 mat(1,2),
224         };
225         const T areaC[2] =
226         {
227                 mat(2,0),       mat(2,1),
228         };
229         const T areaD[1] =
230         {
231                 mat(2,2)
232         };
233         const T nullField[4] = { T(0.0f) };
234
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);
239
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);
242
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;
247
248         const T result[3*3] =
249         {
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,
253         };
254
255         return Matrix<T, 3, 3>(result);
256 }
257
258 template <typename T>
259 Matrix<T, 4, 4> SquareMatrixOps<T, 4>::doInverse (const Matrix<T, 4, 4>& mat)
260 {
261         // Blockwise inversion
262         using matrix::inverse;
263
264         const T areaA[2*2] =
265         {
266                 mat(0,0),       mat(0,1),
267                 mat(1,0),       mat(1,1)
268         };
269         const T areaB[2*2] =
270         {
271                 mat(0,2),       mat(0,3),
272                 mat(1,2),       mat(1,3)
273         };
274         const T areaC[2*2] =
275         {
276                 mat(2,0),       mat(2,1),
277                 mat(3,0),       mat(3,1)
278         };
279         const T areaD[2*2] =
280         {
281                 mat(2,2),       mat(2,3),
282                 mat(3,2),       mat(3,3)
283         };
284         const T nullField[4] = { T(0.0f) };
285
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);
290
291         const Matrix<T, 2, 2> schurComplement = inverse(matD - matC*invA*matB);
292         const Matrix<T, 2, 2> zeroMat         = Matrix<T, 2, 2>(nullField);
293
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;
298
299         const T result[4*4] =
300         {
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),
305         };
306
307         return Matrix<T, 4, 4>(result);
308 }
309
310 // Initialize to identity.
311 template <typename T, int Rows, int Cols>
312 Matrix<T, Rows, Cols>::Matrix (void)
313 {
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);
317 }
318
319 // Initialize to diagonal matrix.
320 template <typename T, int Rows, int Cols>
321 Matrix<T, Rows, Cols>::Matrix (const T& src)
322 {
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);
326 }
327
328 // Initialize from data array.
329 template <typename T, int Rows, int Cols>
330 Matrix<T, Rows, Cols>::Matrix (const T src[Rows*Cols])
331 {
332         for (int row = 0; row < Rows; row++)
333                 for (int col = 0; col < Cols; col++)
334                         (*this)(row, col) = src[row*Cols + col];
335 }
336
337 // Initialize to diagonal matrix.
338 template <typename T, int Rows, int Cols>
339 Matrix<T, Rows, Cols>::Matrix (const Vector<T, Rows>& src)
340 {
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);
345 }
346
347 // Copy constructor.
348 template <typename T, int Rows, int Cols>
349 Matrix<T, Rows, Cols>::Matrix (const Matrix<T, Rows, Cols>& src)
350 {
351         *this = src;
352 }
353
354 // Destructor.
355 template <typename T, int Rows, int Cols>
356 Matrix<T, Rows, Cols>::~Matrix (void)
357 {
358 }
359
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)
363 {
364         for (int row = 0; row < Rows; row++)
365                 for (int col = 0; col < Cols; col++)
366                         (*this)(row, col) = src(row, col);
367         return *this;
368 }
369
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)
373 {
374         *this = *this * src;
375         return *this;
376 }
377
378 template <typename T, int Rows, int Cols>
379 void Matrix<T, Rows, Cols>::setRow (int rowNdx, const Vector<T, Cols>& vec)
380 {
381         for (int col = 0; col < Cols; col++)
382                 (*this)(rowNdx, col) = vec.m_data[col];
383 }
384
385 template <typename T, int Rows, int Cols>
386 void Matrix<T, Rows, Cols>::setColumn (int colNdx, const Vector<T, Rows>& vec)
387 {
388         m_data[colNdx] = vec;
389 }
390
391 template <typename T, int Rows, int Cols>
392 Vector<T, Cols> Matrix<T, Rows, Cols>::getRow (int rowNdx) const
393 {
394         Vector<T, Cols> res;
395         for (int col = 0; col < Cols; col++)
396                 res[col] = (*this)(rowNdx, col);
397         return res;
398 }
399
400 template <typename T, int Rows, int Cols>
401 Vector<T, Rows>& Matrix<T, Rows, Cols>::getColumn (int colNdx)
402 {
403         return m_data[colNdx];
404 }
405
406 template <typename T, int Rows, int Cols>
407 const Vector<T, Rows>& Matrix<T, Rows, Cols>::getColumn (int colNdx) const
408 {
409         return m_data[colNdx];
410 }
411
412 template <typename T, int Rows, int Cols>
413 Array<T, Rows*Cols> Matrix<T, Rows, Cols>::getColumnMajorData (void) const
414 {
415         Array<T, Rows*Cols> a;
416         T* dst = a.getPtr();
417         for (int col = 0; col < Cols; col++)
418                 for (int row = 0; row < Rows; row++)
419                         *dst++ = (*this)(row, col);
420         return a;
421 }
422
423 template <typename T, int Rows, int Cols>
424 Array<T, Rows*Cols> Matrix<T, Rows, Cols>::getRowMajorData (void) const
425 {
426         Array<T, Rows*Cols> a;
427         T* dst = a.getPtr();
428         for (int row = 0; row < Rows; row++)
429                 for (int col = 0; col < Cols; col++)
430                         *dst++ = (*this)(row, col);
431         return a;
432 }
433
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)
437 {
438         DE_STATIC_ASSERT(Cols0 == Rows1);
439         Matrix<T, Rows0, Cols1> res;
440         for (int row = 0; row < Rows0; row++)
441         {
442                 for (int col = 0; col < Cols1; col++)
443                 {
444                         T v = T(0);
445                         for (int ndx = 0; ndx < Cols0; ndx++)
446                                 v += a(row,ndx) * b(ndx,col);
447                         res(row,col) = v;
448                 }
449         }
450         return res;
451 }
452
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)
456 {
457         Vector<T, Rows> res;
458         for (int row = 0; row < Rows; row++)
459         {
460                 T v = T(0);
461                 for (int col = 0; col < Cols; col++)
462                         v += mtx(row,col) * vec.m_data[col];
463                 res.m_data[row] = v;
464         }
465         return res;
466 }
467
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)
471 {
472         Vector<T, Cols> res;
473         for (int col = 0; col < Cols; col++)
474         {
475                 T v = T(0);
476                 for (int row = 0; row < Rows; row++)
477                         v += mtx(row,col) * vec.m_data[row];
478                 res.m_data[col] = v;
479         }
480         return res;
481 }
482
483 // Common typedefs.
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;
490
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;
501
502 // Matrix-scalar operators.
503
504 template <typename T, int Rows, int Cols>
505 Matrix<T, Rows, Cols> operator+ (const Matrix<T, Rows, Cols>& mtx, T scalar)
506 {
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;
511         return res;
512 }
513
514 template <typename T, int Rows, int Cols>
515 Matrix<T, Rows, Cols> operator- (const Matrix<T, Rows, Cols>& mtx, T scalar)
516 {
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;
521         return res;
522 }
523
524 template <typename T, int Rows, int Cols>
525 Matrix<T, Rows, Cols> operator* (const Matrix<T, Rows, Cols>& mtx, T scalar)
526 {
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;
531         return res;
532 }
533
534 template <typename T, int Rows, int Cols>
535 Matrix<T, Rows, Cols> operator/ (const Matrix<T, Rows, Cols>& mtx, T scalar)
536 {
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;
541         return res;
542 }
543
544 // Matrix-matrix component-wise operators.
545
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)
548 {
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);
553         return res;
554 }
555
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)
558 {
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);
563         return res;
564 }
565
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)
568 {
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);
573         return res;
574 }
575
576 } // tcu
577
578 #endif // _TCUMATRIX_HPP