/* * 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. */ #pragma once #include #include #include #include #define PURE __attribute__((pure)) #if __cplusplus >= 201402L #define CONSTEXPR constexpr #else #define CONSTEXPR #endif namespace android { // ------------------------------------------------------------------------------------- namespace details { /** * A 2x2 column-major matrix class. * * Conceptually a 2x2 matrix is a an array of 2 column vec2: * * mat2 m = * \f$ * \left( * \begin{array}{cc} * m[0] & m[1] \\ * \end{array} * \right) * \f$ * = * \f$ * \left( * \begin{array}{cc} * m[0][0] & m[1][0] \\ * m[0][1] & m[1][1] \\ * \end{array} * \right) * \f$ * = * \f$ * \left( * \begin{array}{cc} * m(0,0) & m(0,1) \\ * m(1,0) & m(1,1) \\ * \end{array} * \right) * \f$ * * m[n] is the \f$ n^{th} \f$ column of the matrix and is a vec2. * */ template class TMat22 : public TVecUnaryOperators, public TVecComparisonOperators, public TVecAddOperators, public TMatProductOperators, public TMatSquareFunctions, public TMatHelpers, public TMatDebug { public: enum no_init { NO_INIT }; typedef T value_type; typedef T& reference; typedef T const& const_reference; typedef size_t size_type; typedef TVec2 col_type; typedef TVec2 row_type; static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows) static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns) static constexpr size_t NUM_ROWS = COL_SIZE; static constexpr size_t NUM_COLS = ROW_SIZE; private: /* * <-- N columns --> * * a[0][0] a[1][0] a[2][0] ... a[N][0] ^ * a[0][1] a[1][1] a[2][1] ... a[N][1] | * a[0][2] a[1][2] a[2][2] ... a[N][2] M rows * ... | * a[0][M] a[1][M] a[2][M] ... a[N][M] v * * COL_SIZE = M * ROW_SIZE = N * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ] */ col_type m_value[NUM_COLS]; public: // array access inline constexpr col_type const& operator[](size_t column) const { #if __cplusplus >= 201402L // only possible in C++0x14 with constexpr assert(column < NUM_COLS); #endif return m_value[column]; } inline col_type& operator[](size_t column) { assert(column < NUM_COLS); return m_value[column]; } // ----------------------------------------------------------------------- // we want the compiler generated versions for these... TMat22(const TMat22&) = default; ~TMat22() = default; TMat22& operator = (const TMat22&) = default; /** * constructors */ /** * leaves object uninitialized. use with caution. */ explicit constexpr TMat22(no_init) : m_value{ col_type(col_type::NO_INIT), col_type(col_type::NO_INIT) } {} /** * initialize to identity. * * \f$ * \left( * \begin{array}{cc} * 1 & 0 \\ * 0 & 1 \\ * \end{array} * \right) * \f$ */ CONSTEXPR TMat22(); /** * initialize to Identity*scalar. * * \f$ * \left( * \begin{array}{cc} * v & 0 \\ * 0 & v \\ * \end{array} * \right) * \f$ */ template explicit CONSTEXPR TMat22(U v); /** * sets the diagonal to a vector. * * \f$ * \left( * \begin{array}{cc} * v[0] & 0 \\ * 0 & v[1] \\ * \end{array} * \right) * \f$ */ template explicit CONSTEXPR TMat22(const TVec2& v); /** * construct from another matrix of the same size */ template explicit CONSTEXPR TMat22(const TMat22& rhs); /** * construct from 2 column vectors. * * \f$ * \left( * \begin{array}{cc} * v0 & v1 \\ * \end{array} * \right) * \f$ */ template CONSTEXPR TMat22(const TVec2& v0, const TVec2& v1); /** construct from 4 elements in column-major form. * * \f$ * \left( * \begin{array}{cc} * m[0][0] & m[1][0] \\ * m[0][1] & m[1][1] \\ * \end{array} * \right) * \f$ */ template < typename A, typename B, typename C, typename D> CONSTEXPR TMat22(A m00, B m01, C m10, D m11); /** * construct from a C array in column major form. */ template explicit CONSTEXPR TMat22(U const* rawArray); /** * Rotate by radians in the 2D plane */ static CONSTEXPR TMat22 rotate(T radian) { TMat22 r(TMat22::NO_INIT); T c = std::cos(radian); T s = std::sin(radian); r[0][0] = c; r[1][1] = c; r[0][1] = s; r[1][0] = -s; return r; } }; // ---------------------------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------------------------- // Since the matrix code could become pretty big quickly, we don't inline most // operations. template CONSTEXPR TMat22::TMat22() { m_value[0] = col_type(1, 0); m_value[1] = col_type(0, 1); } template template CONSTEXPR TMat22::TMat22(U v) { m_value[0] = col_type(v, 0); m_value[1] = col_type(0, v); } template template CONSTEXPR TMat22::TMat22(const TVec2& v) { m_value[0] = col_type(v.x, 0); m_value[1] = col_type(0, v.y); } // construct from 4 scalars. Note that the arrangement // of values in the constructor is the transpose of the matrix // notation. template template < typename A, typename B, typename C, typename D> CONSTEXPR TMat22::TMat22( A m00, B m01, C m10, D m11) { m_value[0] = col_type(m00, m01); m_value[1] = col_type(m10, m11); } template template CONSTEXPR TMat22::TMat22(const TMat22& rhs) { for (size_t col = 0; col < NUM_COLS; ++col) { m_value[col] = col_type(rhs[col]); } } // Construct from 2 column vectors. template template CONSTEXPR TMat22::TMat22(const TVec2& v0, const TVec2& v1) { m_value[0] = v0; m_value[1] = v1; } // Construct from raw array, in column-major form. template template CONSTEXPR TMat22::TMat22(U const* rawArray) { for (size_t col = 0; col < NUM_COLS; ++col) { for (size_t row = 0; row < NUM_ROWS; ++row) { m_value[col][row] = *rawArray++; } } } // ---------------------------------------------------------------------------------------- // Arithmetic operators outside of class // ---------------------------------------------------------------------------------------- /* We use non-friend functions here to prevent the compiler from using * implicit conversions, for instance of a scalar to a vector. The result would * not be what the caller expects. * * Also note that the order of the arguments in the inner loop is important since * it determines the output type (only relevant when T != U). */ // matrix * column-vector, result is a vector of the same type than the input vector template CONSTEXPR typename TMat22::col_type PURE operator *(const TMat22& lhs, const TVec2& rhs) { // Result is initialized to zero. typename TMat22::col_type result; for (size_t col = 0; col < TMat22::NUM_COLS; ++col) { result += lhs[col] * rhs[col]; } return result; } // row-vector * matrix, result is a vector of the same type than the input vector template CONSTEXPR typename TMat22::row_type PURE operator *(const TVec2& lhs, const TMat22& rhs) { typename TMat22::row_type result(TMat22::row_type::NO_INIT); for (size_t col = 0; col < TMat22::NUM_COLS; ++col) { result[col] = dot(lhs, rhs[col]); } return result; } // matrix * scalar, result is a matrix of the same type than the input matrix template constexpr typename std::enable_if::value, TMat22>::type PURE operator*(TMat22 lhs, U rhs) { return lhs *= rhs; } // scalar * matrix, result is a matrix of the same type than the input matrix template constexpr typename std::enable_if::value, TMat22>::type PURE operator*(U lhs, const TMat22& rhs) { return rhs * lhs; } // ---------------------------------------------------------------------------------------- /* FIXME: this should go into TMatSquareFunctions<> but for some reason * BASE::col_type is not accessible from there (???) */ template CONSTEXPR typename TMat22::col_type PURE diag(const TMat22& m) { return matrix::diag(m); } } // namespace details // ---------------------------------------------------------------------------------------- typedef details::TMat22 mat2d; typedef details::TMat22 mat2; typedef details::TMat22 mat2f; // ---------------------------------------------------------------------------------------- } // namespace android #undef PURE #undef CONSTEXPR