1595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/* 2595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Copyright 2013 The Android Open Source Project 3595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * 4595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 5595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * you may not use this file except in compliance with the License. 6595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * You may obtain a copy of the License at 7595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * 8595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 9595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * 10595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Unless required by applicable law or agreed to in writing, software 11595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 12595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * See the License for the specific language governing permissions and 14595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * limitations under the License. 15595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */ 16595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 171d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#pragma once 18595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <math.h> 20595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#include <stdint.h> 21595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#include <sys/types.h> 225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <cmath> 245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <exception> 255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <iomanip> 265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <stdexcept> 275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 281d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#include <math/quat.h> 291d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#include <math/TVecHelpers.h> 305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <utils/String8.h> 325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 3347df7e3817badac69c6a875d6c230f930bf73b47Jaesoo Lee#ifndef LIKELY 3447df7e3817badac69c6a875d6c230f930bf73b47Jaesoo Lee#define LIKELY_DEFINED_LOCAL 355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#ifdef __cplusplus 365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy# define LIKELY( exp ) (__builtin_expect( !!(exp), true )) 375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy# define UNLIKELY( exp ) (__builtin_expect( !!(exp), false )) 385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#else 395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy# define LIKELY( exp ) (__builtin_expect( !!(exp), 1 )) 405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy# define UNLIKELY( exp ) (__builtin_expect( !!(exp), 0 )) 415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#endif 4247df7e3817badac69c6a875d6c230f930bf73b47Jaesoo Lee#endif 43595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 44595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#define PURE __attribute__((pure)) 45595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 46caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#if __cplusplus >= 201402L 47caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#define CONSTEXPR constexpr 48caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#else 49caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#define CONSTEXPR 50caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#endif 51caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy 52595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiannamespace android { 535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guynamespace details { 54595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian// ------------------------------------------------------------------------------------- 55595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 56595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/* 57595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * No user serviceable parts here. 58595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * 59595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Don't use this file directly, instead include ui/mat*.h 60595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */ 61595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 62595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 63595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/* 64595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Matrix utilities 65595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */ 66595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 67595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiannamespace matrix { 68595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyinline constexpr int transpose(int v) { return v; } 705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyinline constexpr float transpose(float v) { return v; } 715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyinline constexpr double transpose(double v) { return v; } 72595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyinline constexpr int trace(int v) { return v; } 745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyinline constexpr float trace(float v) { return v; } 755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyinline constexpr double trace(double v) { return v; } 76595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy/* 785d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * Matrix inversion 795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy */ 80595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiantemplate<typename MATRIX> 815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain GuyMATRIX PURE gaussJordanInverse(const MATRIX& src) { 825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typedef typename MATRIX::value_type T; 835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static constexpr unsigned int N = MATRIX::NUM_ROWS; 84595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian MATRIX tmp(src); 855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy MATRIX inverted(1); 865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t i = 0; i < N; ++i) { 885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // look for largest element in i'th column 895d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy size_t swap = i; 905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T t = std::abs(tmp[i][i]); 915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t j = i + 1; j < N; ++j) { 925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T t2 = std::abs(tmp[j][i]); 935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (t2 > t) { 94595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian swap = j; 955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy t = t2; 96595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 97595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 98595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 99595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian if (swap != i) { 1005d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // swap columns. 1015d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy std::swap(tmp[i], tmp[swap]); 1025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy std::swap(inverted[i], inverted[swap]); 103595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 104595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 1055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T denom(tmp[i][i]); 1065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t k = 0; k < N; ++k) { 1075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy tmp[i][k] /= denom; 1085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[i][k] /= denom; 109595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 1105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Factor out the lower triangle 1125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t j = 0; j < N; ++j) { 113595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian if (j != i) { 114caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy const T d = tmp[j][i]; 1155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t k = 0; k < N; ++k) { 116caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy tmp[j][k] -= tmp[i][k] * d; 117caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy inverted[j][k] -= inverted[i][k] * d; 118595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 119595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 120595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 121595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 1225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return inverted; 1245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy} 1255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy//------------------------------------------------------------------------------ 1285d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// 2x2 matrix inverse is easy. 1295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate <typename MATRIX> 130caf2ca414f69d460c516e2370cf42bcf49178d95Romain GuyCONSTEXPR MATRIX PURE fastInverse2(const MATRIX& x) { 1315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typedef typename MATRIX::value_type T; 1325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Assuming the input matrix is: 1345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | a b | 1355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | c d | 1365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // 1375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // The analytic inverse is 1385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | d -b | 1395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | -c a | / (a d - b c) 1405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // 1415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Importantly, our matrices are column-major! 1425d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1435d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy MATRIX inverted(MATRIX::NO_INIT); 1445d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T a = x[0][0]; 1465d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T c = x[0][1]; 1475d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T b = x[1][0]; 1485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T d = x[1][1]; 1495d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T det((a * d) - (b * c)); 1515d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[0][0] = d / det; 1525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[0][1] = -c / det; 1535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[1][0] = -b / det; 1545d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[1][1] = a / det; 1555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return inverted; 1565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy} 1575d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1585d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1595d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy//------------------------------------------------------------------------------ 1605d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// From the Wikipedia article on matrix inversion's section on fast 3x3 1615d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// matrix inversion: 1625d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// http://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3.C3.973_matrices 1635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate <typename MATRIX> 164caf2ca414f69d460c516e2370cf42bcf49178d95Romain GuyCONSTEXPR MATRIX PURE fastInverse3(const MATRIX& x) { 1655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typedef typename MATRIX::value_type T; 1665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1675d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Assuming the input matrix is: 1685d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | a b c | 1695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | d e f | 1705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | g h i | 1715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // 1725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // The analytic inverse is 1735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | A B C |^T 1745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | D E F | 1755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | G H I | / determinant 1765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // 1775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Which is 1785d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | A D G | 1795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | B E H | 1805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // | C F I | / determinant 1815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // 1825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Where: 1835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // A = (ei - fh), B = (fg - di), C = (dh - eg) 1845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // D = (ch - bi), E = (ai - cg), F = (bg - ah) 1855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // G = (bf - ce), H = (cd - af), I = (ae - bd) 1865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // 1875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // and the determinant is a*A + b*B + c*C (The rule of Sarrus) 1885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // 1895d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Importantly, our matrices are column-major! 1905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy MATRIX inverted(MATRIX::NO_INIT); 1925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 1935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T a = x[0][0]; 1945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T b = x[1][0]; 1955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T c = x[2][0]; 1965d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T d = x[0][1]; 1975d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T e = x[1][1]; 1985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T f = x[2][1]; 1995d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T g = x[0][2]; 2005d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T h = x[1][2]; 2015d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T i = x[2][2]; 2025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 2035d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Do the full analytic inverse 2045d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T A = e * i - f * h; 2055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T B = f * g - d * i; 2065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T C = d * h - e * g; 2075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[0][0] = A; // A 2085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[0][1] = B; // B 2095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[0][2] = C; // C 2105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[1][0] = c * h - b * i; // D 2115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[1][1] = a * i - c * g; // E 2125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[1][2] = b * g - a * h; // F 2135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[2][0] = b * f - c * e; // G 2145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[2][1] = c * d - a * f; // H 2155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[2][2] = a * e - b * d; // I 2165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 2175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T det(a * A + b * B + c * C); 2185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < 3; ++col) { 2195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t row = 0; row < 3; ++row) { 2205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inverted[col][row] /= det; 2215d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 2225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 2235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 2245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return inverted; 2255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy} 2265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 2275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy/** 2285d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * Inversion function which switches on the matrix size. 2295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * @warning This function assumes the matrix is invertible. The result is 2305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * undefined if it is not. It is the responsibility of the caller to 2315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * make sure the matrix is not singular. 2325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy */ 2335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate <typename MATRIX> 2345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyinline constexpr MATRIX PURE inverse(const MATRIX& matrix) { 2355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(MATRIX::NUM_ROWS == MATRIX::NUM_COLS, "only square matrices can be inverted"); 2365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return (MATRIX::NUM_ROWS == 2) ? fastInverse2<MATRIX>(matrix) : 2375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy ((MATRIX::NUM_ROWS == 3) ? fastInverse3<MATRIX>(matrix) : 2385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy gaussJordanInverse<MATRIX>(matrix)); 239595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian} 240595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 241595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiantemplate<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B> 242caf2ca414f69d460c516e2370cf42bcf49178d95Romain GuyCONSTEXPR MATRIX_R PURE multiply(const MATRIX_A& lhs, const MATRIX_B& rhs) { 243595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian // pre-requisite: 244595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian // lhs : D columns, R rows 245595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian // rhs : C columns, D rows 246595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian // res : C columns, R rows 247595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 2485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(MATRIX_A::NUM_COLS == MATRIX_B::NUM_ROWS, 2495d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy "matrices can't be multiplied. invalid dimensions."); 2505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(MATRIX_R::NUM_COLS == MATRIX_B::NUM_COLS, 2515d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy "invalid dimension of matrix multiply result."); 2525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(MATRIX_R::NUM_ROWS == MATRIX_A::NUM_ROWS, 2535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy "invalid dimension of matrix multiply result."); 254595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 255595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian MATRIX_R res(MATRIX_R::NO_INIT); 2565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < MATRIX_R::NUM_COLS; ++col) { 2575d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy res[col] = lhs * rhs[col]; 258595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 259595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian return res; 260595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian} 261595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 262595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian// transpose. this handles matrices of matrices 263595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiantemplate <typename MATRIX> 264caf2ca414f69d460c516e2370cf42bcf49178d95Romain GuyCONSTEXPR MATRIX PURE transpose(const MATRIX& m) { 265595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian // for now we only handle square matrix transpose 2665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(MATRIX::NUM_COLS == MATRIX::NUM_ROWS, "transpose only supports square matrices"); 267595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian MATRIX result(MATRIX::NO_INIT); 2685d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) { 2695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t row = 0; row < MATRIX::NUM_ROWS; ++row) { 2705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy result[col][row] = transpose(m[row][col]); 2715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 2725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 273595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian return result; 274595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian} 275595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 276595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian// trace. this handles matrices of matrices 277595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiantemplate <typename MATRIX> 278caf2ca414f69d460c516e2370cf42bcf49178d95Romain GuyCONSTEXPR typename MATRIX::value_type PURE trace(const MATRIX& m) { 2795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(MATRIX::NUM_COLS == MATRIX::NUM_ROWS, "trace only defined for square matrices"); 280595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian typename MATRIX::value_type result(0); 2815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) { 2825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy result += trace(m[col][col]); 2835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 284595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian return result; 285595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian} 286595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 2875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// diag. this handles matrices of matrices 288595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiantemplate <typename MATRIX> 289caf2ca414f69d460c516e2370cf42bcf49178d95Romain GuyCONSTEXPR typename MATRIX::col_type PURE diag(const MATRIX& m) { 2905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(MATRIX::NUM_COLS == MATRIX::NUM_ROWS, "diag only defined for square matrices"); 291595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian typename MATRIX::col_type result(MATRIX::col_type::NO_INIT); 2925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < MATRIX::NUM_COLS; ++col) { 2935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy result[col] = m[col][col]; 2945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 295595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian return result; 296595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian} 297595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 2985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy//------------------------------------------------------------------------------ 2995d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// This is taken from the Imath MatrixAlgo code, and is identical to Eigen. 3005d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate <typename MATRIX> 3015d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain GuyTQuaternion<typename MATRIX::value_type> extractQuat(const MATRIX& mat) { 3025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typedef typename MATRIX::value_type T; 3035d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 3045d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy TQuaternion<T> quat(TQuaternion<T>::NO_INIT); 3055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 3065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Compute the trace to see if it is positive or not. 3075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const T trace = mat[0][0] + mat[1][1] + mat[2][2]; 3085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 3095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // check the sign of the trace 3105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (LIKELY(trace > 0)) { 3115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // trace is positive 3125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T s = std::sqrt(trace + 1); 3135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat.w = T(0.5) * s; 3145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy s = T(0.5) / s; 3155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat.x = (mat[1][2] - mat[2][1]) * s; 3165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat.y = (mat[2][0] - mat[0][2]) * s; 3175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat.z = (mat[0][1] - mat[1][0]) * s; 3185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else { 3195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // trace is negative 3205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 3215d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Find the index of the greatest diagonal 3225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy size_t i = 0; 3235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (mat[1][1] > mat[0][0]) { i = 1; } 3245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (mat[2][2] > mat[i][i]) { i = 2; } 3255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 3265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Get the next indices: (n+1)%3 3275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static constexpr size_t next_ijk[3] = { 1, 2, 0 }; 3285d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy size_t j = next_ijk[i]; 3295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy size_t k = next_ijk[j]; 3305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T s = std::sqrt((mat[i][i] - (mat[j][j] + mat[k][k])) + 1); 3315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat[i] = T(0.5) * s; 3325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (s != 0) { 3335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy s = T(0.5) / s; 3345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 3355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat.w = (mat[j][k] - mat[k][j]) * s; 3365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat[j] = (mat[i][j] + mat[j][i]) * s; 3375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy quat[k] = (mat[i][k] + mat[k][i]) * s; 3385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 3395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return quat; 3405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy} 3415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 342595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiantemplate <typename MATRIX> 343595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias AgopianString8 asString(const MATRIX& m) { 344595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian String8 s; 3455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t c = 0; c < MATRIX::col_size(); c++) { 346595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian s.append("| "); 3475d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t r = 0; r < MATRIX::row_size(); r++) { 348595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian s.appendFormat("%7.2f ", m[r][c]); 349595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 350595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian s.append("|\n"); 351595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian } 352595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian return s; 353595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian} 354595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 3555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy} // namespace matrix 356595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 357595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian// ------------------------------------------------------------------------------------- 3581d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 3591d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian/* 3601d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * TMatProductOperators implements basic arithmetic and basic compound assignments 3611d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * operators on a vector of type BASE<T>. 3621d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * 3631d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * BASE only needs to implement operator[] and size(). 3641d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically 3651d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * get all the functionality here. 3661d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian */ 3671d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 3681d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopiantemplate <template<typename T> class BASE, typename T> 3691d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianclass TMatProductOperators { 3701d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianpublic: 3711d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian // multiply by a scalar 3721d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian BASE<T>& operator *= (T v) { 3731d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian BASE<T>& lhs(static_cast< BASE<T>& >(*this)); 3745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) { 3755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy lhs[col] *= v; 3761d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian } 3771d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian return lhs; 3781d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian } 3791d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 3805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // matrix *= matrix 3815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy template<typename U> 3825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy const BASE<T>& operator *= (const BASE<U>& rhs) { 3835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy BASE<T>& lhs(static_cast< BASE<T>& >(*this)); 3845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy lhs = matrix::multiply<BASE<T> >(lhs, rhs); 3855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return lhs; 3865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 3875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 3881d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian // divide by a scalar 3891d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian BASE<T>& operator /= (T v) { 3901d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian BASE<T>& lhs(static_cast< BASE<T>& >(*this)); 3915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) { 3925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy lhs[col] /= v; 3931d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian } 3941d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian return lhs; 3951d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian } 3961d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 3971d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian // matrix * matrix, result is a matrix of the same type than the lhs matrix 3981d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian template<typename U> 399caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy friend CONSTEXPR BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) { 4001d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian return matrix::multiply<BASE<T> >(lhs, rhs); 4011d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian } 4021d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian}; 4031d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 4041d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian/* 4051d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * TMatSquareFunctions implements functions on a matrix of type BASE<T>. 4061d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * 4071d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * BASE only needs to implement: 4081d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * - operator[] 4091d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * - col_type 4101d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * - row_type 4111d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * - COL_SIZE 4121d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * - ROW_SIZE 4131d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * 4141d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically 4151d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * get all the functionality here. 4161d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian */ 4171d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 4181d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopiantemplate<template<typename U> class BASE, typename T> 4191d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianclass TMatSquareFunctions { 4201d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianpublic: 4215d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4221d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian /* 4231d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * NOTE: the functions below ARE NOT member methods. They are friend functions 4241d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * with they definition inlined with their declaration. This makes these 4251d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * template functions available to the compiler when (and only when) this class 4261d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * is instantiated, at which point they're only templated on the 2nd parameter 4271d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * (the first one, BASE<T> being known). 4281d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian */ 429caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy friend inline CONSTEXPR BASE<T> PURE inverse(const BASE<T>& matrix) { 4305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return matrix::inverse(matrix); 4315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy friend inline constexpr BASE<T> PURE transpose(const BASE<T>& m) { 4335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return matrix::transpose(m); 4345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy friend inline constexpr T PURE trace(const BASE<T>& m) { 4365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return matrix::trace(m); 4375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}; 4395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate<template<typename U> class BASE, typename T> 4415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyclass TMatHelpers { 4425d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guypublic: 4435d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy constexpr inline size_t getColumnSize() const { return BASE<T>::COL_SIZE; } 4445d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy constexpr inline size_t getRowSize() const { return BASE<T>::ROW_SIZE; } 4455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy constexpr inline size_t getColumnCount() const { return BASE<T>::NUM_COLS; } 4465d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy constexpr inline size_t getRowCount() const { return BASE<T>::NUM_ROWS; } 4475d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy constexpr inline size_t size() const { return BASE<T>::ROW_SIZE; } // for TVec*<> 4485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4495d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // array access 4505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy constexpr T const* asArray() const { 4515d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return &static_cast<BASE<T> const &>(*this)[0][0]; 4525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4545d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // element access 4555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inline constexpr T const& operator()(size_t row, size_t col) const { 4565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return static_cast<BASE<T> const &>(*this)[col][row]; 4575d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4585d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4595d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inline T& operator()(size_t row, size_t col) { 4605d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return static_cast<BASE<T>&>(*this)[col][row]; 4615d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4625d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy template <typename VEC> 464caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy static CONSTEXPR BASE<T> translate(const VEC& t) { 4655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy BASE<T> r; 4665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[BASE<T>::NUM_COLS-1] = t; 4675d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return r; 4685d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy template <typename VEC> 4715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static constexpr BASE<T> scale(const VEC& s) { 4725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return BASE<T>(s); 4735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 475caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy friend inline CONSTEXPR BASE<T> PURE abs(BASE<T> m) { 4765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) { 4775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy m[col] = abs(m[col]); 4785d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return m; 4805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}; 4825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy// functions for 3x3 and 4x4 matrices 4845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate<template<typename U> class BASE, typename T> 4855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyclass TMatTransform { 4865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guypublic: 4875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy inline constexpr TMatTransform() { 4885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy static_assert(BASE<T>::NUM_ROWS == 3 || BASE<T>::NUM_ROWS == 4, "3x3 or 4x4 matrices only"); 4895d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 4905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 4915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy template <typename A, typename VEC> 492caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy static CONSTEXPR BASE<T> rotate(A radian, const VEC& about) { 4935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy BASE<T> r; 4945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T c = std::cos(radian); 4955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T s = std::sin(radian); 4965d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (about.x == 1 && about.y == 0 && about.z == 0) { 4975d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[1][1] = c; r[2][2] = c; 4985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[1][2] = s; r[2][1] = -s; 4995d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else if (about.x == 0 && about.y == 1 && about.z == 0) { 5005d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][0] = c; r[2][2] = c; 5015d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[2][0] = s; r[0][2] = -s; 5025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else if (about.x == 0 && about.y == 0 && about.z == 1) { 5035d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][0] = c; r[1][1] = c; 5045d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][1] = s; r[1][0] = -s; 5055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else { 5065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy VEC nabout = normalize(about); 5075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename VEC::value_type x = nabout.x; 5085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename VEC::value_type y = nabout.y; 5095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename VEC::value_type z = nabout.z; 5105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T nc = 1 - c; 5115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T xy = x * y; 5125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T yz = y * z; 5135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T zx = z * x; 5145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T xs = x * s; 5155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T ys = y * s; 5165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T zs = z * s; 5175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][0] = x*x*nc + c; r[1][0] = xy*nc - zs; r[2][0] = zx*nc + ys; 5185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][1] = xy*nc + zs; r[1][1] = y*y*nc + c; r[2][1] = yz*nc - xs; 5195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][2] = zx*nc - ys; r[1][2] = yz*nc + xs; r[2][2] = z*z*nc + c; 5205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 5215d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Clamp results to -1, 1. 5225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < 3; ++col) { 5235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t row = 0; row < 3; ++row) { 5245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[col][row] = std::min(std::max(r[col][row], T(-1)), T(1)); 5255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5285d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return r; 5295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 5315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy /** 5325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * Create a matrix from euler angles using YPR around YXZ respectively 5335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * @param yaw about Y axis 5345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * @param pitch about X axis 5355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * @param roll about Z axis 5365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy */ 5375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy template < 5385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename Y, typename P, typename R, 5395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename = typename std::enable_if<std::is_arithmetic<Y>::value >::type, 5405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename = typename std::enable_if<std::is_arithmetic<P>::value >::type, 5415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename = typename std::enable_if<std::is_arithmetic<R>::value >::type 5425d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy > 543caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy static CONSTEXPR BASE<T> eulerYXZ(Y yaw, P pitch, R roll) { 5445d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return eulerZYX(roll, pitch, yaw); 5455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5465d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 5475d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy /** 5485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * Create a matrix from euler angles using YPR around ZYX respectively 5495d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * @param roll about X axis 5505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * @param pitch about Y axis 5515d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * @param yaw about Z axis 5525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * 5535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * The euler angles are applied in ZYX order. i.e: a vector is first rotated 5545d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * about X (roll) then Y (pitch) and then Z (yaw). 5555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy */ 5565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy template < 5575d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename Y, typename P, typename R, 5585d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename = typename std::enable_if<std::is_arithmetic<Y>::value >::type, 5595d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename = typename std::enable_if<std::is_arithmetic<P>::value >::type, 5605d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy typename = typename std::enable_if<std::is_arithmetic<R>::value >::type 5615d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy > 562caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy static CONSTEXPR BASE<T> eulerZYX(Y yaw, P pitch, R roll) { 5635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy BASE<T> r; 5645d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T cy = std::cos(yaw); 5655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T sy = std::sin(yaw); 5665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T cp = std::cos(pitch); 5675d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T sp = std::sin(pitch); 5685d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T cr = std::cos(roll); 5695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T sr = std::sin(roll); 5705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T cc = cr * cy; 5715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T cs = cr * sy; 5725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T sc = sr * cy; 5735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy T ss = sr * sy; 5745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][0] = cp * cy; 5755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][1] = cp * sy; 5765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[0][2] = -sp; 5775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[1][0] = sp * sc - cs; 5785d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[1][1] = sp * ss + cc; 5795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[1][2] = cp * sr; 5805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[2][0] = sp * cc + ss; 5815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[2][1] = sp * cs - sc; 5825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[2][2] = cp * cr; 5835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 5845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy // Clamp results to -1, 1. 5855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < 3; ++col) { 5865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t row = 0; row < 3; ++row) { 5875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy r[col][row] = std::min(std::max(r[col][row], T(-1)), T(1)); 5885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5895d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return r; 5915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 5935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy TQuaternion<T> toQuaternion() const { 5945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return matrix::extractQuat(static_cast<const BASE<T>&>(*this)); 5955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 5961d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian}; 5971d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 5985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 5991d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopiantemplate <template<typename T> class BASE, typename T> 6001d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianclass TMatDebug { 6011d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianpublic: 6025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy friend std::ostream& operator<<(std::ostream& stream, const BASE<T>& m) { 6035d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t row = 0; row < BASE<T>::NUM_ROWS; ++row) { 6045d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (row != 0) { 6055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << std::endl; 6065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 6075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (row == 0) { 6085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << "/ "; 6095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else if (row == BASE<T>::NUM_ROWS-1) { 6105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << "\\ "; 6115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else { 6125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << "| "; 6135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 6145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy for (size_t col = 0; col < BASE<T>::NUM_COLS; ++col) { 6155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << std::setw(10) << std::to_string(m[col][row]); 6165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 6175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy if (row == 0) { 6185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << " \\"; 6195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else if (row == BASE<T>::NUM_ROWS-1) { 6205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << " /"; 6215d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } else { 6225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy stream << " |"; 6235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 6245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 6255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return stream; 6265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy } 6275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy 6281d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian String8 asString() const { 6295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy return matrix::asString(static_cast<const BASE<T>&>(*this)); 6301d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian } 6311d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian}; 6321d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian 6331d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian// ------------------------------------------------------------------------------------- 6345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy} // namespace details 6355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy} // namespace android 636595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian 63747df7e3817badac69c6a875d6c230f930bf73b47Jaesoo Lee#ifdef LIKELY_DEFINED_LOCAL 63847df7e3817badac69c6a875d6c230f930bf73b47Jaesoo Lee#undef LIKELY_DEFINED_LOCAL 6395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#undef LIKELY 6405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#undef UNLIKELY 64147df7e3817badac69c6a875d6c230f930bf73b47Jaesoo Lee#endif //LIKELY_DEFINED_LOCAL 64247df7e3817badac69c6a875d6c230f930bf73b47Jaesoo Lee 643595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#undef PURE 644caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#undef CONSTEXPR 645