1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // Matrix:
7*8975f5c5SAndroid Build Coastguard Worker // Utility class implementing various matrix operations.
8*8975f5c5SAndroid Build Coastguard Worker // Supports matrices with minimum 2 and maximum 4 number of rows/columns.
9*8975f5c5SAndroid Build Coastguard Worker //
10*8975f5c5SAndroid Build Coastguard Worker // TODO: Check if we can merge Matrix.h in sample_util with this and replace it with this
11*8975f5c5SAndroid Build Coastguard Worker // implementation.
12*8975f5c5SAndroid Build Coastguard Worker // TODO: Rename this file to Matrix.h once we remove Matrix.h in sample_util.
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard Worker #ifndef COMMON_MATRIX_UTILS_H_
15*8975f5c5SAndroid Build Coastguard Worker #define COMMON_MATRIX_UTILS_H_
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Worker #include <array>
18*8975f5c5SAndroid Build Coastguard Worker #include <vector>
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "common/vector_utils.h"
23*8975f5c5SAndroid Build Coastguard Worker
24*8975f5c5SAndroid Build Coastguard Worker namespace
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker template <typename T4x4>
CofactorTransposed(const T4x4 & mat,T4x4 & coft)27*8975f5c5SAndroid Build Coastguard Worker void CofactorTransposed(const T4x4 &mat, T4x4 &coft)
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker coft(0, 0) = mat(1, 1) * mat(2, 2) * mat(3, 3) + mat(2, 1) * mat(3, 2) * mat(1, 3) +
30*8975f5c5SAndroid Build Coastguard Worker mat(3, 1) * mat(1, 2) * mat(2, 3) - mat(1, 1) * mat(3, 2) * mat(2, 3) -
31*8975f5c5SAndroid Build Coastguard Worker mat(2, 1) * mat(1, 2) * mat(3, 3) - mat(3, 1) * mat(2, 2) * mat(1, 3);
32*8975f5c5SAndroid Build Coastguard Worker coft(1, 0) = -(mat(1, 0) * mat(2, 2) * mat(3, 3) + mat(2, 0) * mat(3, 2) * mat(1, 3) +
33*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(1, 2) * mat(2, 3) - mat(1, 0) * mat(3, 2) * mat(2, 3) -
34*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(1, 2) * mat(3, 3) - mat(3, 0) * mat(2, 2) * mat(1, 3));
35*8975f5c5SAndroid Build Coastguard Worker coft(2, 0) = mat(1, 0) * mat(2, 1) * mat(3, 3) + mat(2, 0) * mat(3, 1) * mat(1, 3) +
36*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(1, 1) * mat(2, 3) - mat(1, 0) * mat(3, 1) * mat(2, 3) -
37*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(1, 1) * mat(3, 3) - mat(3, 0) * mat(2, 1) * mat(1, 3);
38*8975f5c5SAndroid Build Coastguard Worker coft(3, 0) = -(mat(1, 0) * mat(2, 1) * mat(3, 2) + mat(2, 0) * mat(3, 1) * mat(1, 2) +
39*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(1, 1) * mat(2, 2) - mat(1, 0) * mat(3, 1) * mat(2, 2) -
40*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(1, 1) * mat(3, 2) - mat(3, 0) * mat(2, 1) * mat(1, 2));
41*8975f5c5SAndroid Build Coastguard Worker coft(0, 1) = -(mat(0, 1) * mat(2, 2) * mat(3, 3) + mat(2, 1) * mat(3, 2) * mat(0, 3) +
42*8975f5c5SAndroid Build Coastguard Worker mat(3, 1) * mat(0, 2) * mat(2, 3) - mat(0, 1) * mat(3, 2) * mat(2, 3) -
43*8975f5c5SAndroid Build Coastguard Worker mat(2, 1) * mat(0, 2) * mat(3, 3) - mat(3, 1) * mat(2, 2) * mat(0, 3));
44*8975f5c5SAndroid Build Coastguard Worker coft(1, 1) = mat(0, 0) * mat(2, 2) * mat(3, 3) + mat(2, 0) * mat(3, 2) * mat(0, 3) +
45*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(0, 2) * mat(2, 3) - mat(0, 0) * mat(3, 2) * mat(2, 3) -
46*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(0, 2) * mat(3, 3) - mat(3, 0) * mat(2, 2) * mat(0, 3);
47*8975f5c5SAndroid Build Coastguard Worker coft(2, 1) = -(mat(0, 0) * mat(2, 1) * mat(3, 3) + mat(2, 0) * mat(3, 1) * mat(0, 3) +
48*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(0, 1) * mat(2, 3) - mat(0, 0) * mat(3, 1) * mat(2, 3) -
49*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(0, 1) * mat(3, 3) - mat(3, 0) * mat(2, 1) * mat(0, 3));
50*8975f5c5SAndroid Build Coastguard Worker coft(3, 1) = mat(0, 0) * mat(2, 1) * mat(3, 2) + mat(2, 0) * mat(3, 1) * mat(0, 2) +
51*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(0, 1) * mat(2, 2) - mat(0, 0) * mat(3, 1) * mat(2, 2) -
52*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(0, 1) * mat(3, 2) - mat(3, 0) * mat(2, 1) * mat(0, 2);
53*8975f5c5SAndroid Build Coastguard Worker coft(0, 2) = mat(0, 1) * mat(1, 2) * mat(3, 3) + mat(1, 1) * mat(3, 2) * mat(0, 3) +
54*8975f5c5SAndroid Build Coastguard Worker mat(3, 1) * mat(0, 2) * mat(1, 3) - mat(0, 1) * mat(3, 2) * mat(1, 3) -
55*8975f5c5SAndroid Build Coastguard Worker mat(1, 1) * mat(0, 2) * mat(3, 3) - mat(3, 1) * mat(1, 2) * mat(0, 3);
56*8975f5c5SAndroid Build Coastguard Worker coft(1, 2) = -(mat(0, 0) * mat(1, 2) * mat(3, 3) + mat(1, 0) * mat(3, 2) * mat(0, 3) +
57*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(0, 2) * mat(1, 3) - mat(0, 0) * mat(3, 2) * mat(1, 3) -
58*8975f5c5SAndroid Build Coastguard Worker mat(1, 0) * mat(0, 2) * mat(3, 3) - mat(3, 0) * mat(1, 2) * mat(0, 3));
59*8975f5c5SAndroid Build Coastguard Worker coft(2, 2) = mat(0, 0) * mat(1, 1) * mat(3, 3) + mat(1, 0) * mat(3, 1) * mat(0, 3) +
60*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(0, 1) * mat(1, 3) - mat(0, 0) * mat(3, 1) * mat(1, 3) -
61*8975f5c5SAndroid Build Coastguard Worker mat(1, 0) * mat(0, 1) * mat(3, 3) - mat(3, 0) * mat(1, 1) * mat(0, 3);
62*8975f5c5SAndroid Build Coastguard Worker coft(3, 2) = -(mat(0, 0) * mat(1, 1) * mat(3, 2) + mat(1, 0) * mat(3, 1) * mat(0, 2) +
63*8975f5c5SAndroid Build Coastguard Worker mat(3, 0) * mat(0, 1) * mat(1, 2) - mat(0, 0) * mat(3, 1) * mat(1, 2) -
64*8975f5c5SAndroid Build Coastguard Worker mat(1, 0) * mat(0, 1) * mat(3, 2) - mat(3, 0) * mat(1, 1) * mat(0, 2));
65*8975f5c5SAndroid Build Coastguard Worker coft(0, 3) = -(mat(0, 1) * mat(1, 2) * mat(2, 3) + mat(1, 1) * mat(2, 2) * mat(0, 3) +
66*8975f5c5SAndroid Build Coastguard Worker mat(2, 1) * mat(0, 2) * mat(1, 3) - mat(0, 1) * mat(2, 2) * mat(1, 3) -
67*8975f5c5SAndroid Build Coastguard Worker mat(1, 1) * mat(0, 2) * mat(2, 3) - mat(2, 1) * mat(1, 2) * mat(0, 3));
68*8975f5c5SAndroid Build Coastguard Worker coft(1, 3) = mat(0, 0) * mat(1, 2) * mat(2, 3) + mat(1, 0) * mat(2, 2) * mat(0, 3) +
69*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(0, 2) * mat(1, 3) - mat(0, 0) * mat(2, 2) * mat(1, 3) -
70*8975f5c5SAndroid Build Coastguard Worker mat(1, 0) * mat(0, 2) * mat(2, 3) - mat(2, 0) * mat(1, 2) * mat(0, 3);
71*8975f5c5SAndroid Build Coastguard Worker coft(2, 3) = -(mat(0, 0) * mat(1, 1) * mat(2, 3) + mat(1, 0) * mat(2, 1) * mat(0, 3) +
72*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(0, 1) * mat(1, 3) - mat(0, 0) * mat(2, 1) * mat(1, 3) -
73*8975f5c5SAndroid Build Coastguard Worker mat(1, 0) * mat(0, 1) * mat(2, 3) - mat(2, 0) * mat(1, 1) * mat(0, 3));
74*8975f5c5SAndroid Build Coastguard Worker coft(3, 3) = mat(0, 0) * mat(1, 1) * mat(2, 2) + mat(1, 0) * mat(2, 1) * mat(0, 2) +
75*8975f5c5SAndroid Build Coastguard Worker mat(2, 0) * mat(0, 1) * mat(1, 2) - mat(0, 0) * mat(2, 1) * mat(1, 2) -
76*8975f5c5SAndroid Build Coastguard Worker mat(1, 0) * mat(0, 1) * mat(2, 2) - mat(2, 0) * mat(1, 1) * mat(0, 2);
77*8975f5c5SAndroid Build Coastguard Worker }
78*8975f5c5SAndroid Build Coastguard Worker } // namespace
79*8975f5c5SAndroid Build Coastguard Worker
80*8975f5c5SAndroid Build Coastguard Worker namespace angle
81*8975f5c5SAndroid Build Coastguard Worker {
82*8975f5c5SAndroid Build Coastguard Worker
83*8975f5c5SAndroid Build Coastguard Worker template <typename T>
84*8975f5c5SAndroid Build Coastguard Worker class Matrix
85*8975f5c5SAndroid Build Coastguard Worker {
86*8975f5c5SAndroid Build Coastguard Worker public:
Matrix(const std::vector<T> & elements,const unsigned int numRows,const unsigned int numCols)87*8975f5c5SAndroid Build Coastguard Worker Matrix(const std::vector<T> &elements, const unsigned int numRows, const unsigned int numCols)
88*8975f5c5SAndroid Build Coastguard Worker : mElements(elements), mRows(numRows), mCols(numCols)
89*8975f5c5SAndroid Build Coastguard Worker {
90*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() >= 1 && rows() <= 4);
91*8975f5c5SAndroid Build Coastguard Worker ASSERT(columns() >= 1 && columns() <= 4);
92*8975f5c5SAndroid Build Coastguard Worker }
93*8975f5c5SAndroid Build Coastguard Worker
Matrix(const std::vector<T> & elements,const unsigned int size)94*8975f5c5SAndroid Build Coastguard Worker Matrix(const std::vector<T> &elements, const unsigned int size)
95*8975f5c5SAndroid Build Coastguard Worker : mElements(elements), mRows(size), mCols(size)
96*8975f5c5SAndroid Build Coastguard Worker {
97*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() >= 1 && rows() <= 4);
98*8975f5c5SAndroid Build Coastguard Worker ASSERT(columns() >= 1 && columns() <= 4);
99*8975f5c5SAndroid Build Coastguard Worker }
100*8975f5c5SAndroid Build Coastguard Worker
Matrix(const T * elements,const unsigned int size)101*8975f5c5SAndroid Build Coastguard Worker Matrix(const T *elements, const unsigned int size) : mRows(size), mCols(size)
102*8975f5c5SAndroid Build Coastguard Worker {
103*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() >= 1 && rows() <= 4);
104*8975f5c5SAndroid Build Coastguard Worker ASSERT(columns() >= 1 && columns() <= 4);
105*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < size * size; i++)
106*8975f5c5SAndroid Build Coastguard Worker mElements.push_back(elements[i]);
107*8975f5c5SAndroid Build Coastguard Worker }
108*8975f5c5SAndroid Build Coastguard Worker
operator()109*8975f5c5SAndroid Build Coastguard Worker const T &operator()(const unsigned int rowIndex, const unsigned int columnIndex) const
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker ASSERT(rowIndex < mRows);
112*8975f5c5SAndroid Build Coastguard Worker ASSERT(columnIndex < mCols);
113*8975f5c5SAndroid Build Coastguard Worker return mElements[rowIndex * columns() + columnIndex];
114*8975f5c5SAndroid Build Coastguard Worker }
115*8975f5c5SAndroid Build Coastguard Worker
operator()116*8975f5c5SAndroid Build Coastguard Worker T &operator()(const unsigned int rowIndex, const unsigned int columnIndex)
117*8975f5c5SAndroid Build Coastguard Worker {
118*8975f5c5SAndroid Build Coastguard Worker ASSERT(rowIndex < mRows);
119*8975f5c5SAndroid Build Coastguard Worker ASSERT(columnIndex < mCols);
120*8975f5c5SAndroid Build Coastguard Worker return mElements[rowIndex * columns() + columnIndex];
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker
at(const unsigned int rowIndex,const unsigned int columnIndex)123*8975f5c5SAndroid Build Coastguard Worker const T &at(const unsigned int rowIndex, const unsigned int columnIndex) const
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker ASSERT(rowIndex < mRows);
126*8975f5c5SAndroid Build Coastguard Worker ASSERT(columnIndex < mCols);
127*8975f5c5SAndroid Build Coastguard Worker return operator()(rowIndex, columnIndex);
128*8975f5c5SAndroid Build Coastguard Worker }
129*8975f5c5SAndroid Build Coastguard Worker
130*8975f5c5SAndroid Build Coastguard Worker Matrix<T> operator*(const Matrix<T> &m)
131*8975f5c5SAndroid Build Coastguard Worker {
132*8975f5c5SAndroid Build Coastguard Worker ASSERT(columns() == m.rows());
133*8975f5c5SAndroid Build Coastguard Worker
134*8975f5c5SAndroid Build Coastguard Worker unsigned int resultRows = rows();
135*8975f5c5SAndroid Build Coastguard Worker unsigned int resultCols = m.columns();
136*8975f5c5SAndroid Build Coastguard Worker Matrix<T> result(std::vector<T>(resultRows * resultCols), resultRows, resultCols);
137*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < resultRows; i++)
138*8975f5c5SAndroid Build Coastguard Worker {
139*8975f5c5SAndroid Build Coastguard Worker for (unsigned int j = 0; j < resultCols; j++)
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker T tmp = 0.0f;
142*8975f5c5SAndroid Build Coastguard Worker for (unsigned int k = 0; k < columns(); k++)
143*8975f5c5SAndroid Build Coastguard Worker tmp += at(i, k) * m(k, j);
144*8975f5c5SAndroid Build Coastguard Worker result(i, j) = tmp;
145*8975f5c5SAndroid Build Coastguard Worker }
146*8975f5c5SAndroid Build Coastguard Worker }
147*8975f5c5SAndroid Build Coastguard Worker
148*8975f5c5SAndroid Build Coastguard Worker return result;
149*8975f5c5SAndroid Build Coastguard Worker }
150*8975f5c5SAndroid Build Coastguard Worker
151*8975f5c5SAndroid Build Coastguard Worker void operator*=(const Matrix<T> &m)
152*8975f5c5SAndroid Build Coastguard Worker {
153*8975f5c5SAndroid Build Coastguard Worker ASSERT(columns() == m.rows());
154*8975f5c5SAndroid Build Coastguard Worker Matrix<T> res = (*this) * m;
155*8975f5c5SAndroid Build Coastguard Worker size_t numElts = res.elements().size();
156*8975f5c5SAndroid Build Coastguard Worker mElements.resize(numElts);
157*8975f5c5SAndroid Build Coastguard Worker memcpy(mElements.data(), res.data(), numElts * sizeof(float));
158*8975f5c5SAndroid Build Coastguard Worker }
159*8975f5c5SAndroid Build Coastguard Worker
160*8975f5c5SAndroid Build Coastguard Worker bool operator==(const Matrix<T> &m) const
161*8975f5c5SAndroid Build Coastguard Worker {
162*8975f5c5SAndroid Build Coastguard Worker ASSERT(columns() == m.columns());
163*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() == m.rows());
164*8975f5c5SAndroid Build Coastguard Worker return mElements == m.elements();
165*8975f5c5SAndroid Build Coastguard Worker }
166*8975f5c5SAndroid Build Coastguard Worker
167*8975f5c5SAndroid Build Coastguard Worker bool operator!=(const Matrix<T> &m) const { return !(mElements == m.elements()); }
168*8975f5c5SAndroid Build Coastguard Worker
nearlyEqual(T epsilon,const Matrix<T> & m)169*8975f5c5SAndroid Build Coastguard Worker bool nearlyEqual(T epsilon, const Matrix<T> &m) const
170*8975f5c5SAndroid Build Coastguard Worker {
171*8975f5c5SAndroid Build Coastguard Worker ASSERT(columns() == m.columns());
172*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() == m.rows());
173*8975f5c5SAndroid Build Coastguard Worker const auto &otherElts = m.elements();
174*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < otherElts.size(); i++)
175*8975f5c5SAndroid Build Coastguard Worker {
176*8975f5c5SAndroid Build Coastguard Worker if ((mElements[i] - otherElts[i] > epsilon) && (otherElts[i] - mElements[i] > epsilon))
177*8975f5c5SAndroid Build Coastguard Worker return false;
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker return true;
180*8975f5c5SAndroid Build Coastguard Worker }
181*8975f5c5SAndroid Build Coastguard Worker
size()182*8975f5c5SAndroid Build Coastguard Worker unsigned int size() const
183*8975f5c5SAndroid Build Coastguard Worker {
184*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() == columns());
185*8975f5c5SAndroid Build Coastguard Worker return rows();
186*8975f5c5SAndroid Build Coastguard Worker }
187*8975f5c5SAndroid Build Coastguard Worker
rows()188*8975f5c5SAndroid Build Coastguard Worker unsigned int rows() const { return mRows; }
189*8975f5c5SAndroid Build Coastguard Worker
columns()190*8975f5c5SAndroid Build Coastguard Worker unsigned int columns() const { return mCols; }
191*8975f5c5SAndroid Build Coastguard Worker
elements()192*8975f5c5SAndroid Build Coastguard Worker std::vector<T> elements() const { return mElements; }
data()193*8975f5c5SAndroid Build Coastguard Worker T *data() { return mElements.data(); }
constData()194*8975f5c5SAndroid Build Coastguard Worker const T *constData() const { return mElements.data(); }
195*8975f5c5SAndroid Build Coastguard Worker
compMult(const Matrix<T> & mat1)196*8975f5c5SAndroid Build Coastguard Worker Matrix<T> compMult(const Matrix<T> &mat1) const
197*8975f5c5SAndroid Build Coastguard Worker {
198*8975f5c5SAndroid Build Coastguard Worker Matrix result(std::vector<T>(mElements.size()), rows(), columns());
199*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < rows(); i++)
200*8975f5c5SAndroid Build Coastguard Worker {
201*8975f5c5SAndroid Build Coastguard Worker for (unsigned int j = 0; j < columns(); j++)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker T lhs = at(i, j);
204*8975f5c5SAndroid Build Coastguard Worker T rhs = mat1(i, j);
205*8975f5c5SAndroid Build Coastguard Worker result(i, j) = rhs * lhs;
206*8975f5c5SAndroid Build Coastguard Worker }
207*8975f5c5SAndroid Build Coastguard Worker }
208*8975f5c5SAndroid Build Coastguard Worker
209*8975f5c5SAndroid Build Coastguard Worker return result;
210*8975f5c5SAndroid Build Coastguard Worker }
211*8975f5c5SAndroid Build Coastguard Worker
outerProduct(const Matrix<T> & mat1)212*8975f5c5SAndroid Build Coastguard Worker Matrix<T> outerProduct(const Matrix<T> &mat1) const
213*8975f5c5SAndroid Build Coastguard Worker {
214*8975f5c5SAndroid Build Coastguard Worker unsigned int cols = mat1.columns();
215*8975f5c5SAndroid Build Coastguard Worker Matrix result(std::vector<T>(rows() * cols), rows(), cols);
216*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < rows(); i++)
217*8975f5c5SAndroid Build Coastguard Worker for (unsigned int j = 0; j < cols; j++)
218*8975f5c5SAndroid Build Coastguard Worker result(i, j) = at(i, 0) * mat1(0, j);
219*8975f5c5SAndroid Build Coastguard Worker
220*8975f5c5SAndroid Build Coastguard Worker return result;
221*8975f5c5SAndroid Build Coastguard Worker }
222*8975f5c5SAndroid Build Coastguard Worker
transpose()223*8975f5c5SAndroid Build Coastguard Worker Matrix<T> transpose() const
224*8975f5c5SAndroid Build Coastguard Worker {
225*8975f5c5SAndroid Build Coastguard Worker Matrix result(std::vector<T>(mElements.size()), columns(), rows());
226*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < columns(); i++)
227*8975f5c5SAndroid Build Coastguard Worker for (unsigned int j = 0; j < rows(); j++)
228*8975f5c5SAndroid Build Coastguard Worker result(i, j) = at(j, i);
229*8975f5c5SAndroid Build Coastguard Worker
230*8975f5c5SAndroid Build Coastguard Worker return result;
231*8975f5c5SAndroid Build Coastguard Worker }
232*8975f5c5SAndroid Build Coastguard Worker
determinant()233*8975f5c5SAndroid Build Coastguard Worker T determinant() const
234*8975f5c5SAndroid Build Coastguard Worker {
235*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() == columns());
236*8975f5c5SAndroid Build Coastguard Worker
237*8975f5c5SAndroid Build Coastguard Worker switch (size())
238*8975f5c5SAndroid Build Coastguard Worker {
239*8975f5c5SAndroid Build Coastguard Worker case 2:
240*8975f5c5SAndroid Build Coastguard Worker return at(0, 0) * at(1, 1) - at(0, 1) * at(1, 0);
241*8975f5c5SAndroid Build Coastguard Worker
242*8975f5c5SAndroid Build Coastguard Worker case 3:
243*8975f5c5SAndroid Build Coastguard Worker return at(0, 0) * at(1, 1) * at(2, 2) + at(0, 1) * at(1, 2) * at(2, 0) +
244*8975f5c5SAndroid Build Coastguard Worker at(0, 2) * at(1, 0) * at(2, 1) - at(0, 2) * at(1, 1) * at(2, 0) -
245*8975f5c5SAndroid Build Coastguard Worker at(0, 1) * at(1, 0) * at(2, 2) - at(0, 0) * at(1, 2) * at(2, 1);
246*8975f5c5SAndroid Build Coastguard Worker
247*8975f5c5SAndroid Build Coastguard Worker case 4:
248*8975f5c5SAndroid Build Coastguard Worker {
249*8975f5c5SAndroid Build Coastguard Worker const float minorMatrices[4][3 * 3] = {{
250*8975f5c5SAndroid Build Coastguard Worker at(1, 1),
251*8975f5c5SAndroid Build Coastguard Worker at(2, 1),
252*8975f5c5SAndroid Build Coastguard Worker at(3, 1),
253*8975f5c5SAndroid Build Coastguard Worker at(1, 2),
254*8975f5c5SAndroid Build Coastguard Worker at(2, 2),
255*8975f5c5SAndroid Build Coastguard Worker at(3, 2),
256*8975f5c5SAndroid Build Coastguard Worker at(1, 3),
257*8975f5c5SAndroid Build Coastguard Worker at(2, 3),
258*8975f5c5SAndroid Build Coastguard Worker at(3, 3),
259*8975f5c5SAndroid Build Coastguard Worker },
260*8975f5c5SAndroid Build Coastguard Worker {
261*8975f5c5SAndroid Build Coastguard Worker at(1, 0),
262*8975f5c5SAndroid Build Coastguard Worker at(2, 0),
263*8975f5c5SAndroid Build Coastguard Worker at(3, 0),
264*8975f5c5SAndroid Build Coastguard Worker at(1, 2),
265*8975f5c5SAndroid Build Coastguard Worker at(2, 2),
266*8975f5c5SAndroid Build Coastguard Worker at(3, 2),
267*8975f5c5SAndroid Build Coastguard Worker at(1, 3),
268*8975f5c5SAndroid Build Coastguard Worker at(2, 3),
269*8975f5c5SAndroid Build Coastguard Worker at(3, 3),
270*8975f5c5SAndroid Build Coastguard Worker },
271*8975f5c5SAndroid Build Coastguard Worker {
272*8975f5c5SAndroid Build Coastguard Worker at(1, 0),
273*8975f5c5SAndroid Build Coastguard Worker at(2, 0),
274*8975f5c5SAndroid Build Coastguard Worker at(3, 0),
275*8975f5c5SAndroid Build Coastguard Worker at(1, 1),
276*8975f5c5SAndroid Build Coastguard Worker at(2, 1),
277*8975f5c5SAndroid Build Coastguard Worker at(3, 1),
278*8975f5c5SAndroid Build Coastguard Worker at(1, 3),
279*8975f5c5SAndroid Build Coastguard Worker at(2, 3),
280*8975f5c5SAndroid Build Coastguard Worker at(3, 3),
281*8975f5c5SAndroid Build Coastguard Worker },
282*8975f5c5SAndroid Build Coastguard Worker {
283*8975f5c5SAndroid Build Coastguard Worker at(1, 0),
284*8975f5c5SAndroid Build Coastguard Worker at(2, 0),
285*8975f5c5SAndroid Build Coastguard Worker at(3, 0),
286*8975f5c5SAndroid Build Coastguard Worker at(1, 1),
287*8975f5c5SAndroid Build Coastguard Worker at(2, 1),
288*8975f5c5SAndroid Build Coastguard Worker at(3, 1),
289*8975f5c5SAndroid Build Coastguard Worker at(1, 2),
290*8975f5c5SAndroid Build Coastguard Worker at(2, 2),
291*8975f5c5SAndroid Build Coastguard Worker at(3, 2),
292*8975f5c5SAndroid Build Coastguard Worker }};
293*8975f5c5SAndroid Build Coastguard Worker return at(0, 0) * Matrix<T>(minorMatrices[0], 3).determinant() -
294*8975f5c5SAndroid Build Coastguard Worker at(0, 1) * Matrix<T>(minorMatrices[1], 3).determinant() +
295*8975f5c5SAndroid Build Coastguard Worker at(0, 2) * Matrix<T>(minorMatrices[2], 3).determinant() -
296*8975f5c5SAndroid Build Coastguard Worker at(0, 3) * Matrix<T>(minorMatrices[3], 3).determinant();
297*8975f5c5SAndroid Build Coastguard Worker }
298*8975f5c5SAndroid Build Coastguard Worker
299*8975f5c5SAndroid Build Coastguard Worker default:
300*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
301*8975f5c5SAndroid Build Coastguard Worker break;
302*8975f5c5SAndroid Build Coastguard Worker }
303*8975f5c5SAndroid Build Coastguard Worker
304*8975f5c5SAndroid Build Coastguard Worker return T();
305*8975f5c5SAndroid Build Coastguard Worker }
306*8975f5c5SAndroid Build Coastguard Worker
inverse()307*8975f5c5SAndroid Build Coastguard Worker Matrix<T> inverse() const
308*8975f5c5SAndroid Build Coastguard Worker {
309*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() == columns());
310*8975f5c5SAndroid Build Coastguard Worker
311*8975f5c5SAndroid Build Coastguard Worker Matrix<T> coft(std::vector<T>(mElements.size()), rows(), columns());
312*8975f5c5SAndroid Build Coastguard Worker switch (size())
313*8975f5c5SAndroid Build Coastguard Worker {
314*8975f5c5SAndroid Build Coastguard Worker case 2:
315*8975f5c5SAndroid Build Coastguard Worker coft(0, 0) = at(1, 1);
316*8975f5c5SAndroid Build Coastguard Worker coft(1, 0) = -at(1, 0);
317*8975f5c5SAndroid Build Coastguard Worker coft(0, 1) = -at(0, 1);
318*8975f5c5SAndroid Build Coastguard Worker coft(1, 1) = at(0, 0);
319*8975f5c5SAndroid Build Coastguard Worker break;
320*8975f5c5SAndroid Build Coastguard Worker
321*8975f5c5SAndroid Build Coastguard Worker case 3:
322*8975f5c5SAndroid Build Coastguard Worker coft(0, 0) = at(1, 1) * at(2, 2) - at(2, 1) * at(1, 2);
323*8975f5c5SAndroid Build Coastguard Worker coft(1, 0) = -(at(1, 0) * at(2, 2) - at(2, 0) * at(1, 2));
324*8975f5c5SAndroid Build Coastguard Worker coft(2, 0) = at(1, 0) * at(2, 1) - at(2, 0) * at(1, 1);
325*8975f5c5SAndroid Build Coastguard Worker coft(0, 1) = -(at(0, 1) * at(2, 2) - at(2, 1) * at(0, 2));
326*8975f5c5SAndroid Build Coastguard Worker coft(1, 1) = at(0, 0) * at(2, 2) - at(2, 0) * at(0, 2);
327*8975f5c5SAndroid Build Coastguard Worker coft(2, 1) = -(at(0, 0) * at(2, 1) - at(2, 0) * at(0, 1));
328*8975f5c5SAndroid Build Coastguard Worker coft(0, 2) = at(0, 1) * at(1, 2) - at(1, 1) * at(0, 2);
329*8975f5c5SAndroid Build Coastguard Worker coft(1, 2) = -(at(0, 0) * at(1, 2) - at(1, 0) * at(0, 2));
330*8975f5c5SAndroid Build Coastguard Worker coft(2, 2) = at(0, 0) * at(1, 1) - at(1, 0) * at(0, 1);
331*8975f5c5SAndroid Build Coastguard Worker break;
332*8975f5c5SAndroid Build Coastguard Worker
333*8975f5c5SAndroid Build Coastguard Worker case 4:
334*8975f5c5SAndroid Build Coastguard Worker CofactorTransposed(*this, coft);
335*8975f5c5SAndroid Build Coastguard Worker break;
336*8975f5c5SAndroid Build Coastguard Worker
337*8975f5c5SAndroid Build Coastguard Worker default:
338*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
339*8975f5c5SAndroid Build Coastguard Worker break;
340*8975f5c5SAndroid Build Coastguard Worker }
341*8975f5c5SAndroid Build Coastguard Worker
342*8975f5c5SAndroid Build Coastguard Worker // The inverse of A is the transpose of the cofactor matrix times the reciprocal of the
343*8975f5c5SAndroid Build Coastguard Worker // determinant of A.
344*8975f5c5SAndroid Build Coastguard Worker T det = determinant();
345*8975f5c5SAndroid Build Coastguard Worker Matrix<T> result(std::vector<T>(mElements.size()), rows(), columns());
346*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < rows(); i++)
347*8975f5c5SAndroid Build Coastguard Worker for (unsigned int j = 0; j < columns(); j++)
348*8975f5c5SAndroid Build Coastguard Worker result(i, j) = (det != static_cast<T>(0)) ? coft(i, j) / det : T();
349*8975f5c5SAndroid Build Coastguard Worker
350*8975f5c5SAndroid Build Coastguard Worker return result;
351*8975f5c5SAndroid Build Coastguard Worker }
352*8975f5c5SAndroid Build Coastguard Worker
setToIdentity()353*8975f5c5SAndroid Build Coastguard Worker void setToIdentity()
354*8975f5c5SAndroid Build Coastguard Worker {
355*8975f5c5SAndroid Build Coastguard Worker ASSERT(rows() == columns());
356*8975f5c5SAndroid Build Coastguard Worker
357*8975f5c5SAndroid Build Coastguard Worker const auto one = T(1);
358*8975f5c5SAndroid Build Coastguard Worker const auto zero = T(0);
359*8975f5c5SAndroid Build Coastguard Worker
360*8975f5c5SAndroid Build Coastguard Worker for (auto &e : mElements)
361*8975f5c5SAndroid Build Coastguard Worker e = zero;
362*8975f5c5SAndroid Build Coastguard Worker
363*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < rows(); ++i)
364*8975f5c5SAndroid Build Coastguard Worker {
365*8975f5c5SAndroid Build Coastguard Worker const auto pos = i * columns() + (i % columns());
366*8975f5c5SAndroid Build Coastguard Worker mElements[pos] = one;
367*8975f5c5SAndroid Build Coastguard Worker }
368*8975f5c5SAndroid Build Coastguard Worker }
369*8975f5c5SAndroid Build Coastguard Worker
370*8975f5c5SAndroid Build Coastguard Worker template <unsigned int Size>
setToIdentity(T (& matrix)[Size])371*8975f5c5SAndroid Build Coastguard Worker static void setToIdentity(T (&matrix)[Size])
372*8975f5c5SAndroid Build Coastguard Worker {
373*8975f5c5SAndroid Build Coastguard Worker static_assert(gl::iSquareRoot<Size>() != 0, "Matrix is not square.");
374*8975f5c5SAndroid Build Coastguard Worker
375*8975f5c5SAndroid Build Coastguard Worker const auto cols = gl::iSquareRoot<Size>();
376*8975f5c5SAndroid Build Coastguard Worker const auto one = T(1);
377*8975f5c5SAndroid Build Coastguard Worker const auto zero = T(0);
378*8975f5c5SAndroid Build Coastguard Worker
379*8975f5c5SAndroid Build Coastguard Worker for (auto &e : matrix)
380*8975f5c5SAndroid Build Coastguard Worker e = zero;
381*8975f5c5SAndroid Build Coastguard Worker
382*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < cols; ++i)
383*8975f5c5SAndroid Build Coastguard Worker {
384*8975f5c5SAndroid Build Coastguard Worker const auto pos = i * cols + (i % cols);
385*8975f5c5SAndroid Build Coastguard Worker matrix[pos] = one;
386*8975f5c5SAndroid Build Coastguard Worker }
387*8975f5c5SAndroid Build Coastguard Worker }
388*8975f5c5SAndroid Build Coastguard Worker
389*8975f5c5SAndroid Build Coastguard Worker protected:
390*8975f5c5SAndroid Build Coastguard Worker std::vector<T> mElements;
391*8975f5c5SAndroid Build Coastguard Worker unsigned int mRows;
392*8975f5c5SAndroid Build Coastguard Worker unsigned int mCols;
393*8975f5c5SAndroid Build Coastguard Worker };
394*8975f5c5SAndroid Build Coastguard Worker
395*8975f5c5SAndroid Build Coastguard Worker // Not derived from Matrix<float>: fixed-size std::array instead, to avoid malloc
396*8975f5c5SAndroid Build Coastguard Worker class Mat4
397*8975f5c5SAndroid Build Coastguard Worker {
398*8975f5c5SAndroid Build Coastguard Worker public:
399*8975f5c5SAndroid Build Coastguard Worker Mat4();
400*8975f5c5SAndroid Build Coastguard Worker Mat4(const Matrix<float> generalMatrix);
401*8975f5c5SAndroid Build Coastguard Worker Mat4(const std::vector<float> &elements);
402*8975f5c5SAndroid Build Coastguard Worker Mat4(const float *elements);
403*8975f5c5SAndroid Build Coastguard Worker Mat4(float m00,
404*8975f5c5SAndroid Build Coastguard Worker float m01,
405*8975f5c5SAndroid Build Coastguard Worker float m02,
406*8975f5c5SAndroid Build Coastguard Worker float m03,
407*8975f5c5SAndroid Build Coastguard Worker float m10,
408*8975f5c5SAndroid Build Coastguard Worker float m11,
409*8975f5c5SAndroid Build Coastguard Worker float m12,
410*8975f5c5SAndroid Build Coastguard Worker float m13,
411*8975f5c5SAndroid Build Coastguard Worker float m20,
412*8975f5c5SAndroid Build Coastguard Worker float m21,
413*8975f5c5SAndroid Build Coastguard Worker float m22,
414*8975f5c5SAndroid Build Coastguard Worker float m23,
415*8975f5c5SAndroid Build Coastguard Worker float m30,
416*8975f5c5SAndroid Build Coastguard Worker float m31,
417*8975f5c5SAndroid Build Coastguard Worker float m32,
418*8975f5c5SAndroid Build Coastguard Worker float m33);
419*8975f5c5SAndroid Build Coastguard Worker
420*8975f5c5SAndroid Build Coastguard Worker static Mat4 Rotate(float angle, const Vector3 &axis);
421*8975f5c5SAndroid Build Coastguard Worker static Mat4 Translate(const Vector3 &t);
422*8975f5c5SAndroid Build Coastguard Worker static Mat4 Scale(const Vector3 &s);
423*8975f5c5SAndroid Build Coastguard Worker static Mat4 Frustum(float l, float r, float b, float t, float n, float f);
424*8975f5c5SAndroid Build Coastguard Worker static Mat4 Perspective(float fov, float aspectRatio, float n, float f);
425*8975f5c5SAndroid Build Coastguard Worker static Mat4 Ortho(float l, float r, float b, float t, float n, float f);
426*8975f5c5SAndroid Build Coastguard Worker
427*8975f5c5SAndroid Build Coastguard Worker Mat4 product(const Mat4 &m);
428*8975f5c5SAndroid Build Coastguard Worker Vector4 product(const Vector4 &b);
429*8975f5c5SAndroid Build Coastguard Worker void dump();
430*8975f5c5SAndroid Build Coastguard Worker
data()431*8975f5c5SAndroid Build Coastguard Worker float *data() { return mElements.data(); }
constData()432*8975f5c5SAndroid Build Coastguard Worker const float *constData() const { return mElements.data(); }
433*8975f5c5SAndroid Build Coastguard Worker
operator()434*8975f5c5SAndroid Build Coastguard Worker float operator()(const unsigned int rowIndex, const unsigned int columnIndex) const
435*8975f5c5SAndroid Build Coastguard Worker {
436*8975f5c5SAndroid Build Coastguard Worker ASSERT(rowIndex < 4);
437*8975f5c5SAndroid Build Coastguard Worker ASSERT(columnIndex < 4);
438*8975f5c5SAndroid Build Coastguard Worker return mElements[rowIndex * 4 + columnIndex];
439*8975f5c5SAndroid Build Coastguard Worker }
440*8975f5c5SAndroid Build Coastguard Worker
operator()441*8975f5c5SAndroid Build Coastguard Worker float &operator()(const unsigned int rowIndex, const unsigned int columnIndex)
442*8975f5c5SAndroid Build Coastguard Worker {
443*8975f5c5SAndroid Build Coastguard Worker ASSERT(rowIndex < 4);
444*8975f5c5SAndroid Build Coastguard Worker ASSERT(columnIndex < 4);
445*8975f5c5SAndroid Build Coastguard Worker return mElements[rowIndex * 4 + columnIndex];
446*8975f5c5SAndroid Build Coastguard Worker }
447*8975f5c5SAndroid Build Coastguard Worker
at(const unsigned int rowIndex,const unsigned int columnIndex)448*8975f5c5SAndroid Build Coastguard Worker float at(const unsigned int rowIndex, const unsigned int columnIndex) const
449*8975f5c5SAndroid Build Coastguard Worker {
450*8975f5c5SAndroid Build Coastguard Worker ASSERT(rowIndex < 4);
451*8975f5c5SAndroid Build Coastguard Worker ASSERT(columnIndex < 4);
452*8975f5c5SAndroid Build Coastguard Worker return operator()(rowIndex, columnIndex);
453*8975f5c5SAndroid Build Coastguard Worker }
454*8975f5c5SAndroid Build Coastguard Worker
455*8975f5c5SAndroid Build Coastguard Worker bool operator==(const Mat4 &m) const { return mElements == m.elements(); }
456*8975f5c5SAndroid Build Coastguard Worker
nearlyEqual(float epsilon,const Mat4 & m)457*8975f5c5SAndroid Build Coastguard Worker bool nearlyEqual(float epsilon, const Mat4 &m) const
458*8975f5c5SAndroid Build Coastguard Worker {
459*8975f5c5SAndroid Build Coastguard Worker const auto &otherElts = m.elements();
460*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < otherElts.size(); i++)
461*8975f5c5SAndroid Build Coastguard Worker {
462*8975f5c5SAndroid Build Coastguard Worker if ((mElements[i] - otherElts[i] > epsilon) && (otherElts[i] - mElements[i] > epsilon))
463*8975f5c5SAndroid Build Coastguard Worker return false;
464*8975f5c5SAndroid Build Coastguard Worker }
465*8975f5c5SAndroid Build Coastguard Worker return true;
466*8975f5c5SAndroid Build Coastguard Worker }
467*8975f5c5SAndroid Build Coastguard Worker
elements()468*8975f5c5SAndroid Build Coastguard Worker const std::array<float, 4 * 4> &elements() const { return mElements; }
469*8975f5c5SAndroid Build Coastguard Worker
transpose()470*8975f5c5SAndroid Build Coastguard Worker Mat4 transpose() const
471*8975f5c5SAndroid Build Coastguard Worker {
472*8975f5c5SAndroid Build Coastguard Worker Mat4 result;
473*8975f5c5SAndroid Build Coastguard Worker for (unsigned int i = 0; i < 4; i++)
474*8975f5c5SAndroid Build Coastguard Worker for (unsigned int j = 0; j < 4; j++)
475*8975f5c5SAndroid Build Coastguard Worker result(i, j) = at(j, i);
476*8975f5c5SAndroid Build Coastguard Worker
477*8975f5c5SAndroid Build Coastguard Worker return result;
478*8975f5c5SAndroid Build Coastguard Worker }
479*8975f5c5SAndroid Build Coastguard Worker
inverse()480*8975f5c5SAndroid Build Coastguard Worker Mat4 inverse() const
481*8975f5c5SAndroid Build Coastguard Worker {
482*8975f5c5SAndroid Build Coastguard Worker Mat4 coft;
483*8975f5c5SAndroid Build Coastguard Worker CofactorTransposed(*this, coft);
484*8975f5c5SAndroid Build Coastguard Worker
485*8975f5c5SAndroid Build Coastguard Worker float det = at(0, 0) * coft(0, 0) + at(0, 1) * coft(1, 0) + at(0, 2) * coft(2, 0) +
486*8975f5c5SAndroid Build Coastguard Worker at(0, 3) * coft(3, 0);
487*8975f5c5SAndroid Build Coastguard Worker
488*8975f5c5SAndroid Build Coastguard Worker Mat4 result = coft;
489*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < 16; i++)
490*8975f5c5SAndroid Build Coastguard Worker {
491*8975f5c5SAndroid Build Coastguard Worker result.data()[i] /= det;
492*8975f5c5SAndroid Build Coastguard Worker }
493*8975f5c5SAndroid Build Coastguard Worker
494*8975f5c5SAndroid Build Coastguard Worker return result;
495*8975f5c5SAndroid Build Coastguard Worker }
496*8975f5c5SAndroid Build Coastguard Worker
497*8975f5c5SAndroid Build Coastguard Worker private:
498*8975f5c5SAndroid Build Coastguard Worker std::array<float, 4 * 4> mElements;
499*8975f5c5SAndroid Build Coastguard Worker };
500*8975f5c5SAndroid Build Coastguard Worker
501*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
502*8975f5c5SAndroid Build Coastguard Worker
503*8975f5c5SAndroid Build Coastguard Worker #endif // COMMON_MATRIX_UTILS_H_
504