TMatHelpers.h 7.5 KB

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