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 #pragma once 18 19 #include <math/TMatHelpers.h> 20 #include <math/vec2.h> 21 #include <stdint.h> 22 #include <sys/types.h> 23 24 #define PURE __attribute__((pure)) 25 26 #if __cplusplus >= 201402L 27 #define CONSTEXPR constexpr 28 #else 29 #define CONSTEXPR 30 #endif 31 32 namespace android { 33 // ------------------------------------------------------------------------------------- 34 namespace details { 35 36 /** 37 * A 2x2 column-major matrix class. 38 * 39 * Conceptually a 2x2 matrix is a an array of 2 column vec2: 40 * 41 * mat2 m = 42 * \f$ 43 * \left( 44 * \begin{array}{cc} 45 * m[0] & m[1] \\ 46 * \end{array} 47 * \right) 48 * \f$ 49 * = 50 * \f$ 51 * \left( 52 * \begin{array}{cc} 53 * m[0][0] & m[1][0] \\ 54 * m[0][1] & m[1][1] \\ 55 * \end{array} 56 * \right) 57 * \f$ 58 * = 59 * \f$ 60 * \left( 61 * \begin{array}{cc} 62 * m(0,0) & m(0,1) \\ 63 * m(1,0) & m(1,1) \\ 64 * \end{array} 65 * \right) 66 * \f$ 67 * 68 * m[n] is the \f$ n^{th} \f$ column of the matrix and is a vec2. 69 * 70 */ 71 template <typename T> 72 class TMat22 : public TVecUnaryOperators<TMat22, T>, 73 public TVecComparisonOperators<TMat22, T>, 74 public TVecAddOperators<TMat22, T>, 75 public TMatProductOperators<TMat22, T>, 76 public TMatSquareFunctions<TMat22, T>, 77 public TMatHelpers<TMat22, T>, 78 public TMatDebug<TMat22, T> { 79 public: 80 enum no_init { NO_INIT }; 81 typedef T value_type; 82 typedef T& reference; 83 typedef T const& const_reference; 84 typedef size_t size_type; 85 typedef TVec2<T> col_type; 86 typedef TVec2<T> row_type; 87 88 static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows) 89 static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns) 90 static constexpr size_t NUM_ROWS = COL_SIZE; 91 static constexpr size_t NUM_COLS = ROW_SIZE; 92 93 private: 94 /* 95 * <-- N columns --> 96 * 97 * a[0][0] a[1][0] a[2][0] ... a[N][0] ^ 98 * a[0][1] a[1][1] a[2][1] ... a[N][1] | 99 * a[0][2] a[1][2] a[2][2] ... a[N][2] M rows 100 * ... | 101 * a[0][M] a[1][M] a[2][M] ... a[N][M] v 102 * 103 * COL_SIZE = M 104 * ROW_SIZE = N 105 * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ] 106 */ 107 108 col_type m_value[NUM_COLS]; 109 110 public: 111 // array access 112 inline constexpr col_type const& operator[](size_t column) const { 113 #if __cplusplus >= 201402L 114 // only possible in C++0x14 with constexpr 115 assert(column < NUM_COLS); 116 #endif 117 return m_value[column]; 118 } 119 120 inline col_type& operator[](size_t column) { 121 assert(column < NUM_COLS); 122 return m_value[column]; 123 } 124 125 // ----------------------------------------------------------------------- 126 // we want the compiler generated versions for these... 127 TMat22(const TMat22&) = default; 128 ~TMat22() = default; 129 TMat22& operator = (const TMat22&) = default; 130 131 /** 132 * constructors 133 */ 134 135 /** 136 * leaves object uninitialized. use with caution. 137 */ 138 explicit constexpr TMat22(no_init) 139 : m_value{ col_type(col_type::NO_INIT), 140 col_type(col_type::NO_INIT) } {} 141 142 143 /** 144 * initialize to identity. 145 * 146 * \f$ 147 * \left( 148 * \begin{array}{cc} 149 * 1 & 0 \\ 150 * 0 & 1 \\ 151 * \end{array} 152 * \right) 153 * \f$ 154 */ 155 CONSTEXPR TMat22(); 156 157 /** 158 * initialize to Identity*scalar. 159 * 160 * \f$ 161 * \left( 162 * \begin{array}{cc} 163 * v & 0 \\ 164 * 0 & v \\ 165 * \end{array} 166 * \right) 167 * \f$ 168 */ 169 template<typename U> 170 explicit CONSTEXPR TMat22(U v); 171 172 /** 173 * sets the diagonal to a vector. 174 * 175 * \f$ 176 * \left( 177 * \begin{array}{cc} 178 * v[0] & 0 \\ 179 * 0 & v[1] \\ 180 * \end{array} 181 * \right) 182 * \f$ 183 */ 184 template <typename U> 185 explicit CONSTEXPR TMat22(const TVec2<U>& v); 186 187 /** 188 * construct from another matrix of the same size 189 */ 190 template <typename U> 191 explicit CONSTEXPR TMat22(const TMat22<U>& rhs); 192 193 /** 194 * construct from 2 column vectors. 195 * 196 * \f$ 197 * \left( 198 * \begin{array}{cc} 199 * v0 & v1 \\ 200 * \end{array} 201 * \right) 202 * \f$ 203 */ 204 template <typename A, typename B> 205 CONSTEXPR TMat22(const TVec2<A>& v0, const TVec2<B>& v1); 206 207 /** construct from 4 elements in column-major form. 208 * 209 * \f$ 210 * \left( 211 * \begin{array}{cc} 212 * m[0][0] & m[1][0] \\ 213 * m[0][1] & m[1][1] \\ 214 * \end{array} 215 * \right) 216 * \f$ 217 */ 218 template < 219 typename A, typename B, 220 typename C, typename D> 221 CONSTEXPR TMat22(A m00, B m01, C m10, D m11); 222 223 /** 224 * construct from a C array in column major form. 225 */ 226 template <typename U> 227 explicit CONSTEXPR TMat22(U const* rawArray); 228 229 /** 230 * Rotate by radians in the 2D plane 231 */ 232 static CONSTEXPR TMat22<T> rotate(T radian) { 233 TMat22<T> r(TMat22<T>::NO_INIT); 234 T c = std::cos(radian); 235 T s = std::sin(radian); 236 r[0][0] = c; r[1][1] = c; 237 r[0][1] = s; r[1][0] = -s; 238 return r; 239 } 240 }; 241 242 // ---------------------------------------------------------------------------------------- 243 // Constructors 244 // ---------------------------------------------------------------------------------------- 245 246 // Since the matrix code could become pretty big quickly, we don't inline most 247 // operations. 248 249 template <typename T> 250 CONSTEXPR TMat22<T>::TMat22() { 251 m_value[0] = col_type(1, 0); 252 m_value[1] = col_type(0, 1); 253 } 254 255 template <typename T> 256 template <typename U> 257 CONSTEXPR TMat22<T>::TMat22(U v) { 258 m_value[0] = col_type(v, 0); 259 m_value[1] = col_type(0, v); 260 } 261 262 template<typename T> 263 template<typename U> 264 CONSTEXPR TMat22<T>::TMat22(const TVec2<U>& v) { 265 m_value[0] = col_type(v.x, 0); 266 m_value[1] = col_type(0, v.y); 267 } 268 269 // construct from 4 scalars. Note that the arrangement 270 // of values in the constructor is the transpose of the matrix 271 // notation. 272 template<typename T> 273 template < 274 typename A, typename B, 275 typename C, typename D> 276 CONSTEXPR TMat22<T>::TMat22( A m00, B m01, C m10, D m11) { 277 m_value[0] = col_type(m00, m01); 278 m_value[1] = col_type(m10, m11); 279 } 280 281 template <typename T> 282 template <typename U> 283 CONSTEXPR TMat22<T>::TMat22(const TMat22<U>& rhs) { 284 for (size_t col = 0; col < NUM_COLS; ++col) { 285 m_value[col] = col_type(rhs[col]); 286 } 287 } 288 289 // Construct from 2 column vectors. 290 template <typename T> 291 template <typename A, typename B> 292 CONSTEXPR TMat22<T>::TMat22(const TVec2<A>& v0, const TVec2<B>& v1) { 293 m_value[0] = v0; 294 m_value[1] = v1; 295 } 296 297 // Construct from raw array, in column-major form. 298 template <typename T> 299 template <typename U> 300 CONSTEXPR TMat22<T>::TMat22(U const* rawArray) { 301 for (size_t col = 0; col < NUM_COLS; ++col) { 302 for (size_t row = 0; row < NUM_ROWS; ++row) { 303 m_value[col][row] = *rawArray++; 304 } 305 } 306 } 307 308 // ---------------------------------------------------------------------------------------- 309 // Arithmetic operators outside of class 310 // ---------------------------------------------------------------------------------------- 311 312 /* We use non-friend functions here to prevent the compiler from using 313 * implicit conversions, for instance of a scalar to a vector. The result would 314 * not be what the caller expects. 315 * 316 * Also note that the order of the arguments in the inner loop is important since 317 * it determines the output type (only relevant when T != U). 318 */ 319 320 // matrix * column-vector, result is a vector of the same type than the input vector 321 template <typename T, typename U> 322 CONSTEXPR typename TMat22<U>::col_type PURE operator *(const TMat22<T>& lhs, const TVec2<U>& rhs) { 323 // Result is initialized to zero. 324 typename TMat22<U>::col_type result; 325 for (size_t col = 0; col < TMat22<T>::NUM_COLS; ++col) { 326 result += lhs[col] * rhs[col]; 327 } 328 return result; 329 } 330 331 // row-vector * matrix, result is a vector of the same type than the input vector 332 template <typename T, typename U> 333 CONSTEXPR typename TMat22<U>::row_type PURE operator *(const TVec2<U>& lhs, const TMat22<T>& rhs) { 334 typename TMat22<U>::row_type result(TMat22<U>::row_type::NO_INIT); 335 for (size_t col = 0; col < TMat22<T>::NUM_COLS; ++col) { 336 result[col] = dot(lhs, rhs[col]); 337 } 338 return result; 339 } 340 341 // matrix * scalar, result is a matrix of the same type than the input matrix 342 template<typename T, typename U> 343 constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat22<T>>::type PURE 344 operator*(TMat22<T> lhs, U rhs) { 345 return lhs *= rhs; 346 } 347 348 // scalar * matrix, result is a matrix of the same type than the input matrix 349 template<typename T, typename U> 350 constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat22<T>>::type PURE 351 operator*(U lhs, const TMat22<T>& rhs) { 352 return rhs * lhs; 353 } 354 355 // ---------------------------------------------------------------------------------------- 356 357 /* FIXME: this should go into TMatSquareFunctions<> but for some reason 358 * BASE<T>::col_type is not accessible from there (???) 359 */ 360 template<typename T> 361 CONSTEXPR typename TMat22<T>::col_type PURE diag(const TMat22<T>& m) { 362 return matrix::diag(m); 363 } 364 365 } // namespace details 366 367 // ---------------------------------------------------------------------------------------- 368 369 typedef details::TMat22<double> mat2d; 370 typedef details::TMat22<float> mat2; 371 typedef details::TMat22<float> mat2f; 372 373 // ---------------------------------------------------------------------------------------- 374 } // namespace android 375 376 #undef PURE 377 #undef CONSTEXPR 378