123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- /*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #ifndef TMAT_IMPLEMENTATION
- #error "Don't include TMatHelpers.h directly. use ui/mat*.h instead"
- #else
- #undef TMAT_IMPLEMENTATION
- #endif
- #ifndef UI_TMAT_HELPERS_H
- #define UI_TMAT_HELPERS_H
- #include <stdint.h>
- #include <sys/types.h>
- #include <math.h>
- #include <utils/Debug.h>
- #include <utils/String8.h>
- #define PURE __attribute__((pure))
- namespace android {
- // -------------------------------------------------------------------------------------
- /*
- * No user serviceable parts here.
- *
- * Don't use this file directly, instead include ui/mat*.h
- */
- /*
- * Matrix utilities
- */
- namespace matrix {
- inline int PURE transpose(int v) { return v; }
- inline float PURE transpose(float v) { return v; }
- inline double PURE transpose(double v) { return v; }
- inline int PURE trace(int v) { return v; }
- inline float PURE trace(float v) { return v; }
- inline double PURE trace(double v) { return v; }
- template<typename MATRIX>
- MATRIX PURE inverse(const MATRIX& src) {
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::COL_SIZE == MATRIX::ROW_SIZE );
- typename MATRIX::value_type t;
- const size_t N = MATRIX::col_size();
- size_t swap;
- MATRIX tmp(src);
- MATRIX inverse(1);
- for (size_t i=0 ; i<N ; i++) {
- // look for largest element in column
- swap = i;
- for (size_t j=i+1 ; j<N ; j++) {
- if (fabs(tmp[j][i]) > fabs(tmp[i][i])) {
- swap = j;
- }
- }
- if (swap != i) {
- /* swap rows. */
- for (size_t k=0 ; k<N ; k++) {
- t = tmp[i][k];
- tmp[i][k] = tmp[swap][k];
- tmp[swap][k] = t;
- t = inverse[i][k];
- inverse[i][k] = inverse[swap][k];
- inverse[swap][k] = t;
- }
- }
- t = 1 / tmp[i][i];
- for (size_t k=0 ; k<N ; k++) {
- tmp[i][k] *= t;
- inverse[i][k] *= t;
- }
- for (size_t j=0 ; j<N ; j++) {
- if (j != i) {
- t = tmp[j][i];
- for (size_t k=0 ; k<N ; k++) {
- tmp[j][k] -= tmp[i][k] * t;
- inverse[j][k] -= inverse[i][k] * t;
- }
- }
- }
- }
- return inverse;
- }
- template<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B>
- MATRIX_R PURE multiply(const MATRIX_A& lhs, const MATRIX_B& rhs) {
- // pre-requisite:
- // lhs : D columns, R rows
- // rhs : C columns, D rows
- // res : C columns, R rows
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_A::ROW_SIZE == MATRIX_B::COL_SIZE );
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::ROW_SIZE == MATRIX_B::ROW_SIZE );
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::COL_SIZE == MATRIX_A::COL_SIZE );
- MATRIX_R res(MATRIX_R::NO_INIT);
- for (size_t r=0 ; r<MATRIX_R::row_size() ; r++) {
- res[r] = lhs * rhs[r];
- }
- return res;
- }
- // transpose. this handles matrices of matrices
- template <typename MATRIX>
- MATRIX PURE transpose(const MATRIX& m) {
- // for now we only handle square matrix transpose
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
- MATRIX result(MATRIX::NO_INIT);
- for (size_t r=0 ; r<MATRIX::row_size() ; r++)
- for (size_t c=0 ; c<MATRIX::col_size() ; c++)
- result[c][r] = transpose(m[r][c]);
- return result;
- }
- // trace. this handles matrices of matrices
- template <typename MATRIX>
- typename MATRIX::value_type PURE trace(const MATRIX& m) {
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
- typename MATRIX::value_type result(0);
- for (size_t r=0 ; r<MATRIX::row_size() ; r++)
- result += trace(m[r][r]);
- return result;
- }
- // trace. this handles matrices of matrices
- template <typename MATRIX>
- typename MATRIX::col_type PURE diag(const MATRIX& m) {
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
- typename MATRIX::col_type result(MATRIX::col_type::NO_INIT);
- for (size_t r=0 ; r<MATRIX::row_size() ; r++)
- result[r] = m[r][r];
- return result;
- }
- template <typename MATRIX>
- String8 asString(const MATRIX& m) {
- String8 s;
- for (size_t c=0 ; c<MATRIX::col_size() ; c++) {
- s.append("| ");
- for (size_t r=0 ; r<MATRIX::row_size() ; r++) {
- s.appendFormat("%7.2f ", m[r][c]);
- }
- s.append("|\n");
- }
- return s;
- }
- }; // namespace matrix
- // -------------------------------------------------------------------------------------
- /*
- * TMatProductOperators implements basic arithmetic and basic compound assignments
- * operators on a vector of type BASE<T>.
- *
- * BASE only needs to implement operator[] and size().
- * By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically
- * get all the functionality here.
- */
- template <template<typename T> class BASE, typename T>
- class TMatProductOperators {
- public:
- // multiply by a scalar
- BASE<T>& operator *= (T v) {
- BASE<T>& lhs(static_cast< BASE<T>& >(*this));
- for (size_t r=0 ; r<lhs.row_size() ; r++) {
- lhs[r] *= v;
- }
- return lhs;
- }
- // divide by a scalar
- BASE<T>& operator /= (T v) {
- BASE<T>& lhs(static_cast< BASE<T>& >(*this));
- for (size_t r=0 ; r<lhs.row_size() ; r++) {
- lhs[r] /= v;
- }
- return lhs;
- }
- // matrix * matrix, result is a matrix of the same type than the lhs matrix
- template<typename U>
- friend BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) {
- return matrix::multiply<BASE<T> >(lhs, rhs);
- }
- };
- /*
- * TMatSquareFunctions implements functions on a matrix of type BASE<T>.
- *
- * BASE only needs to implement:
- * - operator[]
- * - col_type
- * - row_type
- * - COL_SIZE
- * - ROW_SIZE
- *
- * By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
- * get all the functionality here.
- */
- template<template<typename U> class BASE, typename T>
- class TMatSquareFunctions {
- public:
- /*
- * NOTE: the functions below ARE NOT member methods. They are friend functions
- * with they definition inlined with their declaration. This makes these
- * template functions available to the compiler when (and only when) this class
- * is instantiated, at which point they're only templated on the 2nd parameter
- * (the first one, BASE<T> being known).
- */
- friend BASE<T> PURE inverse(const BASE<T>& m) { return matrix::inverse(m); }
- friend BASE<T> PURE transpose(const BASE<T>& m) { return matrix::transpose(m); }
- friend T PURE trace(const BASE<T>& m) { return matrix::trace(m); }
- };
- template <template<typename T> class BASE, typename T>
- class TMatDebug {
- public:
- String8 asString() const {
- return matrix::asString( static_cast< const BASE<T>& >(*this) );
- }
- };
- // -------------------------------------------------------------------------------------
- }; // namespace android
- #undef PURE
- #endif /* UI_TMAT_HELPERS_H */
|