blob: 5ae73dcd5912a82e5d796bf099c3d50db43dc133 [file] [log] [blame]
Romain Guy5d4bae72016-11-08 09:49:25 -08001/*
2 * Copyright 2013 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#ifndef UI_MAT2_H_
18#define UI_MAT2_H_
19
20#include <ui/TMatHelpers.h>
21#include <ui/vec2.h>
22#include <stdint.h>
23#include <sys/types.h>
24
25#define PURE __attribute__((pure))
26
27namespace android {
28// -------------------------------------------------------------------------------------
29namespace details {
30
31/**
32 * A 2x2 column-major matrix class.
33 *
34 * Conceptually a 2x2 matrix is a an array of 2 column vec2:
35 *
36 * mat2 m =
37 * \f$
38 * \left(
39 * \begin{array}{cc}
40 * m[0] & m[1] \\
41 * \end{array}
42 * \right)
43 * \f$
44 * =
45 * \f$
46 * \left(
47 * \begin{array}{cc}
48 * m[0][0] & m[1][0] \\
49 * m[0][1] & m[1][1] \\
50 * \end{array}
51 * \right)
52 * \f$
53 * =
54 * \f$
55 * \left(
56 * \begin{array}{cc}
57 * m(0,0) & m(0,1) \\
58 * m(1,0) & m(1,1) \\
59 * \end{array}
60 * \right)
61 * \f$
62 *
63 * m[n] is the \f$ n^{th} \f$ column of the matrix and is a vec2.
64 *
65 */
66template <typename T>
67class 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> {
74public:
75 enum no_init { NO_INIT };
76 typedef T value_type;
77 typedef T& reference;
78 typedef T const& const_reference;
79 typedef size_t size_type;
80 typedef TVec2<T> col_type;
81 typedef TVec2<T> row_type;
82
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;
87
88private:
89 /*
90 * <-- N columns -->
91 *
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
95 * ... |
96 * a[0][M] a[1][M] a[2][M] ... a[N][M] v
97 *
98 * COL_SIZE = M
99 * ROW_SIZE = N
100 * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
101 */
102
103 col_type m_value[NUM_COLS];
104
105public:
106 // array access
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);
111#endif
112 return m_value[column];
113 }
114
115 inline col_type& operator[](size_t column) {
116 assert(column < NUM_COLS);
117 return m_value[column];
118 }
119
120 // -----------------------------------------------------------------------
121 // we want the compiler generated versions for these...
122 TMat22(const TMat22&) = default;
123 ~TMat22() = default;
124 TMat22& operator = (const TMat22&) = default;
125
126 /**
127 * constructors
128 */
129
130 /**
131 * leaves object uninitialized. use with caution.
132 */
133 explicit
134 constexpr TMat22(no_init)
135 : m_value{ col_type(col_type::NO_INIT),
136 col_type(col_type::NO_INIT) } {}
137
138
139 /**
140 * initialize to identity.
141 *
142 * \f$
143 * \left(
144 * \begin{array}{cc}
145 * 1 & 0 \\
146 * 0 & 1 \\
147 * \end{array}
148 * \right)
149 * \f$
150 */
151 TMat22();
152
153 /**
154 * initialize to Identity*scalar.
155 *
156 * \f$
157 * \left(
158 * \begin{array}{cc}
159 * v & 0 \\
160 * 0 & v \\
161 * \end{array}
162 * \right)
163 * \f$
164 */
165 template<typename U>
166 explicit TMat22(U v);
167
168 /**
169 * sets the diagonal to a vector.
170 *
171 * \f$
172 * \left(
173 * \begin{array}{cc}
174 * v[0] & 0 \\
175 * 0 & v[1] \\
176 * \end{array}
177 * \right)
178 * \f$
179 */
180 template <typename U>
181 explicit TMat22(const TVec2<U>& v);
182
183 /**
184 * construct from another matrix of the same size
185 */
186 template <typename U>
187 explicit TMat22(const TMat22<U>& rhs);
188
189 /**
190 * construct from 2 column vectors.
191 *
192 * \f$
193 * \left(
194 * \begin{array}{cc}
195 * v0 & v1 \\
196 * \end{array}
197 * \right)
198 * \f$
199 */
200 template <typename A, typename B>
201 TMat22(const TVec2<A>& v0, const TVec2<B>& v1);
202
203 /** construct from 4 elements in column-major form.
204 *
205 * \f$
206 * \left(
207 * \begin{array}{cc}
208 * m[0][0] & m[1][0] \\
209 * m[0][1] & m[1][1] \\
210 * \end{array}
211 * \right)
212 * \f$
213 */
214 template <
215 typename A, typename B,
216 typename C, typename D>
217 TMat22(A m00, B m01,
218 C m10, D m11);
219
220 /**
221 * construct from a C array in column major form.
222 */
223 template <typename U>
224 explicit TMat22(U const* rawArray);
225
226 /**
227 * Rotate by radians in the 2D plane
228 */
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;
235 return r;
236 }
237};
238
239// ----------------------------------------------------------------------------------------
240// Constructors
241// ----------------------------------------------------------------------------------------
242
243// Since the matrix code could become pretty big quickly, we don't inline most
244// operations.
245
246template <typename T>
247TMat22<T>::TMat22() {
248 m_value[0] = col_type(1, 0);
249 m_value[1] = col_type(0, 1);
250}
251
252template <typename T>
253template <typename U>
254TMat22<T>::TMat22(U v) {
255 m_value[0] = col_type(v, 0);
256 m_value[1] = col_type(0, v);
257}
258
259template<typename T>
260template<typename U>
261TMat22<T>::TMat22(const TVec2<U>& v) {
262 m_value[0] = col_type(v.x, 0);
263 m_value[1] = col_type(0, v.y);
264}
265
266// construct from 4 scalars. Note that the arrangement
267// of values in the constructor is the transpose of the matrix
268// notation.
269template<typename T>
270template <
271 typename A, typename B,
272 typename C, typename D>
273TMat22<T>::TMat22(A m00, B m01,
274 C m10, D m11) {
275 m_value[0] = col_type(m00, m01);
276 m_value[1] = col_type(m10, m11);
277}
278
279template <typename T>
280template <typename U>
281TMat22<T>::TMat22(const TMat22<U>& rhs) {
282 for (size_t col = 0; col < NUM_COLS; ++col) {
283 m_value[col] = col_type(rhs[col]);
284 }
285}
286
287// Construct from 2 column vectors.
288template <typename T>
289template <typename A, typename B>
290TMat22<T>::TMat22(const TVec2<A>& v0, const TVec2<B>& v1) {
291 m_value[0] = v0;
292 m_value[1] = v1;
293}
294
295// Construct from raw array, in column-major form.
296template <typename T>
297template <typename U>
298TMat22<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++;
302 }
303 }
304}
305
306// ----------------------------------------------------------------------------------------
307// Arithmetic operators outside of class
308// ----------------------------------------------------------------------------------------
309
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.
313 *
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).
316 */
317
318// matrix * column-vector, result is a vector of the same type than the input vector
319template <typename T, typename U>
320typename 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];
325 }
326 return result;
327}
328
329// row-vector * matrix, result is a vector of the same type than the input vector
330template <typename T, typename U>
331typename 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]);
335 }
336 return result;
337}
338
339// matrix * scalar, result is a matrix of the same type than the input matrix
340template<typename T, typename U>
341constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat22<T>>::type PURE
342operator*(TMat22<T> lhs, U rhs) {
343 return lhs *= rhs;
344}
345
346// scalar * matrix, result is a matrix of the same type than the input matrix
347template<typename T, typename U>
348constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat22<T>>::type PURE
349operator*(U lhs, const TMat22<T>& rhs) {
350 return rhs * lhs;
351}
352
353// ----------------------------------------------------------------------------------------
354
355/* FIXME: this should go into TMatSquareFunctions<> but for some reason
356 * BASE<T>::col_type is not accessible from there (???)
357 */
358template<typename T>
359typename TMat22<T>::col_type PURE diag(const TMat22<T>& m) {
360 return matrix::diag(m);
361}
362
363} // namespace details
364
365// ----------------------------------------------------------------------------------------
366
367typedef details::TMat22<double> mat2d;
368typedef details::TMat22<float> mat2;
369typedef details::TMat22<float> mat2f;
370
371// ----------------------------------------------------------------------------------------
372} // namespace android
373
374#undef PURE
375
376#endif // UI_MAT2_H_