xref: /aosp_15_r20/external/angle/src/common/matrix_utils.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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