2 * Copyright 2013 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <ui/TMatHelpers.h>
23 #include <sys/types.h>
25 #define PURE __attribute__((pure))
28 // -------------------------------------------------------------------------------------
32 * A 2x2 column-major matrix class.
34 * Conceptually a 2x2 matrix is a an array of 2 column vec2:
48 * m[0][0] & m[1][0] \\
49 * m[0][1] & m[1][1] \\
63 * m[n] is the \f$ n^{th} \f$ column of the matrix and is a vec2.
67 class TMat22 : public TVecUnaryOperators<TMat22, T>,
68 public TVecComparisonOperators<TMat22, T>,
69 public TVecAddOperators<TMat22, T>,
70 public TMatProductOperators<TMat22, T>,
71 public TMatSquareFunctions<TMat22, T>,
72 public TMatHelpers<TMat22, T>,
73 public TMatDebug<TMat22, T> {
75 enum no_init { NO_INIT };
78 typedef T const& const_reference;
79 typedef size_t size_type;
80 typedef TVec2<T> col_type;
81 typedef TVec2<T> row_type;
83 static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows)
84 static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns)
85 static constexpr size_t NUM_ROWS = COL_SIZE;
86 static constexpr size_t NUM_COLS = ROW_SIZE;
92 * a[0][0] a[1][0] a[2][0] ... a[N][0] ^
93 * a[0][1] a[1][1] a[2][1] ... a[N][1] |
94 * a[0][2] a[1][2] a[2][2] ... a[N][2] M rows
96 * a[0][M] a[1][M] a[2][M] ... a[N][M] v
100 * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
103 col_type m_value[NUM_COLS];
107 inline constexpr col_type const& operator[](size_t column) const {
108 #if __cplusplus >= 201402L
109 // only possible in C++0x14 with constexpr
110 assert(column < NUM_COLS);
112 return m_value[column];
115 inline col_type& operator[](size_t column) {
116 assert(column < NUM_COLS);
117 return m_value[column];
120 // -----------------------------------------------------------------------
121 // we want the compiler generated versions for these...
122 TMat22(const TMat22&) = default;
124 TMat22& operator = (const TMat22&) = default;
131 * leaves object uninitialized. use with caution.
134 constexpr TMat22(no_init)
135 : m_value{ col_type(col_type::NO_INIT),
136 col_type(col_type::NO_INIT) } {}
140 * initialize to identity.
154 * initialize to Identity*scalar.
166 explicit TMat22(U v);
169 * sets the diagonal to a vector.
180 template <typename U>
181 explicit TMat22(const TVec2<U>& v);
184 * construct from another matrix of the same size
186 template <typename U>
187 explicit TMat22(const TMat22<U>& rhs);
190 * construct from 2 column vectors.
200 template <typename A, typename B>
201 TMat22(const TVec2<A>& v0, const TVec2<B>& v1);
203 /** construct from 4 elements in column-major form.
208 * m[0][0] & m[1][0] \\
209 * m[0][1] & m[1][1] \\
215 typename A, typename B,
216 typename C, typename D>
221 * construct from a C array in column major form.
223 template <typename U>
224 explicit TMat22(U const* rawArray);
227 * Rotate by radians in the 2D plane
229 static TMat22<T> rotate(T radian) {
230 TMat22<T> r(TMat22<T>::NO_INIT);
231 T c = std::cos(radian);
232 T s = std::sin(radian);
233 r[0][0] = c; r[1][1] = c;
234 r[0][1] = s; r[1][0] = -s;
239 // ----------------------------------------------------------------------------------------
241 // ----------------------------------------------------------------------------------------
243 // Since the matrix code could become pretty big quickly, we don't inline most
246 template <typename T>
247 TMat22<T>::TMat22() {
248 m_value[0] = col_type(1, 0);
249 m_value[1] = col_type(0, 1);
252 template <typename T>
253 template <typename U>
254 TMat22<T>::TMat22(U v) {
255 m_value[0] = col_type(v, 0);
256 m_value[1] = col_type(0, v);
261 TMat22<T>::TMat22(const TVec2<U>& v) {
262 m_value[0] = col_type(v.x, 0);
263 m_value[1] = col_type(0, v.y);
266 // construct from 4 scalars. Note that the arrangement
267 // of values in the constructor is the transpose of the matrix
271 typename A, typename B,
272 typename C, typename D>
273 TMat22<T>::TMat22(A m00, B m01,
275 m_value[0] = col_type(m00, m01);
276 m_value[1] = col_type(m10, m11);
279 template <typename T>
280 template <typename U>
281 TMat22<T>::TMat22(const TMat22<U>& rhs) {
282 for (size_t col = 0; col < NUM_COLS; ++col) {
283 m_value[col] = col_type(rhs[col]);
287 // Construct from 2 column vectors.
288 template <typename T>
289 template <typename A, typename B>
290 TMat22<T>::TMat22(const TVec2<A>& v0, const TVec2<B>& v1) {
295 // Construct from raw array, in column-major form.
296 template <typename T>
297 template <typename U>
298 TMat22<T>::TMat22(U const* rawArray) {
299 for (size_t col = 0; col < NUM_COLS; ++col) {
300 for (size_t row = 0; row < NUM_ROWS; ++row) {
301 m_value[col][row] = *rawArray++;
306 // ----------------------------------------------------------------------------------------
307 // Arithmetic operators outside of class
308 // ----------------------------------------------------------------------------------------
310 /* We use non-friend functions here to prevent the compiler from using
311 * implicit conversions, for instance of a scalar to a vector. The result would
312 * not be what the caller expects.
314 * Also note that the order of the arguments in the inner loop is important since
315 * it determines the output type (only relevant when T != U).
318 // matrix * column-vector, result is a vector of the same type than the input vector
319 template <typename T, typename U>
320 typename TMat22<U>::col_type PURE operator *(const TMat22<T>& lhs, const TVec2<U>& rhs) {
321 // Result is initialized to zero.
322 typename TMat22<U>::col_type result;
323 for (size_t col = 0; col < TMat22<T>::NUM_COLS; ++col) {
324 result += lhs[col] * rhs[col];
329 // row-vector * matrix, result is a vector of the same type than the input vector
330 template <typename T, typename U>
331 typename TMat22<U>::row_type PURE operator *(const TVec2<U>& lhs, const TMat22<T>& rhs) {
332 typename TMat22<U>::row_type result(TMat22<U>::row_type::NO_INIT);
333 for (size_t col = 0; col < TMat22<T>::NUM_COLS; ++col) {
334 result[col] = dot(lhs, rhs[col]);
339 // matrix * scalar, result is a matrix of the same type than the input matrix
340 template<typename T, typename U>
341 constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat22<T>>::type PURE
342 operator*(TMat22<T> lhs, U rhs) {
346 // scalar * matrix, result is a matrix of the same type than the input matrix
347 template<typename T, typename U>
348 constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat22<T>>::type PURE
349 operator*(U lhs, const TMat22<T>& rhs) {
353 // ----------------------------------------------------------------------------------------
355 /* FIXME: this should go into TMatSquareFunctions<> but for some reason
356 * BASE<T>::col_type is not accessible from there (???)
359 typename TMat22<T>::col_type PURE diag(const TMat22<T>& m) {
360 return matrix::diag(m);
363 } // namespace details
365 // ----------------------------------------------------------------------------------------
367 typedef details::TMat22<double> mat2d;
368 typedef details::TMat22<float> mat2;
369 typedef details::TMat22<float> mat2f;
371 // ----------------------------------------------------------------------------------------
372 } // namespace android