1 /*
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 TMAT_IMPLEMENTATION
18 #error "Don't include TMatHelpers.h directly. use ui/mat*.h instead"
19 #else
20 #undef TMAT_IMPLEMENTATION
21 #endif
22
23
24 #ifndef UI_TMAT_HELPERS_H
25 #define UI_TMAT_HELPERS_H
26
27 #include <stdint.h>
28 #include <sys/types.h>
29 #include <math.h>
30 #include <utils/Debug.h>
31 #include <utils/String8.h>
32
33 #define PURE __attribute__((pure))
34
35 namespace android {
36 // -------------------------------------------------------------------------------------
37
38 /*
39 * No user serviceable parts here.
40 *
41 * Don't use this file directly, instead include ui/mat*.h
42 */
43
44
45 /*
46 * Matrix utilities
47 */
48
49 namespace matrix {
50
transpose(int v)51 inline int PURE transpose(int v) { return v; }
transpose(float v)52 inline float PURE transpose(float v) { return v; }
transpose(double v)53 inline double PURE transpose(double v) { return v; }
54
trace(int v)55 inline int PURE trace(int v) { return v; }
trace(float v)56 inline float PURE trace(float v) { return v; }
trace(double v)57 inline double PURE trace(double v) { return v; }
58
59 template<typename MATRIX>
inverse(const MATRIX & src)60 MATRIX PURE inverse(const MATRIX& src) {
61
62 COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::COL_SIZE == MATRIX::ROW_SIZE );
63
64 typename MATRIX::value_type t;
65 const size_t N = MATRIX::col_size();
66 size_t swap;
67 MATRIX tmp(src);
68 MATRIX inverse(1);
69
70 for (size_t i=0 ; i<N ; i++) {
71 // look for largest element in column
72 swap = i;
73 for (size_t j=i+1 ; j<N ; j++) {
74 if (fabs(tmp[j][i]) > fabs(tmp[i][i])) {
75 swap = j;
76 }
77 }
78
79 if (swap != i) {
80 /* swap rows. */
81 for (size_t k=0 ; k<N ; k++) {
82 t = tmp[i][k];
83 tmp[i][k] = tmp[swap][k];
84 tmp[swap][k] = t;
85
86 t = inverse[i][k];
87 inverse[i][k] = inverse[swap][k];
88 inverse[swap][k] = t;
89 }
90 }
91
92 t = 1 / tmp[i][i];
93 for (size_t k=0 ; k<N ; k++) {
94 tmp[i][k] *= t;
95 inverse[i][k] *= t;
96 }
97 for (size_t j=0 ; j<N ; j++) {
98 if (j != i) {
99 t = tmp[j][i];
100 for (size_t k=0 ; k<N ; k++) {
101 tmp[j][k] -= tmp[i][k] * t;
102 inverse[j][k] -= inverse[i][k] * t;
103 }
104 }
105 }
106 }
107 return inverse;
108 }
109
110 template<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B>
multiply(const MATRIX_A & lhs,const MATRIX_B & rhs)111 MATRIX_R PURE multiply(const MATRIX_A& lhs, const MATRIX_B& rhs) {
112 // pre-requisite:
113 // lhs : D columns, R rows
114 // rhs : C columns, D rows
115 // res : C columns, R rows
116
117 COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_A::ROW_SIZE == MATRIX_B::COL_SIZE );
118 COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::ROW_SIZE == MATRIX_B::ROW_SIZE );
119 COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::COL_SIZE == MATRIX_A::COL_SIZE );
120
121 MATRIX_R res(MATRIX_R::NO_INIT);
122 for (size_t r=0 ; r<MATRIX_R::row_size() ; r++) {
123 res[r] = lhs * rhs[r];
124 }
125 return res;
126 }
127
128 // transpose. this handles matrices of matrices
129 template <typename MATRIX>
transpose(const MATRIX & m)130 MATRIX PURE transpose(const MATRIX& m) {
131 // for now we only handle square matrix transpose
132 COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
133 MATRIX result(MATRIX::NO_INIT);
134 for (size_t r=0 ; r<MATRIX::row_size() ; r++)
135 for (size_t c=0 ; c<MATRIX::col_size() ; c++)
136 result[c][r] = transpose(m[r][c]);
137 return result;
138 }
139
140 // trace. this handles matrices of matrices
141 template <typename MATRIX>
trace(const MATRIX & m)142 typename MATRIX::value_type PURE trace(const MATRIX& m) {
143 COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
144 typename MATRIX::value_type result(0);
145 for (size_t r=0 ; r<MATRIX::row_size() ; r++)
146 result += trace(m[r][r]);
147 return result;
148 }
149
150 // trace. this handles matrices of matrices
151 template <typename MATRIX>
diag(const MATRIX & m)152 typename MATRIX::col_type PURE diag(const MATRIX& m) {
153 COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
154 typename MATRIX::col_type result(MATRIX::col_type::NO_INIT);
155 for (size_t r=0 ; r<MATRIX::row_size() ; r++)
156 result[r] = m[r][r];
157 return result;
158 }
159
160 template <typename MATRIX>
asString(const MATRIX & m)161 String8 asString(const MATRIX& m) {
162 String8 s;
163 for (size_t c=0 ; c<MATRIX::col_size() ; c++) {
164 s.append("| ");
165 for (size_t r=0 ; r<MATRIX::row_size() ; r++) {
166 s.appendFormat("%7.2f ", m[r][c]);
167 }
168 s.append("|\n");
169 }
170 return s;
171 }
172
173 }; // namespace matrix
174
175 // -------------------------------------------------------------------------------------
176
177 /*
178 * TMatProductOperators implements basic arithmetic and basic compound assignments
179 * operators on a vector of type BASE<T>.
180 *
181 * BASE only needs to implement operator[] and size().
182 * By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically
183 * get all the functionality here.
184 */
185
186 template <template<typename T> class BASE, typename T>
187 class TMatProductOperators {
188 public:
189 // multiply by a scalar
190 BASE<T>& operator *= (T v) {
191 BASE<T>& lhs(static_cast< BASE<T>& >(*this));
192 for (size_t r=0 ; r<lhs.row_size() ; r++) {
193 lhs[r] *= v;
194 }
195 return lhs;
196 }
197
198 // divide by a scalar
199 BASE<T>& operator /= (T v) {
200 BASE<T>& lhs(static_cast< BASE<T>& >(*this));
201 for (size_t r=0 ; r<lhs.row_size() ; r++) {
202 lhs[r] /= v;
203 }
204 return lhs;
205 }
206
207 // matrix * matrix, result is a matrix of the same type than the lhs matrix
208 template<typename U>
209 friend BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) {
210 return matrix::multiply<BASE<T> >(lhs, rhs);
211 }
212 };
213
214
215 /*
216 * TMatSquareFunctions implements functions on a matrix of type BASE<T>.
217 *
218 * BASE only needs to implement:
219 * - operator[]
220 * - col_type
221 * - row_type
222 * - COL_SIZE
223 * - ROW_SIZE
224 *
225 * By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
226 * get all the functionality here.
227 */
228
229 template<template<typename U> class BASE, typename T>
230 class TMatSquareFunctions {
231 public:
232 /*
233 * NOTE: the functions below ARE NOT member methods. They are friend functions
234 * with they definition inlined with their declaration. This makes these
235 * template functions available to the compiler when (and only when) this class
236 * is instantiated, at which point they're only templated on the 2nd parameter
237 * (the first one, BASE<T> being known).
238 */
inverse(const BASE<T> & m)239 friend BASE<T> PURE inverse(const BASE<T>& m) { return matrix::inverse(m); }
transpose(const BASE<T> & m)240 friend BASE<T> PURE transpose(const BASE<T>& m) { return matrix::transpose(m); }
trace(const BASE<T> & m)241 friend T PURE trace(const BASE<T>& m) { return matrix::trace(m); }
242 };
243
244 template <template<typename T> class BASE, typename T>
245 class TMatDebug {
246 public:
asString()247 String8 asString() const {
248 return matrix::asString( static_cast< const BASE<T>& >(*this) );
249 }
250 };
251
252 // -------------------------------------------------------------------------------------
253 }; // namespace android
254
255 #undef PURE
256
257 #endif /* UI_TMAT_HELPERS_H */
258