• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h>
20 #include <stdint.h>
21 #include <sys/types.h>
22 
23 #include <cmath>
24 #include <exception>
25 #include <iomanip>
26 #include <stdexcept>
27 
28 #include <math/quat.h>
29 #include <math/TVecHelpers.h>
30 
31 #include  <utils/String8.h>
32 
33 #ifndef LIKELY
34 #define LIKELY_DEFINED_LOCAL
35 #ifdef __cplusplus
36 #   define LIKELY( exp )    (__builtin_expect( !!(exp), true ))
37 #   define UNLIKELY( exp )  (__builtin_expect( !!(exp), false ))
38 #else
39 #   define LIKELY( exp )    (__builtin_expect( !!(exp), 1 ))
40 #   define UNLIKELY( exp )  (__builtin_expect( !!(exp), 0 ))
41 #endif
42 #endif
43 
44 #define PURE __attribute__((pure))
45 
46 #if __cplusplus >= 201402L
47 #define CONSTEXPR constexpr
48 #else
49 #define CONSTEXPR
50 #endif
51 
52 namespace android {
53 namespace details {
54 // -------------------------------------------------------------------------------------
55 
56 /*
57  * No user serviceable parts here.
58  *
59  * Don't use this file directly, instead include ui/mat*.h
60  */
61 
62 
63 /*
64  * Matrix utilities
65  */
66 
67 namespace matrix {
68 
transpose(int v)69 inline constexpr int     transpose(int v)    { return v; }
transpose(float v)70 inline constexpr float   transpose(float v)  { return v; }
transpose(double v)71 inline constexpr double  transpose(double v) { return v; }
72 
trace(int v)73 inline constexpr int     trace(int v)    { return v; }
trace(float v)74 inline constexpr float   trace(float v)  { return v; }
trace(double v)75 inline constexpr double  trace(double v) { return v; }
76 
77 /*
78  * Matrix inversion
79  */
80 template<typename MATRIX>
gaussJordanInverse(const MATRIX & src)81 MATRIX PURE gaussJordanInverse(const MATRIX& src) {
82     typedef typename MATRIX::value_type T;
83     static constexpr unsigned int N = MATRIX::NUM_ROWS;
84     MATRIX tmp(src);
85     MATRIX inverted(1);
86 
87     for (size_t i = 0; i < N; ++i) {
88         // look for largest element in i'th column
89         size_t swap = i;
90         T t = std::abs(tmp[i][i]);
91         for (size_t j = i + 1; j < N; ++j) {
92             const T t2 = std::abs(tmp[j][i]);
93             if (t2 > t) {
94                 swap = j;
95                 t = t2;
96             }
97         }
98 
99         if (swap != i) {
100             // swap columns.
101             std::swap(tmp[i], tmp[swap]);
102             std::swap(inverted[i], inverted[swap]);
103         }
104 
105         const T denom(tmp[i][i]);
106         for (size_t k = 0; k < N; ++k) {
107             tmp[i][k] /= denom;
108             inverted[i][k] /= denom;
109         }
110 
111         // Factor out the lower triangle
112         for (size_t j = 0; j < N; ++j) {
113             if (j != i) {
114                 const T d = tmp[j][i];
115                 for (size_t k = 0; k < N; ++k) {
116                     tmp[j][k] -= tmp[i][k] * d;
117                     inverted[j][k] -= inverted[i][k] * d;
118                 }
119             }
120         }
121     }
122 
123     return inverted;
124 }
125 
126 
127 //------------------------------------------------------------------------------
128 // 2x2 matrix inverse is easy.
129 template <typename MATRIX>
fastInverse2(const MATRIX & x)130 CONSTEXPR MATRIX PURE fastInverse2(const MATRIX& x) {
131     typedef typename MATRIX::value_type T;
132 
133     // Assuming the input matrix is:
134     // | a b |
135     // | c d |
136     //
137     // The analytic inverse is
138     // | d -b |
139     // | -c a | / (a d - b c)
140     //
141     // Importantly, our matrices are column-major!
142 
143     MATRIX inverted(MATRIX::NO_INIT);
144 
145     const T a = x[0][0];
146     const T c = x[0][1];
147     const T b = x[1][0];
148     const T d = x[1][1];
149 
150     const T det((a * d) - (b * c));
151     inverted[0][0] =  d / det;
152     inverted[0][1] = -c / det;
153     inverted[1][0] = -b / det;
154     inverted[1][1] =  a / det;
155     return inverted;
156 }
157 
158 
159 //------------------------------------------------------------------------------
160 // From the Wikipedia article on matrix inversion's section on fast 3x3
161 // matrix inversion:
162 // http://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3.C3.973_matrices
163 template <typename MATRIX>
fastInverse3(const MATRIX & x)164 CONSTEXPR MATRIX PURE fastInverse3(const MATRIX& x) {
165     typedef typename MATRIX::value_type T;
166 
167     // Assuming the input matrix is:
168     // | a b c |
169     // | d e f |
170     // | g h i |
171     //
172     // The analytic inverse is
173     // | A B C |^T
174     // | D E F |
175     // | G H I | / determinant
176     //
177     // Which is
178     // | A D G |
179     // | B E H |
180     // | C F I | / determinant
181     //
182     // Where:
183     // A = (ei - fh), B = (fg - di), C = (dh - eg)
184     // D = (ch - bi), E = (ai - cg), F = (bg - ah)
185     // G = (bf - ce), H = (cd - af), I = (ae - bd)
186     //
187     // and the determinant is a*A + b*B + c*C (The rule of Sarrus)
188     //
189     // Importantly, our matrices are column-major!
190 
191     MATRIX inverted(MATRIX::NO_INIT);
192 
193     const T a = x[0][0];
194     const T b = x[1][0];
195     const T c = x[2][0];
196     const T d = x[0][1];
197     const T e = x[1][1];
198     const T f = x[2][1];
199     const T g = x[0][2];
200     const T h = x[1][2];
201     const T i = x[2][2];
202 
203     // Do the full analytic inverse
204     const T A = e * i - f * h;
205     const T B = f * g - d * i;
206     const T C = d * h - e * g;
207     inverted[0][0] = A;                 // A
208     inverted[0][1] = B;                 // B
209     inverted[0][2] = C;                 // C
210     inverted[1][0] = c * h - b * i;     // D
211     inverted[1][1] = a * i - c * g;     // E
212     inverted[1][2] = b * g - a * h;     // F
213     inverted[2][0] = b * f - c * e;     // G
214     inverted[2][1] = c * d - a * f;     // H
215     inverted[2][2] = a * e - b * d;     // I
216 
217     const T det(a * A + b * B + c * C);
218     for (size_t col = 0; col < 3; ++col) {
219         for (size_t row = 0; row < 3; ++row) {
220             inverted[col][row] /= det;
221         }
222     }
223 
224     return inverted;
225 }
226 
227 /**
228  * Inversion function which switches on the matrix size.
229  * @warning This function assumes the matrix is invertible. The result is
230  * undefined if it is not. It is the responsibility of the caller to
231  * make sure the matrix is not singular.
232  */
233 template <typename MATRIX>
inverse(const MATRIX & matrix)234 inline constexpr MATRIX PURE inverse(const MATRIX& matrix) {
235     static_assert(MATRIX::NUM_ROWS == MATRIX::NUM_COLS, "only square matrices can be inverted");
236     return (MATRIX::NUM_ROWS == 2) ? fastInverse2<MATRIX>(matrix) :
237           ((MATRIX::NUM_ROWS == 3) ? fastInverse3<MATRIX>(matrix) :
238                     gaussJordanInverse<MATRIX>(matrix));
239 }
240 
241 template<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B>
multiply(const MATRIX_A & lhs,const MATRIX_B & rhs)242 CONSTEXPR MATRIX_R PURE multiply(const MATRIX_A& lhs, const MATRIX_B& rhs) {
243     // pre-requisite:
244     //  lhs : D columns, R rows
245     //  rhs : C columns, D rows
246     //  res : C columns, R rows
247 
248     static_assert(MATRIX_A::NUM_COLS == MATRIX_B::NUM_ROWS,
249             "matrices can't be multiplied. invalid dimensions.");
250     static_assert(MATRIX_R::NUM_COLS == MATRIX_B::NUM_COLS,
251             "invalid dimension of matrix multiply result.");
252     static_assert(MATRIX_R::NUM_ROWS == MATRIX_A::NUM_ROWS,
253             "invalid dimension of matrix multiply result.");
254 
255     MATRIX_R res(MATRIX_R::NO_INIT);
256     for (size_t col = 0; col < MATRIX_R::NUM_COLS; ++col) {
257         res[col] = lhs * rhs[col];
258     }
259     return res;
260 }
261 
262 // transpose. this handles matrices of matrices
263 template <typename MATRIX>
transpose(const MATRIX & m)264 CONSTEXPR MATRIX PURE transpose(const MATRIX& m) {
265     // for now we only handle square matrix transpose
266     static_assert(MATRIX::NUM_COLS == MATRIX::NUM_ROWS, "transpose only supports square matrices");
267     MATRIX result(MATRIX::NO_INIT);
268     for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) {
269         for (size_t row = 0; row < MATRIX::NUM_ROWS; ++row) {
270             result[col][row] = transpose(m[row][col]);
271         }
272     }
273     return result;
274 }
275 
276 // trace. this handles matrices of matrices
277 template <typename MATRIX>
trace(const MATRIX & m)278 CONSTEXPR typename MATRIX::value_type PURE trace(const MATRIX& m) {
279     static_assert(MATRIX::NUM_COLS == MATRIX::NUM_ROWS, "trace only defined for square matrices");
280     typename MATRIX::value_type result(0);
281     for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) {
282         result += trace(m[col][col]);
283     }
284     return result;
285 }
286 
287 // diag. this handles matrices of matrices
288 template <typename MATRIX>
diag(const MATRIX & m)289 CONSTEXPR typename MATRIX::col_type PURE diag(const MATRIX& m) {
290     static_assert(MATRIX::NUM_COLS == MATRIX::NUM_ROWS, "diag only defined for square matrices");
291     typename MATRIX::col_type result(MATRIX::col_type::NO_INIT);
292     for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) {
293         result[col] = m[col][col];
294     }
295     return result;
296 }
297 
298 //------------------------------------------------------------------------------
299 // This is taken from the Imath MatrixAlgo code, and is identical to Eigen.
300 template <typename MATRIX>
extractQuat(const MATRIX & mat)301 TQuaternion<typename MATRIX::value_type> extractQuat(const MATRIX& mat) {
302     typedef typename MATRIX::value_type T;
303 
304     TQuaternion<T> quat(TQuaternion<T>::NO_INIT);
305 
306     // Compute the trace to see if it is positive or not.
307     const T trace = mat[0][0] + mat[1][1] + mat[2][2];
308 
309     // check the sign of the trace
310     if (LIKELY(trace > 0)) {
311         // trace is positive
312         T s = std::sqrt(trace + 1);
313         quat.w = T(0.5) * s;
314         s = T(0.5) / s;
315         quat.x = (mat[1][2] - mat[2][1]) * s;
316         quat.y = (mat[2][0] - mat[0][2]) * s;
317         quat.z = (mat[0][1] - mat[1][0]) * s;
318     } else {
319         // trace is negative
320 
321         // Find the index of the greatest diagonal
322         size_t i = 0;
323         if (mat[1][1] > mat[0][0]) { i = 1; }
324         if (mat[2][2] > mat[i][i]) { i = 2; }
325 
326         // Get the next indices: (n+1)%3
327         static constexpr size_t next_ijk[3] = { 1, 2, 0 };
328         size_t j = next_ijk[i];
329         size_t k = next_ijk[j];
330         T s = std::sqrt((mat[i][i] - (mat[j][j] + mat[k][k])) + 1);
331         quat[i] = T(0.5) * s;
332         if (s != 0) {
333             s = T(0.5) / s;
334         }
335         quat.w  = (mat[j][k] - mat[k][j]) * s;
336         quat[j] = (mat[i][j] + mat[j][i]) * s;
337         quat[k] = (mat[i][k] + mat[k][i]) * s;
338     }
339     return quat;
340 }
341 
342 template <typename MATRIX>
asString(const MATRIX & m)343 String8 asString(const MATRIX& m) {
344     String8 s;
345     for (size_t c = 0; c < MATRIX::COL_SIZE; c++) {
346         s.append("|  ");
347         for (size_t r = 0; r < MATRIX::ROW_SIZE; r++) {
348             s.appendFormat("%7.2f  ", m[r][c]);
349         }
350         s.append("|\n");
351     }
352     return s;
353 }
354 
355 }  // namespace matrix
356 
357 // -------------------------------------------------------------------------------------
358 
359 /*
360  * TMatProductOperators implements basic arithmetic and basic compound assignments
361  * operators on a vector of type BASE<T>.
362  *
363  * BASE only needs to implement operator[] and size().
364  * By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically
365  * get all the functionality here.
366  */
367 
368 template <template<typename T> class BASE, typename T>
369 class TMatProductOperators {
370 public:
371     // multiply by a scalar
372     BASE<T>& operator *= (T v) {
373         BASE<T>& lhs(static_cast< BASE<T>& >(*this));
374         for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
375             lhs[col] *= v;
376         }
377         return lhs;
378     }
379 
380     //  matrix *= matrix
381     template<typename U>
382     const BASE<T>& operator *= (const BASE<U>& rhs) {
383         BASE<T>& lhs(static_cast< BASE<T>& >(*this));
384         lhs = matrix::multiply<BASE<T> >(lhs, rhs);
385         return lhs;
386     }
387 
388     // divide by a scalar
389     BASE<T>& operator /= (T v) {
390         BASE<T>& lhs(static_cast< BASE<T>& >(*this));
391         for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
392             lhs[col] /= v;
393         }
394         return lhs;
395     }
396 
397     // matrix * matrix, result is a matrix of the same type than the lhs matrix
398     template<typename U>
399     friend CONSTEXPR BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) {
400         return matrix::multiply<BASE<T> >(lhs, rhs);
401     }
402 };
403 
404 /*
405  * TMatSquareFunctions implements functions on a matrix of type BASE<T>.
406  *
407  * BASE only needs to implement:
408  *  - operator[]
409  *  - col_type
410  *  - row_type
411  *  - COL_SIZE
412  *  - ROW_SIZE
413  *
414  * By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
415  * get all the functionality here.
416  */
417 
418 template<template<typename U> class BASE, typename T>
419 class TMatSquareFunctions {
420 public:
421 
422     /*
423      * NOTE: the functions below ARE NOT member methods. They are friend functions
424      * with they definition inlined with their declaration. This makes these
425      * template functions available to the compiler when (and only when) this class
426      * is instantiated, at which point they're only templated on the 2nd parameter
427      * (the first one, BASE<T> being known).
428      */
inverse(const BASE<T> & matrix)429     friend inline CONSTEXPR BASE<T> PURE inverse(const BASE<T>& matrix) {
430         return matrix::inverse(matrix);
431     }
transpose(const BASE<T> & m)432     friend inline constexpr BASE<T> PURE transpose(const BASE<T>& m) {
433         return matrix::transpose(m);
434     }
trace(const BASE<T> & m)435     friend inline constexpr T PURE trace(const BASE<T>& m) {
436         return matrix::trace(m);
437     }
438 };
439 
440 template<template<typename U> class BASE, typename T>
441 class TMatHelpers {
442 public:
getColumnSize()443     constexpr inline size_t getColumnSize() const   { return BASE<T>::COL_SIZE; }
getRowSize()444     constexpr inline size_t getRowSize() const      { return BASE<T>::ROW_SIZE; }
getColumnCount()445     constexpr inline size_t getColumnCount() const  { return BASE<T>::NUM_COLS; }
getRowCount()446     constexpr inline size_t getRowCount() const     { return BASE<T>::NUM_ROWS; }
size()447     constexpr inline size_t size()  const           { return BASE<T>::ROW_SIZE; }  // for TVec*<>
448 
449     // array access
asArray()450     constexpr T const* asArray() const {
451         return &static_cast<BASE<T> const &>(*this)[0][0];
452     }
453 
454     // element access
operator()455     inline constexpr T const& operator()(size_t row, size_t col) const {
456         return static_cast<BASE<T> const &>(*this)[col][row];
457     }
458 
operator()459     inline T& operator()(size_t row, size_t col) {
460         return static_cast<BASE<T>&>(*this)[col][row];
461     }
462 
463     template <typename VEC>
translate(const VEC & t)464     static CONSTEXPR BASE<T> translate(const VEC& t) {
465         BASE<T> r;
466         r[BASE<T>::NUM_COLS-1] = t;
467         return r;
468     }
469 
470     template <typename VEC>
scale(const VEC & s)471     static constexpr BASE<T> scale(const VEC& s) {
472         return BASE<T>(s);
473     }
474 
abs(BASE<T> m)475     friend inline CONSTEXPR BASE<T> PURE abs(BASE<T> m) {
476         for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
477             m[col] = abs(m[col]);
478         }
479         return m;
480     }
481 };
482 
483 // functions for 3x3 and 4x4 matrices
484 template<template<typename U> class BASE, typename T>
485 class TMatTransform {
486 public:
TMatTransform()487     inline constexpr TMatTransform() {
488         static_assert(BASE<T>::NUM_ROWS == 3 || BASE<T>::NUM_ROWS == 4, "3x3 or 4x4 matrices only");
489     }
490 
491     template <typename A, typename VEC>
rotate(A radian,const VEC & about)492     static CONSTEXPR BASE<T> rotate(A radian, const VEC& about) {
493         BASE<T> r;
494         T c = std::cos(radian);
495         T s = std::sin(radian);
496         if (about.x == 1 && about.y == 0 && about.z == 0) {
497             r[1][1] = c;   r[2][2] = c;
498             r[1][2] = s;   r[2][1] = -s;
499         } else if (about.x == 0 && about.y == 1 && about.z == 0) {
500             r[0][0] = c;   r[2][2] = c;
501             r[2][0] = s;   r[0][2] = -s;
502         } else if (about.x == 0 && about.y == 0 && about.z == 1) {
503             r[0][0] = c;   r[1][1] = c;
504             r[0][1] = s;   r[1][0] = -s;
505         } else {
506             VEC nabout = normalize(about);
507             typename VEC::value_type x = nabout.x;
508             typename VEC::value_type y = nabout.y;
509             typename VEC::value_type z = nabout.z;
510             T nc = 1 - c;
511             T xy = x * y;
512             T yz = y * z;
513             T zx = z * x;
514             T xs = x * s;
515             T ys = y * s;
516             T zs = z * s;
517             r[0][0] = x*x*nc +  c;    r[1][0] =  xy*nc - zs;    r[2][0] =  zx*nc + ys;
518             r[0][1] =  xy*nc + zs;    r[1][1] = y*y*nc +  c;    r[2][1] =  yz*nc - xs;
519             r[0][2] =  zx*nc - ys;    r[1][2] =  yz*nc + xs;    r[2][2] = z*z*nc +  c;
520 
521             // Clamp results to -1, 1.
522             for (size_t col = 0; col < 3; ++col) {
523                 for (size_t row = 0; row < 3; ++row) {
524                     r[col][row] = std::min(std::max(r[col][row], T(-1)), T(1));
525                 }
526             }
527         }
528         return r;
529     }
530 
531     /**
532      * Create a matrix from euler angles using YPR around YXZ respectively
533      * @param yaw about Y axis
534      * @param pitch about X axis
535      * @param roll about Z axis
536      */
537     template <
538         typename Y, typename P, typename R,
539         typename = typename std::enable_if<std::is_arithmetic<Y>::value >::type,
540         typename = typename std::enable_if<std::is_arithmetic<P>::value >::type,
541         typename = typename std::enable_if<std::is_arithmetic<R>::value >::type
542     >
eulerYXZ(Y yaw,P pitch,R roll)543     static CONSTEXPR BASE<T> eulerYXZ(Y yaw, P pitch, R roll) {
544         return eulerZYX(roll, pitch, yaw);
545     }
546 
547     /**
548      * Create a matrix from euler angles using YPR around ZYX respectively
549      * @param roll about X axis
550      * @param pitch about Y axis
551      * @param yaw about Z axis
552      *
553      * The euler angles are applied in ZYX order. i.e: a vector is first rotated
554      * about X (roll) then Y (pitch) and then Z (yaw).
555      */
556     template <
557     typename Y, typename P, typename R,
558     typename = typename std::enable_if<std::is_arithmetic<Y>::value >::type,
559     typename = typename std::enable_if<std::is_arithmetic<P>::value >::type,
560     typename = typename std::enable_if<std::is_arithmetic<R>::value >::type
561     >
eulerZYX(Y yaw,P pitch,R roll)562     static CONSTEXPR BASE<T> eulerZYX(Y yaw, P pitch, R roll) {
563         BASE<T> r;
564         T cy = std::cos(yaw);
565         T sy = std::sin(yaw);
566         T cp = std::cos(pitch);
567         T sp = std::sin(pitch);
568         T cr = std::cos(roll);
569         T sr = std::sin(roll);
570         T cc = cr * cy;
571         T cs = cr * sy;
572         T sc = sr * cy;
573         T ss = sr * sy;
574         r[0][0] = cp * cy;
575         r[0][1] = cp * sy;
576         r[0][2] = -sp;
577         r[1][0] = sp * sc - cs;
578         r[1][1] = sp * ss + cc;
579         r[1][2] = cp * sr;
580         r[2][0] = sp * cc + ss;
581         r[2][1] = sp * cs - sc;
582         r[2][2] = cp * cr;
583 
584         // Clamp results to -1, 1.
585         for (size_t col = 0; col < 3; ++col) {
586             for (size_t row = 0; row < 3; ++row) {
587                 r[col][row] = std::min(std::max(r[col][row], T(-1)), T(1));
588             }
589         }
590         return r;
591     }
592 
toQuaternion()593     TQuaternion<T> toQuaternion() const {
594         return matrix::extractQuat(static_cast<const BASE<T>&>(*this));
595     }
596 };
597 
598 
599 template <template<typename T> class BASE, typename T>
600 class TMatDebug {
601 public:
602     friend std::ostream& operator<<(std::ostream& stream, const BASE<T>& m) {
603         for (size_t row = 0; row < BASE<T>::NUM_ROWS; ++row) {
604             if (row != 0) {
605                 stream << std::endl;
606             }
607             if (row == 0) {
608                 stream << "/ ";
609             } else if (row == BASE<T>::NUM_ROWS-1) {
610                 stream << "\\ ";
611             } else {
612                 stream << "| ";
613             }
614             for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) {
615                 stream << std::setw(10) << std::to_string(m[col][row]);
616             }
617             if (row == 0) {
618                 stream << " \\";
619             } else if (row == BASE<T>::NUM_ROWS-1) {
620                 stream << " /";
621             } else {
622                 stream << " |";
623             }
624         }
625         return stream;
626     }
627 
asString()628     String8 asString() const {
629         return matrix::asString(static_cast<const BASE<T>&>(*this));
630     }
631 };
632 
633 // -------------------------------------------------------------------------------------
634 }  // namespace details
635 }  // namespace android
636 
637 #ifdef LIKELY_DEFINED_LOCAL
638 #undef LIKELY_DEFINED_LOCAL
639 #undef LIKELY
640 #undef UNLIKELY
641 #endif //LIKELY_DEFINED_LOCAL
642 
643 #undef PURE
644 #undef CONSTEXPR
645