mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
377 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba05572dcb | ||
|
|
5c3995769c | ||
|
|
fbe672d599 | ||
|
|
ca0ba0d9a4 | ||
|
|
c80587c92b | ||
|
|
3f1d0cdc22 | ||
|
|
78e93ac1ad | ||
|
|
3e37166d0b | ||
|
|
0585b2965d | ||
|
|
e6e77ed08b | ||
|
|
b238f387b4 | ||
|
|
c8db17301e | ||
|
|
a07bb428df | ||
|
|
598de8b193 | ||
|
|
e44519744e | ||
|
|
0a6ae41555 | ||
|
|
b730952414 | ||
|
|
7a0e96b80d | ||
|
|
51af6ae971 | ||
|
|
0a9ad6fc72 | ||
|
|
d5f88e2357 | ||
|
|
0b4b0f11e8 | ||
|
|
306daa24a3 | ||
|
|
8471cf1996 | ||
|
|
b0c5bfdf78 | ||
|
|
2ebb314fa7 | ||
|
|
530f20c21a | ||
|
|
c3ce4f9ac0 | ||
|
|
7d64e6752c | ||
|
|
0a4c4d40b4 | ||
|
|
3ecb343dc3 | ||
|
|
6ed571744b | ||
|
|
97feea9d39 | ||
|
|
ca6a2a5248 | ||
|
|
5f2dd503ff | ||
|
|
1644bafe29 | ||
|
|
b15a5dc3f4 | ||
|
|
aad72f3c6d | ||
|
|
3e194a6a73 | ||
|
|
58146be99b | ||
|
|
13fc18d3a2 | ||
|
|
2634f9386c | ||
|
|
9e8f07d7b5 | ||
|
|
b027d7a8cf | ||
|
|
b11aab5fcc | ||
|
|
53c77061f0 | ||
|
|
e8e56c7642 | ||
|
|
40f62974b7 | ||
|
|
cf20b30d65 | ||
|
|
03b63e182c | ||
|
|
d3943cd50c | ||
|
|
8fb162fc85 | ||
|
|
e36cb91c99 | ||
|
|
2e188dd4d4 | ||
|
|
15380f9a87 | ||
|
|
692b30ca95 | ||
|
|
050c681bdd | ||
|
|
e742da8b28 | ||
|
|
524fa4c46f | ||
|
|
737e4152c3 | ||
|
|
d0ee2267d6 | ||
|
|
a94791b69a | ||
|
|
ac63d6891c | ||
|
|
7e4a6754b2 | ||
|
|
38b6048e14 | ||
|
|
e74612b9a0 | ||
|
|
78d2926508 | ||
|
|
2e2f48e30e | ||
|
|
f939c351cb | ||
|
|
091d373ee9 | ||
|
|
471075f7ad | ||
|
|
5c366fe1d7 | ||
|
|
86711497c4 | ||
|
|
47150af1c8 | ||
|
|
89e315152c | ||
|
|
7f0599b6eb | ||
|
|
5727e4d89c | ||
|
|
5266ff8966 | ||
|
|
5c68051cd7 | ||
|
|
4860727ac2 | ||
|
|
507b661106 | ||
|
|
a498ff7df6 | ||
|
|
8ba3c41fcf | ||
|
|
a7473d6d5a | ||
|
|
5e64cea896 | ||
|
|
33fba3f08d | ||
|
|
bfc264abe8 | ||
|
|
e2e9cdd169 | ||
|
|
d485d12c51 | ||
|
|
48c635e223 | ||
|
|
9f3276981c | ||
|
|
80b5133789 | ||
|
|
4131074818 | ||
|
|
cb5cd69872 | ||
|
|
78b569f685 | ||
|
|
9c2b6c049b | ||
|
|
6f3cd529af | ||
|
|
d7f9679a34 | ||
|
|
ae1385c7e4 | ||
|
|
73b0012945 | ||
|
|
c84084c0c0 | ||
|
|
4387433acf | ||
|
|
aad20d700d | ||
|
|
8b69d5d730 | ||
|
|
ed7a220b04 | ||
|
|
ceee1c008b | ||
|
|
698ff69450 | ||
|
|
7f67e6dfdb | ||
|
|
765615609d | ||
|
|
3ed67cb0bb | ||
|
|
6af5ac7e27 | ||
|
|
2f6d1607c8 | ||
|
|
881b90e984 | ||
|
|
616a7a1912 | ||
|
|
409e887d78 | ||
|
|
9d6d0dff8f | ||
|
|
8b84801f7f | ||
|
|
422530946f | ||
|
|
67b4f45836 | ||
|
|
27f3970453 | ||
|
|
3860a0bc8f | ||
|
|
33500050c3 | ||
|
|
27d7628f16 | ||
|
|
2bda1b0d93 | ||
|
|
dd602e62c8 | ||
|
|
f3a00dd2b5 | ||
|
|
892afb9416 | ||
|
|
779774f98c | ||
|
|
6565f8d60f | ||
|
|
48dfe98abd | ||
|
|
fe29157d02 | ||
|
|
f6ac51a054 | ||
|
|
00d4e65f00 | ||
|
|
86caba838d | ||
|
|
b9f7a17e47 | ||
|
|
1301d744f8 | ||
|
|
2a69290ddb | ||
|
|
3946768916 | ||
|
|
77e27fbeee | ||
|
|
2ada122bc6 | ||
|
|
8f2bdde373 | ||
|
|
ba0f844d6b | ||
|
|
9bcdc8b756 | ||
|
|
50e3bbfc90 | ||
|
|
ca3746c6f8 | ||
|
|
8bde7da086 | ||
|
|
66cbabafed | ||
|
|
4b377715d7 | ||
|
|
aecc51a3e8 | ||
|
|
1fc3a21ed0 | ||
|
|
9fa2c8650e | ||
|
|
ac5377e161 | ||
|
|
5269d11935 | ||
|
|
26f9907542 | ||
|
|
608b1acd6d | ||
|
|
b2c6dc48d9 | ||
|
|
8a66ca4b10 | ||
|
|
59e9edfbf1 | ||
|
|
3ada6e4bed | ||
|
|
c3ca9b1e76 | ||
|
|
5dcc6d301a | ||
|
|
c771df6bc3 | ||
|
|
b91e021172 | ||
|
|
cb81975714 | ||
|
|
bf03820339 | ||
|
|
de05a18fe0 | ||
|
|
4cc2c73e6a | ||
|
|
ce3557ca69 | ||
|
|
6edd2e2851 | ||
|
|
4adeababf9 | ||
|
|
18f6e47815 | ||
|
|
ee62f168e6 | ||
|
|
ca7f061a5f | ||
|
|
50e203c717 | ||
|
|
fa9049a544 | ||
|
|
b33144e4df | ||
|
|
c0d56a543e | ||
|
|
488ad7dd1b | ||
|
|
779faaaeba | ||
|
|
1c8347e554 | ||
|
|
ff47717f25 | ||
|
|
309190cf02 | ||
|
|
c10620b2b0 | ||
|
|
73c8f2f697 | ||
|
|
e4d4d15588 | ||
|
|
4dfd888c92 | ||
|
|
028e299577 | ||
|
|
5f50f12d2c | ||
|
|
8321dcce76 | ||
|
|
eb6ba00cc8 | ||
|
|
a618094b62 | ||
|
|
228ae29591 | ||
|
|
471eac5399 | ||
|
|
d780983f59 | ||
|
|
85fb517eaf | ||
|
|
447f269561 | ||
|
|
b046a3f87d | ||
|
|
3cb914f332 | ||
|
|
e1642f485c | ||
|
|
19a95b3309 | ||
|
|
dabc81751f | ||
|
|
e13071dd13 | ||
|
|
d123717e21 | ||
|
|
87a8a1975e | ||
|
|
13df3441ae | ||
|
|
373c340b71 | ||
|
|
cadd124d73 | ||
|
|
05b0518077 | ||
|
|
adf864fec0 | ||
|
|
5a6be66cef | ||
|
|
13e93ca8b7 | ||
|
|
6c05c3dd49 | ||
|
|
49c0390ce0 | ||
|
|
d6c8366d84 | ||
|
|
039e225f7f | ||
|
|
c53f783705 | ||
|
|
ef54723dbe | ||
|
|
46475eff9a | ||
|
|
72a4d49315 | ||
|
|
f9f32e9e2d | ||
|
|
3d946e42b3 | ||
|
|
221f619bea | ||
|
|
a1e092d1e8 | ||
|
|
836fa25a82 | ||
|
|
84cf6e42ca | ||
|
|
7ae819123c | ||
|
|
218c37beb4 | ||
|
|
efe2c225c9 | ||
|
|
3456247437 | ||
|
|
8c48d42530 | ||
|
|
e7fbbc2748 | ||
|
|
1e2ab8b0b3 | ||
|
|
9c9e23858e | ||
|
|
cffe8bbff7 | ||
|
|
c57317035a | ||
|
|
1f84f0d33a | ||
|
|
68e803a26e | ||
|
|
e074f720c7 | ||
|
|
2915e1fc5d | ||
|
|
7e029d1d6e | ||
|
|
a93e354d92 | ||
|
|
6cd7b9ea6b | ||
|
|
8f4b4ad5fb | ||
|
|
35a8e94577 | ||
|
|
0decc31aa8 | ||
|
|
fd9caa1bc2 | ||
|
|
68d1897e8a | ||
|
|
fe60856fed | ||
|
|
0f56b5a6de | ||
|
|
965e595f02 | ||
|
|
1329c55875 | ||
|
|
441b7eaab2 | ||
|
|
8132a12625 | ||
|
|
bde9b456dc | ||
|
|
326320ec7b | ||
|
|
ea2e968257 | ||
|
|
0a6a50d1b0 | ||
|
|
00b2666853 | ||
|
|
504a4404f1 | ||
|
|
e47a8928ec | ||
|
|
6739f6bb1b | ||
|
|
ef3de20481 | ||
|
|
b3151bca40 | ||
|
|
a4c266f827 | ||
|
|
82147cefff | ||
|
|
068ccab9fe | ||
|
|
581b6472d1 | ||
|
|
59bacfe520 | ||
|
|
34ae80179a | ||
|
|
2556565b4b | ||
|
|
30dd6f5e34 | ||
|
|
fe73648c98 | ||
|
|
9636a8ed43 | ||
|
|
c83b754ee0 | ||
|
|
e3a8dfb02f | ||
|
|
64e68cbe87 | ||
|
|
5157ce8cbf | ||
|
|
aee693ac52 | ||
|
|
72096f3bd4 | ||
|
|
3e4a33d4ba | ||
|
|
1031223c09 | ||
|
|
5cf1e4c79b | ||
|
|
fe4b927e9c | ||
|
|
fe778427f2 | ||
|
|
5eea1c7f97 | ||
|
|
9506343349 | ||
|
|
b50d8f8c4a | ||
|
|
fad9828769 | ||
|
|
373bb12dc6 | ||
|
|
17b9a55d98 | ||
|
|
ca2cee2739 | ||
|
|
d92df04ce8 | ||
|
|
81099ef482 | ||
|
|
a20b58845f | ||
|
|
819d0cea1b | ||
|
|
f4404777ff | ||
|
|
fd220dd8b0 | ||
|
|
e256acec7c | ||
|
|
7995cec90c | ||
|
|
02fe89f5ef | ||
|
|
2693fd54bf | ||
|
|
c5b893f434 | ||
|
|
5e51a361fe | ||
|
|
ca5effa16c | ||
|
|
4057f9b1fc | ||
|
|
5fbe7aa604 | ||
|
|
a72752caac | ||
|
|
cc2f6d68b1 | ||
|
|
188590db82 | ||
|
|
8972323c08 | ||
|
|
5d94dc85e5 | ||
|
|
0d7039319c | ||
|
|
d3d7c6245d | ||
|
|
0eece608b4 | ||
|
|
78f37ca03c | ||
|
|
c52c8d76da | ||
|
|
d937a420a2 | ||
|
|
2d5731e40a | ||
|
|
49b005181a | ||
|
|
130f891bb0 | ||
|
|
7944d4431f | ||
|
|
647a51b426 | ||
|
|
a452dedb4f | ||
|
|
18c67df31c | ||
|
|
1569a7d7ab | ||
|
|
2b17f34574 | ||
|
|
841e075154 | ||
|
|
0425118e2a | ||
|
|
9537e8b118 | ||
|
|
eeb0d880ee | ||
|
|
8e198d6835 | ||
|
|
6edfe8771b | ||
|
|
6e1c086593 | ||
|
|
06206482d9 | ||
|
|
e30133e439 | ||
|
|
52e4cbf539 | ||
|
|
2aaaf22623 | ||
|
|
f899e08946 | ||
|
|
4c05fb03a3 | ||
|
|
577a07a86e | ||
|
|
3b8da4be5a | ||
|
|
2f28ccbea3 | ||
|
|
7a4bd337d9 | ||
|
|
07a247dcf4 | ||
|
|
fa5a8f055a | ||
|
|
ef3ac9d05a | ||
|
|
d7b75e8d86 | ||
|
|
5e89ded685 | ||
|
|
5f85662ad8 | ||
|
|
d37ee89ca8 | ||
|
|
8bfe739cd2 | ||
|
|
d6e596174d | ||
|
|
3ca1ae2bb7 | ||
|
|
23f69ab936 | ||
|
|
6c9cf117c1 | ||
|
|
d93b71a301 | ||
|
|
ef66f2887b | ||
|
|
85b6d82b49 | ||
|
|
c1a42c2d0d | ||
|
|
0366478df8 | ||
|
|
3cfd16f3af | ||
|
|
67f44365ea | ||
|
|
a282eb1363 | ||
|
|
7832485575 | ||
|
|
99093c0fe0 | ||
|
|
9f9d8d2f62 | ||
|
|
b74887d5f2 | ||
|
|
6ffb208c77 | ||
|
|
994d1c60b9 | ||
|
|
c006ecace1 | ||
|
|
bfed274df3 | ||
|
|
b091b7e6ea | ||
|
|
fabd8474ff | ||
|
|
6752a69aa5 | ||
|
|
b8861b0c25 | ||
|
|
9a415fb1e2 | ||
|
|
5e0a178df2 |
@@ -1,4 +1,4 @@
|
||||
project(Eigen)
|
||||
project(Eigen3)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.5)
|
||||
|
||||
@@ -8,6 +8,11 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
|
||||
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
|
||||
endif()
|
||||
|
||||
# Alias Eigen_*_DIR to Eigen3_*_DIR:
|
||||
|
||||
set(Eigen_SOURCE_DIR ${Eigen3_SOURCE_DIR})
|
||||
set(Eigen_BINARY_DIR ${Eigen3_BINARY_DIR})
|
||||
|
||||
# guard against bad build-type strings
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
@@ -93,9 +98,11 @@ else()
|
||||
endif()
|
||||
|
||||
option(EIGEN_BUILD_BTL "Build benchmark suite" OFF)
|
||||
if(NOT WIN32)
|
||||
|
||||
# Disable pkgconfig only for native Windows builds
|
||||
if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
|
||||
option(EIGEN_BUILD_PKGCONFIG "Build pkg-config .pc file for Eigen" ON)
|
||||
endif(NOT WIN32)
|
||||
endif()
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
@@ -126,7 +133,6 @@ if(NOT MSVC)
|
||||
if(COMPILER_SUPPORT_WERROR)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||
endif()
|
||||
|
||||
ei_add_cxx_compiler_flag("-pedantic")
|
||||
ei_add_cxx_compiler_flag("-Wall")
|
||||
ei_add_cxx_compiler_flag("-Wextra")
|
||||
@@ -224,6 +230,12 @@ if(NOT MSVC)
|
||||
message(STATUS "Enabling FMA in tests/examples")
|
||||
endif()
|
||||
|
||||
option(EIGEN_TEST_AVX512 "Enable/Disable AVX512 in tests/examples" OFF)
|
||||
if(EIGEN_TEST_AVX512)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -fabi-version=6 -DEIGEN_ENABLE_AVX512")
|
||||
message(STATUS "Enabling AVX512 in tests/examples")
|
||||
endif()
|
||||
|
||||
option(EIGEN_TEST_F16C "Enable/Disable F16C in tests/examples" OFF)
|
||||
if(EIGEN_TEST_F16C)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
|
||||
@@ -398,7 +410,7 @@ if(EIGEN_BUILD_PKGCONFIG)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen3.pc
|
||||
DESTINATION ${PKGCONFIG_INSTALL_DIR}
|
||||
)
|
||||
endif(EIGEN_BUILD_PKGCONFIG)
|
||||
endif()
|
||||
|
||||
add_subdirectory(Eigen)
|
||||
|
||||
@@ -424,6 +436,13 @@ else()
|
||||
add_subdirectory(lapack EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
# add SYCL
|
||||
option(EIGEN_TEST_SYCL "Add Sycl support." OFF)
|
||||
if(EIGEN_TEST_SYCL)
|
||||
set (CMAKE_MODULE_PATH "${CMAKE_ROOT}/Modules" "cmake/Modules/" "${CMAKE_MODULE_PATH}")
|
||||
include(FindComputeCpp)
|
||||
endif()
|
||||
|
||||
add_subdirectory(unsupported)
|
||||
|
||||
add_subdirectory(demos EXCLUDE_FROM_ALL)
|
||||
|
||||
@@ -16,4 +16,4 @@ install(FILES
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen COMPONENT Devel
|
||||
)
|
||||
|
||||
add_subdirectory(src)
|
||||
install(DIRECTORY src DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen COMPONENT Devel FILES_MATCHING PATTERN "*.h")
|
||||
|
||||
64
Eigen/Core
64
Eigen/Core
@@ -14,9 +14,19 @@
|
||||
// first thing Eigen does: stop the compiler from committing suicide
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
// Handle NVCC/CUDA
|
||||
#ifdef __CUDACC__
|
||||
// Do not try asserts on CUDA!
|
||||
/// This will no longer be needed after the next release of the computecppCE
|
||||
#ifdef EIGEN_USE_SYCL
|
||||
#undef min
|
||||
#undef max
|
||||
#undef isnan
|
||||
#undef isinf
|
||||
#undef isfinite
|
||||
#include <SYCL/sycl.hpp>
|
||||
#endif
|
||||
|
||||
// Handle NVCC/CUDA/SYCL
|
||||
#if defined(__CUDACC__) || defined(__SYCL_DEVICE_ONLY__)
|
||||
// Do not try asserts on CUDA and SYCL!
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
#define EIGEN_NO_DEBUG
|
||||
#endif
|
||||
@@ -25,17 +35,24 @@
|
||||
#undef EIGEN_INTERNAL_DEBUGGING
|
||||
#endif
|
||||
|
||||
// Do not try to vectorize on CUDA!
|
||||
#ifndef EIGEN_DONT_VECTORIZE
|
||||
#define EIGEN_DONT_VECTORIZE
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
#undef EIGEN_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
// All functions callable from CUDA code must be qualified with __device__
|
||||
#define EIGEN_DEVICE_FUNC __host__ __device__
|
||||
#ifdef __CUDACC__
|
||||
// Do not try to vectorize on CUDA and SYCL!
|
||||
#ifndef EIGEN_DONT_VECTORIZE
|
||||
#define EIGEN_DONT_VECTORIZE
|
||||
#endif
|
||||
|
||||
#define EIGEN_DEVICE_FUNC __host__ __device__
|
||||
// We need math_functions.hpp to ensure that that EIGEN_USING_STD_MATH macro
|
||||
// works properly on the device side
|
||||
#include <math_functions.hpp>
|
||||
#else
|
||||
#define EIGEN_DEVICE_FUNC
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define EIGEN_DEVICE_FUNC
|
||||
@@ -51,7 +68,7 @@
|
||||
#define EIGEN_USING_STD_MATH(FUNC) using std::FUNC;
|
||||
#endif
|
||||
|
||||
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__) && !defined(EIGEN_EXCEPTIONS)
|
||||
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__) && !defined(EIGEN_EXCEPTIONS) && !defined(EIGEN_USE_SYCL)
|
||||
#define EIGEN_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
@@ -140,6 +157,15 @@
|
||||
#ifdef __FMA__
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#endif
|
||||
#if defined(__AVX512F__) && defined(EIGEN_ENABLE_AVX512)
|
||||
#define EIGEN_VECTORIZE_AVX512
|
||||
#define EIGEN_VECTORIZE_AVX2
|
||||
#define EIGEN_VECTORIZE_AVX
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#ifdef __AVX512DQ__
|
||||
#define EIGEN_VECTORIZE_AVX512DQ
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// include files
|
||||
|
||||
@@ -171,7 +197,7 @@
|
||||
#ifdef EIGEN_VECTORIZE_SSE4_2
|
||||
#include <nmmintrin.h>
|
||||
#endif
|
||||
#ifdef EIGEN_VECTORIZE_AVX
|
||||
#if defined(EIGEN_VECTORIZE_AVX) || defined(EIGEN_VECTORIZE_AVX512)
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
#endif
|
||||
@@ -271,7 +297,9 @@
|
||||
namespace Eigen {
|
||||
|
||||
inline static const char *SimdInstructionSetsInUse(void) {
|
||||
#if defined(EIGEN_VECTORIZE_AVX)
|
||||
#if defined(EIGEN_VECTORIZE_AVX512)
|
||||
return "AVX512, FMA, AVX2, AVX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
|
||||
#elif defined(EIGEN_VECTORIZE_AVX)
|
||||
return "AVX SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
|
||||
#elif defined(EIGEN_VECTORIZE_SSE4_2)
|
||||
return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
|
||||
@@ -329,8 +357,14 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/NumTraits.h"
|
||||
#include "src/Core/MathFunctions.h"
|
||||
#include "src/Core/GenericPacketMath.h"
|
||||
#include "src/Core/MathFunctionsImpl.h"
|
||||
|
||||
#if defined EIGEN_VECTORIZE_AVX
|
||||
#if defined EIGEN_VECTORIZE_AVX512
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/AVX/PacketMath.h"
|
||||
#include "src/Core/arch/AVX512/PacketMath.h"
|
||||
#include "src/Core/arch/AVX512/MathFunctions.h"
|
||||
#elif defined EIGEN_VECTORIZE_AVX
|
||||
// Use AVX for floats and doubles, SSE for integers
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
@@ -377,6 +411,10 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/functors/StlFunctors.h"
|
||||
#include "src/Core/functors/AssignmentFunctors.h"
|
||||
|
||||
// Specialized functors to enable the processing of complex numbers
|
||||
// on CUDA devices
|
||||
#include "src/Core/arch/CUDA/Complex.h"
|
||||
|
||||
#include "src/Core/DenseCoeffsBase.h"
|
||||
#include "src/Core/DenseBase.h"
|
||||
#include "src/Core/MatrixBase.h"
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
file(GLOB Eigen_src_subdirectories "*")
|
||||
escape_string_as_regex(ESCAPED_CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach(f ${Eigen_src_subdirectories})
|
||||
if(NOT f MATCHES "\\.txt" AND NOT f MATCHES "${ESCAPED_CMAKE_CURRENT_SOURCE_DIR}/[.].+" )
|
||||
add_subdirectory(${f})
|
||||
endif()
|
||||
endforeach()
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Cholesky_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Cholesky_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Cholesky COMPONENT Devel
|
||||
)
|
||||
@@ -253,7 +253,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
ComputationInfo info() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
||||
return Success;
|
||||
return m_info;
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
@@ -281,6 +281,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
TmpMatrixType m_temporary;
|
||||
internal::SignMatrix m_sign;
|
||||
bool m_isInitialized;
|
||||
ComputationInfo m_info;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
@@ -298,6 +299,8 @@ template<> struct ldlt_inplace<Lower>
|
||||
typedef typename TranspositionType::StorageIndex IndexType;
|
||||
eigen_assert(mat.rows()==mat.cols());
|
||||
const Index size = mat.rows();
|
||||
bool found_zero_pivot = false;
|
||||
bool ret = true;
|
||||
|
||||
if (size <= 1)
|
||||
{
|
||||
@@ -356,9 +359,27 @@ template<> struct ldlt_inplace<Lower>
|
||||
// we should only make sure that we do not introduce INF or NaN values.
|
||||
// Remark that LAPACK also uses 0 as the cutoff value.
|
||||
RealScalar realAkk = numext::real(mat.coeffRef(k,k));
|
||||
if((rs>0) && (abs(realAkk) > RealScalar(0)))
|
||||
bool pivot_is_valid = (abs(realAkk) > RealScalar(0));
|
||||
|
||||
if(k==0 && !pivot_is_valid)
|
||||
{
|
||||
// The entire diagonal is zero, there is nothing more to do
|
||||
// except filling the transpositions, and checking whether the matrix is zero.
|
||||
sign = ZeroSign;
|
||||
for(Index j = 0; j<size; ++j)
|
||||
{
|
||||
transpositions.coeffRef(j) = IndexType(j);
|
||||
ret = ret && (mat.col(j).tail(size-j-1).array()==Scalar(0)).all();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if((rs>0) && pivot_is_valid)
|
||||
A21 /= realAkk;
|
||||
|
||||
if(found_zero_pivot && pivot_is_valid) ret = false; // factorization failed
|
||||
else if(!pivot_is_valid) found_zero_pivot = true;
|
||||
|
||||
if (sign == PositiveSemiDef) {
|
||||
if (realAkk < static_cast<RealScalar>(0)) sign = Indefinite;
|
||||
} else if (sign == NegativeSemiDef) {
|
||||
@@ -369,7 +390,7 @@ template<> struct ldlt_inplace<Lower>
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Reference for the algorithm: Davis and Hager, "Multiple Rank
|
||||
@@ -493,7 +514,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const EigenBase<InputTyp
|
||||
m_temporary.resize(size);
|
||||
m_sign = internal::ZeroSign;
|
||||
|
||||
internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign);
|
||||
m_info = internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign) ? Success : NumericalIssue;
|
||||
|
||||
m_isInitialized = true;
|
||||
return *this;
|
||||
@@ -621,7 +642,6 @@ MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef __CUDACC__
|
||||
/** \cholesky_module
|
||||
* \returns the Cholesky decomposition with full pivoting without square root of \c *this
|
||||
* \sa MatrixBase::ldlt()
|
||||
@@ -643,7 +663,6 @@ MatrixBase<Derived>::ldlt() const
|
||||
{
|
||||
return LDLT<PlainObject>(derived());
|
||||
}
|
||||
#endif // __CUDACC__
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
|
||||
@@ -507,7 +507,6 @@ MatrixType LLT<MatrixType,_UpLo>::reconstructedMatrix() const
|
||||
return matrixL() * matrixL().adjoint().toDenseMatrix();
|
||||
}
|
||||
|
||||
#ifndef __CUDACC__
|
||||
/** \cholesky_module
|
||||
* \returns the LLT decomposition of \c *this
|
||||
* \sa SelfAdjointView::llt()
|
||||
@@ -529,7 +528,6 @@ SelfAdjointView<MatrixType, UpLo>::llt() const
|
||||
{
|
||||
return LLT<PlainObject,UpLo>(m_matrix);
|
||||
}
|
||||
#endif // __CUDACC__
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_CholmodSupport_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_CholmodSupport_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/CholmodSupport COMPONENT Devel
|
||||
)
|
||||
@@ -14,34 +14,40 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Scalar, typename CholmodType>
|
||||
void cholmod_configure_matrix(CholmodType& mat)
|
||||
{
|
||||
if (internal::is_same<Scalar,float>::value)
|
||||
{
|
||||
mat.xtype = CHOLMOD_REAL;
|
||||
mat.dtype = CHOLMOD_SINGLE;
|
||||
}
|
||||
else if (internal::is_same<Scalar,double>::value)
|
||||
{
|
||||
template<typename Scalar> struct cholmod_configure_matrix;
|
||||
|
||||
template<> struct cholmod_configure_matrix<double> {
|
||||
template<typename CholmodType>
|
||||
static void run(CholmodType& mat) {
|
||||
mat.xtype = CHOLMOD_REAL;
|
||||
mat.dtype = CHOLMOD_DOUBLE;
|
||||
}
|
||||
else if (internal::is_same<Scalar,std::complex<float> >::value)
|
||||
{
|
||||
mat.xtype = CHOLMOD_COMPLEX;
|
||||
mat.dtype = CHOLMOD_SINGLE;
|
||||
}
|
||||
else if (internal::is_same<Scalar,std::complex<double> >::value)
|
||||
{
|
||||
};
|
||||
|
||||
template<> struct cholmod_configure_matrix<std::complex<double> > {
|
||||
template<typename CholmodType>
|
||||
static void run(CholmodType& mat) {
|
||||
mat.xtype = CHOLMOD_COMPLEX;
|
||||
mat.dtype = CHOLMOD_DOUBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
eigen_assert(false && "Scalar type not supported by CHOLMOD");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Other scalar types are not yet suppotred by Cholmod
|
||||
// template<> struct cholmod_configure_matrix<float> {
|
||||
// template<typename CholmodType>
|
||||
// static void run(CholmodType& mat) {
|
||||
// mat.xtype = CHOLMOD_REAL;
|
||||
// mat.dtype = CHOLMOD_SINGLE;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// template<> struct cholmod_configure_matrix<std::complex<float> > {
|
||||
// template<typename CholmodType>
|
||||
// static void run(CholmodType& mat) {
|
||||
// mat.xtype = CHOLMOD_COMPLEX;
|
||||
// mat.dtype = CHOLMOD_SINGLE;
|
||||
// }
|
||||
// };
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -53,7 +59,7 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_StorageIndex>& mat)
|
||||
{
|
||||
cholmod_sparse res;
|
||||
res.nzmax = mat.nonZeros();
|
||||
res.nrow = mat.rows();;
|
||||
res.nrow = mat.rows();
|
||||
res.ncol = mat.cols();
|
||||
res.p = mat.outerIndexPtr();
|
||||
res.i = mat.innerIndexPtr();
|
||||
@@ -88,7 +94,7 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_StorageIndex>& mat)
|
||||
}
|
||||
|
||||
// setup res.xtype
|
||||
internal::cholmod_configure_matrix<_Scalar>(res);
|
||||
internal::cholmod_configure_matrix<_Scalar>::run(res);
|
||||
|
||||
res.stype = 0;
|
||||
|
||||
@@ -131,7 +137,7 @@ cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
|
||||
res.x = (void*)(mat.derived().data());
|
||||
res.z = 0;
|
||||
|
||||
internal::cholmod_configure_matrix<Scalar>(res);
|
||||
internal::cholmod_configure_matrix<Scalar>::run(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -180,14 +186,16 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
CholmodBase()
|
||||
: m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
|
||||
{
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
cholmod_start(&m_cholmod);
|
||||
}
|
||||
|
||||
explicit CholmodBase(const MatrixType& matrix)
|
||||
: m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
|
||||
{
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
cholmod_start(&m_cholmod);
|
||||
compute(matrix);
|
||||
}
|
||||
@@ -254,7 +262,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
||||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
||||
cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
|
||||
|
||||
|
||||
// If the factorization failed, minor is the column at which it did. On success minor == n.
|
||||
this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
|
||||
m_factorizationIsOk = true;
|
||||
@@ -324,7 +332,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
*/
|
||||
Derived& setShift(const RealScalar& offset)
|
||||
{
|
||||
m_shiftOffset[0] = offset;
|
||||
m_shiftOffset[0] = double(offset);
|
||||
return derived();
|
||||
}
|
||||
|
||||
@@ -386,7 +394,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
protected:
|
||||
mutable cholmod_common m_cholmod;
|
||||
cholmod_factor* m_cholmodFactor;
|
||||
RealScalar m_shiftOffset[2];
|
||||
double m_shiftOffset[2];
|
||||
mutable ComputationInfo m_info;
|
||||
int m_factorizationIsOk;
|
||||
int m_analysisIsOk;
|
||||
@@ -410,6 +418,8 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLLT
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
@@ -459,6 +469,8 @@ class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimpl
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLDLT
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
@@ -506,6 +518,8 @@ class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimp
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseSolverConcept
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
@@ -555,6 +569,8 @@ class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSuper
|
||||
*
|
||||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
|
||||
*
|
||||
* \warning Only double precision real and complex scalar types are supported by Cholmod.
|
||||
*
|
||||
* \sa \ref TutorialSparseSolverConcept
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo = Lower>
|
||||
|
||||
@@ -37,7 +37,7 @@ struct traits<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > : tra
|
||||
* storage layout.
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_ARRAY_PLUGIN.
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_ARRAY_PLUGIN.
|
||||
*
|
||||
* \sa \blank \ref TutorialArrayClass, \ref TopicClassHierarchy
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ template<typename ExpressionType> class MatrixWrapper;
|
||||
* \tparam Derived is the derived type, e.g., an array or an expression type.
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_ARRAYBASE_PLUGIN.
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_ARRAYBASE_PLUGIN.
|
||||
*
|
||||
* \sa class MatrixBase, \ref TopicClassHierarchy
|
||||
*/
|
||||
@@ -87,6 +87,7 @@ template<typename Derived> class ArrayBase
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::ArrayBase
|
||||
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
|
||||
# include "../plugins/CommonCwiseUnaryOps.h"
|
||||
# include "../plugins/MatrixCwiseUnaryOps.h"
|
||||
# include "../plugins/ArrayCwiseUnaryOps.h"
|
||||
@@ -97,6 +98,7 @@ template<typename Derived> class ArrayBase
|
||||
# include EIGEN_ARRAYBASE_PLUGIN
|
||||
# endif
|
||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
||||
#undef EIGEN_DOC_UNARY_ADDONS
|
||||
|
||||
/** Special case of the template operator=, in order to prevent the compiler
|
||||
* from generating a default operator= (issue hit with g++ 4.1)
|
||||
|
||||
@@ -54,6 +54,8 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
||||
|
||||
typedef typename internal::ref_selector<ExpressionType>::non_const_type NestedExpressionType;
|
||||
|
||||
using Base::coeffRef;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
@@ -71,66 +73,18 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar* data() const { return m_expression.data(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline CoeffReturnType coeff(Index rowId, Index colId) const
|
||||
{
|
||||
return m_expression.coeff(rowId, colId);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Scalar& coeffRef(Index rowId, Index colId)
|
||||
{
|
||||
return m_expression.coeffRef(rowId, colId);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar& coeffRef(Index rowId, Index colId) const
|
||||
{
|
||||
return m_expression.coeffRef(rowId, colId);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_expression.coeff(index);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Scalar& coeffRef(Index index)
|
||||
{
|
||||
return m_expression.coeffRef(index);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar& coeffRef(Index index) const
|
||||
{
|
||||
return m_expression.coeffRef(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index rowId, Index colId) const
|
||||
{
|
||||
return m_expression.template packet<LoadMode>(rowId, colId);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
|
||||
{
|
||||
m_expression.template writePacket<LoadMode>(rowId, colId, val);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index index) const
|
||||
{
|
||||
return m_expression.template packet<LoadMode>(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index index, const PacketScalar& val)
|
||||
{
|
||||
m_expression.template writePacket<LoadMode>(index, val);
|
||||
}
|
||||
|
||||
template<typename Dest>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline void evalTo(Dest& dst) const { dst = m_expression; }
|
||||
@@ -197,6 +151,8 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
||||
|
||||
typedef typename internal::ref_selector<ExpressionType>::non_const_type NestedExpressionType;
|
||||
|
||||
using Base::coeffRef;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
@@ -214,66 +170,18 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar* data() const { return m_expression.data(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline CoeffReturnType coeff(Index rowId, Index colId) const
|
||||
{
|
||||
return m_expression.coeff(rowId, colId);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Scalar& coeffRef(Index rowId, Index colId)
|
||||
{
|
||||
return m_expression.coeffRef(rowId, colId);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar& coeffRef(Index rowId, Index colId) const
|
||||
{
|
||||
return m_expression.derived().coeffRef(rowId, colId);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_expression.coeff(index);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Scalar& coeffRef(Index index)
|
||||
{
|
||||
return m_expression.coeffRef(index);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar& coeffRef(Index index) const
|
||||
{
|
||||
return m_expression.coeffRef(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index rowId, Index colId) const
|
||||
{
|
||||
return m_expression.template packet<LoadMode>(rowId, colId);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
|
||||
{
|
||||
m_expression.template writePacket<LoadMode>(rowId, colId, val);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index index) const
|
||||
{
|
||||
return m_expression.template packet<LoadMode>(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index index, const PacketScalar& val)
|
||||
{
|
||||
m_expression.template writePacket<LoadMode>(index, val);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
const typename internal::remove_all<NestedExpressionType>::type&
|
||||
nestedExpression() const
|
||||
|
||||
@@ -88,10 +88,11 @@ private:
|
||||
/* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
|
||||
so it's only good for large enough sizes. */
|
||||
MaySliceVectorize = bool(MightVectorize) && bool(DstHasDirectAccess)
|
||||
&& (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=3*InnerPacketSize)
|
||||
&& (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=(EIGEN_UNALIGNED_VECTORIZE?InnerPacketSize:(3*InnerPacketSize)))
|
||||
/* slice vectorization can be slow, so we only want it if the slices are big, which is
|
||||
indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block
|
||||
in a fixed-size matrix */
|
||||
in a fixed-size matrix
|
||||
However, with EIGEN_UNALIGNED_VECTORIZE and unrolling, slice vectorization is still worth it */
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -136,6 +137,11 @@ public:
|
||||
: int(Traversal) == int(LinearTraversal)
|
||||
? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
|
||||
: int(NoUnrolling) )
|
||||
#if EIGEN_UNALIGNED_VECTORIZE
|
||||
: int(Traversal) == int(SliceVectorizedTraversal)
|
||||
? ( bool(MayUnrollInner) ? int(InnerUnrolling)
|
||||
: int(NoUnrolling) )
|
||||
#endif
|
||||
: int(NoUnrolling)
|
||||
};
|
||||
|
||||
@@ -277,24 +283,20 @@ struct copy_using_evaluator_innervec_CompleteUnrolling<Kernel, Stop, Stop>
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
|
||||
};
|
||||
|
||||
template<typename Kernel, int Index_, int Stop>
|
||||
template<typename Kernel, int Index_, int Stop, int SrcAlignment, int DstAlignment>
|
||||
struct copy_using_evaluator_innervec_InnerUnrolling
|
||||
{
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
enum {
|
||||
SrcAlignment = Kernel::AssignmentTraits::SrcAlignment,
|
||||
DstAlignment = Kernel::AssignmentTraits::DstAlignment
|
||||
};
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
|
||||
{
|
||||
kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, Index_);
|
||||
enum { NextIndex = Index_ + unpacket_traits<PacketType>::size };
|
||||
copy_using_evaluator_innervec_InnerUnrolling<Kernel, NextIndex, Stop>::run(kernel, outer);
|
||||
copy_using_evaluator_innervec_InnerUnrolling<Kernel, NextIndex, Stop, SrcAlignment, DstAlignment>::run(kernel, outer);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Kernel, int Stop>
|
||||
struct copy_using_evaluator_innervec_InnerUnrolling<Kernel, Stop, Stop>
|
||||
template<typename Kernel, int Stop, int SrcAlignment, int DstAlignment>
|
||||
struct copy_using_evaluator_innervec_InnerUnrolling<Kernel, Stop, Stop, SrcAlignment, DstAlignment>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &, Index) { }
|
||||
};
|
||||
@@ -423,9 +425,10 @@ struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, CompleteUnrollin
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
|
||||
{
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
|
||||
enum { size = DstXprType::SizeAtCompileTime,
|
||||
packetSize = packet_traits<typename Kernel::Scalar>::size,
|
||||
packetSize =unpacket_traits<PacketType>::size,
|
||||
alignedSize = (size/packetSize)*packetSize };
|
||||
|
||||
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, alignedSize>::run(kernel);
|
||||
@@ -472,9 +475,11 @@ struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, InnerUnrolling>
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
|
||||
{
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
typedef typename Kernel::AssignmentTraits Traits;
|
||||
const Index outerSize = kernel.outerSize();
|
||||
for(Index outer = 0; outer < outerSize; ++outer)
|
||||
copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime>::run(kernel, outer);
|
||||
copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime,
|
||||
Traits::SrcAlignment, Traits::DstAlignment>::run(kernel, outer);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -549,11 +554,34 @@ struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
|
||||
for(Index inner = alignedEnd; inner<innerSize ; ++inner)
|
||||
kernel.assignCoeffByOuterInner(outer, inner);
|
||||
|
||||
alignedStart = std::min<Index>((alignedStart+alignedStep)%packetSize, innerSize);
|
||||
alignedStart = numext::mini((alignedStart+alignedStep)%packetSize, innerSize);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if EIGEN_UNALIGNED_VECTORIZE
|
||||
template<typename Kernel>
|
||||
struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, InnerUnrolling>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel)
|
||||
{
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
|
||||
enum { size = DstXprType::InnerSizeAtCompileTime,
|
||||
packetSize =unpacket_traits<PacketType>::size,
|
||||
vectorizableSize = (size/packetSize)*packetSize };
|
||||
|
||||
for(Index outer = 0; outer < kernel.outerSize(); ++outer)
|
||||
{
|
||||
copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, vectorizableSize, 0, 0>::run(kernel, outer);
|
||||
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, vectorizableSize, size>::run(kernel, outer);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Part 4 : Generic dense assignment kernel
|
||||
***************************************************************************/
|
||||
@@ -669,24 +697,30 @@ protected:
|
||||
***************************************************************************/
|
||||
|
||||
template<typename DstXprType, typename SrcXprType, typename Functor>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, const Functor &func)
|
||||
{
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||
|
||||
typedef evaluator<DstXprType> DstEvaluatorType;
|
||||
typedef evaluator<SrcXprType> SrcEvaluatorType;
|
||||
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
SrcEvaluatorType srcEvaluator(src);
|
||||
|
||||
// NOTE To properly handle A = (A*A.transpose())/s with A rectangular,
|
||||
// we need to resize the destination after the source evaluator has been created.
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
|
||||
typedef generic_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
|
||||
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
|
||||
|
||||
|
||||
dense_assignment_loop<Kernel>::run(kernel);
|
||||
}
|
||||
|
||||
template<typename DstXprType, typename SrcXprType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src)
|
||||
{
|
||||
call_dense_assignment_loop(dst, src, internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar>());
|
||||
}
|
||||
@@ -768,11 +802,6 @@ void call_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
|
||||
) && int(Dst::SizeAtCompileTime) != 1
|
||||
};
|
||||
|
||||
Index dstRows = NeedToTranspose ? src.cols() : src.rows();
|
||||
Index dstCols = NeedToTranspose ? src.rows() : src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst>::type ActualDstTypeCleaned;
|
||||
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst&>::type ActualDstType;
|
||||
ActualDstType actualDst(dst);
|
||||
@@ -795,15 +824,11 @@ template<typename Dst, typename Src, typename Func>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src, const Func& func)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
// TODO check whether this is the right place to perform these checks:
|
||||
EIGEN_STATIC_ASSERT_LVALUE(Dst)
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Dst,Src)
|
||||
|
||||
EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename Dst::Scalar,typename Src::Scalar);
|
||||
|
||||
Assignment<Dst,Src,Func>::run(dst, src, func);
|
||||
}
|
||||
template<typename Dst, typename Src>
|
||||
@@ -825,8 +850,6 @@ struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Weak>
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
|
||||
{
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
internal::check_for_aliasing(dst, src);
|
||||
#endif
|
||||
@@ -845,6 +868,11 @@ struct Assignment<DstXprType, SrcXprType, Functor, EigenBase2EigenBase, Weak>
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||
src.evalTo(dst);
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core COMPONENT Devel
|
||||
)
|
||||
|
||||
ADD_SUBDIRECTORY(products)
|
||||
ADD_SUBDIRECTORY(util)
|
||||
ADD_SUBDIRECTORY(arch)
|
||||
ADD_SUBDIRECTORY(functors)
|
||||
@@ -80,12 +80,7 @@ struct CommaInitializer
|
||||
EIGEN_DEVICE_FUNC
|
||||
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
||||
{
|
||||
if(other.rows()==0)
|
||||
{
|
||||
m_col += other.cols();
|
||||
return *this;
|
||||
}
|
||||
if (m_col==m_xpr.cols())
|
||||
if (m_col==m_xpr.cols() && (other.cols()!=0 || other.rows()!=m_currentBlockRows))
|
||||
{
|
||||
m_row+=m_currentBlockRows;
|
||||
m_col = 0;
|
||||
@@ -93,15 +88,11 @@ struct CommaInitializer
|
||||
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
||||
&& "Too many rows passed to comma initializer (operator<<)");
|
||||
}
|
||||
eigen_assert((m_col<m_xpr.cols() || (m_xpr.cols()==0 && m_col==0))
|
||||
eigen_assert((m_col + other.cols() <= m_xpr.cols())
|
||||
&& "Too many coefficients passed to comma initializer (operator<<)");
|
||||
eigen_assert(m_currentBlockRows==other.rows());
|
||||
if (OtherDerived::SizeAtCompileTime != Dynamic)
|
||||
m_xpr.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
|
||||
OtherDerived::ColsAtCompileTime != Dynamic ? OtherDerived::ColsAtCompileTime : 1>
|
||||
(m_row, m_col) = other;
|
||||
else
|
||||
m_xpr.block(m_row, m_col, other.rows(), other.cols()) = other;
|
||||
m_xpr.template block<OtherDerived::RowsAtCompileTime, OtherDerived::ColsAtCompileTime>
|
||||
(m_row, m_col, other.rows(), other.cols()) = other;
|
||||
m_col += other.cols();
|
||||
return *this;
|
||||
}
|
||||
@@ -112,9 +103,7 @@ struct CommaInitializer
|
||||
EIGEN_EXCEPTION_SPEC(Eigen::eigen_assert_exception)
|
||||
#endif
|
||||
{
|
||||
eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows()
|
||||
&& m_col == m_xpr.cols()
|
||||
&& "Too few coefficients passed to comma initializer (operator<<)");
|
||||
finished();
|
||||
}
|
||||
|
||||
/** \returns the built matrix once all its coefficients have been set.
|
||||
@@ -125,7 +114,12 @@ struct CommaInitializer
|
||||
* \endcode
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline XprType& finished() { return m_xpr; }
|
||||
inline XprType& finished() {
|
||||
eigen_assert(((m_row+m_currentBlockRows) == m_xpr.rows() || m_xpr.cols() == 0)
|
||||
&& m_col == m_xpr.cols()
|
||||
&& "Too few coefficients passed to comma initializer (operator<<)");
|
||||
return m_xpr;
|
||||
}
|
||||
|
||||
XprType& m_xpr; // target expression
|
||||
Index m_row; // current row id
|
||||
|
||||
@@ -337,6 +337,120 @@ protected:
|
||||
// Like Matrix and Array, this is not really a unary expression, so we directly specialize evaluator.
|
||||
// Likewise, there is not need to more sophisticated dispatching here.
|
||||
|
||||
template<typename Scalar,typename NullaryOp,
|
||||
bool has_nullary = has_nullary_operator<NullaryOp>::value,
|
||||
bool has_unary = has_unary_operator<NullaryOp>::value,
|
||||
bool has_binary = has_binary_operator<NullaryOp>::value>
|
||||
struct nullary_wrapper
|
||||
{
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const { return op(i,j); }
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { return op(i); }
|
||||
|
||||
template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const { return op.template packetOp<T>(i,j); }
|
||||
template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { return op.template packetOp<T>(i); }
|
||||
};
|
||||
|
||||
template<typename Scalar,typename NullaryOp>
|
||||
struct nullary_wrapper<Scalar,NullaryOp,true,false,false>
|
||||
{
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType=0, IndexType=0) const { return op(); }
|
||||
template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType=0, IndexType=0) const { return op.template packetOp<T>(); }
|
||||
};
|
||||
|
||||
template<typename Scalar,typename NullaryOp>
|
||||
struct nullary_wrapper<Scalar,NullaryOp,false,false,true>
|
||||
{
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j=0) const { return op(i,j); }
|
||||
template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j=0) const { return op.template packetOp<T>(i,j); }
|
||||
};
|
||||
|
||||
// We need the following specialization for vector-only functors assigned to a runtime vector,
|
||||
// for instance, using linspace and assigning a RowVectorXd to a MatrixXd or even a row of a MatrixXd.
|
||||
// In this case, i==0 and j is used for the actual iteration.
|
||||
template<typename Scalar,typename NullaryOp>
|
||||
struct nullary_wrapper<Scalar,NullaryOp,false,true,false>
|
||||
{
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const {
|
||||
eigen_assert(i==0 || j==0);
|
||||
return op(i+j);
|
||||
}
|
||||
template <typename T, typename IndexType> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const {
|
||||
eigen_assert(i==0 || j==0);
|
||||
return op.template packetOp<T>(i+j);
|
||||
}
|
||||
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { return op(i); }
|
||||
template <typename T, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { return op.template packetOp<T>(i); }
|
||||
};
|
||||
|
||||
template<typename Scalar,typename NullaryOp>
|
||||
struct nullary_wrapper<Scalar,NullaryOp,false,false,false> {};
|
||||
|
||||
#if 0 && EIGEN_COMP_MSVC>0
|
||||
// Disable this ugly workaround. This is now handled in traits<Ref>::match,
|
||||
// but this piece of code might still become handly if some other weird compilation
|
||||
// erros pop up again.
|
||||
|
||||
// MSVC exhibits a weird compilation error when
|
||||
// compiling:
|
||||
// Eigen::MatrixXf A = MatrixXf::Random(3,3);
|
||||
// Ref<const MatrixXf> R = 2.f*A;
|
||||
// and that has_*ary_operator<scalar_constant_op<float>> have not been instantiated yet.
|
||||
// The "problem" is that evaluator<2.f*A> is instantiated by traits<Ref>::match<2.f*A>
|
||||
// and at that time has_*ary_operator<T> returns true regardless of T.
|
||||
// Then nullary_wrapper is badly instantiated as nullary_wrapper<.,.,true,true,true>.
|
||||
// The trick is thus to defer the proper instantiation of nullary_wrapper when coeff(),
|
||||
// and packet() are really instantiated as implemented below:
|
||||
|
||||
// This is a simple wrapper around Index to enforce the re-instantiation of
|
||||
// has_*ary_operator when needed.
|
||||
template<typename T> struct nullary_wrapper_workaround_msvc {
|
||||
nullary_wrapper_workaround_msvc(const T&);
|
||||
operator T()const;
|
||||
};
|
||||
|
||||
template<typename Scalar,typename NullaryOp>
|
||||
struct nullary_wrapper<Scalar,NullaryOp,true,true,true>
|
||||
{
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const {
|
||||
return nullary_wrapper<Scalar,NullaryOp,
|
||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().operator()(op,i,j);
|
||||
}
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const {
|
||||
return nullary_wrapper<Scalar,NullaryOp,
|
||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().operator()(op,i);
|
||||
}
|
||||
|
||||
template <typename T, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const {
|
||||
return nullary_wrapper<Scalar,NullaryOp,
|
||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().template packetOp<T>(op,i,j);
|
||||
}
|
||||
template <typename T, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const {
|
||||
return nullary_wrapper<Scalar,NullaryOp,
|
||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().template packetOp<T>(op,i);
|
||||
}
|
||||
};
|
||||
#endif // MSVC workaround
|
||||
|
||||
template<typename NullaryOp, typename PlainObjectType>
|
||||
struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
||||
: evaluator_base<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
||||
@@ -356,41 +470,44 @@ struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& n)
|
||||
: m_functor(n.functor())
|
||||
: m_functor(n.functor()), m_wrapper()
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
CoeffReturnType coeff(IndexType row, IndexType col) const
|
||||
{
|
||||
return m_functor(row, col);
|
||||
return m_wrapper(m_functor, row, col);
|
||||
}
|
||||
|
||||
template <typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index index) const
|
||||
CoeffReturnType coeff(IndexType index) const
|
||||
{
|
||||
return m_functor(index);
|
||||
return m_wrapper(m_functor,index);
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
template<int LoadMode, typename PacketType, typename IndexType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index row, Index col) const
|
||||
PacketType packet(IndexType row, IndexType col) const
|
||||
{
|
||||
return m_functor.template packetOp<Index,PacketType>(row, col);
|
||||
return m_wrapper.template packetOp<PacketType>(m_functor, row, col);
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
template<int LoadMode, typename PacketType, typename IndexType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index index) const
|
||||
PacketType packet(IndexType index) const
|
||||
{
|
||||
return m_functor.template packetOp<Index,PacketType>(index);
|
||||
return m_wrapper.template packetOp<PacketType>(m_functor, index);
|
||||
}
|
||||
|
||||
protected:
|
||||
const NullaryOp m_functor;
|
||||
const internal::nullary_wrapper<CoeffReturnType,NullaryOp> m_wrapper;
|
||||
};
|
||||
|
||||
// -------------------- CwiseUnaryOp --------------------
|
||||
@@ -700,73 +817,79 @@ struct mapbase_evaluator : evaluator_base<Derived>
|
||||
ColsAtCompileTime = XprType::ColsAtCompileTime,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost
|
||||
};
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit mapbase_evaluator(const XprType& map)
|
||||
: m_data(const_cast<PointerType>(map.data())),
|
||||
m_xpr(map)
|
||||
: m_data(const_cast<PointerType>(map.data())),
|
||||
m_innerStride(map.innerStride()),
|
||||
m_outerStride(map.outerStride())
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(evaluator<Derived>::Flags&PacketAccessBit, internal::inner_stride_at_compile_time<Derived>::ret==1),
|
||||
PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_data[col * m_xpr.colStride() + row * m_xpr.rowStride()];
|
||||
return m_data[col * colStride() + row * rowStride()];
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_data[index * m_xpr.innerStride()];
|
||||
return m_data[index * m_innerStride.value()];
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
return m_data[col * m_xpr.colStride() + row * m_xpr.rowStride()];
|
||||
return m_data[col * colStride() + row * rowStride()];
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index index)
|
||||
{
|
||||
return m_data[index * m_xpr.innerStride()];
|
||||
return m_data[index * m_innerStride.value()];
|
||||
}
|
||||
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index row, Index col) const
|
||||
PacketType packet(Index row, Index col) const
|
||||
{
|
||||
PointerType ptr = m_data + row * m_xpr.rowStride() + col * m_xpr.colStride();
|
||||
PointerType ptr = m_data + row * rowStride() + col * colStride();
|
||||
return internal::ploadt<PacketType, LoadMode>(ptr);
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index index) const
|
||||
PacketType packet(Index index) const
|
||||
{
|
||||
return internal::ploadt<PacketType, LoadMode>(m_data + index * m_xpr.innerStride());
|
||||
return internal::ploadt<PacketType, LoadMode>(m_data + index * m_innerStride.value());
|
||||
}
|
||||
|
||||
|
||||
template<int StoreMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
void writePacket(Index row, Index col, const PacketType& x)
|
||||
void writePacket(Index row, Index col, const PacketType& x)
|
||||
{
|
||||
PointerType ptr = m_data + row * m_xpr.rowStride() + col * m_xpr.colStride();
|
||||
PointerType ptr = m_data + row * rowStride() + col * colStride();
|
||||
return internal::pstoret<Scalar, PacketType, StoreMode>(ptr, x);
|
||||
}
|
||||
|
||||
|
||||
template<int StoreMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
void writePacket(Index index, const PacketType& x)
|
||||
void writePacket(Index index, const PacketType& x)
|
||||
{
|
||||
internal::pstoret<Scalar, PacketType, StoreMode>(m_data + index * m_xpr.innerStride(), x);
|
||||
internal::pstoret<Scalar, PacketType, StoreMode>(m_data + index * m_innerStride.value(), x);
|
||||
}
|
||||
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index rowStride() const { return XprType::IsRowMajor ? m_outerStride.value() : m_innerStride.value(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index colStride() const { return XprType::IsRowMajor ? m_innerStride.value() : m_outerStride.value(); }
|
||||
|
||||
PointerType m_data;
|
||||
const XprType& m_xpr;
|
||||
const internal::variable_if_dynamic<Index, XprType::InnerStrideAtCompileTime> m_innerStride;
|
||||
const internal::variable_if_dynamic<Index, XprType::OuterStrideAtCompileTime> m_outerStride;
|
||||
};
|
||||
|
||||
template<typename PlainObjectType, int MapOptions, typename StrideType>
|
||||
@@ -1179,7 +1302,7 @@ struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
}
|
||||
|
||||
protected:
|
||||
const ArgTypeNested m_arg;
|
||||
typename internal::add_const_on_value_type<ArgTypeNested>::type m_arg;
|
||||
const MemberOp m_functor;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType> > : traits<PlainObjectT
|
||||
Flags = traits<PlainObjectType>::Flags & RowMajorBit
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/** \class CwiseNullaryOp
|
||||
* \ingroup Core_Module
|
||||
@@ -37,7 +38,23 @@ struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType> > : traits<PlainObjectT
|
||||
* However, if you want to write a function returning such an expression, you
|
||||
* will need to use this class.
|
||||
*
|
||||
* \sa class CwiseUnaryOp, class CwiseBinaryOp, DenseBase::NullaryExpr()
|
||||
* The functor NullaryOp must expose one of the following method:
|
||||
<table class="manual">
|
||||
<tr ><td>\c operator()() </td><td>if the procedural generation does not depend on the coefficient entries (e.g., random numbers)</td></tr>
|
||||
<tr class="alt"><td>\c operator()(Index i)</td><td>if the procedural generation makes sense for vectors only and that it depends on the coefficient index \c i (e.g., linspace) </td></tr>
|
||||
<tr ><td>\c operator()(Index i,Index j)</td><td>if the procedural generation depends on the matrix coordinates \c i, \c j (e.g., to generate a checkerboard with 0 and 1)</td></tr>
|
||||
</table>
|
||||
* It is also possible to expose the last two operators if the generation makes sense for matrices but can be optimized for vectors.
|
||||
*
|
||||
* See DenseBase::NullaryExpr(Index,const CustomNullaryOp&) for an example binding
|
||||
* C++11 random number generators.
|
||||
*
|
||||
* A nullary expression can also be used to implement custom sophisticated matrix manipulations
|
||||
* that cannot be covered by the existing set of natively supported matrix manipulations.
|
||||
* See this \ref TopicCustomizing_NullaryExpr "page" for some examples and additional explanations
|
||||
* on the behavior of CwiseNullaryOp.
|
||||
*
|
||||
* \sa class CwiseUnaryOp, class CwiseBinaryOp, DenseBase::NullaryExpr
|
||||
*/
|
||||
template<typename NullaryOp, typename PlainObjectType>
|
||||
class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp, PlainObjectType> >::type, internal::no_assignment_operator
|
||||
@@ -62,30 +79,6 @@ class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
|
||||
{
|
||||
return m_functor(rowId, colId);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const
|
||||
{
|
||||
return m_functor.packetOp(rowId, colId);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
|
||||
{
|
||||
return m_functor(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
|
||||
{
|
||||
return m_functor.packetOp(index);
|
||||
}
|
||||
|
||||
/** \returns the functor representing the nullary operation */
|
||||
EIGEN_DEVICE_FUNC
|
||||
const NullaryOp& functor() const { return m_functor; }
|
||||
@@ -222,42 +215,29 @@ DenseBase<Derived>::Constant(const Scalar& value)
|
||||
return DenseBase<Derived>::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_constant_op<Scalar>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets a linearly spaced vector.
|
||||
/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(Index,const Scalar&,const Scalar&)
|
||||
*
|
||||
* The function generates 'size' equally spaced values in the closed interval [low,high].
|
||||
* This particular version of LinSpaced() uses sequential access, i.e. vector access is
|
||||
* assumed to be a(0), a(1), ..., a(size). This assumption allows for better vectorization
|
||||
* and yields faster code than the random access version.
|
||||
*
|
||||
* When size is set to 1, a vector of length 1 containing 'high' is returned.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* Example: \include DenseBase_LinSpaced_seq.cpp
|
||||
* Output: \verbinclude DenseBase_LinSpaced_seq.out
|
||||
*
|
||||
* \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Index,Scalar,Scalar), CwiseNullaryOp
|
||||
* \sa LinSpaced(Index,Scalar,Scalar), setLinSpaced(Index,const Scalar&,const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::SequentialLinSpacedReturnType
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,PacketScalar,false>(low,high,size));
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,PacketScalar>(low,high,size));
|
||||
}
|
||||
|
||||
/**
|
||||
* \copydoc DenseBase::LinSpaced(Sequential_t, Index, const Scalar&, const Scalar&)
|
||||
* Special version for fixed size types which does not require the size parameter.
|
||||
/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(const Scalar&,const Scalar&)
|
||||
*
|
||||
* \sa LinSpaced(Scalar,Scalar)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::SequentialLinSpacedReturnType
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,PacketScalar,false>(low,high,Derived::SizeAtCompileTime));
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,PacketScalar>(low,high,Derived::SizeAtCompileTime));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,14 +251,24 @@ DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig
|
||||
* Example: \include DenseBase_LinSpaced.cpp
|
||||
* Output: \verbinclude DenseBase_LinSpaced.out
|
||||
*
|
||||
* \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Sequential_t,Index,const Scalar&,const Scalar&,Index), CwiseNullaryOp
|
||||
* For integer scalar types, an even spacing is possible if and only if the length of the range,
|
||||
* i.e., \c high-low is a scalar multiple of \c size-1, or if \c size is a scalar multiple of the
|
||||
* number of values \c high-low+1 (meaning each value can be repeated the same number of time).
|
||||
* If one of these two considions is not satisfied, then \c high is lowered to the largest value
|
||||
* satisfying one of this constraint.
|
||||
* Here are some examples:
|
||||
*
|
||||
* Example: \include DenseBase_LinSpacedInt.cpp
|
||||
* Output: \verbinclude DenseBase_LinSpacedInt.out
|
||||
*
|
||||
* \sa setLinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,PacketScalar,true>(low,high,size));
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,PacketScalar>(low,high,size));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,7 +281,7 @@ DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,PacketScalar,true>(low,high,Derived::SizeAtCompileTime));
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,PacketScalar>(low,high,Derived::SizeAtCompileTime));
|
||||
}
|
||||
|
||||
/** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */
|
||||
@@ -384,24 +374,30 @@ PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& val)
|
||||
* Example: \include DenseBase_setLinSpaced.cpp
|
||||
* Output: \verbinclude DenseBase_setLinSpaced.out
|
||||
*
|
||||
* \sa CwiseNullaryOp
|
||||
* For integer scalar types, do not miss the explanations on the definition
|
||||
* of \link LinSpaced(Index,const Scalar&,const Scalar&) even spacing \endlink.
|
||||
*
|
||||
* \sa LinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op<Scalar,PacketScalar,false>(low,high,newSize));
|
||||
return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op<Scalar,PacketScalar>(low,high,newSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets a linearly spaced vector.
|
||||
*
|
||||
* The function fill *this with equally spaced values in the closed interval [low,high].
|
||||
* The function fills \c *this with equally spaced values in the closed interval [low,high].
|
||||
* When size is set to 1, a vector of length 1 containing 'high' is returned.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \sa setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp
|
||||
* For integer scalar types, do not miss the explanations on the definition
|
||||
* of \link LinSpaced(Index,const Scalar&,const Scalar&) even spacing \endlink.
|
||||
*
|
||||
* \sa LinSpaced(Index,const Scalar&,const Scalar&), setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low, const Scalar& high)
|
||||
@@ -759,7 +755,7 @@ struct setIdentity_impl<Derived, true>
|
||||
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
|
||||
{
|
||||
m.setZero();
|
||||
const Index size = (std::min)(m.rows(), m.cols());
|
||||
const Index size = numext::mini(m.rows(), m.cols());
|
||||
for(Index i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ static inline void check_DenseIndex_is_signed() {
|
||||
* \tparam Derived is the derived type, e.g., a matrix type or an expression.
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_DENSEBASE_PLUGIN.
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_DENSEBASE_PLUGIN.
|
||||
*
|
||||
* \sa \blank \ref TopicClassHierarchy
|
||||
*/
|
||||
@@ -260,10 +260,10 @@ template<typename Derived> class DenseBase
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal Represents a matrix with all coefficients equal to one another*/
|
||||
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,PlainObject> ConstantReturnType;
|
||||
/** \internal Represents a vector with linearly spaced coefficients that allows sequential access only. */
|
||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar,false>,PlainObject> SequentialLinSpacedReturnType;
|
||||
/** \internal \deprecated Represents a vector with linearly spaced coefficients that allows sequential access only. */
|
||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar>,PlainObject> SequentialLinSpacedReturnType;
|
||||
/** \internal Represents a vector with linearly spaced coefficients that allows random access. */
|
||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar,true>,PlainObject> RandomAccessLinSpacedReturnType;
|
||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar>,PlainObject> RandomAccessLinSpacedReturnType;
|
||||
/** \internal the return type of MatrixBase::eigenvalues() */
|
||||
typedef Matrix<typename NumTraits<typename internal::traits<Derived>::Scalar>::Real, internal::traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType;
|
||||
|
||||
@@ -558,12 +558,15 @@ template<typename Derived> class DenseBase
|
||||
EIGEN_DEVICE_FUNC void reverseInPlace();
|
||||
|
||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase
|
||||
#define EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL
|
||||
#define EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(COND)
|
||||
# include "../plugins/BlockMethods.h"
|
||||
# ifdef EIGEN_DENSEBASE_PLUGIN
|
||||
# include EIGEN_DENSEBASE_PLUGIN
|
||||
# endif
|
||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
||||
|
||||
#undef EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL
|
||||
#undef EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF
|
||||
|
||||
// disable the use of evalTo for dense objects with a nice compilation error
|
||||
template<typename Dest>
|
||||
|
||||
@@ -624,7 +624,7 @@ struct first_aligned_impl<Alignment, Derived, false>
|
||||
{
|
||||
static inline Index run(const Derived& m)
|
||||
{
|
||||
return internal::first_aligned<Alignment>(&m.const_cast_derived().coeffRef(0,0), m.size());
|
||||
return internal::first_aligned<Alignment>(m.data(), m.size());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -290,12 +290,11 @@ MatrixBase<Derived>::asDiagonal() const
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const
|
||||
{
|
||||
using std::abs;
|
||||
if(cols() != rows()) return false;
|
||||
RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
{
|
||||
RealScalar absOnDiagonal = abs(coeff(j,j));
|
||||
RealScalar absOnDiagonal = numext::abs(coeff(j,j));
|
||||
if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
|
||||
}
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
@@ -321,6 +320,11 @@ struct Assignment<DstXprType, SrcXprType, Functor, Diagonal2Dense>
|
||||
{
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
dst.setZero();
|
||||
dst.diagonal() = src.diagonal();
|
||||
}
|
||||
|
||||
@@ -159,20 +159,20 @@ struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
|
||||
template<typename Scalar,int Size,int MaxSize>
|
||||
struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
|
||||
{
|
||||
#if EIGEN_MAX_STATIC_ALIGN_BYTES!=0
|
||||
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
|
||||
EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; }
|
||||
#else
|
||||
// Some architectures cannot align on the stack,
|
||||
// => let's manually enforce alignment by allocating more data and return the address of the first aligned element.
|
||||
enum {
|
||||
ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
|
||||
PacketSize = internal::packet_traits<Scalar>::size
|
||||
};
|
||||
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
|
||||
#if EIGEN_MAX_STATIC_ALIGN_BYTES!=0
|
||||
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0,EIGEN_PLAIN_ENUM_MIN(AlignedMax,PacketSize)> m_data;
|
||||
EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; }
|
||||
#else
|
||||
// Some architectures cannot align on the stack,
|
||||
// => let's manually enforce alignment by allocating more data and return the address of the first aligned element.
|
||||
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?EIGEN_MAX_ALIGN_BYTES:0),0> m_data;
|
||||
EIGEN_STRONG_INLINE Scalar* data() {
|
||||
return ForceAlignment
|
||||
? reinterpret_cast<Scalar*>((internal::UIntPtr(m_data.array) & ~(size_t(EIGEN_MAX_ALIGN_BYTES-1))) + EIGEN_MAX_ALIGN_BYTES)
|
||||
? reinterpret_cast<Scalar*>((internal::UIntPtr(m_data.array) & ~(std::size_t(EIGEN_MAX_ALIGN_BYTES-1))) + EIGEN_MAX_ALIGN_BYTES)
|
||||
: m_data.array;
|
||||
}
|
||||
#endif
|
||||
@@ -207,7 +207,7 @@ template<> struct gemv_dense_selector<OnTheRight,ColMajor,true>
|
||||
typedef internal::blas_traits<Rhs> RhsBlasTraits;
|
||||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
||||
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1>, EIGEN_PLAIN_ENUM_MIN(AlignedMax,internal::packet_traits<ResScalar>::size)> MappedDest;
|
||||
|
||||
ActualLhsType actualLhs = LhsBlasTraits::extract(lhs);
|
||||
ActualRhsType actualRhs = RhsBlasTraits::extract(rhs);
|
||||
|
||||
@@ -329,7 +329,7 @@ template<typename Packet> EIGEN_DEVICE_FUNC inline typename unpacket_traits<Pack
|
||||
*/
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline
|
||||
typename conditional<(unpacket_traits<Packet>::size%8)==0,typename unpacket_traits<Packet>::half,Packet>::type
|
||||
predux4(const Packet& a)
|
||||
predux_downto4(const Packet& a)
|
||||
{ return a; }
|
||||
|
||||
/** \internal \returns the product of the elements of \a a*/
|
||||
@@ -558,6 +558,34 @@ pblend(const Selector<unpacket_traits<Packet>::size>& ifPacket, const Packet& th
|
||||
return ifPacket.select[0] ? thenPacket : elsePacket;
|
||||
}
|
||||
|
||||
/** \internal \returns \a a with the first coefficient replaced by the scalar b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pinsertfirst(const Packet& a, typename unpacket_traits<Packet>::type b)
|
||||
{
|
||||
// Default implementation based on pblend.
|
||||
// It must be specialized for higher performance.
|
||||
Selector<unpacket_traits<Packet>::size> mask;
|
||||
mask.select[0] = true;
|
||||
// This for loop should be optimized away by the compiler.
|
||||
for(Index i=1; i<unpacket_traits<Packet>::size; ++i)
|
||||
mask.select[i] = false;
|
||||
return pblend(mask, pset1<Packet>(b), a);
|
||||
}
|
||||
|
||||
/** \internal \returns \a a with the last coefficient replaced by the scalar b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pinsertlast(const Packet& a, typename unpacket_traits<Packet>::type b)
|
||||
{
|
||||
// Default implementation based on pblend.
|
||||
// It must be specialized for higher performance.
|
||||
Selector<unpacket_traits<Packet>::size> mask;
|
||||
// This for loop should be optimized away by the compiler.
|
||||
for(Index i=0; i<unpacket_traits<Packet>::size-1; ++i)
|
||||
mask.select[i] = false;
|
||||
mask.select[unpacket_traits<Packet>::size-1] = true;
|
||||
return pblend(mask, pset1<Packet>(b), a);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
typedef typename internal::ref_selector<Inverse>::type Nested;
|
||||
typedef typename internal::remove_all<XprType>::type NestedExpression;
|
||||
|
||||
explicit Inverse(const XprType &xpr)
|
||||
explicit EIGEN_DEVICE_FUNC Inverse(const XprType &xpr)
|
||||
: m_xpr(xpr)
|
||||
{}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Eigen {
|
||||
* Typical users do not have to directly deal with this class.
|
||||
*
|
||||
* This class can be extended by through the macro plugin \c EIGEN_MAPBASE_PLUGIN.
|
||||
* See \link TopicCustomizingEigen customizing Eigen \endlink for details.
|
||||
* See \link TopicCustomizing_Plugins customizing Eigen \endlink for details.
|
||||
*
|
||||
* The \c Derived class has to provide the following two methods describing the memory layout:
|
||||
* \code Index innerStride() const; \endcode
|
||||
|
||||
@@ -97,6 +97,19 @@ struct real_default_impl<Scalar,true>
|
||||
|
||||
template<typename Scalar> struct real_impl : real_default_impl<Scalar> {};
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
template<typename T>
|
||||
struct real_impl<std::complex<T> >
|
||||
{
|
||||
typedef T RealScalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline T run(const std::complex<T>& x)
|
||||
{
|
||||
return x.real();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename Scalar>
|
||||
struct real_retval
|
||||
{
|
||||
@@ -132,6 +145,19 @@ struct imag_default_impl<Scalar,true>
|
||||
|
||||
template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {};
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
template<typename T>
|
||||
struct imag_impl<std::complex<T> >
|
||||
{
|
||||
typedef T RealScalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline T run(const std::complex<T>& x)
|
||||
{
|
||||
return x.imag();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename Scalar>
|
||||
struct imag_retval
|
||||
{
|
||||
@@ -459,30 +485,33 @@ struct arg_retval
|
||||
/****************************************************************************
|
||||
* Implementation of log1p *
|
||||
****************************************************************************/
|
||||
template<typename Scalar, bool isComplex = NumTraits<Scalar>::IsComplex >
|
||||
struct log1p_impl
|
||||
{
|
||||
static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x)
|
||||
{
|
||||
|
||||
namespace std_fallback {
|
||||
// fallback log1p implementation in case there is no log1p(Scalar) function in namespace of Scalar,
|
||||
// or that there is no suitable std::log1p function available
|
||||
template<typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline Scalar log1p(const Scalar& x) {
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
EIGEN_USING_STD_MATH(log);
|
||||
Scalar x1p = RealScalar(1) + x;
|
||||
return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_CXX11_MATH && !defined(__CUDACC__)
|
||||
template<typename Scalar>
|
||||
struct log1p_impl<Scalar, false> {
|
||||
struct log1p_impl {
|
||||
static inline Scalar run(const Scalar& x)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
using std::log1p;
|
||||
#endif
|
||||
using std_fallback::log1p;
|
||||
return log1p(x);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
template<typename Scalar>
|
||||
struct log1p_retval
|
||||
@@ -615,16 +644,18 @@ struct random_default_impl<Scalar, false, true>
|
||||
typedef typename conditional<NumTraits<Scalar>::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX;
|
||||
if(y<x)
|
||||
return x;
|
||||
// the following difference might overflow on a 32 bits system,
|
||||
// but since y>=x the result converted to an unsigned long is still correct.
|
||||
std::size_t range = ScalarX(y)-ScalarX(x);
|
||||
std::size_t offset = 0;
|
||||
// rejection sampling
|
||||
std::size_t divisor = (range+RAND_MAX-1)/(range+1);
|
||||
std::size_t multiplier = (range+RAND_MAX-1)/std::size_t(RAND_MAX);
|
||||
|
||||
std::size_t divisor = 1;
|
||||
std::size_t multiplier = 1;
|
||||
if(range<RAND_MAX) divisor = (std::size_t(RAND_MAX)+1)/(range+1);
|
||||
else multiplier = 1 + range/(std::size_t(RAND_MAX)+1);
|
||||
do {
|
||||
offset = ( (std::size_t(std::rand()) * multiplier) / divisor );
|
||||
offset = (std::size_t(std::rand()) * multiplier) / divisor;
|
||||
} while (offset > range);
|
||||
|
||||
return Scalar(ScalarX(x) + offset);
|
||||
}
|
||||
|
||||
@@ -785,6 +816,8 @@ template<typename T> EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex<T>&
|
||||
template<typename T> EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex<T>& x);
|
||||
template<typename T> EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex<T>& x);
|
||||
|
||||
template<typename T> T generic_fast_tanh_float(const T& a_x);
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/****************************************************************************
|
||||
@@ -921,6 +954,14 @@ inline EIGEN_MATHFUNC_RETVAL(log1p, Scalar) log1p(const Scalar& x)
|
||||
return EIGEN_MATHFUNC_IMPL(log1p, Scalar)::run(x);
|
||||
}
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float log1p(const float &x) { return ::log1pf(x); }
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
double log1p(const double &x) { return ::log1p(x); }
|
||||
#endif
|
||||
|
||||
template<typename ScalarX,typename ScalarY>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename internal::pow_impl<ScalarX,ScalarY>::result_type pow(const ScalarX& x, const ScalarY& y)
|
||||
@@ -1031,6 +1072,16 @@ float abs(const float &x) { return ::fabsf(x); }
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
double abs(const double &x) { return ::fabs(x); }
|
||||
|
||||
template <> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float abs(const std::complex<float>& x) {
|
||||
return ::hypotf(x.real(), x.imag());
|
||||
}
|
||||
|
||||
template <> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
double abs(const std::complex<double>& x) {
|
||||
return ::hypot(x.real(), x.imag());
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
@@ -1176,6 +1227,11 @@ T tanh(const T &x) {
|
||||
return tanh(x);
|
||||
}
|
||||
|
||||
#if (!defined(__CUDACC__)) && EIGEN_FAST_MATH
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float tanh(float x) { return internal::generic_fast_tanh_float(x); }
|
||||
#endif
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float tanh(const float &x) { return ::tanhf(x); }
|
||||
@@ -1282,11 +1338,12 @@ template<typename Scalar>
|
||||
struct scalar_fuzzy_default_impl<Scalar, true, false>
|
||||
{
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
template<typename OtherScalar>
|
||||
template<typename OtherScalar> EIGEN_DEVICE_FUNC
|
||||
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
|
||||
{
|
||||
return numext::abs2(x) <= numext::abs2(y) * prec * prec;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
||||
{
|
||||
return numext::abs2(x - y) <= numext::mini(numext::abs2(x), numext::abs2(y)) * prec * prec;
|
||||
|
||||
78
Eigen/src/Core/MathFunctionsImpl.h
Normal file
78
Eigen/src/Core/MathFunctionsImpl.h
Normal file
@@ -0,0 +1,78 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2014 Pedro Gonnet (pedro.gonnet@gmail.com)
|
||||
// Copyright (C) 2016 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_MATHFUNCTIONSIMPL_H
|
||||
#define EIGEN_MATHFUNCTIONSIMPL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal \returns the hyperbolic tan of \a a (coeff-wise)
|
||||
Doesn't do anything fancy, just a 13/6-degree rational interpolant which
|
||||
is accurate up to a couple of ulp in the range [-9, 9], outside of which
|
||||
the tanh(x) = +/-1.
|
||||
|
||||
This implementation works on both scalars and packets.
|
||||
*/
|
||||
template<typename T>
|
||||
T generic_fast_tanh_float(const T& a_x)
|
||||
{
|
||||
// Clamp the inputs to the range [-9, 9] since anything outside
|
||||
// this range is +/-1.0f in single-precision.
|
||||
const T plus_9 = pset1<T>(9.f);
|
||||
const T minus_9 = pset1<T>(-9.f);
|
||||
// NOTE GCC prior to 6.3 might improperly optimize this max/min
|
||||
// step such that if a_x is nan, x will be either 9 or -9,
|
||||
// and tanh will return 1 or -1 instead of nan.
|
||||
// This is supposed to be fixed in gcc6.3,
|
||||
// see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72867
|
||||
const T x = pmax(minus_9,pmin(plus_9,a_x));
|
||||
// The monomial coefficients of the numerator polynomial (odd).
|
||||
const T alpha_1 = pset1<T>(4.89352455891786e-03f);
|
||||
const T alpha_3 = pset1<T>(6.37261928875436e-04f);
|
||||
const T alpha_5 = pset1<T>(1.48572235717979e-05f);
|
||||
const T alpha_7 = pset1<T>(5.12229709037114e-08f);
|
||||
const T alpha_9 = pset1<T>(-8.60467152213735e-11f);
|
||||
const T alpha_11 = pset1<T>(2.00018790482477e-13f);
|
||||
const T alpha_13 = pset1<T>(-2.76076847742355e-16f);
|
||||
|
||||
// The monomial coefficients of the denominator polynomial (even).
|
||||
const T beta_0 = pset1<T>(4.89352518554385e-03f);
|
||||
const T beta_2 = pset1<T>(2.26843463243900e-03f);
|
||||
const T beta_4 = pset1<T>(1.18534705686654e-04f);
|
||||
const T beta_6 = pset1<T>(1.19825839466702e-06f);
|
||||
|
||||
// Since the polynomials are odd/even, we need x^2.
|
||||
const T x2 = pmul(x, x);
|
||||
|
||||
// Evaluate the numerator polynomial p.
|
||||
T p = pmadd(x2, alpha_13, alpha_11);
|
||||
p = pmadd(x2, p, alpha_9);
|
||||
p = pmadd(x2, p, alpha_7);
|
||||
p = pmadd(x2, p, alpha_5);
|
||||
p = pmadd(x2, p, alpha_3);
|
||||
p = pmadd(x2, p, alpha_1);
|
||||
p = pmul(x, p);
|
||||
|
||||
// Evaluate the denominator polynomial p.
|
||||
T q = pmadd(x2, beta_6, beta_4);
|
||||
q = pmadd(x2, q, beta_2);
|
||||
q = pmadd(x2, q, beta_0);
|
||||
|
||||
// Divide the numerator by the denominator.
|
||||
return pdiv(p, q);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_MATHFUNCTIONSIMPL_H
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
* \endcode
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_MATRIX_PLUGIN.
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_MATRIX_PLUGIN.
|
||||
*
|
||||
* <i><b>Some notes:</b></i>
|
||||
*
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Eigen {
|
||||
* \endcode
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_MATRIXBASE_PLUGIN.
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_MATRIXBASE_PLUGIN.
|
||||
*
|
||||
* \sa \blank \ref TopicClassHierarchy
|
||||
*/
|
||||
@@ -98,7 +98,7 @@ template<typename Derived> class MatrixBase
|
||||
/** \returns the size of the main diagonal, which is min(rows(),cols()).
|
||||
* \sa rows(), cols(), SizeAtCompileTime. */
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index diagonalSize() const { return (std::min)(rows(),cols()); }
|
||||
inline Index diagonalSize() const { return (numext::mini)(rows(),cols()); }
|
||||
|
||||
typedef typename Base::PlainObject PlainObject;
|
||||
|
||||
@@ -121,6 +121,7 @@ template<typename Derived> class MatrixBase
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::MatrixBase
|
||||
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
|
||||
# include "../plugins/CommonCwiseUnaryOps.h"
|
||||
# include "../plugins/CommonCwiseBinaryOps.h"
|
||||
# include "../plugins/MatrixCwiseUnaryOps.h"
|
||||
@@ -129,6 +130,7 @@ template<typename Derived> class MatrixBase
|
||||
# include EIGEN_MATRIXBASE_PLUGIN
|
||||
# endif
|
||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
||||
#undef EIGEN_DOC_UNARY_ADDONS
|
||||
|
||||
/** Special case of the template operator=, in order to prevent the compiler
|
||||
* from generating a default operator= (issue hit with g++ 4.1)
|
||||
@@ -328,15 +330,11 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
/////////// LU module ///////////
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const FullPivLU<PlainObject> fullPivLu() const;
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const PartialPivLU<PlainObject> partialPivLu() const;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const PartialPivLU<PlainObject> lu() const;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Inverse<Derived> inverse() const;
|
||||
|
||||
template<typename ResultType>
|
||||
@@ -401,12 +399,14 @@ template<typename Derived> class MatrixBase
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline PlainObject unitOrthogonal(void) const;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Matrix<Scalar,3,1> eulerAngles(Index a0, Index a1, Index a2) const;
|
||||
|
||||
// put this as separate enum value to work around possible GCC 4.3 bug (?)
|
||||
enum { HomogeneousReturnTypeDirection = ColsAtCompileTime==1&&RowsAtCompileTime==1 ? ((internal::traits<Derived>::Flags&RowMajorBit)==RowMajorBit ? Horizontal : Vertical)
|
||||
: ColsAtCompileTime==1 ? Vertical : Horizontal };
|
||||
typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType;
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline HomogeneousReturnType homogeneous() const;
|
||||
|
||||
enum {
|
||||
@@ -416,7 +416,7 @@ template<typename Derived> class MatrixBase
|
||||
internal::traits<Derived>::ColsAtCompileTime==1 ? SizeMinusOne : 1,
|
||||
internal::traits<Derived>::ColsAtCompileTime==1 ? 1 : SizeMinusOne> ConstStartMinusOne;
|
||||
typedef EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(ConstStartMinusOne,Scalar,quotient) HNormalizedReturnType;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const HNormalizedReturnType hnormalized() const;
|
||||
|
||||
////////// Householder module ///////////
|
||||
|
||||
@@ -97,23 +97,6 @@ template<typename T> struct GenericNumTraits
|
||||
MulCost = 1
|
||||
};
|
||||
|
||||
// Division is messy but important, because it is expensive and throughput
|
||||
// varies significantly. The following numbers are based on min division
|
||||
// throughput on Haswell.
|
||||
template<bool Vectorized>
|
||||
struct Div {
|
||||
enum {
|
||||
#ifdef EIGEN_VECTORIZE_AVX
|
||||
AVX = true,
|
||||
#else
|
||||
AVX = false,
|
||||
#endif
|
||||
Cost = IsInteger ? (sizeof(T) == 8 ? (IsSigned ? 24 : 21) : (IsSigned ? 8 : 9)):
|
||||
Vectorized ? (sizeof(T) == 8 ? (AVX ? 16 : 8) : (AVX ? 14 : 7)) : 8
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
typedef T Real;
|
||||
typedef typename internal::conditional<
|
||||
IsInteger,
|
||||
@@ -255,6 +238,9 @@ private:
|
||||
static inline std::string quiet_NaN();
|
||||
};
|
||||
|
||||
// Empty specialization for void to allow template specialization based on NumTraits<T>::Real with T==void and SFINAE.
|
||||
template<> struct NumTraits<void> {};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_NUMTRAITS_H
|
||||
|
||||
@@ -63,7 +63,7 @@ template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct m
|
||||
* \brief %Dense storage base class for matrices and arrays.
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN.
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN.
|
||||
*
|
||||
* \sa \ref TopicClassHierarchy
|
||||
*/
|
||||
@@ -916,8 +916,8 @@ struct conservative_resize_like_impl
|
||||
{
|
||||
// The storage order does not allow us to use reallocation.
|
||||
typename Derived::PlainObject tmp(rows,cols);
|
||||
const Index common_rows = (std::min)(rows, _this.rows());
|
||||
const Index common_cols = (std::min)(cols, _this.cols());
|
||||
const Index common_rows = numext::mini(rows, _this.rows());
|
||||
const Index common_cols = numext::mini(cols, _this.cols());
|
||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||
_this.derived().swap(tmp);
|
||||
}
|
||||
@@ -950,8 +950,8 @@ struct conservative_resize_like_impl
|
||||
{
|
||||
// The storage order does not allow us to use reallocation.
|
||||
typename Derived::PlainObject tmp(other);
|
||||
const Index common_rows = (std::min)(tmp.rows(), _this.rows());
|
||||
const Index common_cols = (std::min)(tmp.cols(), _this.cols());
|
||||
const Index common_rows = numext::mini(tmp.rows(), _this.rows());
|
||||
const Index common_cols = numext::mini(tmp.cols(), _this.cols());
|
||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||
_this.derived().swap(tmp);
|
||||
}
|
||||
|
||||
@@ -140,6 +140,10 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::assign_op<Scal
|
||||
static EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
// FIXME shall we handle nested_eval here?
|
||||
generic_product_impl<Lhs, Rhs>::evalTo(dst, src.lhs(), src.rhs());
|
||||
}
|
||||
@@ -154,6 +158,10 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::add_assign_op<
|
||||
static EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
// FIXME shall we handle nested_eval here?
|
||||
generic_product_impl<Lhs, Rhs>::addTo(dst, src.lhs(), src.rhs());
|
||||
}
|
||||
@@ -168,6 +176,10 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::sub_assign_op<
|
||||
static EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
// FIXME shall we handle nested_eval here?
|
||||
generic_product_impl<Lhs, Rhs>::subTo(dst, src.lhs(), src.rhs());
|
||||
}
|
||||
@@ -194,7 +206,6 @@ struct Assignment<DstXprType, CwiseBinaryOp<internal::scalar_product_op<ScalarBi
|
||||
//----------------------------------------
|
||||
// Catch "Dense ?= xpr + Product<>" expression to save one temporary
|
||||
// FIXME we could probably enable these rules for any product, i.e., not only Dense and DefaultProduct
|
||||
// TODO enable it for "Dense ?= xpr - Product<>" as well.
|
||||
|
||||
template<typename OtherXpr, typename Lhs, typename Rhs>
|
||||
struct evaluator_assume_aliasing<CwiseBinaryOp<internal::scalar_sum_op<typename OtherXpr::Scalar,typename Product<Lhs,Rhs,DefaultProduct>::Scalar>, const OtherXpr,
|
||||
@@ -203,10 +214,9 @@ struct evaluator_assume_aliasing<CwiseBinaryOp<internal::scalar_sum_op<typename
|
||||
};
|
||||
|
||||
template<typename DstXprType, typename OtherXpr, typename ProductType, typename Func1, typename Func2>
|
||||
struct assignment_from_xpr_plus_product
|
||||
struct assignment_from_xpr_op_product
|
||||
{
|
||||
typedef CwiseBinaryOp<internal::scalar_sum_op<typename OtherXpr::Scalar,typename ProductType::Scalar>, const OtherXpr, const ProductType> SrcXprType;
|
||||
template<typename InitialFunc>
|
||||
template<typename SrcXprType, typename InitialFunc>
|
||||
static EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const InitialFunc& /*func*/)
|
||||
{
|
||||
@@ -215,21 +225,21 @@ struct assignment_from_xpr_plus_product
|
||||
}
|
||||
};
|
||||
|
||||
template< typename DstXprType, typename OtherXpr, typename Lhs, typename Rhs, typename DstScalar, typename SrcScalar, typename OtherScalar,typename ProdScalar>
|
||||
struct Assignment<DstXprType, CwiseBinaryOp<internal::scalar_sum_op<OtherScalar,ProdScalar>, const OtherXpr,
|
||||
const Product<Lhs,Rhs,DefaultProduct> >, internal::assign_op<DstScalar,SrcScalar>, Dense2Dense>
|
||||
: assignment_from_xpr_plus_product<DstXprType, OtherXpr, Product<Lhs,Rhs,DefaultProduct>, internal::assign_op<DstScalar,OtherScalar>, internal::add_assign_op<DstScalar,ProdScalar> >
|
||||
{};
|
||||
template< typename DstXprType, typename OtherXpr, typename Lhs, typename Rhs, typename DstScalar, typename SrcScalar, typename OtherScalar,typename ProdScalar>
|
||||
struct Assignment<DstXprType, CwiseBinaryOp<internal::scalar_sum_op<OtherScalar,ProdScalar>, const OtherXpr,
|
||||
const Product<Lhs,Rhs,DefaultProduct> >, internal::add_assign_op<DstScalar,SrcScalar>, Dense2Dense>
|
||||
: assignment_from_xpr_plus_product<DstXprType, OtherXpr, Product<Lhs,Rhs,DefaultProduct>, internal::add_assign_op<DstScalar,OtherScalar>, internal::add_assign_op<DstScalar,ProdScalar> >
|
||||
{};
|
||||
template< typename DstXprType, typename OtherXpr, typename Lhs, typename Rhs, typename DstScalar, typename SrcScalar, typename OtherScalar,typename ProdScalar>
|
||||
struct Assignment<DstXprType, CwiseBinaryOp<internal::scalar_sum_op<OtherScalar,ProdScalar>, const OtherXpr,
|
||||
const Product<Lhs,Rhs,DefaultProduct> >, internal::sub_assign_op<DstScalar,SrcScalar>, Dense2Dense>
|
||||
: assignment_from_xpr_plus_product<DstXprType, OtherXpr, Product<Lhs,Rhs,DefaultProduct>, internal::sub_assign_op<DstScalar,OtherScalar>, internal::sub_assign_op<DstScalar,ProdScalar> >
|
||||
{};
|
||||
#define EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(ASSIGN_OP,BINOP,ASSIGN_OP2) \
|
||||
template< typename DstXprType, typename OtherXpr, typename Lhs, typename Rhs, typename DstScalar, typename SrcScalar, typename OtherScalar,typename ProdScalar> \
|
||||
struct Assignment<DstXprType, CwiseBinaryOp<internal::BINOP<OtherScalar,ProdScalar>, const OtherXpr, \
|
||||
const Product<Lhs,Rhs,DefaultProduct> >, internal::ASSIGN_OP<DstScalar,SrcScalar>, Dense2Dense> \
|
||||
: assignment_from_xpr_op_product<DstXprType, OtherXpr, Product<Lhs,Rhs,DefaultProduct>, internal::ASSIGN_OP<DstScalar,OtherScalar>, internal::ASSIGN_OP2<DstScalar,ProdScalar> > \
|
||||
{}
|
||||
|
||||
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_sum_op,add_assign_op);
|
||||
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op,scalar_sum_op,add_assign_op);
|
||||
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op,scalar_sum_op,sub_assign_op);
|
||||
|
||||
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_difference_op,sub_assign_op);
|
||||
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op,scalar_difference_op,sub_assign_op);
|
||||
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op,scalar_difference_op,add_assign_op);
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
@@ -267,7 +277,7 @@ void outer_product_selector_run(Dst& dst, const Lhs &lhs, const Rhs &rhs, const
|
||||
// FIXME not very good if rhs is real and lhs complex while alpha is real too
|
||||
const Index cols = dst.cols();
|
||||
for (Index j=0; j<cols; ++j)
|
||||
func(dst.col(j), rhsEval.coeff(0,j) * actual_lhs);
|
||||
func(dst.col(j), rhsEval.coeff(Index(0),j) * actual_lhs);
|
||||
}
|
||||
|
||||
// Row major result
|
||||
@@ -280,7 +290,7 @@ void outer_product_selector_run(Dst& dst, const Lhs &lhs, const Rhs &rhs, const
|
||||
// FIXME not very good if lhs is real and rhs complex while alpha is real too
|
||||
const Index rows = dst.rows();
|
||||
for (Index i=0; i<rows; ++i)
|
||||
func(dst.row(i), lhsEval.coeff(i,0) * actual_rhs);
|
||||
func(dst.row(i), lhsEval.coeff(i,Index(0)) * actual_rhs);
|
||||
}
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
@@ -439,6 +449,18 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::MulCost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::AddCost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
#if 0
|
||||
std::cerr << "LhsOuterStrideBytes= " << LhsOuterStrideBytes << "\n";
|
||||
std::cerr << "RhsOuterStrideBytes= " << RhsOuterStrideBytes << "\n";
|
||||
std::cerr << "LhsAlignment= " << LhsAlignment << "\n";
|
||||
std::cerr << "RhsAlignment= " << RhsAlignment << "\n";
|
||||
std::cerr << "CanVectorizeLhs= " << CanVectorizeLhs << "\n";
|
||||
std::cerr << "CanVectorizeRhs= " << CanVectorizeRhs << "\n";
|
||||
std::cerr << "CanVectorizeInner= " << CanVectorizeInner << "\n";
|
||||
std::cerr << "EvalToRowMajor= " << EvalToRowMajor << "\n";
|
||||
std::cerr << "Alignment= " << Alignment << "\n";
|
||||
std::cerr << "Flags= " << Flags << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Everything below here is taken from CoeffBasedProduct.h
|
||||
@@ -489,11 +511,8 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
|
||||
SameType = is_same<typename LhsNestedCleaned::Scalar,typename RhsNestedCleaned::Scalar>::value,
|
||||
|
||||
CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags & PacketAccessBit)
|
||||
&& (ColsAtCompileTime == Dynamic || ((ColsAtCompileTime % RhsVecPacketSize) == 0) ),
|
||||
|
||||
CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit)
|
||||
&& (RowsAtCompileTime == Dynamic || ((RowsAtCompileTime % LhsVecPacketSize) == 0) ),
|
||||
CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags & PacketAccessBit) && (ColsAtCompileTime!=1),
|
||||
CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit) && (RowsAtCompileTime!=1),
|
||||
|
||||
EvalToRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||
@@ -508,8 +527,8 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
LhsOuterStrideBytes = int(LhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename LhsNestedCleaned::Scalar)),
|
||||
RhsOuterStrideBytes = int(RhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename RhsNestedCleaned::Scalar)),
|
||||
|
||||
Alignment = bool(CanVectorizeLhs) ? (LhsOuterStrideBytes<0 || (int(LhsOuterStrideBytes) % EIGEN_PLAIN_ENUM_MAX(1,LhsAlignment))!=0 ? 0 : LhsAlignment)
|
||||
: bool(CanVectorizeRhs) ? (RhsOuterStrideBytes<0 || (int(RhsOuterStrideBytes) % EIGEN_PLAIN_ENUM_MAX(1,RhsAlignment))!=0 ? 0 : RhsAlignment)
|
||||
Alignment = bool(CanVectorizeLhs) ? (LhsOuterStrideBytes<=0 || (int(LhsOuterStrideBytes) % EIGEN_PLAIN_ENUM_MAX(1,LhsAlignment))!=0 ? 0 : LhsAlignment)
|
||||
: bool(CanVectorizeRhs) ? (RhsOuterStrideBytes<=0 || (int(RhsOuterStrideBytes) % EIGEN_PLAIN_ENUM_MAX(1,RhsAlignment))!=0 ? 0 : RhsAlignment)
|
||||
: 0,
|
||||
|
||||
/* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside
|
||||
@@ -535,8 +554,8 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC const CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
const Index row = RowsAtCompileTime == 1 ? 0 : index;
|
||||
const Index col = RowsAtCompileTime == 1 ? index : 0;
|
||||
const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? 0 : index;
|
||||
const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? index : 0;
|
||||
return (m_lhs.row(row).transpose().cwiseProduct( m_rhs.col(col) )).sum();
|
||||
}
|
||||
|
||||
@@ -554,14 +573,14 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
template<int LoadMode, typename PacketType>
|
||||
const PacketType packet(Index index) const
|
||||
{
|
||||
const Index row = RowsAtCompileTime == 1 ? 0 : index;
|
||||
const Index col = RowsAtCompileTime == 1 ? index : 0;
|
||||
const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? 0 : index;
|
||||
const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? index : 0;
|
||||
return packet<LoadMode,PacketType>(row,col);
|
||||
}
|
||||
|
||||
protected:
|
||||
const LhsNested m_lhs;
|
||||
const RhsNested m_rhs;
|
||||
typename internal::add_const_on_value_type<LhsNested>::type m_lhs;
|
||||
typename internal::add_const_on_value_type<RhsNested>::type m_rhs;
|
||||
|
||||
LhsEtorType m_lhsImpl;
|
||||
RhsEtorType m_rhsImpl;
|
||||
@@ -595,7 +614,7 @@ struct etor_product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, Load
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet &res)
|
||||
{
|
||||
etor_product_packet_impl<RowMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, innerDim, res);
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex-1)), rhs.template packet<LoadMode,Packet>(UnrollingIndex-1, col), res);
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, Index(UnrollingIndex-1))), rhs.template packet<LoadMode,Packet>(Index(UnrollingIndex-1), col), res);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -605,7 +624,7 @@ struct etor_product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, Load
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet &res)
|
||||
{
|
||||
etor_product_packet_impl<ColMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, innerDim, res);
|
||||
res = pmadd(lhs.template packet<LoadMode,Packet>(row, UnrollingIndex-1), pset1<Packet>(rhs.coeff(UnrollingIndex-1, col)), res);
|
||||
res = pmadd(lhs.template packet<LoadMode,Packet>(row, Index(UnrollingIndex-1)), pset1<Packet>(rhs.coeff(Index(UnrollingIndex-1), col)), res);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -614,7 +633,7 @@ struct etor_product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, Packet &res)
|
||||
{
|
||||
res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode,Packet>(0, col));
|
||||
res = pmul(pset1<Packet>(lhs.coeff(row, Index(0))),rhs.template packet<LoadMode,Packet>(Index(0), col));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -623,7 +642,7 @@ struct etor_product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, Packet &res)
|
||||
{
|
||||
res = pmul(lhs.template packet<LoadMode,Packet>(row, 0), pset1<Packet>(rhs.coeff(0, col)));
|
||||
res = pmul(lhs.template packet<LoadMode,Packet>(row, Index(0)), pset1<Packet>(rhs.coeff(Index(0), col)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -632,7 +651,7 @@ struct etor_product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Index /*innerDim*/, Packet &res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -641,7 +660,7 @@ struct etor_product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Index /*innerDim*/, Packet &res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -650,7 +669,7 @@ struct etor_product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet& res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
for(Index i = 0; i < innerDim; ++i)
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode,Packet>(i, col), res);
|
||||
}
|
||||
@@ -661,7 +680,7 @@ struct etor_product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet& res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
for(Index i = 0; i < innerDim; ++i)
|
||||
res = pmadd(lhs.template packet<LoadMode,Packet>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace internal {
|
||||
|
||||
template<typename Scalar> struct scalar_random_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_random_op)
|
||||
template<typename Index>
|
||||
inline const Scalar operator() (Index, Index = 0) const { return random<Scalar>(); }
|
||||
inline const Scalar operator() () const { return random<Scalar>(); }
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
|
||||
@@ -35,7 +35,13 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
|
||||
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
|
||||
OuterStrideMatch = Derived::IsVectorAtCompileTime
|
||||
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
|
||||
AlignmentMatch = (int(traits<PlainObjectType>::Alignment)==int(Unaligned)) || (int(evaluator<Derived>::Alignment) >= int(Alignment)), // FIXME the first condition is not very clear, it should be replaced by the required alignment
|
||||
// NOTE, this indirection of evaluator<Derived>::Alignment is needed
|
||||
// to workaround a very strange bug in MSVC related to the instantiation
|
||||
// of has_*ary_operator in evaluator<CwiseNullaryOp>.
|
||||
// This line is surprisingly very sensitive. For instance, simply adding parenthesis
|
||||
// as "DerivedAlignment = (int(evaluator<Derived>::Alignment))," will make MSVC fail...
|
||||
DerivedAlignment = int(evaluator<Derived>::Alignment),
|
||||
AlignmentMatch = (int(traits<PlainObjectType>::Alignment)==int(Unaligned)) || (DerivedAlignment >= int(Alignment)), // FIXME the first condition is not very clear, it should be replaced by the required alignment
|
||||
ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
|
||||
MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
|
||||
};
|
||||
|
||||
@@ -139,7 +139,11 @@ struct Assignment<DstXprType, Solve<DecType,RhsType>, internal::assign_op<Scalar
|
||||
typedef Solve<DecType,RhsType> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
// FIXME shall we resize dst here?
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
src.dec()._solve_impl(src.rhs(), dst);
|
||||
}
|
||||
};
|
||||
@@ -151,6 +155,11 @@ struct Assignment<DstXprType, Solve<Transpose<const DecType>,RhsType>, internal:
|
||||
typedef Solve<Transpose<const DecType>,RhsType> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
src.dec().nestedExpression().template _solve_impl_transposed<false>(src.rhs(), dst);
|
||||
}
|
||||
};
|
||||
@@ -163,6 +172,11 @@ struct Assignment<DstXprType, Solve<CwiseUnaryOp<internal::scalar_conjugate_op<t
|
||||
typedef Solve<CwiseUnaryOp<internal::scalar_conjugate_op<typename DecType::Scalar>, const Transpose<const DecType> >,RhsType> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
src.dec().nestedExpression().nestedExpression().template _solve_impl_transposed<true>(src.rhs(), dst);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -78,6 +78,11 @@ template<typename MatrixType> class Transpose
|
||||
typename internal::remove_reference<MatrixTypeNested>::type&
|
||||
nestedExpression() { return m_matrix; }
|
||||
|
||||
/** \internal */
|
||||
void resize(Index nrows, Index ncols) {
|
||||
m_matrix.resize(ncols,nrows);
|
||||
}
|
||||
|
||||
protected:
|
||||
typename internal::ref_selector<MatrixType>::non_const_type m_matrix;
|
||||
};
|
||||
|
||||
@@ -641,21 +641,20 @@ MatrixBase<Derived>::triangularView() const
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const
|
||||
{
|
||||
using std::abs;
|
||||
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
{
|
||||
Index maxi = (std::min)(j, rows()-1);
|
||||
Index maxi = numext::mini(j, rows()-1);
|
||||
for(Index i = 0; i <= maxi; ++i)
|
||||
{
|
||||
RealScalar absValue = abs(coeff(i,j));
|
||||
RealScalar absValue = numext::abs(coeff(i,j));
|
||||
if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
|
||||
}
|
||||
}
|
||||
RealScalar threshold = maxAbsOnUpperPart * prec;
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
for(Index i = j+1; i < rows(); ++i)
|
||||
if(abs(coeff(i, j)) > threshold) return false;
|
||||
if(numext::abs(coeff(i, j)) > threshold) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -667,20 +666,19 @@ bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const
|
||||
{
|
||||
using std::abs;
|
||||
RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
for(Index i = j; i < rows(); ++i)
|
||||
{
|
||||
RealScalar absValue = abs(coeff(i,j));
|
||||
RealScalar absValue = numext::abs(coeff(i,j));
|
||||
if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
|
||||
}
|
||||
RealScalar threshold = maxAbsOnLowerPart * prec;
|
||||
for(Index j = 1; j < cols(); ++j)
|
||||
{
|
||||
Index maxi = (std::min)(j, rows()-1);
|
||||
Index maxi = numext::mini(j, rows()-1);
|
||||
for(Index i = 0; i < maxi; ++i)
|
||||
if(abs(coeff(i, j)) > threshold) return false;
|
||||
if(numext::abs(coeff(i, j)) > threshold) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -777,15 +775,18 @@ public:
|
||||
|
||||
template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType, typename Functor>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
|
||||
void call_triangular_assignment_loop(DstXprType& dst, const SrcXprType& src, const Functor &func)
|
||||
{
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||
|
||||
typedef evaluator<DstXprType> DstEvaluatorType;
|
||||
typedef evaluator<SrcXprType> SrcEvaluatorType;
|
||||
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
SrcEvaluatorType srcEvaluator(src);
|
||||
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
|
||||
typedef triangular_dense_assignment_kernel< Mode&(Lower|Upper),Mode&(UnitDiag|ZeroDiag|SelfAdjoint),SetOpposite,
|
||||
DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
|
||||
@@ -802,7 +803,7 @@ void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& sr
|
||||
|
||||
template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& src)
|
||||
void call_triangular_assignment_loop(DstXprType& dst, const SrcXprType& src)
|
||||
{
|
||||
call_triangular_assignment_loop<Mode,SetOpposite>(dst, src, internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar>());
|
||||
}
|
||||
@@ -893,7 +894,7 @@ struct triangular_assignment_loop<Kernel, Mode, Dynamic, SetOpposite>
|
||||
{
|
||||
for(Index j = 0; j < kernel.cols(); ++j)
|
||||
{
|
||||
Index maxi = (std::min)(j, kernel.rows());
|
||||
Index maxi = numext::mini(j, kernel.rows());
|
||||
Index i = 0;
|
||||
if (((Mode&Lower) && SetOpposite) || (Mode&Upper))
|
||||
{
|
||||
@@ -938,6 +939,11 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::assign_
|
||||
typedef Product<Lhs,Rhs,DefaultProduct> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename SrcXprType::Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
dst.setZero();
|
||||
dst._assignProduct(src, 1);
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
||||
return m_matrix / extendedTo(other.derived());
|
||||
}
|
||||
|
||||
/** \returns an expression where each column of row of the referenced matrix are normalized.
|
||||
/** \returns an expression where each column (or row) of the referenced matrix are normalized.
|
||||
* The referenced matrix is \b not modified.
|
||||
* \sa MatrixBase::normalized(), normalize()
|
||||
*/
|
||||
@@ -625,6 +625,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
typedef Homogeneous<ExpressionType,Direction> HomogeneousReturnType;
|
||||
EIGEN_DEVICE_FUNC
|
||||
HomogeneousReturnType homogeneous() const;
|
||||
|
||||
typedef typename ExpressionType::PlainObject CrossReturnType;
|
||||
@@ -654,6 +655,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
||||
Direction==Horizontal ? HNormalized_SizeMinusOne : 1> >
|
||||
HNormalizedReturnType;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
const HNormalizedReturnType hnormalized() const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_arch_AVX_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_arch_AVX_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/AVX COMPONENT Devel
|
||||
)
|
||||
@@ -456,6 +456,26 @@ ptranspose(PacketBlock<Packet2cd,2>& kernel) {
|
||||
kernel.packet[0].v = tmp;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cf pinsertfirst(const Packet4cf& a, std::complex<float> b)
|
||||
{
|
||||
return Packet4cf(_mm256_blend_ps(a.v,pset1<Packet4cf>(b).v,1|2));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cd pinsertfirst(const Packet2cd& a, std::complex<double> b)
|
||||
{
|
||||
return Packet2cd(_mm256_blend_pd(a.v,pset1<Packet2cd>(b).v,1|2));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cf pinsertlast(const Packet4cf& a, std::complex<float> b)
|
||||
{
|
||||
return Packet4cf(_mm256_blend_ps(a.v,pset1<Packet4cf>(b).v,(1<<7)|(1<<6)));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cd pinsertlast(const Packet2cd& a, std::complex<double> b)
|
||||
{
|
||||
return Packet2cd(_mm256_blend_pd(a.v,pset1<Packet2cd>(b).v,(1<<3)|(1<<2)));
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -266,52 +266,10 @@ pexp<Packet8f>(const Packet8f& _x) {
|
||||
}
|
||||
|
||||
// Hyperbolic Tangent function.
|
||||
// Doesn't do anything fancy, just a 13/6-degree rational interpolant which
|
||||
// is accurate up to a couple of ulp in the range [-9, 9], outside of which the
|
||||
// fl(tanh(x)) = +/-1.
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8f
|
||||
ptanh<Packet8f>(const Packet8f& _x) {
|
||||
// Clamp the inputs to the range [-9, 9] since anything outside
|
||||
// this range is +/-1.0f in single-precision.
|
||||
_EIGEN_DECLARE_CONST_Packet8f(plus_9, 9.0f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(minus_9, -9.0f);
|
||||
const Packet8f x = pmax(p8f_minus_9, pmin(p8f_plus_9, _x));
|
||||
|
||||
// The monomial coefficients of the numerator polynomial (odd).
|
||||
_EIGEN_DECLARE_CONST_Packet8f(alpha_1, 4.89352455891786e-03f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(alpha_3, 6.37261928875436e-04f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(alpha_5, 1.48572235717979e-05f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(alpha_7, 5.12229709037114e-08f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(alpha_9, -8.60467152213735e-11f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(alpha_11, 2.00018790482477e-13f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(alpha_13, -2.76076847742355e-16f);
|
||||
|
||||
// The monomial coefficients of the denominator polynomial (even).
|
||||
_EIGEN_DECLARE_CONST_Packet8f(beta_0, 4.89352518554385e-03f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(beta_2, 2.26843463243900e-03f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(beta_4, 1.18534705686654e-04f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(beta_6, 1.19825839466702e-06f);
|
||||
|
||||
// Since the polynomials are odd/even, we need x^2.
|
||||
const Packet8f x2 = pmul(x, x);
|
||||
|
||||
// Evaluate the numerator polynomial p.
|
||||
Packet8f p = pmadd(x2, p8f_alpha_13, p8f_alpha_11);
|
||||
p = pmadd(x2, p, p8f_alpha_9);
|
||||
p = pmadd(x2, p, p8f_alpha_7);
|
||||
p = pmadd(x2, p, p8f_alpha_5);
|
||||
p = pmadd(x2, p, p8f_alpha_3);
|
||||
p = pmadd(x2, p, p8f_alpha_1);
|
||||
p = pmul(x, p);
|
||||
|
||||
// Evaluate the denominator polynomial p.
|
||||
Packet8f q = pmadd(x2, p8f_beta_6, p8f_beta_4);
|
||||
q = pmadd(x2, q, p8f_beta_2);
|
||||
q = pmadd(x2, q, p8f_beta_0);
|
||||
|
||||
// Divide the numerator by the denominator.
|
||||
return pdiv(p, q);
|
||||
ptanh<Packet8f>(const Packet8f& x) {
|
||||
return internal::generic_fast_tanh_float(x);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -397,30 +355,27 @@ pexp<Packet4d>(const Packet4d& _x) {
|
||||
// Functions for sqrt.
|
||||
// The EIGEN_FAST_MATH version uses the _mm_rsqrt_ps approximation and one step
|
||||
// of Newton's method, at a cost of 1-2 bits of precision as opposed to the
|
||||
// exact solution. The main advantage of this approach is not just speed, but
|
||||
// also the fact that it can be inlined and pipelined with other computations,
|
||||
// further reducing its effective latency.
|
||||
// exact solution. It does not handle +inf, or denormalized numbers correctly.
|
||||
// The main advantage of this approach is not just speed, but also the fact that
|
||||
// it can be inlined and pipelined with other computations, further reducing its
|
||||
// effective latency. This is similar to Quake3's fast inverse square root.
|
||||
// For detail see here: http://www.beyond3d.com/content/articles/8/
|
||||
#if EIGEN_FAST_MATH
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8f
|
||||
psqrt<Packet8f>(const Packet8f& _x) {
|
||||
_EIGEN_DECLARE_CONST_Packet8f(one_point_five, 1.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f(minus_half, -0.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet8f_FROM_INT(flt_min, 0x00800000);
|
||||
|
||||
Packet8f neg_half = pmul(_x, p8f_minus_half);
|
||||
|
||||
// select only the inverse sqrt of positive normal inputs (denormals are
|
||||
// flushed to zero and cause infs as well).
|
||||
Packet8f non_zero_mask = _mm256_cmp_ps(_x, p8f_flt_min, _CMP_GE_OQ);
|
||||
Packet8f x = _mm256_and_ps(non_zero_mask, _mm256_rsqrt_ps(_x));
|
||||
Packet8f half = pmul(_x, pset1<Packet8f>(.5f));
|
||||
Packet8f denormal_mask = _mm256_and_ps(
|
||||
_mm256_cmp_ps(_x, pset1<Packet8f>((std::numeric_limits<float>::min)()),
|
||||
_CMP_LT_OQ),
|
||||
_mm256_cmp_ps(_x, _mm256_setzero_ps(), _CMP_GE_OQ));
|
||||
|
||||
// Compute approximate reciprocal sqrt.
|
||||
Packet8f x = _mm256_rsqrt_ps(_x);
|
||||
// Do a single step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p8f_one_point_five));
|
||||
|
||||
// Multiply the original _x by it's reciprocal square root to extract the
|
||||
// square root.
|
||||
return pmul(_x, x);
|
||||
x = pmul(x, psub(pset1<Packet8f>(1.5f), pmul(half, pmul(x,x))));
|
||||
// Flush results for denormals to zero.
|
||||
return _mm256_andnot_ps(denormal_mask, pmul(_x,x));
|
||||
}
|
||||
#else
|
||||
template <> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
|
||||
@@ -48,7 +48,9 @@ template<> struct is_arithmetic<__m256d> { enum { value = true }; };
|
||||
#define _EIGEN_DECLARE_CONST_Packet8i(NAME,X) \
|
||||
const Packet8i p8i_##NAME = pset1<Packet8i>(X)
|
||||
|
||||
|
||||
// Use the packet_traits defined in AVX512/PacketMath.h instead if we're going
|
||||
// to leverage AVX512 instructions.
|
||||
#ifndef EIGEN_VECTORIZE_AVX512
|
||||
template<> struct packet_traits<float> : default_packet_traits
|
||||
{
|
||||
typedef Packet8f type;
|
||||
@@ -93,6 +95,10 @@ template<> struct packet_traits<double> : default_packet_traits
|
||||
HasCeil = 1
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
template<> struct scalar_div_cost<float,true> { enum { value = 14 }; };
|
||||
template<> struct scalar_div_cost<double,true> { enum { value = 16 }; };
|
||||
|
||||
/* Proper support for integers is only provided by AVX2. In the meantime, we'll
|
||||
use SSE instructions and packets to deal with integers.
|
||||
@@ -153,7 +159,7 @@ template<> EIGEN_STRONG_INLINE Packet8i pdiv<Packet8i>(const Packet8i& /*a*/, co
|
||||
|
||||
#ifdef __FMA__
|
||||
template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f& b, const Packet8f& c) {
|
||||
#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
|
||||
#if ( EIGEN_COMP_GNUC_STRICT || (EIGEN_COMP_CLANG && (EIGEN_COMP_CLANG<308)) )
|
||||
// clang stupidly generates a vfmadd213ps instruction plus some vmovaps on registers,
|
||||
// and gcc stupidly generates a vfmadd132ps instruction,
|
||||
// so let's enforce it to generate a vfmadd231ps instruction since the most common use case is to accumulate
|
||||
@@ -166,7 +172,7 @@ template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f&
|
||||
#endif
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4d pmadd(const Packet4d& a, const Packet4d& b, const Packet4d& c) {
|
||||
#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
|
||||
#if ( EIGEN_COMP_GNUC_STRICT || (EIGEN_COMP_CLANG && (EIGEN_COMP_CLANG<308)) )
|
||||
// see above
|
||||
Packet4d res = c;
|
||||
__asm__("vfmadd231pd %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b));
|
||||
@@ -301,9 +307,11 @@ template<> EIGEN_STRONG_INLINE void pstore1<Packet8i>(int* to, const int& a)
|
||||
pstore(to, pa);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
|
||||
#endif
|
||||
|
||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet8f>(const Packet8f& a) {
|
||||
return _mm_cvtss_f32(_mm256_castps256_ps128(a));
|
||||
@@ -397,7 +405,7 @@ template<> EIGEN_STRONG_INLINE double predux<Packet4d>(const Packet4d& a)
|
||||
return pfirst(_mm256_hadd_pd(tmp0,tmp0));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f predux4<Packet8f>(const Packet8f& a)
|
||||
template<> EIGEN_STRONG_INLINE Packet4f predux_downto4<Packet8f>(const Packet8f& a)
|
||||
{
|
||||
return _mm_add_ps(_mm256_castps256_ps128(a),_mm256_extractf128_ps(a,1));
|
||||
}
|
||||
@@ -601,6 +609,26 @@ template<> EIGEN_STRONG_INLINE Packet4d pblend(const Selector<4>& ifPacket, cons
|
||||
return _mm256_blendv_pd(thenPacket, elsePacket, false_mask);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8f pinsertfirst(const Packet8f& a, float b)
|
||||
{
|
||||
return _mm256_blend_ps(a,pset1<Packet8f>(b),1);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4d pinsertfirst(const Packet4d& a, double b)
|
||||
{
|
||||
return _mm256_blend_pd(a,pset1<Packet4d>(b),1);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8f pinsertlast(const Packet8f& a, float b)
|
||||
{
|
||||
return _mm256_blend_ps(a,pset1<Packet8f>(b),(1<<7));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4d pinsertlast(const Packet4d& a, double b)
|
||||
{
|
||||
return _mm256_blend_pd(a,pset1<Packet4d>(b),(1<<3));
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
396
Eigen/src/Core/arch/AVX512/MathFunctions.h
Normal file
396
Eigen/src/Core/arch/AVX512/MathFunctions.h
Normal file
@@ -0,0 +1,396 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2016 Pedro Gonnet (pedro.gonnet@gmail.com)
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef THIRD_PARTY_EIGEN3_EIGEN_SRC_CORE_ARCH_AVX512_MATHFUNCTIONS_H_
|
||||
#define THIRD_PARTY_EIGEN3_EIGEN_SRC_CORE_ARCH_AVX512_MATHFUNCTIONS_H_
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Disable the code for older versions of gcc that don't support many of the required avx512 instrinsics.
|
||||
#if EIGEN_GNUC_AT_LEAST(5, 3)
|
||||
|
||||
#define _EIGEN_DECLARE_CONST_Packet16f(NAME, X) \
|
||||
const Packet16f p16f_##NAME = pset1<Packet16f>(X)
|
||||
|
||||
#define _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(NAME, X) \
|
||||
const Packet16f p16f_##NAME = (__m512)pset1<Packet16i>(X)
|
||||
|
||||
#define _EIGEN_DECLARE_CONST_Packet8d(NAME, X) \
|
||||
const Packet8d p8d_##NAME = pset1<Packet8d>(X)
|
||||
|
||||
#define _EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(NAME, X) \
|
||||
const Packet8d p8d_##NAME = _mm512_castsi512_pd(_mm512_set1_epi64(X))
|
||||
|
||||
// Natural logarithm
|
||||
// Computes log(x) as log(2^e * m) = C*e + log(m), where the constant C =log(2)
|
||||
// and m is in the range [sqrt(1/2),sqrt(2)). In this range, the logarithm can
|
||||
// be easily approximated by a polynomial centered on m=1 for stability.
|
||||
#if defined(EIGEN_VECTORIZE_AVX512DQ)
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet16f
|
||||
plog<Packet16f>(const Packet16f& _x) {
|
||||
Packet16f x = _x;
|
||||
_EIGEN_DECLARE_CONST_Packet16f(1, 1.0f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(half, 0.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(126f, 126.0f);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(inv_mant_mask, ~0x7f800000);
|
||||
|
||||
// The smallest non denormalized float number.
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(min_norm_pos, 0x00800000);
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(minus_inf, 0xff800000);
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(nan, 0x7fc00000);
|
||||
|
||||
// Polynomial coefficients.
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_SQRTHF, 0.707106781186547524f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p0, 7.0376836292E-2f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p1, -1.1514610310E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p2, 1.1676998740E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p3, -1.2420140846E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p4, +1.4249322787E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p5, -1.6668057665E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p6, +2.0000714765E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p7, -2.4999993993E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_p8, +3.3333331174E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_q1, -2.12194440e-4f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_log_q2, 0.693359375f);
|
||||
|
||||
// invalid_mask is set to true when x is NaN
|
||||
__mmask16 invalid_mask =
|
||||
_mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_NGE_UQ);
|
||||
__mmask16 iszero_mask =
|
||||
_mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_EQ_UQ);
|
||||
|
||||
// Truncate input values to the minimum positive normal.
|
||||
x = pmax(x, p16f_min_norm_pos);
|
||||
|
||||
// Extract the shifted exponents.
|
||||
Packet16f emm0 = _mm512_cvtepi32_ps(_mm512_srli_epi32((__m512i)x, 23));
|
||||
Packet16f e = _mm512_sub_ps(emm0, p16f_126f);
|
||||
|
||||
// Set the exponents to -1, i.e. x are in the range [0.5,1).
|
||||
x = _mm512_and_ps(x, p16f_inv_mant_mask);
|
||||
x = _mm512_or_ps(x, p16f_half);
|
||||
|
||||
// part2: Shift the inputs from the range [0.5,1) to [sqrt(1/2),sqrt(2))
|
||||
// and shift by -1. The values are then centered around 0, which improves
|
||||
// the stability of the polynomial evaluation.
|
||||
// if( x < SQRTHF ) {
|
||||
// e -= 1;
|
||||
// x = x + x - 1.0;
|
||||
// } else { x = x - 1.0; }
|
||||
__mmask16 mask = _mm512_cmp_ps_mask(x, p16f_cephes_SQRTHF, _CMP_LT_OQ);
|
||||
Packet16f tmp = _mm512_mask_blend_ps(mask, x, _mm512_setzero_ps());
|
||||
x = psub(x, p16f_1);
|
||||
e = psub(e, _mm512_mask_blend_ps(mask, p16f_1, _mm512_setzero_ps()));
|
||||
x = padd(x, tmp);
|
||||
|
||||
Packet16f x2 = pmul(x, x);
|
||||
Packet16f x3 = pmul(x2, x);
|
||||
|
||||
// Evaluate the polynomial approximant of degree 8 in three parts, probably
|
||||
// to improve instruction-level parallelism.
|
||||
Packet16f y, y1, y2;
|
||||
y = pmadd(p16f_cephes_log_p0, x, p16f_cephes_log_p1);
|
||||
y1 = pmadd(p16f_cephes_log_p3, x, p16f_cephes_log_p4);
|
||||
y2 = pmadd(p16f_cephes_log_p6, x, p16f_cephes_log_p7);
|
||||
y = pmadd(y, x, p16f_cephes_log_p2);
|
||||
y1 = pmadd(y1, x, p16f_cephes_log_p5);
|
||||
y2 = pmadd(y2, x, p16f_cephes_log_p8);
|
||||
y = pmadd(y, x3, y1);
|
||||
y = pmadd(y, x3, y2);
|
||||
y = pmul(y, x3);
|
||||
|
||||
// Add the logarithm of the exponent back to the result of the interpolation.
|
||||
y1 = pmul(e, p16f_cephes_log_q1);
|
||||
tmp = pmul(x2, p16f_half);
|
||||
y = padd(y, y1);
|
||||
x = psub(x, tmp);
|
||||
y2 = pmul(e, p16f_cephes_log_q2);
|
||||
x = padd(x, y);
|
||||
x = padd(x, y2);
|
||||
|
||||
// Filter out invalid inputs, i.e. negative arg will be NAN, 0 will be -INF.
|
||||
return _mm512_mask_blend_ps(iszero_mask, p16f_minus_inf,
|
||||
_mm512_mask_blend_ps(invalid_mask, p16f_nan, x));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Exponential function. Works by writing "x = m*log(2) + r" where
|
||||
// "m = floor(x/log(2)+1/2)" and "r" is the remainder. The result is then
|
||||
// "exp(x) = 2^m*exp(r)" where exp(r) is in the range [-1,1).
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet16f
|
||||
pexp<Packet16f>(const Packet16f& _x) {
|
||||
_EIGEN_DECLARE_CONST_Packet16f(1, 1.0f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(half, 0.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(127, 127.0f);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet16f(exp_hi, 88.3762626647950f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(exp_lo, -88.3762626647949f);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_LOG2EF, 1.44269504088896341f);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_exp_p0, 1.9875691500E-4f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_exp_p1, 1.3981999507E-3f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_exp_p2, 8.3334519073E-3f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_exp_p3, 4.1665795894E-2f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_exp_p4, 1.6666665459E-1f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(cephes_exp_p5, 5.0000001201E-1f);
|
||||
|
||||
// Clamp x.
|
||||
Packet16f x = pmax(pmin(_x, p16f_exp_hi), p16f_exp_lo);
|
||||
|
||||
// Express exp(x) as exp(m*ln(2) + r), start by extracting
|
||||
// m = floor(x/ln(2) + 0.5).
|
||||
Packet16f m = _mm512_floor_ps(pmadd(x, p16f_cephes_LOG2EF, p16f_half));
|
||||
|
||||
// Get r = x - m*ln(2). Note that we can do this without losing more than one
|
||||
// ulp precision due to the FMA instruction.
|
||||
_EIGEN_DECLARE_CONST_Packet16f(nln2, -0.6931471805599453f);
|
||||
Packet16f r = _mm512_fmadd_ps(m, p16f_nln2, x);
|
||||
Packet16f r2 = pmul(r, r);
|
||||
|
||||
// TODO(gonnet): Split into odd/even polynomials and try to exploit
|
||||
// instruction-level parallelism.
|
||||
Packet16f y = p16f_cephes_exp_p0;
|
||||
y = pmadd(y, r, p16f_cephes_exp_p1);
|
||||
y = pmadd(y, r, p16f_cephes_exp_p2);
|
||||
y = pmadd(y, r, p16f_cephes_exp_p3);
|
||||
y = pmadd(y, r, p16f_cephes_exp_p4);
|
||||
y = pmadd(y, r, p16f_cephes_exp_p5);
|
||||
y = pmadd(y, r2, r);
|
||||
y = padd(y, p16f_1);
|
||||
|
||||
// Build emm0 = 2^m.
|
||||
Packet16i emm0 = _mm512_cvttps_epi32(padd(m, p16f_127));
|
||||
emm0 = _mm512_slli_epi32(emm0, 23);
|
||||
|
||||
// Return 2^m * exp(r).
|
||||
return pmax(pmul(y, _mm512_castsi512_ps(emm0)), _x);
|
||||
}
|
||||
|
||||
/*template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8d
|
||||
pexp<Packet8d>(const Packet8d& _x) {
|
||||
Packet8d x = _x;
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(1, 1.0);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(2, 2.0);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(exp_hi, 709.437);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(exp_lo, -709.436139303);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_LOG2EF, 1.4426950408889634073599);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_p0, 1.26177193074810590878e-4);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_p1, 3.02994407707441961300e-2);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_p2, 9.99999999999999999910e-1);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q0, 3.00198505138664455042e-6);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q1, 2.52448340349684104192e-3);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q2, 2.27265548208155028766e-1);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q3, 2.00000000000000000009e0);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_C1, 0.693145751953125);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_C2, 1.42860682030941723212e-6);
|
||||
|
||||
// clamp x
|
||||
x = pmax(pmin(x, p8d_exp_hi), p8d_exp_lo);
|
||||
|
||||
// Express exp(x) as exp(g + n*log(2)).
|
||||
const Packet8d n =
|
||||
_mm512_mul_round_pd(p8d_cephes_LOG2EF, x, _MM_FROUND_TO_NEAREST_INT);
|
||||
|
||||
// Get the remainder modulo log(2), i.e. the "g" described above. Subtract
|
||||
// n*log(2) out in two steps, i.e. n*C1 + n*C2, C1+C2=log2 to get the last
|
||||
// digits right.
|
||||
const Packet8d nC1 = pmul(n, p8d_cephes_exp_C1);
|
||||
const Packet8d nC2 = pmul(n, p8d_cephes_exp_C2);
|
||||
x = psub(x, nC1);
|
||||
x = psub(x, nC2);
|
||||
|
||||
const Packet8d x2 = pmul(x, x);
|
||||
|
||||
// Evaluate the numerator polynomial of the rational interpolant.
|
||||
Packet8d px = p8d_cephes_exp_p0;
|
||||
px = pmadd(px, x2, p8d_cephes_exp_p1);
|
||||
px = pmadd(px, x2, p8d_cephes_exp_p2);
|
||||
px = pmul(px, x);
|
||||
|
||||
// Evaluate the denominator polynomial of the rational interpolant.
|
||||
Packet8d qx = p8d_cephes_exp_q0;
|
||||
qx = pmadd(qx, x2, p8d_cephes_exp_q1);
|
||||
qx = pmadd(qx, x2, p8d_cephes_exp_q2);
|
||||
qx = pmadd(qx, x2, p8d_cephes_exp_q3);
|
||||
|
||||
// I don't really get this bit, copied from the SSE2 routines, so...
|
||||
// TODO(gonnet): Figure out what is going on here, perhaps find a better
|
||||
// rational interpolant?
|
||||
x = _mm512_div_pd(px, psub(qx, px));
|
||||
x = pmadd(p8d_2, x, p8d_1);
|
||||
|
||||
// Build e=2^n.
|
||||
const Packet8d e = _mm512_castsi512_pd(_mm512_slli_epi64(
|
||||
_mm512_add_epi64(_mm512_cvtpd_epi64(n), _mm512_set1_epi64(1023)), 52));
|
||||
|
||||
// Construct the result 2^n * exp(g) = e * x. The max is used to catch
|
||||
// non-finite values in the input.
|
||||
return pmax(pmul(x, e), _x);
|
||||
}*/
|
||||
|
||||
// Functions for sqrt.
|
||||
// The EIGEN_FAST_MATH version uses the _mm_rsqrt_ps approximation and one step
|
||||
// of Newton's method, at a cost of 1-2 bits of precision as opposed to the
|
||||
// exact solution. The main advantage of this approach is not just speed, but
|
||||
// also the fact that it can be inlined and pipelined with other computations,
|
||||
// further reducing its effective latency.
|
||||
#if EIGEN_FAST_MATH
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet16f
|
||||
psqrt<Packet16f>(const Packet16f& _x) {
|
||||
_EIGEN_DECLARE_CONST_Packet16f(one_point_five, 1.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(minus_half, -0.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(flt_min, 0x00800000);
|
||||
|
||||
Packet16f neg_half = pmul(_x, p16f_minus_half);
|
||||
|
||||
// select only the inverse sqrt of positive normal inputs (denormals are
|
||||
// flushed to zero and cause infs as well).
|
||||
__mmask16 non_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_GE_OQ);
|
||||
Packet16f x = _mm512_mask_blend_ps(non_zero_mask, _mm512_rsqrt14_ps(_x),
|
||||
_mm512_setzero_ps());
|
||||
|
||||
// Do a single step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five));
|
||||
|
||||
// Multiply the original _x by it's reciprocal square root to extract the
|
||||
// square root.
|
||||
return pmul(_x, x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8d
|
||||
psqrt<Packet8d>(const Packet8d& _x) {
|
||||
_EIGEN_DECLARE_CONST_Packet8d(one_point_five, 1.5);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(minus_half, -0.5);
|
||||
_EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(dbl_min, 0x0010000000000000LL);
|
||||
|
||||
Packet8d neg_half = pmul(_x, p8d_minus_half);
|
||||
|
||||
// select only the inverse sqrt of positive normal inputs (denormals are
|
||||
// flushed to zero and cause infs as well).
|
||||
__mmask8 non_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_GE_OQ);
|
||||
Packet8d x = _mm512_mask_blend_pd(non_zero_mask, _mm512_rsqrt14_pd(_x),
|
||||
_mm512_setzero_pd());
|
||||
|
||||
// Do a first step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five));
|
||||
|
||||
// Do a second step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five));
|
||||
|
||||
// Multiply the original _x by it's reciprocal square root to extract the
|
||||
// square root.
|
||||
return pmul(_x, x);
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f psqrt<Packet16f>(const Packet16f& x) {
|
||||
return _mm512_sqrt_ps(x);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8d psqrt<Packet8d>(const Packet8d& x) {
|
||||
return _mm512_sqrt_pd(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Functions for rsqrt.
|
||||
// Almost identical to the sqrt routine, just leave out the last multiplication
|
||||
// and fill in NaN/Inf where needed. Note that this function only exists as an
|
||||
// iterative version for doubles since there is no instruction for diretly
|
||||
// computing the reciprocal square root in AVX-512.
|
||||
#ifdef EIGEN_FAST_MATH
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet16f
|
||||
prsqrt<Packet16f>(const Packet16f& _x) {
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(inf, 0x7f800000);
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(nan, 0x7fc00000);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(one_point_five, 1.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f(minus_half, -0.5f);
|
||||
_EIGEN_DECLARE_CONST_Packet16f_FROM_INT(flt_min, 0x00800000);
|
||||
|
||||
Packet16f neg_half = pmul(_x, p16f_minus_half);
|
||||
|
||||
// select only the inverse sqrt of positive normal inputs (denormals are
|
||||
// flushed to zero and cause infs as well).
|
||||
__mmask16 le_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_LT_OQ);
|
||||
Packet16f x = _mm512_mask_blend_ps(le_zero_mask, _mm512_setzero_ps(),
|
||||
_mm512_rsqrt14_ps(_x));
|
||||
|
||||
// Fill in NaNs and Infs for the negative/zero entries.
|
||||
__mmask16 neg_mask = _mm512_cmp_ps_mask(_x, _mm512_setzero_ps(), _CMP_LT_OQ);
|
||||
Packet16f infs_and_nans = _mm512_mask_blend_ps(
|
||||
neg_mask, p16f_nan,
|
||||
_mm512_mask_blend_ps(le_zero_mask, p16f_inf, _mm512_setzero_ps()));
|
||||
|
||||
// Do a single step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five));
|
||||
|
||||
// Insert NaNs and Infs in all the right places.
|
||||
return _mm512_mask_blend_ps(le_zero_mask, infs_and_nans, x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8d
|
||||
prsqrt<Packet8d>(const Packet8d& _x) {
|
||||
_EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(inf, 0x7ff0000000000000LL);
|
||||
_EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(nan, 0x7ff1000000000000LL);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(one_point_five, 1.5);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(minus_half, -0.5);
|
||||
_EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(dbl_min, 0x0010000000000000LL);
|
||||
|
||||
Packet8d neg_half = pmul(_x, p8d_minus_half);
|
||||
|
||||
// select only the inverse sqrt of positive normal inputs (denormals are
|
||||
// flushed to zero and cause infs as well).
|
||||
__mmask8 le_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_LT_OQ);
|
||||
Packet8d x = _mm512_mask_blend_pd(le_zero_mask, _mm512_setzero_pd(),
|
||||
_mm512_rsqrt14_pd(_x));
|
||||
|
||||
// Fill in NaNs and Infs for the negative/zero entries.
|
||||
__mmask8 neg_mask = _mm512_cmp_pd_mask(_x, _mm512_setzero_pd(), _CMP_LT_OQ);
|
||||
Packet8d infs_and_nans = _mm512_mask_blend_pd(
|
||||
neg_mask, p8d_nan,
|
||||
_mm512_mask_blend_pd(le_zero_mask, p8d_inf, _mm512_setzero_pd()));
|
||||
|
||||
// Do a first step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five));
|
||||
|
||||
// Do a second step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five));
|
||||
|
||||
// Insert NaNs and Infs in all the right places.
|
||||
return _mm512_mask_blend_pd(le_zero_mask, infs_and_nans, x);
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f prsqrt<Packet16f>(const Packet16f& x) {
|
||||
return _mm512_rsqrt28_ps(x);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // THIRD_PARTY_EIGEN3_EIGEN_SRC_CORE_ARCH_AVX512_MATHFUNCTIONS_H_
|
||||
1316
Eigen/src/Core/arch/AVX512/PacketMath.h
Normal file
1316
Eigen/src/Core/arch/AVX512/PacketMath.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_arch_AltiVec_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_arch_AltiVec_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/AltiVec COMPONENT Devel
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
ADD_SUBDIRECTORY(AltiVec)
|
||||
ADD_SUBDIRECTORY(AVX)
|
||||
ADD_SUBDIRECTORY(CUDA)
|
||||
ADD_SUBDIRECTORY(Default)
|
||||
ADD_SUBDIRECTORY(NEON)
|
||||
ADD_SUBDIRECTORY(SSE)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_arch_CUDA_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_arch_CUDA_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/CUDA COMPONENT Devel
|
||||
)
|
||||
103
Eigen/src/Core/arch/CUDA/Complex.h
Normal file
103
Eigen/src/Core/arch/CUDA/Complex.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_COMPLEX_CUDA_H
|
||||
#define EIGEN_COMPLEX_CUDA_H
|
||||
|
||||
// clang-format off
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
#if defined(__CUDACC__) && defined(EIGEN_USE_GPU)
|
||||
|
||||
// Many std::complex methods such as operator+, operator-, operator* and
|
||||
// operator/ are not constexpr. Due to this, clang does not treat them as device
|
||||
// functions and thus Eigen functors making use of these operators fail to
|
||||
// compile. Here, we manually specialize these functors for complex types when
|
||||
// building for CUDA to avoid non-constexpr methods.
|
||||
|
||||
// Sum
|
||||
template<typename T> struct scalar_sum_op<const std::complex<T>, const std::complex<T> > : binary_op_base<const std::complex<T>, const std::complex<T> > {
|
||||
typedef typename std::complex<T> result_type;
|
||||
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<T> operator() (const std::complex<T>& a, const std::complex<T>& b) const {
|
||||
return std::complex<T>(numext::real(a) + numext::real(b),
|
||||
numext::imag(a) + numext::imag(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct scalar_sum_op<std::complex<T>, std::complex<T> > : scalar_sum_op<const std::complex<T>, const std::complex<T> > {};
|
||||
|
||||
|
||||
// Difference
|
||||
template<typename T> struct scalar_difference_op<const std::complex<T>, const std::complex<T> > : binary_op_base<const std::complex<T>, const std::complex<T> > {
|
||||
typedef typename std::complex<T> result_type;
|
||||
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<T> operator() (const std::complex<T>& a, const std::complex<T>& b) const {
|
||||
return std::complex<T>(numext::real(a) - numext::real(b),
|
||||
numext::imag(a) - numext::imag(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct scalar_difference_op<std::complex<T>, std::complex<T> > : scalar_difference_op<const std::complex<T>, const std::complex<T> > {};
|
||||
|
||||
|
||||
// Product
|
||||
template<typename T> struct scalar_product_op<const std::complex<T>, const std::complex<T> > : binary_op_base<const std::complex<T>, const std::complex<T> > {
|
||||
enum {
|
||||
Vectorizable = packet_traits<std::complex<T>>::HasMul
|
||||
};
|
||||
typedef typename std::complex<T> result_type;
|
||||
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<T> operator() (const std::complex<T>& a, const std::complex<T>& b) const {
|
||||
const T a_real = numext::real(a);
|
||||
const T a_imag = numext::imag(a);
|
||||
const T b_real = numext::real(b);
|
||||
const T b_imag = numext::imag(b);
|
||||
return std::complex<T>(a_real * b_real - a_imag * b_imag,
|
||||
a_real * b_imag + a_imag * b_real);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct scalar_product_op<std::complex<T>, std::complex<T> > : scalar_product_op<const std::complex<T>, const std::complex<T> > {};
|
||||
|
||||
|
||||
// Quotient
|
||||
template<typename T> struct scalar_quotient_op<const std::complex<T>, const std::complex<T> > : binary_op_base<const std::complex<T>, const std::complex<T> > {
|
||||
enum {
|
||||
Vectorizable = packet_traits<std::complex<T>>::HasDiv
|
||||
};
|
||||
typedef typename std::complex<T> result_type;
|
||||
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<T> operator() (const std::complex<T>& a, const std::complex<T>& b) const {
|
||||
const T a_real = numext::real(a);
|
||||
const T a_imag = numext::imag(a);
|
||||
const T b_real = numext::real(b);
|
||||
const T b_imag = numext::imag(b);
|
||||
const T norm = T(1) / (b_real * b_real + b_imag * b_imag);
|
||||
return std::complex<T>((a_real * b_real + a_imag * b_imag) * norm,
|
||||
(a_imag * b_real - a_real * b_imag) * norm);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct scalar_quotient_op<std::complex<T>, std::complex<T> > : scalar_quotient_op<const std::complex<T>, const std::complex<T> > {};
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_COMPLEX_CUDA_H
|
||||
@@ -45,6 +45,8 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
struct half;
|
||||
|
||||
namespace half_impl {
|
||||
|
||||
#if !defined(EIGEN_HAS_CUDA_FP16)
|
||||
@@ -62,60 +64,72 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half raw_uint16_to_half(unsigned short x
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half float_to_half_rtne(float ff);
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half h);
|
||||
|
||||
struct half_base : public __half {
|
||||
EIGEN_DEVICE_FUNC half_base() {}
|
||||
EIGEN_DEVICE_FUNC half_base(const half_base& h) : __half(h) {}
|
||||
EIGEN_DEVICE_FUNC half_base(const __half& h) : __half(h) {}
|
||||
};
|
||||
|
||||
} // namespace half_impl
|
||||
|
||||
// Class definition.
|
||||
struct half : public __half {
|
||||
struct half : public half_impl::half_base {
|
||||
#if !defined(EIGEN_HAS_CUDA_FP16)
|
||||
typedef half_impl::__half __half;
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC half() {}
|
||||
|
||||
EIGEN_DEVICE_FUNC half(const __half& h) : __half(h) {}
|
||||
EIGEN_DEVICE_FUNC half(const half& h) : __half(h) {}
|
||||
EIGEN_DEVICE_FUNC half(const __half& h) : half_impl::half_base(h) {}
|
||||
EIGEN_DEVICE_FUNC half(const half& h) : half_impl::half_base(h) {}
|
||||
|
||||
explicit EIGEN_DEVICE_FUNC half(bool b)
|
||||
: __half(raw_uint16_to_half(b ? 0x3c00 : 0)) {}
|
||||
: half_impl::half_base(half_impl::raw_uint16_to_half(b ? 0x3c00 : 0)) {}
|
||||
template<class T>
|
||||
explicit EIGEN_DEVICE_FUNC half(const T& val)
|
||||
: __half(float_to_half_rtne(static_cast<float>(val))) {}
|
||||
: half_impl::half_base(half_impl::float_to_half_rtne(static_cast<float>(val))) {}
|
||||
explicit EIGEN_DEVICE_FUNC half(float f)
|
||||
: __half(float_to_half_rtne(f)) {}
|
||||
: half_impl::half_base(half_impl::float_to_half_rtne(f)) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(bool) const {
|
||||
// +0.0 and -0.0 become false, everything else becomes true.
|
||||
return (x & 0x7fff) != 0;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(signed char) const {
|
||||
return static_cast<signed char>(half_to_float(*this));
|
||||
return static_cast<signed char>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(unsigned char) const {
|
||||
return static_cast<unsigned char>(half_to_float(*this));
|
||||
return static_cast<unsigned char>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(short) const {
|
||||
return static_cast<short>(half_to_float(*this));
|
||||
return static_cast<short>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(unsigned short) const {
|
||||
return static_cast<unsigned short>(half_to_float(*this));
|
||||
return static_cast<unsigned short>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(int) const {
|
||||
return static_cast<int>(half_to_float(*this));
|
||||
return static_cast<int>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(unsigned int) const {
|
||||
return static_cast<unsigned int>(half_to_float(*this));
|
||||
return static_cast<unsigned int>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(long) const {
|
||||
return static_cast<long>(half_to_float(*this));
|
||||
return static_cast<long>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(unsigned long) const {
|
||||
return static_cast<unsigned long>(half_to_float(*this));
|
||||
return static_cast<unsigned long>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(long long) const {
|
||||
return static_cast<long long>(half_to_float(*this));
|
||||
return static_cast<long long>(half_impl::half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(unsigned long long) const {
|
||||
return static_cast<unsigned long long>(half_to_float(*this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(float) const {
|
||||
return half_to_float(*this);
|
||||
return half_impl::half_to_float(*this);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(double) const {
|
||||
return static_cast<double>(half_to_float(*this));
|
||||
return static_cast<double>(half_impl::half_to_float(*this));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC half& operator=(const half& other) {
|
||||
@@ -124,6 +138,8 @@ struct half : public __half {
|
||||
}
|
||||
};
|
||||
|
||||
namespace half_impl {
|
||||
|
||||
#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530
|
||||
|
||||
// Intrinsics for native fp16 support. Note that on current hardware,
|
||||
@@ -373,7 +389,14 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half exp(const half& a) {
|
||||
return half(::expf(float(a)));
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log(const half& a) {
|
||||
#if defined(EIGEN_HAS_CUDA_FP16) && defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530
|
||||
return Eigen::half(::hlog(a));
|
||||
#else
|
||||
return half(::logf(float(a)));
|
||||
#endif
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log1p(const half& a) {
|
||||
return half(numext::log1p(float(a)));
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log10(const half& a) {
|
||||
return half(::log10f(float(a)));
|
||||
@@ -430,12 +453,12 @@ EIGEN_ALWAYS_INLINE std::ostream& operator << (std::ostream& os, const half& v)
|
||||
} // end namespace half_impl
|
||||
|
||||
// import Eigen::half_impl::half into Eigen namespace
|
||||
using half_impl::half;
|
||||
// using half_impl::half;
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<>
|
||||
struct random_default_impl<half_impl::half, false, false>
|
||||
struct random_default_impl<half, false, false>
|
||||
{
|
||||
static inline half run(const half& x, const half& y)
|
||||
{
|
||||
@@ -447,27 +470,27 @@ struct random_default_impl<half_impl::half, false, false>
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct is_arithmetic<half_impl::half> { enum { value = true }; };
|
||||
template<> struct is_arithmetic<half> { enum { value = true }; };
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
template<> struct NumTraits<Eigen::half_impl::half>
|
||||
: GenericNumTraits<Eigen::half_impl::half>
|
||||
template<> struct NumTraits<Eigen::half>
|
||||
: GenericNumTraits<Eigen::half>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half_impl::half epsilon() {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half epsilon() {
|
||||
return half_impl::raw_uint16_to_half(0x0800);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half_impl::half dummy_precision() { return half_impl::half(1e-2f); }
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half_impl::half highest() {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half dummy_precision() { return Eigen::half(1e-2f); }
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half highest() {
|
||||
return half_impl::raw_uint16_to_half(0x7bff);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half_impl::half lowest() {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half lowest() {
|
||||
return half_impl::raw_uint16_to_half(0xfbff);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half_impl::half infinity() {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half infinity() {
|
||||
return half_impl::raw_uint16_to_half(0x7c00);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half_impl::half quiet_NaN() {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half quiet_NaN() {
|
||||
return half_impl::raw_uint16_to_half(0x7c01);
|
||||
}
|
||||
};
|
||||
@@ -484,7 +507,11 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half exph(const Eigen::half& a) {
|
||||
return Eigen::half(::expf(float(a)));
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half logh(const Eigen::half& a) {
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530
|
||||
return Eigen::half(::hlog(a));
|
||||
#else
|
||||
return Eigen::half(::logf(float(a)));
|
||||
#endif
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half sqrth(const Eigen::half& a) {
|
||||
return Eigen::half(::sqrtf(float(a)));
|
||||
@@ -523,9 +550,36 @@ __device__ EIGEN_STRONG_INLINE Eigen::half __shfl_xor(Eigen::half var, int laneM
|
||||
// ldg() has an overload for __half, but we also need one for Eigen::half.
|
||||
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 350
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half __ldg(const Eigen::half* ptr) {
|
||||
return Eigen::internal::raw_uint16_to_half(
|
||||
return Eigen::half_impl::raw_uint16_to_half(
|
||||
__ldg(reinterpret_cast<const unsigned short*>(ptr)));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__CUDA_ARCH__)
|
||||
namespace Eigen {
|
||||
namespace numext {
|
||||
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
bool (isnan)(const Eigen::half& h) {
|
||||
return (half_impl::isnan)(h);
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
bool (isinf)(const Eigen::half& h) {
|
||||
return (half_impl::isinf)(h);
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
bool (isfinite)(const Eigen::half& h) {
|
||||
return (half_impl::isfinite)(h);
|
||||
}
|
||||
|
||||
} // namespace Eigen
|
||||
} // namespace numext
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_HALF_CUDA_H
|
||||
|
||||
@@ -31,6 +31,18 @@ double2 plog<double2>(const double2& a)
|
||||
return make_double2(log(a.x), log(a.y));
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
float4 plog1p<float4>(const float4& a)
|
||||
{
|
||||
return make_float4(log1pf(a.x), log1pf(a.y), log1pf(a.z), log1pf(a.w));
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
double2 plog1p<double2>(const double2& a)
|
||||
{
|
||||
return make_double2(log1p(a.x), log1p(a.y));
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
float4 pexp<float4>(const float4& a)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
// Most of the following operations require arch >= 3.0
|
||||
#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300
|
||||
#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDACC__) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300
|
||||
|
||||
template<> struct is_arithmetic<half2> { enum { value = true }; };
|
||||
|
||||
@@ -34,21 +34,22 @@ template<> struct packet_traits<Eigen::half> : default_packet_traits
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
HasExp = 1,
|
||||
HasLog = 1
|
||||
HasLog = 1,
|
||||
HasLog1p = 1
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct unpacket_traits<half2> { typedef Eigen::half type; enum {size=2, alignment=Aligned16}; typedef half2 half; };
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pset1<half2>(const Eigen::half& from) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pset1<half2>(const Eigen::half& from) {
|
||||
return __half2half2(from);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pload<half2>(const Eigen::half* from) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pload<half2>(const Eigen::half* from) {
|
||||
return *reinterpret_cast<const half2*>(from);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploadu<half2>(const Eigen::half* from) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 ploadu<half2>(const Eigen::half* from) {
|
||||
return __halves2half2(from[0], from[1]);
|
||||
}
|
||||
|
||||
@@ -56,17 +57,17 @@ template<> EIGEN_STRONG_INLINE half2 ploaddup<half2>(const Eigen::half* from) {
|
||||
return __halves2half2(from[0], from[0]);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<Eigen::half>(Eigen::half* to, const half2& from) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE void pstore<Eigen::half>(Eigen::half* to, const half2& from) {
|
||||
*reinterpret_cast<half2*>(to) = from;
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<Eigen::half>(Eigen::half* to, const half2& from) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE void pstoreu<Eigen::half>(Eigen::half* to, const half2& from) {
|
||||
to[0] = __low2half(from);
|
||||
to[1] = __high2half(from);
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro<half2, Aligned>(const Eigen::half* from) {
|
||||
__device__ EIGEN_ALWAYS_INLINE half2 ploadt_ro<half2, Aligned>(const Eigen::half* from) {
|
||||
#if __CUDA_ARCH__ >= 350
|
||||
return __ldg((const half2*)from);
|
||||
#else
|
||||
@@ -75,7 +76,7 @@ template<>
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro<half2, Unaligned>(const Eigen::half* from) {
|
||||
__device__ EIGEN_ALWAYS_INLINE half2 ploadt_ro<half2, Unaligned>(const Eigen::half* from) {
|
||||
#if __CUDA_ARCH__ >= 350
|
||||
return __halves2half2(__ldg(from+0), __ldg(from+1));
|
||||
#else
|
||||
@@ -83,27 +84,27 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro<half2, Unaligned>(const Ei
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pgather<Eigen::half, half2>(const Eigen::half* from, Index stride) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pgather<Eigen::half, half2>(const Eigen::half* from, Index stride) {
|
||||
return __halves2half2(from[0*stride], from[1*stride]);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter<Eigen::half, half2>(Eigen::half* to, const half2& from, Index stride) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE void pscatter<Eigen::half, half2>(Eigen::half* to, const half2& from, Index stride) {
|
||||
to[stride*0] = __low2half(from);
|
||||
to[stride*1] = __high2half(from);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE Eigen::half pfirst<half2>(const half2& a) {
|
||||
return __low2half(a);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pabs<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pabs<half2>(const half2& a) {
|
||||
half2 result;
|
||||
result.x = a.x & 0x7FFF7FFF;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
|
||||
__device__ EIGEN_STRONG_INLINE void
|
||||
ptranspose(PacketBlock<half2,2>& kernel) {
|
||||
__half a1 = __low2half(kernel.packet[0]);
|
||||
__half a2 = __high2half(kernel.packet[0]);
|
||||
@@ -113,7 +114,7 @@ ptranspose(PacketBlock<half2,2>& kernel) {
|
||||
kernel.packet[1] = __halves2half2(a2, b2);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset<half2>(const Eigen::half& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 plset<half2>(const Eigen::half& a) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __halves2half2(a, __hadd(a, __float2half(1.0f)));
|
||||
#else
|
||||
@@ -122,7 +123,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset<half2>(const Eigen:
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd<half2>(const half2& a, const half2& b) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 padd<half2>(const half2& a, const half2& b) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __hadd2(a, b);
|
||||
#else
|
||||
@@ -136,7 +137,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd<half2>(const half2&
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psub<half2>(const half2& a, const half2& b) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 psub<half2>(const half2& a, const half2& b) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __hsub2(a, b);
|
||||
#else
|
||||
@@ -150,7 +151,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psub<half2>(const half2&
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pnegate(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pnegate(const half2& a) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __hneg2(a);
|
||||
#else
|
||||
@@ -160,9 +161,9 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pnegate(const half2& a) {
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pconj(const half2& a) { return a; }
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pconj(const half2& a) { return a; }
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul<half2>(const half2& a, const half2& b) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pmul<half2>(const half2& a, const half2& b) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __hmul2(a, b);
|
||||
#else
|
||||
@@ -176,7 +177,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul<half2>(const half2&
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmadd<half2>(const half2& a, const half2& b, const half2& c) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pmadd<half2>(const half2& a, const half2& b, const half2& c) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __hfma2(a, b, c);
|
||||
#else
|
||||
@@ -192,7 +193,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmadd<half2>(const half2&
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv<half2>(const half2& a, const half2& b) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pdiv<half2>(const half2& a, const half2& b) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float b1 = __low2float(b);
|
||||
@@ -202,7 +203,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv<half2>(const half2&
|
||||
return __floats2half2_rn(r1, r2);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin<half2>(const half2& a, const half2& b) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pmin<half2>(const half2& a, const half2& b) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float b1 = __low2float(b);
|
||||
@@ -212,7 +213,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin<half2>(const half2&
|
||||
return __halves2half2(r1, r2);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax<half2>(const half2& a, const half2& b) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pmax<half2>(const half2& a, const half2& b) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float b1 = __low2float(b);
|
||||
@@ -222,7 +223,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax<half2>(const half2&
|
||||
return __halves2half2(r1, r2);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux<half2>(const half2& a) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __hadd(__low2half(a), __high2half(a));
|
||||
#else
|
||||
@@ -232,7 +233,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux<half2>(const
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux_max<half2>(const half2& a) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
__half first = __low2half(a);
|
||||
__half second = __high2half(a);
|
||||
@@ -244,7 +245,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max<half2>(c
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux_min<half2>(const half2& a) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
__half first = __low2half(a);
|
||||
__half second = __high2half(a);
|
||||
@@ -256,7 +257,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min<half2>(c
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux_mul<half2>(const half2& a) {
|
||||
#if __CUDA_ARCH__ >= 530
|
||||
return __hmul(__low2half(a), __high2half(a));
|
||||
#else
|
||||
@@ -266,31 +267,39 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul<half2>(c
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 plog1p<half2>(const half2& a) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float r1 = log1pf(a1);
|
||||
float r2 = log1pf(a2);
|
||||
return __floats2half2_rn(r1, r2);
|
||||
}
|
||||
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 530
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
template<> __device__ EIGEN_STRONG_INLINE
|
||||
half2 plog<half2>(const half2& a) {
|
||||
return h2log(a);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
template<> __device__ EIGEN_STRONG_INLINE
|
||||
half2 pexp<half2>(const half2& a) {
|
||||
return h2exp(a);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
template<> __device__ EIGEN_STRONG_INLINE
|
||||
half2 psqrt<half2>(const half2& a) {
|
||||
return h2sqrt(a);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
template<> __device__ EIGEN_STRONG_INLINE
|
||||
half2 prsqrt<half2>(const half2& a) {
|
||||
return h2rsqrt(a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 plog<half2>(const half2& a) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float r1 = logf(a1);
|
||||
@@ -298,7 +307,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog<half2>(const half2&
|
||||
return __floats2half2_rn(r1, r2);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexp<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pexp<half2>(const half2& a) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float r1 = expf(a1);
|
||||
@@ -306,7 +315,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexp<half2>(const half2&
|
||||
return __floats2half2_rn(r1, r2);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psqrt<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 psqrt<half2>(const half2& a) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float r1 = sqrtf(a1);
|
||||
@@ -314,7 +323,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psqrt<half2>(const half2&
|
||||
return __floats2half2_rn(r1, r2);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 prsqrt<half2>(const half2& a) {
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 prsqrt<half2>(const half2& a) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float r1 = rsqrtf(a1);
|
||||
@@ -324,6 +333,374 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 prsqrt<half2>(const half2
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined EIGEN_VECTORIZE_AVX512
|
||||
|
||||
typedef struct {
|
||||
__m256i x;
|
||||
} Packet16h;
|
||||
|
||||
|
||||
template<> struct is_arithmetic<Packet16h> { enum { value = true }; };
|
||||
|
||||
template <>
|
||||
struct packet_traits<half> : default_packet_traits {
|
||||
typedef Packet16h type;
|
||||
// There is no half-size packet for Packet16h.
|
||||
typedef Packet16h half;
|
||||
enum {
|
||||
Vectorizable = 1,
|
||||
AlignedOnScalar = 1,
|
||||
size = 16,
|
||||
HasHalfPacket = 0,
|
||||
HasAdd = 0,
|
||||
HasSub = 0,
|
||||
HasMul = 0,
|
||||
HasNegate = 0,
|
||||
HasAbs = 0,
|
||||
HasAbs2 = 0,
|
||||
HasMin = 0,
|
||||
HasMax = 0,
|
||||
HasConj = 0,
|
||||
HasSetLinear = 0,
|
||||
HasDiv = 0,
|
||||
HasSqrt = 0,
|
||||
HasRsqrt = 0,
|
||||
HasExp = 0,
|
||||
HasLog = 0,
|
||||
HasBlend = 0
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<> struct unpacket_traits<Packet16h> { typedef Eigen::half type; enum {size=16, alignment=Aligned32}; typedef Packet16h half; };
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h pset1<Packet16h>(const Eigen::half& from) {
|
||||
Packet16h result;
|
||||
result.x = _mm256_set1_epi16(from.x);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Eigen::half pfirst<Packet16h>(const Packet16h& from) {
|
||||
return half_impl::raw_uint16_to_half(static_cast<unsigned short>(_mm256_extract_epi16(from.x, 0)));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h pload<Packet16h>(const Eigen::half* from) {
|
||||
Packet16h result;
|
||||
result.x = _mm256_load_si256(reinterpret_cast<const __m256i*>(from));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h ploadu<Packet16h>(const Eigen::half* from) {
|
||||
Packet16h result;
|
||||
result.x = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(from));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void pstore<half>(Eigen::half* to, const Packet16h& from) {
|
||||
_mm256_store_si256((__m256i*)to, from.x);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<half>(Eigen::half* to, const Packet16h& from) {
|
||||
_mm256_storeu_si256((__m256i*)to, from.x);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h
|
||||
ploadquad(const Eigen::half* from) {
|
||||
Packet16h result;
|
||||
unsigned short a = from[0].x;
|
||||
unsigned short b = from[1].x;
|
||||
unsigned short c = from[2].x;
|
||||
unsigned short d = from[3].x;
|
||||
result.x = _mm256_set_epi16(d, d, d, d, c, c, c, c, b, b, b, b, a, a, a, a);
|
||||
return result;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet16f half2float(const Packet16h& a) {
|
||||
#ifdef EIGEN_HAS_FP16_C
|
||||
return _mm512_cvtph_ps(a.x);
|
||||
#else
|
||||
EIGEN_ALIGN64 half aux[16];
|
||||
pstore(aux, a);
|
||||
float f0(aux[0]);
|
||||
float f1(aux[1]);
|
||||
float f2(aux[2]);
|
||||
float f3(aux[3]);
|
||||
float f4(aux[4]);
|
||||
float f5(aux[5]);
|
||||
float f6(aux[6]);
|
||||
float f7(aux[7]);
|
||||
float f8(aux[8]);
|
||||
float f9(aux[9]);
|
||||
float fa(aux[10]);
|
||||
float fb(aux[11]);
|
||||
float fc(aux[12]);
|
||||
float fd(aux[13]);
|
||||
float fe(aux[14]);
|
||||
float ff(aux[15]);
|
||||
|
||||
return _mm512_set_ps(
|
||||
ff, fe, fd, fc, fb, fa, f9, f8, f7, f6, f5, f4, f3, f2, f1, f0);
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet16h float2half(const Packet16f& a) {
|
||||
#ifdef EIGEN_HAS_FP16_C
|
||||
Packet16h result;
|
||||
result.x = _mm512_cvtps_ph(a, _MM_FROUND_TO_NEAREST_INT|_MM_FROUND_NO_EXC);
|
||||
return result;
|
||||
#else
|
||||
EIGEN_ALIGN64 float aux[16];
|
||||
pstore(aux, a);
|
||||
half h0(aux[0]);
|
||||
half h1(aux[1]);
|
||||
half h2(aux[2]);
|
||||
half h3(aux[3]);
|
||||
half h4(aux[4]);
|
||||
half h5(aux[5]);
|
||||
half h6(aux[6]);
|
||||
half h7(aux[7]);
|
||||
half h8(aux[8]);
|
||||
half h9(aux[9]);
|
||||
half ha(aux[10]);
|
||||
half hb(aux[11]);
|
||||
half hc(aux[12]);
|
||||
half hd(aux[13]);
|
||||
half he(aux[14]);
|
||||
half hf(aux[15]);
|
||||
|
||||
Packet16h result;
|
||||
result.x = _mm256_set_epi16(
|
||||
hf.x, he.x, hd.x, hc.x, hb.x, ha.x, h9.x, h8.x,
|
||||
h7.x, h6.x, h5.x, h4.x, h3.x, h2.x, h1.x, h0.x);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h padd<Packet16h>(const Packet16h& a, const Packet16h& b) {
|
||||
Packet16f af = half2float(a);
|
||||
Packet16f bf = half2float(b);
|
||||
Packet16f rf = padd(af, bf);
|
||||
return float2half(rf);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h pmul<Packet16h>(const Packet16h& a, const Packet16h& b) {
|
||||
Packet16f af = half2float(a);
|
||||
Packet16f bf = half2float(b);
|
||||
Packet16f rf = pmul(af, bf);
|
||||
return float2half(rf);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE half predux<Packet16h>(const Packet16h& from) {
|
||||
Packet16f from_float = half2float(from);
|
||||
return half(predux(from_float));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h pgather<Eigen::half, Packet16h>(const Eigen::half* from, Index stride)
|
||||
{
|
||||
Packet16h result;
|
||||
result.x = _mm256_set_epi16(
|
||||
from[15*stride].x, from[14*stride].x, from[13*stride].x, from[12*stride].x,
|
||||
from[11*stride].x, from[10*stride].x, from[9*stride].x, from[8*stride].x,
|
||||
from[7*stride].x, from[6*stride].x, from[5*stride].x, from[4*stride].x,
|
||||
from[3*stride].x, from[2*stride].x, from[1*stride].x, from[0*stride].x);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void pscatter<half, Packet16h>(half* to, const Packet16h& from, Index stride)
|
||||
{
|
||||
EIGEN_ALIGN64 half aux[16];
|
||||
pstore(aux, from);
|
||||
to[stride*0].x = aux[0].x;
|
||||
to[stride*1].x = aux[1].x;
|
||||
to[stride*2].x = aux[2].x;
|
||||
to[stride*3].x = aux[3].x;
|
||||
to[stride*4].x = aux[4].x;
|
||||
to[stride*5].x = aux[5].x;
|
||||
to[stride*6].x = aux[6].x;
|
||||
to[stride*7].x = aux[7].x;
|
||||
to[stride*8].x = aux[8].x;
|
||||
to[stride*9].x = aux[9].x;
|
||||
to[stride*10].x = aux[10].x;
|
||||
to[stride*11].x = aux[11].x;
|
||||
to[stride*12].x = aux[12].x;
|
||||
to[stride*13].x = aux[13].x;
|
||||
to[stride*14].x = aux[14].x;
|
||||
to[stride*15].x = aux[15].x;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE void
|
||||
ptranspose(PacketBlock<Packet16h,16>& kernel) {
|
||||
__m256i a = kernel.packet[0].x;
|
||||
__m256i b = kernel.packet[1].x;
|
||||
__m256i c = kernel.packet[2].x;
|
||||
__m256i d = kernel.packet[3].x;
|
||||
__m256i e = kernel.packet[4].x;
|
||||
__m256i f = kernel.packet[5].x;
|
||||
__m256i g = kernel.packet[6].x;
|
||||
__m256i h = kernel.packet[7].x;
|
||||
__m256i i = kernel.packet[8].x;
|
||||
__m256i j = kernel.packet[9].x;
|
||||
__m256i k = kernel.packet[10].x;
|
||||
__m256i l = kernel.packet[11].x;
|
||||
__m256i m = kernel.packet[12].x;
|
||||
__m256i n = kernel.packet[13].x;
|
||||
__m256i o = kernel.packet[14].x;
|
||||
__m256i p = kernel.packet[15].x;
|
||||
|
||||
__m256i ab_07 = _mm256_unpacklo_epi16(a, b);
|
||||
__m256i cd_07 = _mm256_unpacklo_epi16(c, d);
|
||||
__m256i ef_07 = _mm256_unpacklo_epi16(e, f);
|
||||
__m256i gh_07 = _mm256_unpacklo_epi16(g, h);
|
||||
__m256i ij_07 = _mm256_unpacklo_epi16(i, j);
|
||||
__m256i kl_07 = _mm256_unpacklo_epi16(k, l);
|
||||
__m256i mn_07 = _mm256_unpacklo_epi16(m, n);
|
||||
__m256i op_07 = _mm256_unpacklo_epi16(o, p);
|
||||
|
||||
__m256i ab_8f = _mm256_unpackhi_epi16(a, b);
|
||||
__m256i cd_8f = _mm256_unpackhi_epi16(c, d);
|
||||
__m256i ef_8f = _mm256_unpackhi_epi16(e, f);
|
||||
__m256i gh_8f = _mm256_unpackhi_epi16(g, h);
|
||||
__m256i ij_8f = _mm256_unpackhi_epi16(i, j);
|
||||
__m256i kl_8f = _mm256_unpackhi_epi16(k, l);
|
||||
__m256i mn_8f = _mm256_unpackhi_epi16(m, n);
|
||||
__m256i op_8f = _mm256_unpackhi_epi16(o, p);
|
||||
|
||||
__m256i abcd_03 = _mm256_unpacklo_epi32(ab_07, cd_07);
|
||||
__m256i abcd_47 = _mm256_unpackhi_epi32(ab_07, cd_07);
|
||||
__m256i efgh_03 = _mm256_unpacklo_epi32(ef_07, gh_07);
|
||||
__m256i efgh_47 = _mm256_unpackhi_epi32(ef_07, gh_07);
|
||||
__m256i ijkl_03 = _mm256_unpacklo_epi32(ij_07, kl_07);
|
||||
__m256i ijkl_47 = _mm256_unpackhi_epi32(ij_07, kl_07);
|
||||
__m256i mnop_03 = _mm256_unpacklo_epi32(mn_07, op_07);
|
||||
__m256i mnop_47 = _mm256_unpackhi_epi32(mn_07, op_07);
|
||||
|
||||
__m256i abcd_8b = _mm256_unpacklo_epi32(ab_8f, cd_8f);
|
||||
__m256i abcd_cf = _mm256_unpackhi_epi32(ab_8f, cd_8f);
|
||||
__m256i efgh_8b = _mm256_unpacklo_epi32(ef_8f, gh_8f);
|
||||
__m256i efgh_cf = _mm256_unpackhi_epi32(ef_8f, gh_8f);
|
||||
__m256i ijkl_8b = _mm256_unpacklo_epi32(ij_8f, kl_8f);
|
||||
__m256i ijkl_cf = _mm256_unpackhi_epi32(ij_8f, kl_8f);
|
||||
__m256i mnop_8b = _mm256_unpacklo_epi32(mn_8f, op_8f);
|
||||
__m256i mnop_cf = _mm256_unpackhi_epi32(mn_8f, op_8f);
|
||||
|
||||
__m256i abcdefgh_01 = _mm256_unpacklo_epi64(abcd_03, efgh_03);
|
||||
__m256i abcdefgh_23 = _mm256_unpackhi_epi64(abcd_03, efgh_03);
|
||||
__m256i ijklmnop_01 = _mm256_unpacklo_epi64(ijkl_03, mnop_03);
|
||||
__m256i ijklmnop_23 = _mm256_unpackhi_epi64(ijkl_03, mnop_03);
|
||||
__m256i abcdefgh_45 = _mm256_unpacklo_epi64(abcd_47, efgh_47);
|
||||
__m256i abcdefgh_67 = _mm256_unpackhi_epi64(abcd_47, efgh_47);
|
||||
__m256i ijklmnop_45 = _mm256_unpacklo_epi64(ijkl_47, mnop_47);
|
||||
__m256i ijklmnop_67 = _mm256_unpackhi_epi64(ijkl_47, mnop_47);
|
||||
__m256i abcdefgh_89 = _mm256_unpacklo_epi64(abcd_8b, efgh_8b);
|
||||
__m256i abcdefgh_ab = _mm256_unpackhi_epi64(abcd_8b, efgh_8b);
|
||||
__m256i ijklmnop_89 = _mm256_unpacklo_epi64(ijkl_8b, mnop_8b);
|
||||
__m256i ijklmnop_ab = _mm256_unpackhi_epi64(ijkl_8b, mnop_8b);
|
||||
__m256i abcdefgh_cd = _mm256_unpacklo_epi64(abcd_cf, efgh_cf);
|
||||
__m256i abcdefgh_ef = _mm256_unpackhi_epi64(abcd_cf, efgh_cf);
|
||||
__m256i ijklmnop_cd = _mm256_unpacklo_epi64(ijkl_cf, mnop_cf);
|
||||
__m256i ijklmnop_ef = _mm256_unpackhi_epi64(ijkl_cf, mnop_cf);
|
||||
|
||||
// NOTE: no unpacklo/hi instr in this case, so using permute instr.
|
||||
__m256i a_p_0 = _mm256_permute2x128_si256(abcdefgh_01, ijklmnop_01, 0x20);
|
||||
__m256i a_p_1 = _mm256_permute2x128_si256(abcdefgh_01, ijklmnop_01, 0x31);
|
||||
__m256i a_p_2 = _mm256_permute2x128_si256(abcdefgh_23, ijklmnop_23, 0x20);
|
||||
__m256i a_p_3 = _mm256_permute2x128_si256(abcdefgh_23, ijklmnop_23, 0x31);
|
||||
__m256i a_p_4 = _mm256_permute2x128_si256(abcdefgh_45, ijklmnop_45, 0x20);
|
||||
__m256i a_p_5 = _mm256_permute2x128_si256(abcdefgh_45, ijklmnop_45, 0x31);
|
||||
__m256i a_p_6 = _mm256_permute2x128_si256(abcdefgh_67, ijklmnop_67, 0x20);
|
||||
__m256i a_p_7 = _mm256_permute2x128_si256(abcdefgh_67, ijklmnop_67, 0x31);
|
||||
__m256i a_p_8 = _mm256_permute2x128_si256(abcdefgh_89, ijklmnop_89, 0x20);
|
||||
__m256i a_p_9 = _mm256_permute2x128_si256(abcdefgh_89, ijklmnop_89, 0x31);
|
||||
__m256i a_p_a = _mm256_permute2x128_si256(abcdefgh_ab, ijklmnop_ab, 0x20);
|
||||
__m256i a_p_b = _mm256_permute2x128_si256(abcdefgh_ab, ijklmnop_ab, 0x31);
|
||||
__m256i a_p_c = _mm256_permute2x128_si256(abcdefgh_cd, ijklmnop_cd, 0x20);
|
||||
__m256i a_p_d = _mm256_permute2x128_si256(abcdefgh_cd, ijklmnop_cd, 0x31);
|
||||
__m256i a_p_e = _mm256_permute2x128_si256(abcdefgh_ef, ijklmnop_ef, 0x20);
|
||||
__m256i a_p_f = _mm256_permute2x128_si256(abcdefgh_ef, ijklmnop_ef, 0x31);
|
||||
|
||||
kernel.packet[0].x = a_p_0;
|
||||
kernel.packet[1].x = a_p_1;
|
||||
kernel.packet[2].x = a_p_2;
|
||||
kernel.packet[3].x = a_p_3;
|
||||
kernel.packet[4].x = a_p_4;
|
||||
kernel.packet[5].x = a_p_5;
|
||||
kernel.packet[6].x = a_p_6;
|
||||
kernel.packet[7].x = a_p_7;
|
||||
kernel.packet[8].x = a_p_8;
|
||||
kernel.packet[9].x = a_p_9;
|
||||
kernel.packet[10].x = a_p_a;
|
||||
kernel.packet[11].x = a_p_b;
|
||||
kernel.packet[12].x = a_p_c;
|
||||
kernel.packet[13].x = a_p_d;
|
||||
kernel.packet[14].x = a_p_e;
|
||||
kernel.packet[15].x = a_p_f;
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE void
|
||||
ptranspose(PacketBlock<Packet16h,8>& kernel) {
|
||||
EIGEN_ALIGN64 half in[8][16];
|
||||
pstore<half>(in[0], kernel.packet[0]);
|
||||
pstore<half>(in[1], kernel.packet[1]);
|
||||
pstore<half>(in[2], kernel.packet[2]);
|
||||
pstore<half>(in[3], kernel.packet[3]);
|
||||
pstore<half>(in[4], kernel.packet[4]);
|
||||
pstore<half>(in[5], kernel.packet[5]);
|
||||
pstore<half>(in[6], kernel.packet[6]);
|
||||
pstore<half>(in[7], kernel.packet[7]);
|
||||
|
||||
EIGEN_ALIGN64 half out[8][16];
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
out[i][j] = in[j][2*i];
|
||||
}
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
out[i][j+8] = in[j][2*i+1];
|
||||
}
|
||||
}
|
||||
|
||||
kernel.packet[0] = pload<Packet16h>(out[0]);
|
||||
kernel.packet[1] = pload<Packet16h>(out[1]);
|
||||
kernel.packet[2] = pload<Packet16h>(out[2]);
|
||||
kernel.packet[3] = pload<Packet16h>(out[3]);
|
||||
kernel.packet[4] = pload<Packet16h>(out[4]);
|
||||
kernel.packet[5] = pload<Packet16h>(out[5]);
|
||||
kernel.packet[6] = pload<Packet16h>(out[6]);
|
||||
kernel.packet[7] = pload<Packet16h>(out[7]);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE void
|
||||
ptranspose(PacketBlock<Packet16h,4>& kernel) {
|
||||
EIGEN_ALIGN64 half in[4][16];
|
||||
pstore<half>(in[0], kernel.packet[0]);
|
||||
pstore<half>(in[1], kernel.packet[1]);
|
||||
pstore<half>(in[2], kernel.packet[2]);
|
||||
pstore<half>(in[3], kernel.packet[3]);
|
||||
|
||||
EIGEN_ALIGN64 half out[4][16];
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
out[i][j] = in[j][4*i];
|
||||
}
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
out[i][j+4] = in[j][4*i+1];
|
||||
}
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
out[i][j+8] = in[j][4*i+2];
|
||||
}
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
out[i][j+12] = in[j][4*i+3];
|
||||
}
|
||||
}
|
||||
|
||||
kernel.packet[0] = pload<Packet16h>(out[0]);
|
||||
kernel.packet[1] = pload<Packet16h>(out[1]);
|
||||
kernel.packet[2] = pload<Packet16h>(out[2]);
|
||||
kernel.packet[3] = pload<Packet16h>(out[3]);
|
||||
}
|
||||
|
||||
|
||||
#elif defined EIGEN_VECTORIZE_AVX
|
||||
|
||||
typedef struct {
|
||||
@@ -483,6 +860,30 @@ template<> EIGEN_STRONG_INLINE void pscatter<Eigen::half, Packet8h>(Eigen::half*
|
||||
to[stride*7].x = aux[7].x;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Eigen::half predux<Packet8h>(const Packet8h& a) {
|
||||
Packet8f af = half2float(a);
|
||||
float reduced = predux<Packet8f>(af);
|
||||
return Eigen::half(reduced);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Eigen::half predux_max<Packet8h>(const Packet8h& a) {
|
||||
Packet8f af = half2float(a);
|
||||
float reduced = predux_max<Packet8f>(af);
|
||||
return Eigen::half(reduced);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Eigen::half predux_min<Packet8h>(const Packet8h& a) {
|
||||
Packet8f af = half2float(a);
|
||||
float reduced = predux_min<Packet8f>(af);
|
||||
return Eigen::half(reduced);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Eigen::half predux_mul<Packet8h>(const Packet8h& a) {
|
||||
Packet8f af = half2float(a);
|
||||
float reduced = predux_mul<Packet8f>(af);
|
||||
return Eigen::half(reduced);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE void
|
||||
ptranspose(PacketBlock<Packet8h,8>& kernel) {
|
||||
__m128i a = kernel.packet[0].x;
|
||||
@@ -607,7 +1008,7 @@ template<> EIGEN_STRONG_INLINE Packet4h pset1<Packet4h>(const Eigen::half& from)
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Eigen::half pfirst<Packet4h>(const Packet4h& from) {
|
||||
return raw_uint16_to_half(static_cast<unsigned short>(_mm_cvtsi64_si32(from.x)));
|
||||
return half_impl::raw_uint16_to_half(static_cast<unsigned short>(_mm_cvtsi64_si32(from.x)));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4h pconj(const Packet4h& a) { return a; }
|
||||
@@ -618,17 +1019,17 @@ template<> EIGEN_STRONG_INLINE Packet4h padd<Packet4h>(const Packet4h& a, const
|
||||
|
||||
Eigen::half h[4];
|
||||
|
||||
Eigen::half ha = raw_uint16_to_half(static_cast<unsigned short>(a64));
|
||||
Eigen::half hb = raw_uint16_to_half(static_cast<unsigned short>(b64));
|
||||
Eigen::half ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64));
|
||||
Eigen::half hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64));
|
||||
h[0] = ha + hb;
|
||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
||||
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
||||
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
||||
h[1] = ha + hb;
|
||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
||||
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
||||
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
||||
h[2] = ha + hb;
|
||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
||||
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
||||
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
||||
h[3] = ha + hb;
|
||||
Packet4h result;
|
||||
result.x = _mm_set_pi16(h[3].x, h[2].x, h[1].x, h[0].x);
|
||||
@@ -641,17 +1042,17 @@ template<> EIGEN_STRONG_INLINE Packet4h pmul<Packet4h>(const Packet4h& a, const
|
||||
|
||||
Eigen::half h[4];
|
||||
|
||||
Eigen::half ha = raw_uint16_to_half(static_cast<unsigned short>(a64));
|
||||
Eigen::half hb = raw_uint16_to_half(static_cast<unsigned short>(b64));
|
||||
Eigen::half ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64));
|
||||
Eigen::half hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64));
|
||||
h[0] = ha * hb;
|
||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
||||
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
||||
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
||||
h[1] = ha * hb;
|
||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
||||
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
||||
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
||||
h[2] = ha * hb;
|
||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
||||
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
||||
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
||||
h[3] = ha * hb;
|
||||
Packet4h result;
|
||||
result.x = _mm_set_pi16(h[3].x, h[2].x, h[1].x, h[0].x);
|
||||
|
||||
@@ -100,6 +100,33 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcast<float4, half2>(cons
|
||||
return __floats2half2_rn(a.x, a.y);
|
||||
}
|
||||
|
||||
#elif defined EIGEN_VECTORIZE_AVX512
|
||||
template <>
|
||||
struct type_casting_traits<half, float> {
|
||||
enum {
|
||||
VectorizedCast = 1,
|
||||
SrcCoeffRatio = 1,
|
||||
TgtCoeffRatio = 1
|
||||
};
|
||||
};
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16f pcast<Packet16h, Packet16f>(const Packet16h& a) {
|
||||
return half2float(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct type_casting_traits<float, half> {
|
||||
enum {
|
||||
VectorizedCast = 1,
|
||||
SrcCoeffRatio = 1,
|
||||
TgtCoeffRatio = 1
|
||||
};
|
||||
};
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h pcast<Packet16f, Packet16h>(const Packet16f& a) {
|
||||
return float2half(a);
|
||||
}
|
||||
|
||||
#elif defined EIGEN_VECTORIZE_AVX
|
||||
|
||||
template <>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_arch_Default_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_arch_Default_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/Default COMPONENT Devel
|
||||
)
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_arch_NEON_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_arch_NEON_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/NEON COMPONENT Devel
|
||||
)
|
||||
@@ -16,8 +16,14 @@ namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
inline uint32x4_t p4ui_CONJ_XOR() {
|
||||
// See bug 1325, clang fails to call vld1q_u64.
|
||||
#if EIGEN_COMP_CLANG
|
||||
uint32x4_t ret = { 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
|
||||
return ret;
|
||||
#else
|
||||
static const uint32_t conj_XOR_DATA[] = { 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
|
||||
return vld1q_u32( conj_XOR_DATA );
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32x2_t p2ui_CONJ_XOR() {
|
||||
@@ -282,8 +288,13 @@ ptranspose(PacketBlock<Packet2cf,2>& kernel) {
|
||||
//---------- double ----------
|
||||
#if EIGEN_ARCH_ARM64 && !EIGEN_APPLE_DOUBLE_NEON_BUG
|
||||
|
||||
const uint64_t p2ul_conj_XOR_DATA[] = { 0x0, 0x8000000000000000 };
|
||||
static uint64x2_t p2ul_CONJ_XOR = vld1q_u64( p2ul_conj_XOR_DATA );
|
||||
// See bug 1325, clang fails to call vld1q_u64.
|
||||
#if EIGEN_COMP_CLANG
|
||||
static uint64x2_t p2ul_CONJ_XOR = {0x0, 0x8000000000000000};
|
||||
#else
|
||||
const uint64_t p2ul_conj_XOR_DATA[] = { 0x0, 0x8000000000000000 };
|
||||
static uint64x2_t p2ul_CONJ_XOR = vld1q_u64( p2ul_conj_XOR_DATA );
|
||||
#endif
|
||||
|
||||
struct Packet1cd
|
||||
{
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_arch_SSE_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_arch_SSE_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/SSE COMPONENT Devel
|
||||
)
|
||||
@@ -476,6 +476,26 @@ template<> EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, co
|
||||
return Packet2cf(_mm_castpd_ps(result));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pinsertfirst(const Packet2cf& a, std::complex<float> b)
|
||||
{
|
||||
return Packet2cf(_mm_loadl_pi(a.v, reinterpret_cast<const __m64*>(&b)));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pinsertfirst(const Packet1cd&, std::complex<double> b)
|
||||
{
|
||||
return pset1<Packet1cd>(b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pinsertlast(const Packet2cf& a, std::complex<float> b)
|
||||
{
|
||||
return Packet2cf(_mm_loadh_pi(a.v, reinterpret_cast<const __m64*>(&b)));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pinsertlast(const Packet1cd&, std::complex<double> b)
|
||||
{
|
||||
return pset1<Packet1cd>(b);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -32,7 +32,7 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
|
||||
/* the smallest non denormalized float number */
|
||||
_EIGEN_DECLARE_CONST_Packet4f_FROM_INT(min_norm_pos, 0x00800000);
|
||||
_EIGEN_DECLARE_CONST_Packet4f_FROM_INT(minus_inf, 0xff800000);//-1.f/0.f);
|
||||
|
||||
|
||||
/* natural logarithm computed for 4 simultaneous float
|
||||
return NaN for x <= 0
|
||||
*/
|
||||
@@ -444,25 +444,33 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
|
||||
|
||||
#if EIGEN_FAST_MATH
|
||||
|
||||
// This is based on Quake3's fast inverse square root.
|
||||
// Functions for sqrt.
|
||||
// The EIGEN_FAST_MATH version uses the _mm_rsqrt_ps approximation and one step
|
||||
// of Newton's method, at a cost of 1-2 bits of precision as opposed to the
|
||||
// exact solution. It does not handle +inf, or denormalized numbers correctly.
|
||||
// The main advantage of this approach is not just speed, but also the fact that
|
||||
// it can be inlined and pipelined with other computations, further reducing its
|
||||
// effective latency. This is similar to Quake3's fast inverse square root.
|
||||
// For detail see here: http://www.beyond3d.com/content/articles/8/
|
||||
// It lacks 1 (or 2 bits in some rare cases) of precision, and does not handle negative, +inf, or denormalized numbers correctly.
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
Packet4f psqrt<Packet4f>(const Packet4f& _x)
|
||||
{
|
||||
Packet4f half = pmul(_x, pset1<Packet4f>(.5f));
|
||||
Packet4f denormal_mask = _mm_and_ps(
|
||||
_mm_cmpge_ps(_x, _mm_setzero_ps()),
|
||||
_mm_cmplt_ps(_x, pset1<Packet4f>((std::numeric_limits<float>::min)())));
|
||||
|
||||
/* select only the inverse sqrt of non-zero inputs */
|
||||
Packet4f non_zero_mask = _mm_cmpge_ps(_x, pset1<Packet4f>((std::numeric_limits<float>::min)()));
|
||||
Packet4f x = _mm_and_ps(non_zero_mask, _mm_rsqrt_ps(_x));
|
||||
|
||||
// Compute approximate reciprocal sqrt.
|
||||
Packet4f x = _mm_rsqrt_ps(_x);
|
||||
// Do a single step of Newton's iteration.
|
||||
x = pmul(x, psub(pset1<Packet4f>(1.5f), pmul(half, pmul(x,x))));
|
||||
return pmul(_x,x);
|
||||
// Flush results for denormals to zero.
|
||||
return _mm_andnot_ps(denormal_mask, pmul(_x,x));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<>EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
template<>EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
Packet4f psqrt<Packet4f>(const Packet4f& x) { return _mm_sqrt_ps(x); }
|
||||
|
||||
#endif
|
||||
@@ -491,7 +499,7 @@ Packet4f prsqrt<Packet4f>(const Packet4f& _x) {
|
||||
Packet4f neg_mask = _mm_cmplt_ps(_x, _mm_setzero_ps());
|
||||
Packet4f zero_mask = _mm_andnot_ps(neg_mask, le_zero_mask);
|
||||
Packet4f infs_and_nans = _mm_or_ps(_mm_and_ps(neg_mask, p4f_nan),
|
||||
_mm_and_ps(zero_mask, p4f_inf));
|
||||
_mm_and_ps(zero_mask, p4f_inf));
|
||||
|
||||
// Do a single step of Newton's iteration.
|
||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p4f_one_point_five));
|
||||
@@ -517,52 +525,10 @@ Packet2d prsqrt<Packet2d>(const Packet2d& x) {
|
||||
}
|
||||
|
||||
// Hyperbolic Tangent function.
|
||||
// Doesn't do anything fancy, just a 13/6-degree rational interpolant which
|
||||
// is accurate up to a couple of ulp in the range [-9, 9], outside of which the
|
||||
// fl(tanh(x)) = +/-1.
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet4f
|
||||
ptanh<Packet4f>(const Packet4f& _x) {
|
||||
// Clamp the inputs to the range [-9, 9] since anything outside
|
||||
// this range is +/-1.0f in single-precision.
|
||||
_EIGEN_DECLARE_CONST_Packet4f(plus_9, 9.0f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(minus_9, -9.0f);
|
||||
const Packet4f x = pmax(p4f_minus_9, pmin(p4f_plus_9, _x));
|
||||
|
||||
// The monomial coefficients of the numerator polynomial (odd).
|
||||
_EIGEN_DECLARE_CONST_Packet4f(alpha_1, 4.89352455891786e-03f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(alpha_3, 6.37261928875436e-04f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(alpha_5, 1.48572235717979e-05f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(alpha_7, 5.12229709037114e-08f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(alpha_9, -8.60467152213735e-11f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(alpha_11, 2.00018790482477e-13f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(alpha_13, -2.76076847742355e-16f);
|
||||
|
||||
// The monomial coefficients of the denominator polynomial (even).
|
||||
_EIGEN_DECLARE_CONST_Packet4f(beta_0, 4.89352518554385e-03f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(beta_2, 2.26843463243900e-03f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(beta_4, 1.18534705686654e-04f);
|
||||
_EIGEN_DECLARE_CONST_Packet4f(beta_6, 1.19825839466702e-06f);
|
||||
|
||||
// Since the polynomials are odd/even, we need x^2.
|
||||
const Packet4f x2 = pmul(x, x);
|
||||
|
||||
// Evaluate the numerator polynomial p.
|
||||
Packet4f p = pmadd(x2, p4f_alpha_13, p4f_alpha_11);
|
||||
p = pmadd(x2, p, p4f_alpha_9);
|
||||
p = pmadd(x2, p, p4f_alpha_7);
|
||||
p = pmadd(x2, p, p4f_alpha_5);
|
||||
p = pmadd(x2, p, p4f_alpha_3);
|
||||
p = pmadd(x2, p, p4f_alpha_1);
|
||||
p = pmul(x, p);
|
||||
|
||||
// Evaluate the denominator polynomial p.
|
||||
Packet4f q = pmadd(x2, p4f_beta_6, p4f_beta_4);
|
||||
q = pmadd(x2, q, p4f_beta_2);
|
||||
q = pmadd(x2, q, p4f_beta_0);
|
||||
|
||||
// Divide the numerator by the denominator.
|
||||
return pdiv(p, q);
|
||||
ptanh<Packet4f>(const Packet4f& x) {
|
||||
return internal::generic_fast_tanh_float(x);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
@@ -162,6 +162,11 @@ template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4,
|
||||
template<> struct unpacket_traits<Packet2d> { typedef double type; enum {size=2, alignment=Aligned16}; typedef Packet2d half; };
|
||||
template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; };
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX
|
||||
template<> struct scalar_div_cost<float,true> { enum { value = 7 }; };
|
||||
template<> struct scalar_div_cost<double,true> { enum { value = 8 }; };
|
||||
#endif
|
||||
|
||||
#if EIGEN_COMP_MSVC==1500
|
||||
// Workaround MSVC 9 internal compiler error.
|
||||
// TODO: It has been detected with win64 builds (amd64), so let's check whether it also happens in 32bits+SSE mode
|
||||
@@ -813,6 +818,54 @@ template<> EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, cons
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pinsertfirst(const Packet4f& a, float b)
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE4_1
|
||||
return _mm_blend_ps(a,pset1<Packet4f>(b),1);
|
||||
#else
|
||||
return _mm_move_ss(a, _mm_load_ss(&b));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2d pinsertfirst(const Packet2d& a, double b)
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE4_1
|
||||
return _mm_blend_pd(a,pset1<Packet2d>(b),1);
|
||||
#else
|
||||
return _mm_move_sd(a, _mm_load_sd(&b));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pinsertlast(const Packet4f& a, float b)
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE4_1
|
||||
return _mm_blend_ps(a,pset1<Packet4f>(b),(1<<3));
|
||||
#else
|
||||
const Packet4f mask = _mm_castsi128_ps(_mm_setr_epi32(0x0,0x0,0x0,0xFFFFFFFF));
|
||||
return _mm_or_ps(_mm_andnot_ps(mask, a), _mm_and_ps(mask, pset1<Packet4f>(b)));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2d pinsertlast(const Packet2d& a, double b)
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE4_1
|
||||
return _mm_blend_pd(a,pset1<Packet2d>(b),(1<<1));
|
||||
#else
|
||||
const Packet2d mask = _mm_castsi128_pd(_mm_setr_epi32(0x0,0x0,0xFFFFFFFF,0xFFFFFFFF));
|
||||
return _mm_or_pd(_mm_andnot_pd(mask, a), _mm_and_pd(mask, pset1<Packet2d>(b)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Scalar path for pmadd with FMA to ensure consistency with vectorized path.
|
||||
#ifdef __FMA__
|
||||
template<> EIGEN_STRONG_INLINE float pmadd(const float& a, const float& b, const float& c) {
|
||||
return ::fmaf(a,b,c);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE double pmadd(const double& a, const double& b, const double& c) {
|
||||
return ::fma(a,b,c);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_arch_ZVector_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_arch_ZVector_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/ZVector COMPONENT Devel
|
||||
)
|
||||
@@ -266,7 +266,7 @@ struct scalar_hypot_op<Scalar,Scalar> : binary_op_base<Scalar,Scalar>
|
||||
// typedef typename NumTraits<Scalar>::Real result_type;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
|
||||
{
|
||||
using std::sqrt;
|
||||
EIGEN_USING_STD_MATH(sqrt)
|
||||
Scalar p, qp;
|
||||
if(_x>_y)
|
||||
{
|
||||
@@ -287,7 +287,7 @@ struct functor_traits<scalar_hypot_op<Scalar,Scalar> > {
|
||||
{
|
||||
Cost = 3 * NumTraits<Scalar>::AddCost +
|
||||
2 * NumTraits<Scalar>::MulCost +
|
||||
2 * NumTraits<Scalar>::template Div<false>::Cost,
|
||||
2 * scalar_div_cost<Scalar,false>::value,
|
||||
PacketAccess = false
|
||||
};
|
||||
};
|
||||
@@ -375,7 +375,7 @@ struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
|
||||
typedef typename scalar_quotient_op<LhsScalar,RhsScalar>::result_type result_type;
|
||||
enum {
|
||||
PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv,
|
||||
Cost = NumTraits<result_type>::template Div<PacketAccess>::Cost
|
||||
Cost = scalar_div_cost<result_type,PacketAccess>::value
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_Functor_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_Functor_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/functors COMPONENT Devel
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
@@ -18,10 +18,9 @@ template<typename Scalar>
|
||||
struct scalar_constant_op {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { }
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; }
|
||||
template<typename Index, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetOp(Index, Index = 0) const { return internal::pset1<PacketType>(m_other); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() () const { return m_other; }
|
||||
template<typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetOp() const { return internal::pset1<PacketType>(m_other); }
|
||||
const Scalar m_other;
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -31,94 +30,85 @@ struct functor_traits<scalar_constant_op<Scalar> >
|
||||
|
||||
template<typename Scalar> struct scalar_identity_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); }
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType row, IndexType col) const { return row==col ? Scalar(1) : Scalar(0); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct functor_traits<scalar_identity_op<Scalar> >
|
||||
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
|
||||
|
||||
template <typename Scalar, typename Packet, bool RandomAccess, bool IsInteger> struct linspaced_op_impl;
|
||||
|
||||
// linear access for packet ops:
|
||||
// 1) initialization
|
||||
// base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0])
|
||||
// 2) each step (where size is 1 for coeff access or PacketSize for packet access)
|
||||
// base += [size*step, ..., size*step]
|
||||
//
|
||||
// TODO: Perhaps it's better to initialize lazily (so not in the constructor but in packetOp)
|
||||
// in order to avoid the padd() in operator() ?
|
||||
template <typename Scalar, typename Packet>
|
||||
struct linspaced_op_impl<Scalar,Packet,/*RandomAccess*/false,/*IsInteger*/false>
|
||||
{
|
||||
linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) :
|
||||
m_low(low), m_step(num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1)),
|
||||
m_packetStep(pset1<Packet>(unpacket_traits<Packet>::size*m_step)),
|
||||
m_base(padd(pset1<Packet>(low), pmul(pset1<Packet>(m_step),plset<Packet>(-unpacket_traits<Packet>::size)))) {}
|
||||
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index i) const
|
||||
{
|
||||
m_base = padd(m_base, pset1<Packet>(m_step));
|
||||
return m_low+Scalar(i)*m_step;
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); }
|
||||
|
||||
const Scalar m_low;
|
||||
const Scalar m_step;
|
||||
const Packet m_packetStep;
|
||||
mutable Packet m_base;
|
||||
};
|
||||
|
||||
// random access for packet ops:
|
||||
// 1) each step
|
||||
// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
|
||||
template <typename Scalar, typename Packet>
|
||||
struct linspaced_op_impl<Scalar,Packet,/*RandomAccess*/true,/*IsInteger*/false>
|
||||
{
|
||||
linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) :
|
||||
m_low(low), m_step(num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1)),
|
||||
m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Packet>(0)) {}
|
||||
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
|
||||
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
|
||||
{ return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(Scalar(i)),m_interPacket))); }
|
||||
|
||||
const Scalar m_low;
|
||||
const Scalar m_step;
|
||||
const Packet m_lowPacket;
|
||||
const Packet m_stepPacket;
|
||||
const Packet m_interPacket;
|
||||
};
|
||||
template <typename Scalar, typename Packet, bool IsInteger> struct linspaced_op_impl;
|
||||
|
||||
template <typename Scalar, typename Packet>
|
||||
struct linspaced_op_impl<Scalar,Packet,/*RandomAccess*/true,/*IsInteger*/true>
|
||||
struct linspaced_op_impl<Scalar,Packet,/*IsInteger*/false>
|
||||
{
|
||||
linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) :
|
||||
m_low(low), m_length(high-low), m_divisor(convert_index<Scalar>(num_steps==1?1:num_steps-1)), m_interPacket(plset<Packet>(0))
|
||||
m_low(low), m_high(high), m_size1(num_steps==1 ? 1 : num_steps-1), m_step(num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1)),
|
||||
m_interPacket(plset<Packet>(0)),
|
||||
m_flip(std::abs(high)<std::abs(low))
|
||||
{}
|
||||
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const Scalar operator() (Index i) const {
|
||||
return m_low + (m_length*Scalar(i))/m_divisor;
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType i) const {
|
||||
if(m_flip)
|
||||
return (i==0)? m_low : (m_high - (m_size1-i)*m_step);
|
||||
else
|
||||
return (i==m_size1)? m_high : (m_low + i*m_step);
|
||||
}
|
||||
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const Packet packetOp(Index i) const {
|
||||
return internal::padd(pset1<Packet>(m_low), pdiv(pmul(pset1<Packet>(m_length), padd(pset1<Packet>(Scalar(i)),m_interPacket)),
|
||||
pset1<Packet>(m_divisor))); }
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(IndexType i) const
|
||||
{
|
||||
// Principle:
|
||||
// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
|
||||
if(m_flip)
|
||||
{
|
||||
Packet pi = padd(pset1<Packet>(Scalar(i-m_size1)),m_interPacket);
|
||||
Packet res = padd(pset1<Packet>(m_high), pmul(pset1<Packet>(m_step), pi));
|
||||
if(i==0)
|
||||
res = pinsertfirst(res, m_low);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
Packet pi = padd(pset1<Packet>(Scalar(i)),m_interPacket);
|
||||
Packet res = padd(pset1<Packet>(m_low), pmul(pset1<Packet>(m_step), pi));
|
||||
if(i==m_size1-unpacket_traits<Packet>::size+1)
|
||||
res = pinsertlast(res, m_high);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
const Scalar m_low;
|
||||
const Scalar m_length;
|
||||
const Scalar m_divisor;
|
||||
const Scalar m_high;
|
||||
const Index m_size1;
|
||||
const Scalar m_step;
|
||||
const Packet m_interPacket;
|
||||
const bool m_flip;
|
||||
};
|
||||
|
||||
template <typename Scalar, typename Packet>
|
||||
struct linspaced_op_impl<Scalar,Packet,/*IsInteger*/true>
|
||||
{
|
||||
linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) :
|
||||
m_low(low),
|
||||
m_multiplier((high-low)/convert_index<Scalar>(num_steps<=1 ? 1 : num_steps-1)),
|
||||
m_divisor(convert_index<Scalar>(num_steps+high-low)/(high-low+1)),
|
||||
m_use_divisor((high-low+1)<num_steps)
|
||||
{}
|
||||
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const Scalar operator() (IndexType i) const
|
||||
{
|
||||
if(m_use_divisor) return m_low + convert_index<Scalar>(i)/m_divisor;
|
||||
else return m_low + convert_index<Scalar>(i)*m_multiplier;
|
||||
}
|
||||
|
||||
const Scalar m_low;
|
||||
const Scalar m_multiplier;
|
||||
const Scalar m_divisor;
|
||||
const bool m_use_divisor;
|
||||
};
|
||||
|
||||
// ----- Linspace functor ----------------------------------------------------------------
|
||||
@@ -126,60 +116,64 @@ struct linspaced_op_impl<Scalar,Packet,/*RandomAccess*/true,/*IsInteger*/true>
|
||||
// Forward declaration (we default to random access which does not really give
|
||||
// us a speed gain when using packet access but it allows to use the functor in
|
||||
// nested expressions).
|
||||
template <typename Scalar, typename PacketType, bool RandomAccess = true> struct linspaced_op;
|
||||
template <typename Scalar, typename PacketType, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,PacketType,RandomAccess> >
|
||||
template <typename Scalar, typename PacketType> struct linspaced_op;
|
||||
template <typename Scalar, typename PacketType> struct functor_traits< linspaced_op<Scalar,PacketType> >
|
||||
{
|
||||
enum
|
||||
{
|
||||
Cost = 1,
|
||||
PacketAccess = packet_traits<Scalar>::HasSetLinear
|
||||
&& ((!NumTraits<Scalar>::IsInteger) || packet_traits<Scalar>::HasDiv),
|
||||
PacketAccess = (!NumTraits<Scalar>::IsInteger) && packet_traits<Scalar>::HasSetLinear && packet_traits<Scalar>::HasBlend,
|
||||
/*&& ((!NumTraits<Scalar>::IsInteger) || packet_traits<Scalar>::HasDiv),*/ // <- vectorization for integer is currently disabled
|
||||
IsRepeatable = true
|
||||
};
|
||||
};
|
||||
template <typename Scalar, typename PacketType, bool RandomAccess> struct linspaced_op
|
||||
template <typename Scalar, typename PacketType> struct linspaced_op
|
||||
{
|
||||
linspaced_op(const Scalar& low, const Scalar& high, Index num_steps)
|
||||
: impl((num_steps==1 ? high : low),high,num_steps)
|
||||
{}
|
||||
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType i) const { return impl(i); }
|
||||
|
||||
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
|
||||
// there row==0 and col is used for the actual iteration.
|
||||
template<typename Index>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const
|
||||
{
|
||||
eigen_assert(col==0 || row==0);
|
||||
return impl(col + row);
|
||||
}
|
||||
template<typename Packet,typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(IndexType i) const { return impl.packetOp(i); }
|
||||
|
||||
template<typename Index, typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); }
|
||||
|
||||
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
|
||||
// there row==0 and col is used for the actual iteration.
|
||||
template<typename Index, typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
|
||||
{
|
||||
eigen_assert(col==0 || row==0);
|
||||
return impl.packetOp(col + row);
|
||||
}
|
||||
|
||||
// This proxy object handles the actual required temporaries, the different
|
||||
// implementations (random vs. sequential access) as well as the
|
||||
// correct piping to size 2/4 packet operations.
|
||||
// As long as we don't have a Bresenham-like implementation for linear-access and integer types,
|
||||
// we have to by-pass RandomAccess for integer types. See bug 698.
|
||||
const linspaced_op_impl<Scalar,PacketType,(NumTraits<Scalar>::IsInteger?true:RandomAccess),NumTraits<Scalar>::IsInteger> impl;
|
||||
// This proxy object handles the actual required temporaries and the different
|
||||
// implementations (integer vs. floating point).
|
||||
const linspaced_op_impl<Scalar,PacketType,NumTraits<Scalar>::IsInteger> impl;
|
||||
};
|
||||
|
||||
// all functors allow linear access, except scalar_identity_op. So we fix here a quick meta
|
||||
// to indicate whether a functor allows linear access, just always answering 'yes' except for
|
||||
// scalar_identity_op.
|
||||
template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
|
||||
template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
|
||||
// Linear access is automatically determined from the operator() prototypes available for the given functor.
|
||||
// If it exposes an operator()(i,j), then we assume the i and j coefficients are required independently
|
||||
// and linear access is not possible. In all other cases, linear access is enabled.
|
||||
// Users should not have to deal with this structure.
|
||||
template<typename Functor> struct functor_has_linear_access { enum { ret = !has_binary_operator<Functor>::value }; };
|
||||
|
||||
// For unreliable compilers, let's specialize the has_*ary_operator
|
||||
// helpers so that at least built-in nullary functors work fine.
|
||||
#if !( (EIGEN_COMP_MSVC>1600) || (EIGEN_GNUC_AT_LEAST(4,8)) || (EIGEN_COMP_ICC>=1600))
|
||||
template<typename Scalar,typename IndexType>
|
||||
struct has_nullary_operator<scalar_constant_op<Scalar>,IndexType> { enum { value = 1}; };
|
||||
template<typename Scalar,typename IndexType>
|
||||
struct has_unary_operator<scalar_constant_op<Scalar>,IndexType> { enum { value = 0}; };
|
||||
template<typename Scalar,typename IndexType>
|
||||
struct has_binary_operator<scalar_constant_op<Scalar>,IndexType> { enum { value = 0}; };
|
||||
|
||||
template<typename Scalar,typename IndexType>
|
||||
struct has_nullary_operator<scalar_identity_op<Scalar>,IndexType> { enum { value = 0}; };
|
||||
template<typename Scalar,typename IndexType>
|
||||
struct has_unary_operator<scalar_identity_op<Scalar>,IndexType> { enum { value = 0}; };
|
||||
template<typename Scalar,typename IndexType>
|
||||
struct has_binary_operator<scalar_identity_op<Scalar>,IndexType> { enum { value = 1}; };
|
||||
|
||||
template<typename Scalar, typename PacketType,typename IndexType>
|
||||
struct has_nullary_operator<linspaced_op<Scalar,PacketType>,IndexType> { enum { value = 0}; };
|
||||
template<typename Scalar, typename PacketType,typename IndexType>
|
||||
struct has_unary_operator<linspaced_op<Scalar,PacketType>,IndexType> { enum { value = 1}; };
|
||||
template<typename Scalar, typename PacketType,typename IndexType>
|
||||
struct has_binary_operator<linspaced_op<Scalar,PacketType>,IndexType> { enum { value = 0}; };
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
@@ -248,7 +248,7 @@ struct functor_traits<scalar_exp_op<Scalar> > {
|
||||
// double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
|
||||
: (14 * NumTraits<Scalar>::AddCost +
|
||||
6 * NumTraits<Scalar>::MulCost +
|
||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost))
|
||||
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value))
|
||||
#else
|
||||
Cost =
|
||||
(sizeof(Scalar) == 4
|
||||
@@ -257,7 +257,7 @@ struct functor_traits<scalar_exp_op<Scalar> > {
|
||||
// double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
|
||||
: (23 * NumTraits<Scalar>::AddCost +
|
||||
12 * NumTraits<Scalar>::MulCost +
|
||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost))
|
||||
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value))
|
||||
#endif
|
||||
};
|
||||
};
|
||||
@@ -321,7 +321,7 @@ struct functor_traits<scalar_log1p_op<Scalar> > {
|
||||
*/
|
||||
template<typename Scalar> struct scalar_log10_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_log10_op)
|
||||
EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { using std::log10; return log10(a); }
|
||||
EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { EIGEN_USING_STD_MATH(log10) return log10(a); }
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog10(a); }
|
||||
};
|
||||
@@ -491,85 +491,40 @@ struct functor_traits<scalar_atan_op<Scalar> >
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/** \internal
|
||||
* \brief Template functor to compute the tanh of a scalar
|
||||
* \sa class CwiseUnaryOp, ArrayBase::tanh()
|
||||
*/
|
||||
template<typename Scalar> struct scalar_tanh_op {
|
||||
template <typename Scalar>
|
||||
struct scalar_tanh_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_tanh_op)
|
||||
EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::tanh(a); }
|
||||
EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::tanh(a); }
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& _x) const {
|
||||
/** \internal \returns the hyperbolic tan of \a a (coeff-wise)
|
||||
Doesn't do anything fancy, just a 13/6-degree rational interpolant which
|
||||
is accurate up to a couple of ulp in the range [-9, 9], outside of which the
|
||||
fl(tanh(x)) = +/-1. */
|
||||
|
||||
// Clamp the inputs to the range [-9, 9] since anything outside
|
||||
// this range is +/-1.0f in single-precision.
|
||||
const Packet plus_9 = pset1<Packet>(9.0);
|
||||
const Packet minus_9 = pset1<Packet>(-9.0);
|
||||
const Packet x = pmax(minus_9, pmin(plus_9, _x));
|
||||
|
||||
// The monomial coefficients of the numerator polynomial (odd).
|
||||
const Packet alpha_1 = pset1<Packet>(4.89352455891786e-03);
|
||||
const Packet alpha_3 = pset1<Packet>(6.37261928875436e-04);
|
||||
const Packet alpha_5 = pset1<Packet>(1.48572235717979e-05);
|
||||
const Packet alpha_7 = pset1<Packet>(5.12229709037114e-08);
|
||||
const Packet alpha_9 = pset1<Packet>(-8.60467152213735e-11);
|
||||
const Packet alpha_11 = pset1<Packet>(2.00018790482477e-13);
|
||||
const Packet alpha_13 = pset1<Packet>(-2.76076847742355e-16);
|
||||
|
||||
// The monomial coefficients of the denominator polynomial (even).
|
||||
const Packet beta_0 = pset1<Packet>(4.89352518554385e-03);
|
||||
const Packet beta_2 = pset1<Packet>(2.26843463243900e-03);
|
||||
const Packet beta_4 = pset1<Packet>(1.18534705686654e-04);
|
||||
const Packet beta_6 = pset1<Packet>(1.19825839466702e-06);
|
||||
|
||||
// Since the polynomials are odd/even, we need x^2.
|
||||
const Packet x2 = pmul(x, x);
|
||||
|
||||
// Evaluate the numerator polynomial p.
|
||||
Packet p = pmadd(x2, alpha_13, alpha_11);
|
||||
p = pmadd(x2, p, alpha_9);
|
||||
p = pmadd(x2, p, alpha_7);
|
||||
p = pmadd(x2, p, alpha_5);
|
||||
p = pmadd(x2, p, alpha_3);
|
||||
p = pmadd(x2, p, alpha_1);
|
||||
p = pmul(x, p);
|
||||
|
||||
// Evaluate the denominator polynomial p.
|
||||
Packet q = pmadd(x2, beta_6, beta_4);
|
||||
q = pmadd(x2, q, beta_2);
|
||||
q = pmadd(x2, q, beta_0);
|
||||
|
||||
// Divide the numerator by the denominator.
|
||||
return pdiv(p, q);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const { return ptanh(x); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct functor_traits<scalar_tanh_op<Scalar> >
|
||||
{
|
||||
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_tanh_op<Scalar> > {
|
||||
enum {
|
||||
PacketAccess = packet_traits<Scalar>::HasTanh,
|
||||
Cost =
|
||||
(PacketAccess
|
||||
// The following numbers are based on the AVX implementation,
|
||||
Cost = ( (EIGEN_FAST_MATH && is_same<Scalar,float>::value)
|
||||
// The following numbers are based on the AVX implementation,
|
||||
#ifdef EIGEN_VECTORIZE_FMA
|
||||
// Haswell can issue 2 add/mul/madd per cycle.
|
||||
// 9 pmadd, 2 pmul, 1 div, 2 other
|
||||
? (2 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost +
|
||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost)
|
||||
// Haswell can issue 2 add/mul/madd per cycle.
|
||||
// 9 pmadd, 2 pmul, 1 div, 2 other
|
||||
? (2 * NumTraits<Scalar>::AddCost +
|
||||
6 * NumTraits<Scalar>::MulCost +
|
||||
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)
|
||||
#else
|
||||
? (11 * NumTraits<Scalar>::AddCost +
|
||||
11 * NumTraits<Scalar>::MulCost +
|
||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost)
|
||||
? (11 * NumTraits<Scalar>::AddCost +
|
||||
11 * NumTraits<Scalar>::MulCost +
|
||||
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)
|
||||
#endif
|
||||
// This number assumes a naive implementation of tanh
|
||||
: (6 * NumTraits<Scalar>::AddCost + 3 * NumTraits<Scalar>::MulCost +
|
||||
2 * NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost +
|
||||
functor_traits<scalar_exp_op<Scalar> >::Cost))
|
||||
// This number assumes a naive implementation of tanh
|
||||
: (6 * NumTraits<Scalar>::AddCost +
|
||||
3 * NumTraits<Scalar>::MulCost +
|
||||
2 * scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value +
|
||||
functor_traits<scalar_exp_op<Scalar> >::Cost))
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_Product_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_Product_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/products COMPONENT Devel
|
||||
)
|
||||
@@ -434,15 +434,16 @@ public:
|
||||
template<typename LhsPacketType, typename RhsPacketType, typename AccPacketType>
|
||||
EIGEN_STRONG_INLINE void madd(const LhsPacketType& a, const RhsPacketType& b, AccPacketType& c, AccPacketType& tmp) const
|
||||
{
|
||||
conj_helper<LhsPacketType,RhsPacketType,ConjLhs,ConjRhs> cj;
|
||||
// It would be a lot cleaner to call pmadd all the time. Unfortunately if we
|
||||
// let gcc allocate the register in which to store the result of the pmul
|
||||
// (in the case where there is no FMA) gcc fails to figure out how to avoid
|
||||
// spilling register.
|
||||
#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||
EIGEN_UNUSED_VARIABLE(tmp);
|
||||
c = pmadd(a,b,c);
|
||||
c = cj.pmadd(a,b,c);
|
||||
#else
|
||||
tmp = b; tmp = pmul(a,tmp); c = padd(c,tmp);
|
||||
tmp = b; tmp = cj.pmul(a,tmp); c = padd(c,tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -457,9 +458,6 @@ public:
|
||||
r = pmadd(c,alpha,r);
|
||||
}
|
||||
|
||||
protected:
|
||||
// conj_helper<LhsScalar,RhsScalar,ConjLhs,ConjRhs> cj;
|
||||
// conj_helper<LhsPacket,RhsPacket,ConjLhs,ConjRhs> pcj;
|
||||
};
|
||||
|
||||
template<typename RealScalar, bool _ConjLhs>
|
||||
@@ -582,7 +580,7 @@ DoublePacket<Packet> padd(const DoublePacket<Packet> &a, const DoublePacket<Pack
|
||||
}
|
||||
|
||||
template<typename Packet>
|
||||
const DoublePacket<Packet>& predux4(const DoublePacket<Packet> &a)
|
||||
const DoublePacket<Packet>& predux_downto4(const DoublePacket<Packet> &a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
@@ -1583,10 +1581,10 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
||||
if(SwappedTraits::LhsProgress==8)
|
||||
{
|
||||
// Special case where we have to first reduce the accumulation register C0
|
||||
typedef typename conditional<SwappedTraits::LhsProgress==8,typename unpacket_traits<SResPacket>::half,SResPacket>::type SResPacketHalf;
|
||||
typedef typename conditional<SwappedTraits::LhsProgress==8,typename unpacket_traits<SLhsPacket>::half,SLhsPacket>::type SLhsPacketHalf;
|
||||
typedef typename conditional<SwappedTraits::LhsProgress==8,typename unpacket_traits<SLhsPacket>::half,SRhsPacket>::type SRhsPacketHalf;
|
||||
typedef typename conditional<SwappedTraits::LhsProgress==8,typename unpacket_traits<SAccPacket>::half,SAccPacket>::type SAccPacketHalf;
|
||||
typedef typename conditional<SwappedTraits::LhsProgress>=8,typename unpacket_traits<SResPacket>::half,SResPacket>::type SResPacketHalf;
|
||||
typedef typename conditional<SwappedTraits::LhsProgress>=8,typename unpacket_traits<SLhsPacket>::half,SLhsPacket>::type SLhsPacketHalf;
|
||||
typedef typename conditional<SwappedTraits::LhsProgress>=8,typename unpacket_traits<SLhsPacket>::half,SRhsPacket>::type SRhsPacketHalf;
|
||||
typedef typename conditional<SwappedTraits::LhsProgress>=8,typename unpacket_traits<SAccPacket>::half,SAccPacket>::type SAccPacketHalf;
|
||||
|
||||
SResPacketHalf R = res.template gatherPacket<SResPacketHalf>(i, j2);
|
||||
SResPacketHalf alphav = pset1<SResPacketHalf>(alpha);
|
||||
@@ -1598,13 +1596,13 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
||||
SRhsPacketHalf b0;
|
||||
straits.loadLhsUnaligned(blB, a0);
|
||||
straits.loadRhs(blA, b0);
|
||||
SAccPacketHalf c0 = predux4(C0);
|
||||
SAccPacketHalf c0 = predux_downto4(C0);
|
||||
straits.madd(a0,b0,c0,b0);
|
||||
straits.acc(c0, alphav, R);
|
||||
}
|
||||
else
|
||||
{
|
||||
straits.acc(predux4(C0), alphav, R);
|
||||
straits.acc(predux_downto4(C0), alphav, R);
|
||||
}
|
||||
res.scatterPacket(i, j2, R);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_GENERAL_MATRIX_MATRIX_H
|
||||
#define EIGEN_GENERAL_MATRIX_MATRIX_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -24,7 +24,7 @@ template<
|
||||
struct general_matrix_matrix_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,RowMajor>
|
||||
{
|
||||
typedef gebp_traits<RhsScalar,LhsScalar> Traits;
|
||||
|
||||
|
||||
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
||||
static EIGEN_STRONG_INLINE void run(
|
||||
Index rows, Index cols, Index depth,
|
||||
@@ -54,7 +54,7 @@ struct general_matrix_matrix_product<Index,LhsScalar,LhsStorageOrder,ConjugateLh
|
||||
{
|
||||
|
||||
typedef gebp_traits<LhsScalar,RhsScalar> Traits;
|
||||
|
||||
|
||||
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
||||
static void run(Index rows, Index cols, Index depth,
|
||||
const LhsScalar* _lhs, Index lhsStride,
|
||||
@@ -85,13 +85,13 @@ static void run(Index rows, Index cols, Index depth,
|
||||
// this is the parallel version!
|
||||
Index tid = omp_get_thread_num();
|
||||
Index threads = omp_get_num_threads();
|
||||
|
||||
|
||||
LhsScalar* blockA = blocking.blockA();
|
||||
eigen_internal_assert(blockA!=0);
|
||||
|
||||
|
||||
std::size_t sizeB = kc*nc;
|
||||
ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, 0);
|
||||
|
||||
|
||||
// For each horizontal panel of the rhs, and corresponding vertical panel of the lhs...
|
||||
for(Index k=0; k<depth; k+=kc)
|
||||
{
|
||||
@@ -114,7 +114,7 @@ static void run(Index rows, Index cols, Index depth,
|
||||
|
||||
// Notify the other threads that the part A'_i is ready to go.
|
||||
info[tid].sync = k;
|
||||
|
||||
|
||||
// Computes C_i += A' * B' per A'_i
|
||||
for(Index shift=0; shift<threads; ++shift)
|
||||
{
|
||||
@@ -161,7 +161,7 @@ static void run(Index rows, Index cols, Index depth,
|
||||
|
||||
ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, sizeA, blocking.blockA());
|
||||
ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, blocking.blockB());
|
||||
|
||||
|
||||
const bool pack_rhs_once = mc!=rows && kc==depth && nc==cols;
|
||||
|
||||
// For each horizontal panel of the rhs, and corresponding panel of the lhs...
|
||||
@@ -172,24 +172,24 @@ static void run(Index rows, Index cols, Index depth,
|
||||
for(Index k2=0; k2<depth; k2+=kc)
|
||||
{
|
||||
const Index actual_kc = (std::min)(k2+kc,depth)-k2;
|
||||
|
||||
|
||||
// OK, here we have selected one horizontal panel of rhs and one vertical panel of lhs.
|
||||
// => Pack lhs's panel into a sequential chunk of memory (L2/L3 caching)
|
||||
// Note that this panel will be read as many times as the number of blocks in the rhs's
|
||||
// horizontal panel which is, in practice, a very low number.
|
||||
pack_lhs(blockA, lhs.getSubMapper(i2,k2), actual_kc, actual_mc);
|
||||
|
||||
|
||||
// For each kc x nc block of the rhs's horizontal panel...
|
||||
for(Index j2=0; j2<cols; j2+=nc)
|
||||
{
|
||||
const Index actual_nc = (std::min)(j2+nc,cols)-j2;
|
||||
|
||||
|
||||
// We pack the rhs's block into a sequential chunk of memory (L2 caching)
|
||||
// Note that this block will be read a very high number of times, which is equal to the number of
|
||||
// micro horizontal panel of the large rhs's panel (e.g., rows/12 times).
|
||||
if((!pack_rhs_once) || i2==0)
|
||||
pack_rhs(blockB, rhs.getSubMapper(k2,j2), actual_kc, actual_nc);
|
||||
|
||||
|
||||
// Everything is packed, we can now call the panel * block kernel:
|
||||
gebp(res.getSubMapper(i2, j2), blockA, blockB, actual_mc, actual_kc, actual_nc, alpha);
|
||||
}
|
||||
@@ -229,7 +229,7 @@ struct gemm_functor
|
||||
(Scalar*)&(m_dest.coeffRef(row,col)), m_dest.outerStride(),
|
||||
m_actualAlpha, m_blocking, info);
|
||||
}
|
||||
|
||||
|
||||
typedef typename Gemm::Traits Traits;
|
||||
|
||||
protected:
|
||||
@@ -313,7 +313,7 @@ class gemm_blocking_space<StorageOrder,_LhsScalar,_RhsScalar,MaxRows, MaxCols, M
|
||||
this->m_blockB = reinterpret_cast<RhsScalar*>((internal::UIntPtr(m_staticB) + (EIGEN_DEFAULT_ALIGN_BYTES-1)) & ~std::size_t(EIGEN_DEFAULT_ALIGN_BYTES-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void initParallel(Index, Index, Index, Index)
|
||||
{}
|
||||
|
||||
@@ -359,14 +359,14 @@ class gemm_blocking_space<StorageOrder,_LhsScalar,_RhsScalar,MaxRows, MaxCols, M
|
||||
m_sizeA = this->m_mc * this->m_kc;
|
||||
m_sizeB = this->m_kc * this->m_nc;
|
||||
}
|
||||
|
||||
|
||||
void initParallel(Index rows, Index cols, Index depth, Index num_threads)
|
||||
{
|
||||
this->m_mc = Transpose ? cols : rows;
|
||||
this->m_nc = Transpose ? rows : cols;
|
||||
this->m_kc = depth;
|
||||
|
||||
eigen_internal_assert(this->m_blockA==0 && this->m_blockB==0);
|
||||
|
||||
eigen_internal_assert(this->m_blockA==0 && this->m_blockB==0);
|
||||
Index m = this->m_mc;
|
||||
computeProductBlockingSizes<LhsScalar,RhsScalar,KcFactor>(this->m_kc, m, this->m_nc, num_threads);
|
||||
m_sizeA = this->m_mc * this->m_kc;
|
||||
@@ -401,7 +401,7 @@ class gemm_blocking_space<StorageOrder,_LhsScalar,_RhsScalar,MaxRows, MaxCols, M
|
||||
} // end namespace internal
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct>
|
||||
: generic_product_impl_base<Lhs,Rhs,generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct> >
|
||||
@@ -409,21 +409,21 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct>
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
typedef typename Lhs::Scalar LhsScalar;
|
||||
typedef typename Rhs::Scalar RhsScalar;
|
||||
|
||||
|
||||
typedef internal::blas_traits<Lhs> LhsBlasTraits;
|
||||
typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType;
|
||||
typedef typename internal::remove_all<ActualLhsType>::type ActualLhsTypeCleaned;
|
||||
|
||||
|
||||
typedef internal::blas_traits<Rhs> RhsBlasTraits;
|
||||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
||||
typedef typename internal::remove_all<ActualRhsType>::type ActualRhsTypeCleaned;
|
||||
|
||||
|
||||
enum {
|
||||
MaxDepthAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(Lhs::MaxColsAtCompileTime,Rhs::MaxRowsAtCompileTime)
|
||||
};
|
||||
|
||||
|
||||
typedef generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode> lazyproduct;
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
@@ -453,7 +453,7 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct>
|
||||
else
|
||||
scaleAndAddTo(dst, lhs, rhs, Scalar(-1));
|
||||
}
|
||||
|
||||
|
||||
template<typename Dest>
|
||||
static void scaleAndAddTo(Dest& dst, const Lhs& a_lhs, const Rhs& a_rhs, const Scalar& alpha)
|
||||
{
|
||||
@@ -481,7 +481,7 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct>
|
||||
|
||||
BlockingType blocking(dst.rows(), dst.cols(), lhs.cols(), 1, true);
|
||||
internal::parallelize_gemm<(Dest::MaxRowsAtCompileTime>32 || Dest::MaxRowsAtCompileTime==Dynamic)>
|
||||
(GemmFunctor(lhs, rhs, dst, actualAlpha, blocking), a_lhs.rows(), a_rhs.cols(), Dest::Flags&RowMajorBit);
|
||||
(GemmFunctor(lhs, rhs, dst, actualAlpha, blocking), a_lhs.rows(), a_rhs.cols(), a_lhs.cols(), Dest::Flags&RowMajorBit);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -183,8 +183,8 @@ EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,LhsMapper,C
|
||||
alignmentPattern = AllAligned;
|
||||
}
|
||||
|
||||
const Index offset1 = (FirstAligned && alignmentStep==1?3:1);
|
||||
const Index offset3 = (FirstAligned && alignmentStep==1?1:3);
|
||||
const Index offset1 = (FirstAligned && alignmentStep==1)?3:1;
|
||||
const Index offset3 = (FirstAligned && alignmentStep==1)?1:3;
|
||||
|
||||
Index columnBound = ((cols-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
|
||||
for (Index i=skipColumns; i<columnBound; i+=columnsAtOnce)
|
||||
@@ -457,8 +457,8 @@ EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,LhsMapper,R
|
||||
alignmentPattern = AllAligned;
|
||||
}
|
||||
|
||||
const Index offset1 = (FirstAligned && alignmentStep==1?3:1);
|
||||
const Index offset3 = (FirstAligned && alignmentStep==1?1:3);
|
||||
const Index offset1 = (FirstAligned && alignmentStep==1)?3:1;
|
||||
const Index offset3 = (FirstAligned && alignmentStep==1)?1:3;
|
||||
|
||||
Index rowBound = ((rows-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
|
||||
for (Index i=skipRows; i<rowBound; i+=rowsAtOnce)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_PARALLELIZER_H
|
||||
#define EIGEN_PARALLELIZER_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -83,7 +83,7 @@ template<typename Index> struct GemmParallelInfo
|
||||
};
|
||||
|
||||
template<bool Condition, typename Functor, typename Index>
|
||||
void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpose)
|
||||
void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth, bool transpose)
|
||||
{
|
||||
// TODO when EIGEN_USE_BLAS is defined,
|
||||
// we should still enable OMP for other scalar types
|
||||
@@ -92,6 +92,7 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos
|
||||
// the matrix product when multithreading is enabled. This is a temporary
|
||||
// fix to support row-major destination matrices. This whole
|
||||
// parallelizer mechanism has to be redisigned anyway.
|
||||
EIGEN_UNUSED_VARIABLE(depth);
|
||||
EIGEN_UNUSED_VARIABLE(transpose);
|
||||
func(0,rows, 0,cols);
|
||||
#else
|
||||
@@ -106,6 +107,12 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos
|
||||
// FIXME this has to be fine tuned
|
||||
Index size = transpose ? rows : cols;
|
||||
Index pb_max_threads = std::max<Index>(1,size / 32);
|
||||
// compute the maximal number of threads from the total amount of work:
|
||||
double work = static_cast<double>(rows) * static_cast<double>(cols) *
|
||||
static_cast<double>(depth);
|
||||
double kMinTaskSize = 50000; // Heuristic.
|
||||
pb_max_threads = std::max<Index>(1, std::min<Index>(pb_max_threads, work / kMinTaskSize));
|
||||
|
||||
// compute the number of threads we are going to use
|
||||
Index threads = std::min<Index>(nbThreads(), pb_max_threads);
|
||||
|
||||
@@ -120,19 +127,19 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos
|
||||
|
||||
if(transpose)
|
||||
std::swap(rows,cols);
|
||||
|
||||
|
||||
ei_declare_aligned_stack_constructed_variable(GemmParallelInfo<Index>,info,threads,0);
|
||||
|
||||
|
||||
#pragma omp parallel num_threads(threads)
|
||||
{
|
||||
Index i = omp_get_thread_num();
|
||||
// Note that the actual number of threads might be lower than the number of request ones.
|
||||
Index actual_threads = omp_get_num_threads();
|
||||
|
||||
|
||||
Index blockCols = (cols / actual_threads) & ~Index(0x3);
|
||||
Index blockRows = (rows / actual_threads);
|
||||
blockRows = (blockRows/Functor::Traits::mr)*Functor::Traits::mr;
|
||||
|
||||
|
||||
Index r0 = i*blockRows;
|
||||
Index actualBlockRows = (i+1==actual_threads) ? rows-r0 : blockRows;
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ struct selfadjoint_product_impl<Lhs,LhsMode,false,Rhs,0,true>
|
||||
{
|
||||
typedef typename Dest::Scalar ResScalar;
|
||||
typedef typename Rhs::Scalar RhsScalar;
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1>, EIGEN_PLAIN_ENUM_MIN(AlignedMax,internal::packet_traits<ResScalar>::size)> MappedDest;
|
||||
|
||||
eigen_assert(dest.rows()==a_lhs.rows() && dest.cols()==a_rhs.cols());
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ template<int Mode> struct trmv_selector<Mode,ColMajor>
|
||||
typedef internal::blas_traits<Rhs> RhsBlasTraits;
|
||||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
||||
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1>, EIGEN_PLAIN_ENUM_MIN(AlignedMax,internal::packet_traits<ResScalar>::size)> MappedDest;
|
||||
|
||||
typename internal::add_const_on_value_type<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(lhs);
|
||||
typename internal::add_const_on_value_type<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(rhs);
|
||||
|
||||
@@ -44,16 +44,29 @@ template<bool Conjugate> struct conj_if;
|
||||
|
||||
template<> struct conj_if<true> {
|
||||
template<typename T>
|
||||
inline T operator()(const T& x) { return numext::conj(x); }
|
||||
inline T operator()(const T& x) const { return numext::conj(x); }
|
||||
template<typename T>
|
||||
inline T pconj(const T& x) { return internal::pconj(x); }
|
||||
inline T pconj(const T& x) const { return internal::pconj(x); }
|
||||
};
|
||||
|
||||
template<> struct conj_if<false> {
|
||||
template<typename T>
|
||||
inline const T& operator()(const T& x) { return x; }
|
||||
inline const T& operator()(const T& x) const { return x; }
|
||||
template<typename T>
|
||||
inline const T& pconj(const T& x) { return x; }
|
||||
inline const T& pconj(const T& x) const { return x; }
|
||||
};
|
||||
|
||||
// Generic implementation for custom complex types.
|
||||
template<typename LhsScalar, typename RhsScalar, bool ConjLhs, bool ConjRhs>
|
||||
struct conj_helper
|
||||
{
|
||||
typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar>::ReturnType Scalar;
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const LhsScalar& x, const RhsScalar& y, const Scalar& c) const
|
||||
{ return padd(c, pmul(x,y)); }
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const LhsScalar& x, const RhsScalar& y) const
|
||||
{ return conj_if<ConjLhs>()(x) * conj_if<ConjRhs>()(y); }
|
||||
};
|
||||
|
||||
template<typename Scalar> struct conj_helper<Scalar,Scalar,false,false>
|
||||
@@ -315,6 +328,11 @@ struct blas_traits<CwiseBinaryOp<scalar_product_op<Scalar>, NestedXpr, const Cwi
|
||||
static inline Scalar extractScalarFactor(const XprType& x)
|
||||
{ return Base::extractScalarFactor(x.lhs()) * x.rhs().functor().m_other; }
|
||||
};
|
||||
template<typename Scalar, typename Plain1, typename Plain2>
|
||||
struct blas_traits<CwiseBinaryOp<scalar_product_op<Scalar>, const CwiseNullaryOp<scalar_constant_op<Scalar>,Plain1>,
|
||||
const CwiseNullaryOp<scalar_constant_op<Scalar>,Plain2> > >
|
||||
: blas_traits<CwiseNullaryOp<scalar_constant_op<Scalar>,Plain1> >
|
||||
{};
|
||||
|
||||
// pop opposite
|
||||
template<typename Scalar, typename NestedXpr>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Core_util_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Core_util_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/util COMPONENT Devel
|
||||
)
|
||||
@@ -14,12 +14,13 @@
|
||||
// 4512 - assignment operator could not be generated
|
||||
// 4522 - 'class' : multiple assignment operators specified
|
||||
// 4700 - uninitialized local variable 'xyz' used
|
||||
// 4714 - function marked as __forceinline not inlined
|
||||
// 4717 - 'function' : recursive on all control paths, function will cause runtime stack overflow
|
||||
// 4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning)
|
||||
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
||||
#pragma warning( push )
|
||||
#endif
|
||||
#pragma warning( disable : 4100 4101 4127 4181 4211 4244 4273 4324 4503 4512 4522 4700 4717 4800)
|
||||
#pragma warning( disable : 4100 4101 4127 4181 4211 4244 4273 4324 4503 4512 4522 4700 4714 4717 4800)
|
||||
|
||||
#elif defined __INTEL_COMPILER
|
||||
// 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
|
||||
@@ -56,13 +57,19 @@
|
||||
#pragma diag_suppress code_is_unreachable
|
||||
// Disable the "dynamic initialization in unreachable code" message
|
||||
#pragma diag_suppress initialization_not_reachable
|
||||
// Disable the "calling a __host__ function from a __host__ __device__ function is not allowed" messages (yes, there are 4 of them)
|
||||
// Disable the "invalid error number" message that we get with older versions of nvcc
|
||||
#pragma diag_suppress 1222
|
||||
// Disable the "calling a __host__ function from a __host__ __device__ function is not allowed" messages (yes, there are many of them and they seem to change with every version of the compiler)
|
||||
#pragma diag_suppress 2527
|
||||
#pragma diag_suppress 2529
|
||||
#pragma diag_suppress 2651
|
||||
#pragma diag_suppress 2653
|
||||
#pragma diag_suppress 2668
|
||||
#pragma diag_suppress 2669
|
||||
#pragma diag_suppress 2670
|
||||
#pragma diag_suppress 2671
|
||||
#pragma diag_suppress 2735
|
||||
#pragma diag_suppress 2737
|
||||
#endif
|
||||
|
||||
#endif // not EIGEN_WARNINGS_DISABLED
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
#define EIGEN_MAJOR_VERSION 2
|
||||
#define EIGEN_MINOR_VERSION 93
|
||||
#define EIGEN_MINOR_VERSION 95
|
||||
|
||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||
@@ -28,9 +28,9 @@
|
||||
#define EIGEN_COMP_GNUC 0
|
||||
#endif
|
||||
|
||||
/// \internal EIGEN_COMP_CLANG set to 1 if the compiler is clang (alias for __clang__)
|
||||
/// \internal EIGEN_COMP_CLANG set to major+minor version (e.g., 307 for clang 3.7) if the compiler is clang
|
||||
#if defined(__clang__)
|
||||
#define EIGEN_COMP_CLANG 1
|
||||
#define EIGEN_COMP_CLANG (__clang_major__*100+__clang_minor__)
|
||||
#else
|
||||
#define EIGEN_COMP_CLANG 0
|
||||
#endif
|
||||
@@ -356,6 +356,13 @@
|
||||
#define EIGEN_MAX_CPP_VER 99
|
||||
#endif
|
||||
|
||||
#if EIGEN_MAX_CPP_VER>=11 && defined(__cplusplus) && (__cplusplus >= 201103L)
|
||||
#define EIGEN_HAS_CXX11 1
|
||||
#else
|
||||
#define EIGEN_HAS_CXX11 0
|
||||
#endif
|
||||
|
||||
|
||||
// Do we support r-value references?
|
||||
#ifndef EIGEN_HAS_RVALUE_REFERENCES
|
||||
#if EIGEN_MAX_CPP_VER>=11 && \
|
||||
@@ -392,8 +399,8 @@
|
||||
// Does the compiler support variadic templates?
|
||||
#ifndef EIGEN_HAS_VARIADIC_TEMPLATES
|
||||
#if EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) \
|
||||
&& ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 )
|
||||
// ^^ Disable the use of variadic templates when compiling with nvcc on ARM devices:
|
||||
&& ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000) )
|
||||
// ^^ Disable the use of variadic templates when compiling with versions of nvcc older than 8.0 on ARM devices:
|
||||
// this prevents nvcc from crashing when compiling Eigen on Tegra X1
|
||||
#define EIGEN_HAS_VARIADIC_TEMPLATES 1
|
||||
#else
|
||||
@@ -652,6 +659,9 @@ namespace Eigen {
|
||||
// If the user explicitly disable vectorization, then we also disable alignment
|
||||
#if defined(EIGEN_DONT_VECTORIZE)
|
||||
#define EIGEN_IDEAL_MAX_ALIGN_BYTES 0
|
||||
#elif defined(EIGEN_VECTORIZE_AVX512)
|
||||
// 64 bytes static alignmeent is preferred only if really required
|
||||
#define EIGEN_IDEAL_MAX_ALIGN_BYTES 64
|
||||
#elif defined(__AVX__)
|
||||
// 32 bytes static alignmeent is preferred only if really required
|
||||
#define EIGEN_IDEAL_MAX_ALIGN_BYTES 32
|
||||
@@ -801,7 +811,7 @@ namespace Eigen {
|
||||
// just an empty macro !
|
||||
#define EIGEN_EMPTY
|
||||
|
||||
#if EIGEN_COMP_MSVC_STRICT && EIGEN_COMP_MSVC < 1900 // for older MSVC versions using the base operator is sufficient (cf Bug 1000)
|
||||
#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || __CUDACC_VER__) // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324)
|
||||
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
||||
using Base::operator =;
|
||||
#elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
||||
@@ -954,8 +964,8 @@ namespace Eigen {
|
||||
# define EIGEN_CATCH(X) catch (X)
|
||||
#else
|
||||
# ifdef __CUDA_ARCH__
|
||||
# define EIGEN_THROW_X(X) asm("trap;") return {}
|
||||
# define EIGEN_THROW asm("trap;"); return {}
|
||||
# define EIGEN_THROW_X(X) asm("trap;")
|
||||
# define EIGEN_THROW asm("trap;")
|
||||
# else
|
||||
# define EIGEN_THROW_X(X) std::abort()
|
||||
# define EIGEN_THROW std::abort()
|
||||
|
||||
@@ -275,6 +275,7 @@ template<typename T> EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *
|
||||
destruct_elements_of_array(ptr, i);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -305,6 +306,7 @@ template<typename T> EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size)
|
||||
aligned_free(result);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(size_t size)
|
||||
@@ -320,6 +322,7 @@ template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned
|
||||
conditional_aligned_free<Align>(result);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \internal Deletes objects constructed with aligned_new
|
||||
|
||||
@@ -22,6 +22,16 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
|
||||
|
||||
/**
|
||||
* \brief The Index type as used for the API.
|
||||
* \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
|
||||
* \sa \blank \ref TopicPreprocessorDirectives, StorageIndex.
|
||||
*/
|
||||
|
||||
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal
|
||||
@@ -358,17 +368,46 @@ struct result_of<Func(ArgType0,ArgType1,ArgType2)> {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct meta_yes { char a[1]; };
|
||||
struct meta_no { char a[2]; };
|
||||
|
||||
// Check whether T::ReturnType does exist
|
||||
template <typename T>
|
||||
struct has_ReturnType
|
||||
{
|
||||
typedef char yes[1];
|
||||
typedef char no[2];
|
||||
template <typename C> static meta_yes testFunctor(typename C::ReturnType const *);
|
||||
template <typename C> static meta_no testFunctor(...);
|
||||
|
||||
template <typename C> static yes& testFunctor(C const *, typename C::ReturnType const * = 0);
|
||||
static no& testFunctor(...);
|
||||
enum { value = sizeof(testFunctor<T>(0)) == sizeof(meta_yes) };
|
||||
};
|
||||
|
||||
static const bool value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(yes);
|
||||
template<typename T> const T& return_ref();
|
||||
|
||||
template <typename T, typename IndexType=Index>
|
||||
struct has_nullary_operator
|
||||
{
|
||||
template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()())>0)>::type * = 0);
|
||||
static meta_no testFunctor(...);
|
||||
|
||||
enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
|
||||
};
|
||||
|
||||
template <typename T, typename IndexType=Index>
|
||||
struct has_unary_operator
|
||||
{
|
||||
template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()(IndexType(0)))>0)>::type * = 0);
|
||||
static meta_no testFunctor(...);
|
||||
|
||||
enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
|
||||
};
|
||||
|
||||
template <typename T, typename IndexType=Index>
|
||||
struct has_binary_operator
|
||||
{
|
||||
template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()(IndexType(0),IndexType(0)))>0)>::type * = 0);
|
||||
static meta_no testFunctor(...);
|
||||
|
||||
enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
|
||||
};
|
||||
|
||||
/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#if defined __NVCC__
|
||||
// Don't reenable the diagnostic messages, as it turns out these messages need
|
||||
// to be disabled at the point of the template instantiation (i.e the user code)
|
||||
// otherwise they'll be triggeredby nvcc.
|
||||
// otherwise they'll be triggered by nvcc.
|
||||
// #pragma diag_default code_is_unreachable
|
||||
// #pragma diag_default initialization_not_reachable
|
||||
// #pragma diag_default 2651
|
||||
|
||||
@@ -100,7 +100,8 @@
|
||||
MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY,
|
||||
THIS_TYPE_IS_NOT_SUPPORTED,
|
||||
STORAGE_KIND_MUST_MATCH,
|
||||
STORAGE_INDEX_MUST_MATCH
|
||||
STORAGE_INDEX_MUST_MATCH,
|
||||
CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -24,16 +24,6 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
|
||||
|
||||
/**
|
||||
* \brief The Index type as used for the API.
|
||||
* \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
|
||||
* \sa \blank \ref TopicPreprocessorDirectives, StorageIndex.
|
||||
*/
|
||||
|
||||
typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename IndexDest, typename IndexSrc>
|
||||
@@ -201,7 +191,7 @@ struct find_best_packet
|
||||
#if EIGEN_MAX_STATIC_ALIGN_BYTES>0
|
||||
template<int ArrayBytes, int AlignmentBytes,
|
||||
bool Match = bool((ArrayBytes%AlignmentBytes)==0),
|
||||
bool TryHalf = bool(AlignmentBytes>EIGEN_MIN_ALIGN_BYTES) >
|
||||
bool TryHalf = bool(EIGEN_MIN_ALIGN_BYTES<AlignmentBytes) >
|
||||
struct compute_default_alignment_helper
|
||||
{
|
||||
enum { value = 0 };
|
||||
@@ -674,6 +664,28 @@ bool is_same_dense(const T1 &, const T2 &, typename enable_if<!(has_direct_acces
|
||||
return false;
|
||||
}
|
||||
|
||||
// Internal helper defining the cost of a scalar division for the type T.
|
||||
// The default heuristic can be specialized for each scalar type and architecture.
|
||||
template<typename T,bool Vectorized=false,typename EnaleIf = void>
|
||||
struct scalar_div_cost {
|
||||
enum { value = 8*NumTraits<T>::MulCost };
|
||||
};
|
||||
|
||||
template<typename T,bool Vectorized>
|
||||
struct scalar_div_cost<std::complex<T>, Vectorized> {
|
||||
enum { value = 2*scalar_div_cost<T>::value
|
||||
+ 6*NumTraits<T>::MulCost
|
||||
+ 3*NumTraits<T>::AddCost
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<bool Vectorized>
|
||||
struct scalar_div_cost<signed long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 24 }; };
|
||||
template<bool Vectorized>
|
||||
struct scalar_div_cost<unsigned long,Vectorized,typename conditional<sizeof(long)==8,void,false_type>::type> { enum { value = 21 }; };
|
||||
|
||||
|
||||
#ifdef EIGEN_DEBUG_ASSIGN
|
||||
std::string demangle_traversal(int t)
|
||||
{
|
||||
@@ -717,7 +729,7 @@ std::string demangle_flags(int f)
|
||||
* This class permits to control the scalar return type of any binary operation performed on two different scalar types through (partial) template specializations.
|
||||
*
|
||||
* For instance, let \c U1, \c U2 and \c U3 be three user defined scalar types for which most operations between instances of \c U1 and \c U2 returns an \c U3.
|
||||
* You can let Eigen knows that by defining:
|
||||
* You can let %Eigen knows that by defining:
|
||||
\code
|
||||
template<typename BinaryOp>
|
||||
struct ScalarBinaryOpTraits<U1,U2,BinaryOp> { typedef U3 ReturnType; };
|
||||
@@ -735,6 +747,14 @@ std::string demangle_flags(int f)
|
||||
struct ScalarBinaryOpTraits<U1,U2,internal::scalar_sum_op<U1,U2> > { typedef U1 ReturnType; };
|
||||
\endcode
|
||||
*
|
||||
* By default, the following generic combinations are supported:
|
||||
<table class="manual">
|
||||
<tr><th>ScalarA</th><th>ScalarB</th><th>BinaryOp</th><th>ReturnType</th><th>Note</th></tr>
|
||||
<tr ><td>\c T </td><td>\c T </td><td>\c * </td><td>\c T </td><td></td></tr>
|
||||
<tr class="alt"><td>\c NumTraits<T>::Real </td><td>\c T </td><td>\c * </td><td>\c T </td><td>Only if \c NumTraits<T>::IsComplex </td></tr>
|
||||
<tr ><td>\c T </td><td>\c NumTraits<T>::Real </td><td>\c * </td><td>\c T </td><td>Only if \c NumTraits<T>::IsComplex </td></tr>
|
||||
</table>
|
||||
*
|
||||
* \sa CwiseBinaryOp
|
||||
*/
|
||||
template<typename ScalarA, typename ScalarB, typename BinaryOp=internal::scalar_product_op<ScalarA,ScalarB> >
|
||||
@@ -751,6 +771,17 @@ struct ScalarBinaryOpTraits<T,T,BinaryOp>
|
||||
typedef T ReturnType;
|
||||
};
|
||||
|
||||
template <typename T, typename BinaryOp>
|
||||
struct ScalarBinaryOpTraits<T, typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, BinaryOp>
|
||||
{
|
||||
typedef T ReturnType;
|
||||
};
|
||||
template <typename T, typename BinaryOp>
|
||||
struct ScalarBinaryOpTraits<typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, T, BinaryOp>
|
||||
{
|
||||
typedef T ReturnType;
|
||||
};
|
||||
|
||||
// For Matrix * Permutation
|
||||
template<typename T, typename BinaryOp>
|
||||
struct ScalarBinaryOpTraits<T,void,BinaryOp>
|
||||
@@ -772,18 +803,6 @@ struct ScalarBinaryOpTraits<void,void,BinaryOp>
|
||||
typedef void ReturnType;
|
||||
};
|
||||
|
||||
template<typename T, typename BinaryOp>
|
||||
struct ScalarBinaryOpTraits<T,std::complex<T>,BinaryOp>
|
||||
{
|
||||
typedef std::complex<T> ReturnType;
|
||||
};
|
||||
|
||||
template<typename T, typename BinaryOp>
|
||||
struct ScalarBinaryOpTraits<std::complex<T>, T,BinaryOp>
|
||||
{
|
||||
typedef std::complex<T> ReturnType;
|
||||
};
|
||||
|
||||
// We require Lhs and Rhs to have "compatible" scalar types.
|
||||
// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
|
||||
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_EIGENVALUES_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_EIGENVALUES_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Eigenvalues COMPONENT Devel
|
||||
)
|
||||
@@ -1,8 +1,9 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2012-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
|
||||
// Copyright (C) 2016 Tobias Wood <tobias@spinicist.org.uk>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
@@ -89,7 +90,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
*/
|
||||
typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> VectorType;
|
||||
|
||||
/** \brief Type for vector of complex scalar values eigenvalues as returned by betas().
|
||||
/** \brief Type for vector of complex scalar values eigenvalues as returned by alphas().
|
||||
*
|
||||
* This is a column vector with entries of type #ComplexScalar.
|
||||
* The length of the vector is the size of #MatrixType.
|
||||
@@ -114,7 +115,14 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
*
|
||||
* \sa compute() for an example.
|
||||
*/
|
||||
GeneralizedEigenSolver() : m_eivec(), m_alphas(), m_betas(), m_isInitialized(false), m_realQZ(), m_matS(), m_tmp() {}
|
||||
GeneralizedEigenSolver()
|
||||
: m_eivec(),
|
||||
m_alphas(),
|
||||
m_betas(),
|
||||
m_valuesOkay(false),
|
||||
m_vectorsOkay(false),
|
||||
m_realQZ()
|
||||
{}
|
||||
|
||||
/** \brief Default constructor with memory preallocation
|
||||
*
|
||||
@@ -126,10 +134,9 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
: m_eivec(size, size),
|
||||
m_alphas(size),
|
||||
m_betas(size),
|
||||
m_isInitialized(false),
|
||||
m_eigenvectorsOk(false),
|
||||
m_valuesOkay(false),
|
||||
m_vectorsOkay(false),
|
||||
m_realQZ(size),
|
||||
m_matS(size, size),
|
||||
m_tmp(size)
|
||||
{}
|
||||
|
||||
@@ -149,10 +156,9 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
: m_eivec(A.rows(), A.cols()),
|
||||
m_alphas(A.cols()),
|
||||
m_betas(A.cols()),
|
||||
m_isInitialized(false),
|
||||
m_eigenvectorsOk(false),
|
||||
m_valuesOkay(false),
|
||||
m_vectorsOkay(false),
|
||||
m_realQZ(A.cols()),
|
||||
m_matS(A.rows(), A.cols()),
|
||||
m_tmp(A.cols())
|
||||
{
|
||||
compute(A, B, computeEigenvectors);
|
||||
@@ -160,22 +166,20 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
|
||||
/* \brief Returns the computed generalized eigenvectors.
|
||||
*
|
||||
* \returns %Matrix whose columns are the (possibly complex) eigenvectors.
|
||||
* \returns %Matrix whose columns are the (possibly complex) right eigenvectors.
|
||||
* i.e. the eigenvectors that solve (A - l*B)x = 0. The ordering matches the eigenvalues.
|
||||
*
|
||||
* \pre Either the constructor
|
||||
* GeneralizedEigenSolver(const MatrixType&,const MatrixType&, bool) or the member function
|
||||
* compute(const MatrixType&, const MatrixType& bool) has been called before, and
|
||||
* \p computeEigenvectors was set to true (the default).
|
||||
*
|
||||
* Column \f$ k \f$ of the returned matrix is an eigenvector corresponding
|
||||
* to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The
|
||||
* eigenvectors are normalized to have (Euclidean) norm equal to one. The
|
||||
* matrix returned by this function is the matrix \f$ V \f$ in the
|
||||
* generalized eigendecomposition \f$ A = B V D V^{-1} \f$, if it exists.
|
||||
*
|
||||
* \sa eigenvalues()
|
||||
*/
|
||||
// EigenvectorsType eigenvectors() const;
|
||||
EigenvectorsType eigenvectors() const {
|
||||
eigen_assert(m_vectorsOkay && "Eigenvectors for GeneralizedEigenSolver were not calculated.");
|
||||
return m_eivec;
|
||||
}
|
||||
|
||||
/** \brief Returns an expression of the computed generalized eigenvalues.
|
||||
*
|
||||
@@ -197,7 +201,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
*/
|
||||
EigenvalueType eigenvalues() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
|
||||
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||
return EigenvalueType(m_alphas,m_betas);
|
||||
}
|
||||
|
||||
@@ -208,7 +212,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
* \sa betas(), eigenvalues() */
|
||||
ComplexVectorType alphas() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
|
||||
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||
return m_alphas;
|
||||
}
|
||||
|
||||
@@ -219,7 +223,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
* \sa alphas(), eigenvalues() */
|
||||
VectorType betas() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
|
||||
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||
return m_betas;
|
||||
}
|
||||
|
||||
@@ -250,7 +254,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
|
||||
ComputationInfo info() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
|
||||
eigen_assert(m_valuesOkay && "EigenSolver is not initialized.");
|
||||
return m_realQZ.info();
|
||||
}
|
||||
|
||||
@@ -270,29 +274,14 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
|
||||
}
|
||||
|
||||
MatrixType m_eivec;
|
||||
EigenvectorsType m_eivec;
|
||||
ComplexVectorType m_alphas;
|
||||
VectorType m_betas;
|
||||
bool m_isInitialized;
|
||||
bool m_eigenvectorsOk;
|
||||
bool m_valuesOkay, m_vectorsOkay;
|
||||
RealQZ<MatrixType> m_realQZ;
|
||||
MatrixType m_matS;
|
||||
|
||||
typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ColumnVectorType;
|
||||
ColumnVectorType m_tmp;
|
||||
ComplexVectorType m_tmp;
|
||||
};
|
||||
|
||||
//template<typename MatrixType>
|
||||
//typename GeneralizedEigenSolver<MatrixType>::EigenvectorsType GeneralizedEigenSolver<MatrixType>::eigenvectors() const
|
||||
//{
|
||||
// eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
|
||||
// eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
|
||||
// Index n = m_eivec.cols();
|
||||
// EigenvectorsType matV(n,n);
|
||||
// // TODO
|
||||
// return matV;
|
||||
//}
|
||||
|
||||
template<typename MatrixType>
|
||||
GeneralizedEigenSolver<MatrixType>&
|
||||
GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
|
||||
@@ -302,28 +291,70 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
|
||||
using std::sqrt;
|
||||
using std::abs;
|
||||
eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
|
||||
|
||||
Index size = A.cols();
|
||||
m_valuesOkay = false;
|
||||
m_vectorsOkay = false;
|
||||
// Reduce to generalized real Schur form:
|
||||
// A = Q S Z and B = Q T Z
|
||||
m_realQZ.compute(A, B, computeEigenvectors);
|
||||
|
||||
if (m_realQZ.info() == Success)
|
||||
{
|
||||
m_matS = m_realQZ.matrixS();
|
||||
const MatrixType &matT = m_realQZ.matrixT();
|
||||
// Resize storage
|
||||
m_alphas.resize(size);
|
||||
m_betas.resize(size);
|
||||
if (computeEigenvectors)
|
||||
m_eivec = m_realQZ.matrixZ().transpose();
|
||||
|
||||
// Compute eigenvalues from matS
|
||||
m_alphas.resize(A.cols());
|
||||
m_betas.resize(A.cols());
|
||||
Index i = 0;
|
||||
while (i < A.cols())
|
||||
{
|
||||
if (i == A.cols() - 1 || m_matS.coeff(i+1, i) == Scalar(0))
|
||||
m_eivec.resize(size,size);
|
||||
m_tmp.resize(size);
|
||||
}
|
||||
|
||||
// Aliases:
|
||||
Map<VectorType> v(reinterpret_cast<Scalar*>(m_tmp.data()), size);
|
||||
ComplexVectorType &cv = m_tmp;
|
||||
const MatrixType &mZ = m_realQZ.matrixZ();
|
||||
const MatrixType &mS = m_realQZ.matrixS();
|
||||
const MatrixType &mT = m_realQZ.matrixT();
|
||||
|
||||
Index i = 0;
|
||||
while (i < size)
|
||||
{
|
||||
if (i == size - 1 || mS.coeff(i+1, i) == Scalar(0))
|
||||
{
|
||||
m_alphas.coeffRef(i) = m_matS.coeff(i, i);
|
||||
m_betas.coeffRef(i) = matT.coeff(i,i);
|
||||
// Real eigenvalue
|
||||
m_alphas.coeffRef(i) = mS.diagonal().coeff(i);
|
||||
m_betas.coeffRef(i) = mT.diagonal().coeff(i);
|
||||
if (computeEigenvectors)
|
||||
{
|
||||
v.setConstant(Scalar(0.0));
|
||||
v.coeffRef(i) = Scalar(1.0);
|
||||
// For singular eigenvalues do nothing more
|
||||
if(abs(m_betas.coeffRef(i)) >= (std::numeric_limits<RealScalar>::min)())
|
||||
{
|
||||
// Non-singular eigenvalue
|
||||
const Scalar alpha = real(m_alphas.coeffRef(i));
|
||||
const Scalar beta = m_betas.coeffRef(i);
|
||||
for (Index j = i-1; j >= 0; j--)
|
||||
{
|
||||
const Index st = j+1;
|
||||
const Index sz = i-j;
|
||||
if (j > 0 && mS.coeff(j, j-1) != Scalar(0))
|
||||
{
|
||||
// 2x2 block
|
||||
Matrix<Scalar, 2, 1> rhs = (alpha*mT.template block<2,Dynamic>(j-1,st,2,sz) - beta*mS.template block<2,Dynamic>(j-1,st,2,sz)) .lazyProduct( v.segment(st,sz) );
|
||||
Matrix<Scalar, 2, 2> lhs = beta * mS.template block<2,2>(j-1,j-1) - alpha * mT.template block<2,2>(j-1,j-1);
|
||||
v.template segment<2>(j-1) = lhs.partialPivLu().solve(rhs);
|
||||
j--;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.coeffRef(j) = -v.segment(st,sz).transpose().cwiseProduct(beta*mS.block(j,st,1,sz) - alpha*mT.block(j,st,1,sz)).sum() / (beta*mS.coeffRef(j,j) - alpha*mT.coeffRef(j,j));
|
||||
}
|
||||
}
|
||||
}
|
||||
m_eivec.col(i).real().noalias() = mZ.transpose() * v;
|
||||
m_eivec.col(i).real().normalize();
|
||||
m_eivec.col(i).imag().setConstant(0);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else
|
||||
@@ -333,27 +364,53 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
|
||||
|
||||
// T = [a 0]
|
||||
// [0 b]
|
||||
RealScalar a = matT.diagonal().coeff(i),
|
||||
b = matT.diagonal().coeff(i+1);
|
||||
RealScalar a = mT.diagonal().coeff(i),
|
||||
b = mT.diagonal().coeff(i+1);
|
||||
const RealScalar beta = m_betas.coeffRef(i) = m_betas.coeffRef(i+1) = a*b;
|
||||
|
||||
// ^^ NOTE: using diagonal()(i) instead of coeff(i,i) workarounds a MSVC bug.
|
||||
Matrix<RealScalar,2,2> S2 = m_matS.template block<2,2>(i,i) * Matrix<Scalar,2,1>(b,a).asDiagonal();
|
||||
Matrix<RealScalar,2,2> S2 = mS.template block<2,2>(i,i) * Matrix<Scalar,2,1>(b,a).asDiagonal();
|
||||
|
||||
Scalar p = Scalar(0.5) * (S2.coeff(0,0) - S2.coeff(1,1));
|
||||
Scalar z = sqrt(abs(p * p + S2.coeff(1,0) * S2.coeff(0,1)));
|
||||
m_alphas.coeffRef(i) = ComplexScalar(S2.coeff(1,1) + p, z);
|
||||
m_alphas.coeffRef(i+1) = ComplexScalar(S2.coeff(1,1) + p, -z);
|
||||
const ComplexScalar alpha = ComplexScalar(S2.coeff(1,1) + p, (beta > 0) ? z : -z);
|
||||
m_alphas.coeffRef(i) = conj(alpha);
|
||||
m_alphas.coeffRef(i+1) = alpha;
|
||||
|
||||
m_betas.coeffRef(i) =
|
||||
m_betas.coeffRef(i+1) = a*b;
|
||||
|
||||
if (computeEigenvectors) {
|
||||
// Compute eigenvector in position (i+1) and then position (i) is just the conjugate
|
||||
cv.setZero();
|
||||
cv.coeffRef(i+1) = Scalar(1.0);
|
||||
// here, the "static_cast" workaound expression template issues.
|
||||
cv.coeffRef(i) = -(static_cast<Scalar>(beta*mS.coeffRef(i,i+1)) - alpha*mT.coeffRef(i,i+1))
|
||||
/ (static_cast<Scalar>(beta*mS.coeffRef(i,i)) - alpha*mT.coeffRef(i,i));
|
||||
for (Index j = i-1; j >= 0; j--)
|
||||
{
|
||||
const Index st = j+1;
|
||||
const Index sz = i+1-j;
|
||||
if (j > 0 && mS.coeff(j, j-1) != Scalar(0))
|
||||
{
|
||||
// 2x2 block
|
||||
Matrix<ComplexScalar, 2, 1> rhs = (alpha*mT.template block<2,Dynamic>(j-1,st,2,sz) - beta*mS.template block<2,Dynamic>(j-1,st,2,sz)) .lazyProduct( cv.segment(st,sz) );
|
||||
Matrix<ComplexScalar, 2, 2> lhs = beta * mS.template block<2,2>(j-1,j-1) - alpha * mT.template block<2,2>(j-1,j-1);
|
||||
cv.template segment<2>(j-1) = lhs.partialPivLu().solve(rhs);
|
||||
j--;
|
||||
} else {
|
||||
cv.coeffRef(j) = cv.segment(st,sz).transpose().cwiseProduct(beta*mS.block(j,st,1,sz) - alpha*mT.block(j,st,1,sz)).sum()
|
||||
/ (alpha*mT.coeffRef(j,j) - static_cast<Scalar>(beta*mS.coeffRef(j,j)));
|
||||
}
|
||||
}
|
||||
m_eivec.col(i+1).noalias() = (mZ.transpose() * cv);
|
||||
m_eivec.col(i+1).normalize();
|
||||
m_eivec.col(i) = m_eivec.col(i+1).conjugate();
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
m_valuesOkay = true;
|
||||
m_vectorsOkay = computeEigenvectors;
|
||||
}
|
||||
|
||||
m_isInitialized = true;
|
||||
m_eigenvectorsOk = false;//computeEigenvectors;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ template<typename _MatrixType> class RealSchur
|
||||
typedef Matrix<Scalar,3,1> Vector3s;
|
||||
|
||||
Scalar computeNormOfT();
|
||||
Index findSmallSubdiagEntry(Index iu, const Scalar& maxDiagEntry);
|
||||
Index findSmallSubdiagEntry(Index iu);
|
||||
void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift);
|
||||
void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo);
|
||||
void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector);
|
||||
@@ -293,18 +293,14 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMa
|
||||
|
||||
if(norm!=0)
|
||||
{
|
||||
Scalar maxDiagEntry = m_matT.cwiseAbs().diagonal().maxCoeff();
|
||||
|
||||
while (iu >= 0)
|
||||
{
|
||||
Index il = findSmallSubdiagEntry(iu,maxDiagEntry);
|
||||
Index il = findSmallSubdiagEntry(iu);
|
||||
|
||||
// Check for convergence
|
||||
if (il == iu) // One root found
|
||||
{
|
||||
m_matT.coeffRef(iu,iu) = m_matT.coeff(iu,iu) + exshift;
|
||||
// keep track of the largest diagonal coefficient
|
||||
maxDiagEntry = numext::maxi<Scalar>(maxDiagEntry,abs(m_matT.coeffRef(iu,iu)));
|
||||
if (iu > 0)
|
||||
m_matT.coeffRef(iu, iu-1) = Scalar(0);
|
||||
iu--;
|
||||
@@ -313,8 +309,6 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMa
|
||||
else if (il == iu-1) // Two roots found
|
||||
{
|
||||
splitOffTwoRows(iu, computeU, exshift);
|
||||
// keep track of the largest diagonal coefficient
|
||||
maxDiagEntry = numext::maxi<Scalar>(maxDiagEntry,numext::maxi(abs(m_matT.coeff(iu,iu)), abs(m_matT.coeff(iu-1,iu-1))));
|
||||
iu -= 2;
|
||||
iter = 0;
|
||||
}
|
||||
@@ -329,8 +323,6 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMa
|
||||
Index im;
|
||||
initFrancisQRStep(il, iu, shiftInfo, im, firstHouseholderVector);
|
||||
performFrancisQRStep(il, im, iu, computeU, firstHouseholderVector, workspace);
|
||||
// keep track of the largest diagonal coefficient
|
||||
maxDiagEntry = numext::maxi(maxDiagEntry,m_matT.cwiseAbs().diagonal().segment(im,iu-im).maxCoeff());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,13 +352,14 @@ inline typename MatrixType::Scalar RealSchur<MatrixType>::computeNormOfT()
|
||||
|
||||
/** \internal Look for single small sub-diagonal element and returns its index */
|
||||
template<typename MatrixType>
|
||||
inline Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu, const Scalar& maxDiagEntry)
|
||||
inline Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu)
|
||||
{
|
||||
using std::abs;
|
||||
Index res = iu;
|
||||
while (res > 0)
|
||||
{
|
||||
if (abs(m_matT.coeff(res,res-1)) <= NumTraits<Scalar>::epsilon() * maxDiagEntry)
|
||||
Scalar s = abs(m_matT.coeff(res-1,res-1)) + abs(m_matT.coeff(res,res));
|
||||
if (abs(m_matT.coeff(res,res-1)) <= NumTraits<Scalar>::epsilon() * s)
|
||||
break;
|
||||
res--;
|
||||
}
|
||||
|
||||
@@ -501,7 +501,7 @@ ComputationInfo computeFromTridiagonal_impl(DiagType& diag, SubDiagType& subdiag
|
||||
subdiag[i] = 0;
|
||||
|
||||
// find the largest unreduced block
|
||||
while (end>0 && subdiag[end-1]==0)
|
||||
while (end>0 && subdiag[end-1]==RealScalar(0))
|
||||
{
|
||||
end--;
|
||||
}
|
||||
@@ -569,8 +569,8 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
|
||||
EIGEN_USING_STD_MATH(atan2)
|
||||
EIGEN_USING_STD_MATH(cos)
|
||||
EIGEN_USING_STD_MATH(sin)
|
||||
const Scalar s_inv3 = Scalar(1.0)/Scalar(3.0);
|
||||
const Scalar s_sqrt3 = sqrt(Scalar(3.0));
|
||||
const Scalar s_inv3 = Scalar(1)/Scalar(3);
|
||||
const Scalar s_sqrt3 = sqrt(Scalar(3));
|
||||
|
||||
// The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The
|
||||
// eigenvalues are the roots to this equation, all guaranteed to be
|
||||
@@ -815,14 +815,14 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta
|
||||
// RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2));
|
||||
// This explain the following, somewhat more complicated, version:
|
||||
RealScalar mu = diag[end];
|
||||
if(td==0)
|
||||
if(td==RealScalar(0))
|
||||
mu -= abs(e);
|
||||
else
|
||||
{
|
||||
RealScalar e2 = numext::abs2(subdiag[end-1]);
|
||||
RealScalar h = numext::hypot(td,e);
|
||||
if(e2==0) mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h);
|
||||
else mu -= e2 / (td + (td>0 ? h : -h));
|
||||
if(e2==RealScalar(0)) mu -= (e / (td + (td>RealScalar(0) ? RealScalar(1) : RealScalar(-1)))) * (e / h);
|
||||
else mu -= e2 / (td + (td>RealScalar(0) ? h : -h));
|
||||
}
|
||||
|
||||
RealScalar x = diag[start] - mu;
|
||||
|
||||
@@ -62,57 +62,57 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
|
||||
|
||||
/** Default constructor initializing a null box. */
|
||||
inline AlignedBox()
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox()
|
||||
{ if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
|
||||
|
||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||
inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim)
|
||||
EIGEN_DEVICE_FUNC inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim)
|
||||
{ setEmpty(); }
|
||||
|
||||
/** Constructs a box with extremities \a _min and \a _max.
|
||||
* \warning If either component of \a _min is larger than the same component of \a _max, the constructed box is empty. */
|
||||
template<typename OtherVectorType1, typename OtherVectorType2>
|
||||
inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {}
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {}
|
||||
|
||||
/** Constructs a box containing a single point \a p. */
|
||||
template<typename Derived>
|
||||
inline explicit AlignedBox(const MatrixBase<Derived>& p) : m_min(p), m_max(m_min)
|
||||
EIGEN_DEVICE_FUNC inline explicit AlignedBox(const MatrixBase<Derived>& p) : m_min(p), m_max(m_min)
|
||||
{ }
|
||||
|
||||
~AlignedBox() {}
|
||||
EIGEN_DEVICE_FUNC ~AlignedBox() {}
|
||||
|
||||
/** \returns the dimension in which the box holds */
|
||||
inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); }
|
||||
EIGEN_DEVICE_FUNC inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); }
|
||||
|
||||
/** \deprecated use isEmpty() */
|
||||
inline bool isNull() const { return isEmpty(); }
|
||||
EIGEN_DEVICE_FUNC inline bool isNull() const { return isEmpty(); }
|
||||
|
||||
/** \deprecated use setEmpty() */
|
||||
inline void setNull() { setEmpty(); }
|
||||
EIGEN_DEVICE_FUNC inline void setNull() { setEmpty(); }
|
||||
|
||||
/** \returns true if the box is empty.
|
||||
* \sa setEmpty */
|
||||
inline bool isEmpty() const { return (m_min.array() > m_max.array()).any(); }
|
||||
EIGEN_DEVICE_FUNC inline bool isEmpty() const { return (m_min.array() > m_max.array()).any(); }
|
||||
|
||||
/** Makes \c *this an empty box.
|
||||
* \sa isEmpty */
|
||||
inline void setEmpty()
|
||||
EIGEN_DEVICE_FUNC inline void setEmpty()
|
||||
{
|
||||
m_min.setConstant( ScalarTraits::highest() );
|
||||
m_max.setConstant( ScalarTraits::lowest() );
|
||||
}
|
||||
|
||||
/** \returns the minimal corner */
|
||||
inline const VectorType& (min)() const { return m_min; }
|
||||
EIGEN_DEVICE_FUNC inline const VectorType& (min)() const { return m_min; }
|
||||
/** \returns a non const reference to the minimal corner */
|
||||
inline VectorType& (min)() { return m_min; }
|
||||
EIGEN_DEVICE_FUNC inline VectorType& (min)() { return m_min; }
|
||||
/** \returns the maximal corner */
|
||||
inline const VectorType& (max)() const { return m_max; }
|
||||
EIGEN_DEVICE_FUNC inline const VectorType& (max)() const { return m_max; }
|
||||
/** \returns a non const reference to the maximal corner */
|
||||
inline VectorType& (max)() { return m_max; }
|
||||
EIGEN_DEVICE_FUNC inline VectorType& (max)() { return m_max; }
|
||||
|
||||
/** \returns the center of the box */
|
||||
inline const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(VectorTypeSum, RealScalar, quotient)
|
||||
EIGEN_DEVICE_FUNC inline const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(VectorTypeSum, RealScalar, quotient)
|
||||
center() const
|
||||
{ return (m_min+m_max)/RealScalar(2); }
|
||||
|
||||
@@ -120,18 +120,18 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
* Note that this function does not get the same
|
||||
* result for integral or floating scalar types: see
|
||||
*/
|
||||
inline const CwiseBinaryOp< internal::scalar_difference_op<Scalar,Scalar>, const VectorType, const VectorType> sizes() const
|
||||
EIGEN_DEVICE_FUNC inline const CwiseBinaryOp< internal::scalar_difference_op<Scalar,Scalar>, const VectorType, const VectorType> sizes() const
|
||||
{ return m_max - m_min; }
|
||||
|
||||
/** \returns the volume of the bounding box */
|
||||
inline Scalar volume() const
|
||||
EIGEN_DEVICE_FUNC inline Scalar volume() const
|
||||
{ return sizes().prod(); }
|
||||
|
||||
/** \returns an expression for the bounding box diagonal vector
|
||||
* if the length of the diagonal is needed: diagonal().norm()
|
||||
* will provide it.
|
||||
*/
|
||||
inline CwiseBinaryOp< internal::scalar_difference_op<Scalar,Scalar>, const VectorType, const VectorType> diagonal() const
|
||||
EIGEN_DEVICE_FUNC inline CwiseBinaryOp< internal::scalar_difference_op<Scalar,Scalar>, const VectorType, const VectorType> diagonal() const
|
||||
{ return sizes(); }
|
||||
|
||||
/** \returns the vertex of the bounding box at the corner defined by
|
||||
@@ -143,7 +143,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
* For 3D bounding boxes, the following names are added:
|
||||
* BottomLeftCeil, BottomRightCeil, TopLeftCeil, TopRightCeil.
|
||||
*/
|
||||
inline VectorType corner(CornerType corner) const
|
||||
EIGEN_DEVICE_FUNC inline VectorType corner(CornerType corner) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(_AmbientDim <= 3, THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE);
|
||||
|
||||
@@ -161,7 +161,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
|
||||
/** \returns a random point inside the bounding box sampled with
|
||||
* a uniform distribution */
|
||||
inline VectorType sample() const
|
||||
EIGEN_DEVICE_FUNC inline VectorType sample() const
|
||||
{
|
||||
VectorType r(dim());
|
||||
for(Index d=0; d<dim(); ++d)
|
||||
@@ -179,25 +179,25 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
|
||||
/** \returns true if the point \a p is inside the box \c *this. */
|
||||
template<typename Derived>
|
||||
inline bool contains(const MatrixBase<Derived>& p) const
|
||||
EIGEN_DEVICE_FUNC inline bool contains(const MatrixBase<Derived>& p) const
|
||||
{
|
||||
typename internal::nested_eval<Derived,2>::type p_n(p.derived());
|
||||
return (m_min.array()<=p_n.array()).all() && (p_n.array()<=m_max.array()).all();
|
||||
}
|
||||
|
||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||
inline bool contains(const AlignedBox& b) const
|
||||
EIGEN_DEVICE_FUNC inline bool contains(const AlignedBox& b) const
|
||||
{ return (m_min.array()<=(b.min)().array()).all() && ((b.max)().array()<=m_max.array()).all(); }
|
||||
|
||||
/** \returns true if the box \a b is intersecting the box \c *this.
|
||||
* \sa intersection, clamp */
|
||||
inline bool intersects(const AlignedBox& b) const
|
||||
EIGEN_DEVICE_FUNC inline bool intersects(const AlignedBox& b) const
|
||||
{ return (m_min.array()<=(b.max)().array()).all() && ((b.min)().array()<=m_max.array()).all(); }
|
||||
|
||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this.
|
||||
* \sa extend(const AlignedBox&) */
|
||||
template<typename Derived>
|
||||
inline AlignedBox& extend(const MatrixBase<Derived>& p)
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox& extend(const MatrixBase<Derived>& p)
|
||||
{
|
||||
typename internal::nested_eval<Derived,2>::type p_n(p.derived());
|
||||
m_min = m_min.cwiseMin(p_n);
|
||||
@@ -207,7 +207,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
|
||||
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this.
|
||||
* \sa merged, extend(const MatrixBase&) */
|
||||
inline AlignedBox& extend(const AlignedBox& b)
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox& extend(const AlignedBox& b)
|
||||
{
|
||||
m_min = m_min.cwiseMin(b.m_min);
|
||||
m_max = m_max.cwiseMax(b.m_max);
|
||||
@@ -217,7 +217,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
/** Clamps \c *this by the box \a b and returns a reference to \c *this.
|
||||
* \note If the boxes don't intersect, the resulting box is empty.
|
||||
* \sa intersection(), intersects() */
|
||||
inline AlignedBox& clamp(const AlignedBox& b)
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox& clamp(const AlignedBox& b)
|
||||
{
|
||||
m_min = m_min.cwiseMax(b.m_min);
|
||||
m_max = m_max.cwiseMin(b.m_max);
|
||||
@@ -227,18 +227,18 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
/** Returns an AlignedBox that is the intersection of \a b and \c *this
|
||||
* \note If the boxes don't intersect, the resulting box is empty.
|
||||
* \sa intersects(), clamp, contains() */
|
||||
inline AlignedBox intersection(const AlignedBox& b) const
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox intersection(const AlignedBox& b) const
|
||||
{return AlignedBox(m_min.cwiseMax(b.m_min), m_max.cwiseMin(b.m_max)); }
|
||||
|
||||
/** Returns an AlignedBox that is the union of \a b and \c *this.
|
||||
* \note Merging with an empty box may result in a box bigger than \c *this.
|
||||
* \sa extend(const AlignedBox&) */
|
||||
inline AlignedBox merged(const AlignedBox& b) const
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox merged(const AlignedBox& b) const
|
||||
{ return AlignedBox(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max)); }
|
||||
|
||||
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
||||
template<typename Derived>
|
||||
inline AlignedBox& translate(const MatrixBase<Derived>& a_t)
|
||||
EIGEN_DEVICE_FUNC inline AlignedBox& translate(const MatrixBase<Derived>& a_t)
|
||||
{
|
||||
const typename internal::nested_eval<Derived,2>::type t(a_t.derived());
|
||||
m_min += t;
|
||||
@@ -251,28 +251,28 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
* \sa exteriorDistance(const MatrixBase&), squaredExteriorDistance(const AlignedBox&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& p) const;
|
||||
EIGEN_DEVICE_FUNC inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& p) const;
|
||||
|
||||
/** \returns the squared distance between the boxes \a b and \c *this,
|
||||
* and zero if the boxes intersect.
|
||||
* \sa exteriorDistance(const AlignedBox&), squaredExteriorDistance(const MatrixBase&)
|
||||
*/
|
||||
inline Scalar squaredExteriorDistance(const AlignedBox& b) const;
|
||||
EIGEN_DEVICE_FUNC inline Scalar squaredExteriorDistance(const AlignedBox& b) const;
|
||||
|
||||
/** \returns the distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa squaredExteriorDistance(const MatrixBase&), exteriorDistance(const AlignedBox&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
|
||||
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(p))); }
|
||||
EIGEN_DEVICE_FUNC inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
|
||||
{ EIGEN_USING_STD_MATH(sqrt) return sqrt(NonInteger(squaredExteriorDistance(p))); }
|
||||
|
||||
/** \returns the distance between the boxes \a b and \c *this,
|
||||
* and zero if the boxes intersect.
|
||||
* \sa squaredExteriorDistance(const AlignedBox&), exteriorDistance(const MatrixBase&)
|
||||
*/
|
||||
inline NonInteger exteriorDistance(const AlignedBox& b) const
|
||||
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(b))); }
|
||||
EIGEN_DEVICE_FUNC inline NonInteger exteriorDistance(const AlignedBox& b) const
|
||||
{ EIGEN_USING_STD_MATH(sqrt) return sqrt(NonInteger(squaredExteriorDistance(b))); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
@@ -280,7 +280,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AlignedBox,
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<AlignedBox,
|
||||
@@ -289,7 +289,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_min = (other.min)().template cast<Scalar>();
|
||||
m_max = (other.max)().template cast<Scalar>();
|
||||
@@ -299,7 +299,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AlignedBox& other, const RealScalar& prec = ScalarTraits::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const AlignedBox& other, const RealScalar& prec = ScalarTraits::dummy_precision()) const
|
||||
{ return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
|
||||
|
||||
protected:
|
||||
@@ -311,7 +311,7 @@ protected:
|
||||
|
||||
template<typename Scalar,int AmbientDim>
|
||||
template<typename Derived>
|
||||
inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const MatrixBase<Derived>& a_p) const
|
||||
EIGEN_DEVICE_FUNC inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const MatrixBase<Derived>& a_p) const
|
||||
{
|
||||
typename internal::nested_eval<Derived,2*AmbientDim>::type p(a_p.derived());
|
||||
Scalar dist2(0);
|
||||
@@ -333,7 +333,7 @@ inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const Matri
|
||||
}
|
||||
|
||||
template<typename Scalar,int AmbientDim>
|
||||
inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const AlignedBox& b) const
|
||||
EIGEN_DEVICE_FUNC inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const AlignedBox& b) const
|
||||
{
|
||||
Scalar dist2(0);
|
||||
Scalar aux;
|
||||
|
||||
@@ -69,59 +69,61 @@ protected:
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
AngleAxis() {}
|
||||
EIGEN_DEVICE_FUNC AngleAxis() {}
|
||||
/** Constructs and initialize the angle-axis rotation from an \a angle in radian
|
||||
* and an \a axis which \b must \b be \b normalized.
|
||||
*
|
||||
* \warning If the \a axis vector is not normalized, then the angle-axis object
|
||||
* represents an invalid rotation. */
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline AngleAxis(const Scalar& angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
|
||||
/** Constructs and initialize the angle-axis rotation from a quaternion \a q.
|
||||
* This function implicitly normalizes the quaternion \a q.
|
||||
*/
|
||||
template<typename QuatDerived> inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; }
|
||||
template<typename QuatDerived>
|
||||
EIGEN_DEVICE_FUNC inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; }
|
||||
/** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
|
||||
template<typename Derived>
|
||||
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
||||
EIGEN_DEVICE_FUNC inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
||||
|
||||
/** \returns the value of the rotation angle in radian */
|
||||
Scalar angle() const { return m_angle; }
|
||||
EIGEN_DEVICE_FUNC Scalar angle() const { return m_angle; }
|
||||
/** \returns a read-write reference to the stored angle in radian */
|
||||
Scalar& angle() { return m_angle; }
|
||||
EIGEN_DEVICE_FUNC Scalar& angle() { return m_angle; }
|
||||
|
||||
/** \returns the rotation axis */
|
||||
const Vector3& axis() const { return m_axis; }
|
||||
EIGEN_DEVICE_FUNC const Vector3& axis() const { return m_axis; }
|
||||
/** \returns a read-write reference to the stored rotation axis.
|
||||
*
|
||||
* \warning The rotation axis must remain a \b unit vector.
|
||||
*/
|
||||
Vector3& axis() { return m_axis; }
|
||||
EIGEN_DEVICE_FUNC Vector3& axis() { return m_axis; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const AngleAxis& other) const
|
||||
EIGEN_DEVICE_FUNC inline QuaternionType operator* (const AngleAxis& other) const
|
||||
{ return QuaternionType(*this) * QuaternionType(other); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const QuaternionType& other) const
|
||||
EIGEN_DEVICE_FUNC inline QuaternionType operator* (const QuaternionType& other) const
|
||||
{ return QuaternionType(*this) * other; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
friend inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b)
|
||||
friend EIGEN_DEVICE_FUNC inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b)
|
||||
{ return a * QuaternionType(b); }
|
||||
|
||||
/** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */
|
||||
AngleAxis inverse() const
|
||||
EIGEN_DEVICE_FUNC AngleAxis inverse() const
|
||||
{ return AngleAxis(-m_angle, m_axis); }
|
||||
|
||||
template<class QuatDerived>
|
||||
AngleAxis& operator=(const QuaternionBase<QuatDerived>& q);
|
||||
EIGEN_DEVICE_FUNC AngleAxis& operator=(const QuaternionBase<QuatDerived>& q);
|
||||
template<typename Derived>
|
||||
AngleAxis& operator=(const MatrixBase<Derived>& m);
|
||||
EIGEN_DEVICE_FUNC AngleAxis& operator=(const MatrixBase<Derived>& m);
|
||||
|
||||
template<typename Derived>
|
||||
AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix3 toRotationMatrix(void) const;
|
||||
EIGEN_DEVICE_FUNC AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
EIGEN_DEVICE_FUNC Matrix3 toRotationMatrix(void) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
@@ -129,24 +131,24 @@ public:
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
|
||||
{
|
||||
m_axis = other.axis().template cast<Scalar>();
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
static inline const AngleAxis Identity() { return AngleAxis(Scalar(0), Vector3::UnitX()); }
|
||||
EIGEN_DEVICE_FUNC static inline const AngleAxis Identity() { return AngleAxis(Scalar(0), Vector3::UnitX()); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AngleAxis& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const AngleAxis& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_axis.isApprox(other.m_axis, prec) && internal::isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
@@ -158,21 +160,26 @@ typedef AngleAxis<float> AngleAxisf;
|
||||
typedef AngleAxis<double> AngleAxisd;
|
||||
|
||||
/** Set \c *this from a \b unit quaternion.
|
||||
* The resulting axis is normalized.
|
||||
*
|
||||
* The resulting axis is normalized, and the computed angle is in the [0,pi] range.
|
||||
*
|
||||
* This function implicitly normalizes the quaternion \a q.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename QuatDerived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
|
||||
EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
|
||||
{
|
||||
using std::atan2;
|
||||
EIGEN_USING_STD_MATH(atan2)
|
||||
EIGEN_USING_STD_MATH(abs)
|
||||
Scalar n = q.vec().norm();
|
||||
if(n<NumTraits<Scalar>::epsilon())
|
||||
n = q.vec().stableNorm();
|
||||
if (n > Scalar(0))
|
||||
|
||||
if (n != Scalar(0))
|
||||
{
|
||||
m_angle = Scalar(2)*atan2(n, q.w());
|
||||
m_angle = Scalar(2)*atan2(n, abs(q.w()));
|
||||
if(q.w() < 0)
|
||||
n = -n;
|
||||
m_axis = q.vec() / n;
|
||||
}
|
||||
else
|
||||
@@ -187,7 +194,7 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
|
||||
EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
// Since a direct conversion would not be really faster,
|
||||
// let's use the robust Quaternion implementation:
|
||||
@@ -199,7 +206,7 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
|
||||
**/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
return *this = QuaternionType(mat);
|
||||
}
|
||||
@@ -208,10 +215,10 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derive
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename AngleAxis<Scalar>::Matrix3
|
||||
AngleAxis<Scalar>::toRotationMatrix(void) const
|
||||
EIGEN_DEVICE_FUNC AngleAxis<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
EIGEN_USING_STD_MATH(sin)
|
||||
EIGEN_USING_STD_MATH(cos)
|
||||
Matrix3 res;
|
||||
Vector3 sin_axis = sin(m_angle) * m_axis;
|
||||
Scalar c = cos(m_angle);
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
FILE(GLOB Eigen_Geometry_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Geometry_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Geometry COMPONENT Devel
|
||||
)
|
||||
|
||||
ADD_SUBDIRECTORY(arch)
|
||||
@@ -33,12 +33,12 @@ namespace Eigen {
|
||||
* \sa class AngleAxis
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
|
||||
EIGEN_DEVICE_FUNC inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
|
||||
MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
|
||||
{
|
||||
using std::atan2;
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
EIGEN_USING_STD_MATH(atan2)
|
||||
EIGEN_USING_STD_MATH(sin)
|
||||
EIGEN_USING_STD_MATH(cos)
|
||||
/* Implemented from Graphics Gems IV */
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
|
||||
|
||||
@@ -55,7 +55,12 @@ MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
|
||||
res[0] = atan2(coeff(j,i), coeff(k,i));
|
||||
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0)))
|
||||
{
|
||||
res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(EIGEN_PI) : res[0] + Scalar(EIGEN_PI);
|
||||
if(res[0] > Scalar(0)) {
|
||||
res[0] -= Scalar(EIGEN_PI);
|
||||
}
|
||||
else {
|
||||
res[0] += Scalar(EIGEN_PI);
|
||||
}
|
||||
Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
|
||||
res[1] = -atan2(s2, coeff(i,i));
|
||||
}
|
||||
@@ -84,7 +89,12 @@ MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
|
||||
res[0] = atan2(coeff(j,k), coeff(k,k));
|
||||
Scalar c2 = Vector2(coeff(i,i), coeff(i,j)).norm();
|
||||
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0))) {
|
||||
res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(EIGEN_PI) : res[0] + Scalar(EIGEN_PI);
|
||||
if(res[0] > Scalar(0)) {
|
||||
res[0] -= Scalar(EIGEN_PI);
|
||||
}
|
||||
else {
|
||||
res[0] += Scalar(EIGEN_PI);
|
||||
}
|
||||
res[1] = atan2(-coeff(i,k), -c2);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -68,17 +68,17 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
||||
typedef MatrixBase<Homogeneous> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Homogeneous)
|
||||
|
||||
explicit inline Homogeneous(const MatrixType& matrix)
|
||||
EIGEN_DEVICE_FUNC explicit inline Homogeneous(const MatrixType& matrix)
|
||||
: m_matrix(matrix)
|
||||
{}
|
||||
|
||||
inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
||||
inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
|
||||
EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
||||
EIGEN_DEVICE_FUNC inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
|
||||
|
||||
const NestedExpression& nestedExpression() const { return m_matrix; }
|
||||
EIGEN_DEVICE_FUNC const NestedExpression& nestedExpression() const { return m_matrix; }
|
||||
|
||||
template<typename Rhs>
|
||||
inline const Product<Homogeneous,Rhs>
|
||||
EIGEN_DEVICE_FUNC inline const Product<Homogeneous,Rhs>
|
||||
operator* (const MatrixBase<Rhs>& rhs) const
|
||||
{
|
||||
eigen_assert(int(Direction)==Horizontal);
|
||||
@@ -86,7 +86,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
||||
}
|
||||
|
||||
template<typename Lhs> friend
|
||||
inline const Product<Lhs,Homogeneous>
|
||||
EIGEN_DEVICE_FUNC inline const Product<Lhs,Homogeneous>
|
||||
operator* (const MatrixBase<Lhs>& lhs, const Homogeneous& rhs)
|
||||
{
|
||||
eigen_assert(int(Direction)==Vertical);
|
||||
@@ -94,7 +94,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, int Mode, int Options> friend
|
||||
inline const Product<Transform<Scalar,Dim,Mode,Options>, Homogeneous >
|
||||
EIGEN_DEVICE_FUNC inline const Product<Transform<Scalar,Dim,Mode,Options>, Homogeneous >
|
||||
operator* (const Transform<Scalar,Dim,Mode,Options>& lhs, const Homogeneous& rhs)
|
||||
{
|
||||
eigen_assert(int(Direction)==Vertical);
|
||||
@@ -102,7 +102,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
EIGEN_STRONG_INLINE typename internal::result_of<Func(Scalar,Scalar)>::type
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::result_of<Func(Scalar,Scalar)>::type
|
||||
redux(const Func& func) const
|
||||
{
|
||||
return func(m_matrix.redux(func), Scalar(1));
|
||||
@@ -114,7 +114,9 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \return an expression of the equivalent homogeneous vector
|
||||
* \returns a vector expression that is one longer than the vector argument, with the value 1 symbolically appended as the last coefficient.
|
||||
*
|
||||
* This can be used to convert affine coordinates to homogeneous coordinates.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
@@ -124,7 +126,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
||||
* \sa VectorwiseOp::homogeneous(), class Homogeneous
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename MatrixBase<Derived>::HomogeneousReturnType
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::HomogeneousReturnType
|
||||
MatrixBase<Derived>::homogeneous() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
@@ -133,14 +135,16 @@ MatrixBase<Derived>::homogeneous() const
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \returns a matrix expression of homogeneous column (or row) vectors
|
||||
* \returns an expression where the value 1 is symbolically appended as the final coefficient to each column (or row) of the matrix.
|
||||
*
|
||||
* This can be used to convert affine coordinates to homogeneous coordinates.
|
||||
*
|
||||
* Example: \include VectorwiseOp_homogeneous.cpp
|
||||
* Output: \verbinclude VectorwiseOp_homogeneous.out
|
||||
*
|
||||
* \sa MatrixBase::homogeneous(), class Homogeneous */
|
||||
template<typename ExpressionType, int Direction>
|
||||
inline Homogeneous<ExpressionType,Direction>
|
||||
EIGEN_DEVICE_FUNC inline Homogeneous<ExpressionType,Direction>
|
||||
VectorwiseOp<ExpressionType,Direction>::homogeneous() const
|
||||
{
|
||||
return HomogeneousReturnType(_expression());
|
||||
@@ -148,14 +152,23 @@ VectorwiseOp<ExpressionType,Direction>::homogeneous() const
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \returns an expression of the homogeneous normalized vector of \c *this
|
||||
* \brief homogeneous normalization
|
||||
*
|
||||
* \returns a vector expression of the N-1 first coefficients of \c *this divided by that last coefficient.
|
||||
*
|
||||
* This can be used to convert homogeneous coordinates to affine coordinates.
|
||||
*
|
||||
* It is essentially a shortcut for:
|
||||
* \code
|
||||
this->head(this->size()-1)/this->coeff(this->size()-1);
|
||||
\endcode
|
||||
*
|
||||
* Example: \include MatrixBase_hnormalized.cpp
|
||||
* Output: \verbinclude MatrixBase_hnormalized.out
|
||||
*
|
||||
* \sa VectorwiseOp::hnormalized() */
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::HNormalizedReturnType
|
||||
EIGEN_DEVICE_FUNC inline const typename MatrixBase<Derived>::HNormalizedReturnType
|
||||
MatrixBase<Derived>::hnormalized() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
@@ -166,14 +179,20 @@ MatrixBase<Derived>::hnormalized() const
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \returns an expression of the homogeneous normalized vector of \c *this
|
||||
* \brief column or row-wise homogeneous normalization
|
||||
*
|
||||
* \returns an expression of the first N-1 coefficients of each column (or row) of \c *this divided by the last coefficient of each column (or row).
|
||||
*
|
||||
* This can be used to convert homogeneous coordinates to affine coordinates.
|
||||
*
|
||||
* It is conceptually equivalent to calling MatrixBase::hnormalized() to each column (or row) of \c *this.
|
||||
*
|
||||
* Example: \include DirectionWise_hnormalized.cpp
|
||||
* Output: \verbinclude DirectionWise_hnormalized.out
|
||||
*
|
||||
* \sa MatrixBase::hnormalized() */
|
||||
template<typename ExpressionType, int Direction>
|
||||
inline const typename VectorwiseOp<ExpressionType,Direction>::HNormalizedReturnType
|
||||
EIGEN_DEVICE_FUNC inline const typename VectorwiseOp<ExpressionType,Direction>::HNormalizedReturnType
|
||||
VectorwiseOp<ExpressionType,Direction>::hnormalized() const
|
||||
{
|
||||
return HNormalized_Block(_expression(),0,0,
|
||||
@@ -197,7 +216,7 @@ template<typename MatrixOrTransformType>
|
||||
struct take_matrix_for_product
|
||||
{
|
||||
typedef MatrixOrTransformType type;
|
||||
static const type& run(const type &x) { return x; }
|
||||
EIGEN_DEVICE_FUNC static const type& run(const type &x) { return x; }
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim, int Mode,int Options>
|
||||
@@ -205,7 +224,7 @@ struct take_matrix_for_product<Transform<Scalar, Dim, Mode, Options> >
|
||||
{
|
||||
typedef Transform<Scalar, Dim, Mode, Options> TransformType;
|
||||
typedef typename internal::add_const<typename TransformType::ConstAffinePart>::type type;
|
||||
static type run (const TransformType& x) { return x.affine(); }
|
||||
EIGEN_DEVICE_FUNC static type run (const TransformType& x) { return x.affine(); }
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim, int Options>
|
||||
@@ -213,7 +232,7 @@ struct take_matrix_for_product<Transform<Scalar, Dim, Projective, Options> >
|
||||
{
|
||||
typedef Transform<Scalar, Dim, Projective, Options> TransformType;
|
||||
typedef typename TransformType::MatrixType type;
|
||||
static const type& run (const TransformType& x) { return x.matrix(); }
|
||||
EIGEN_DEVICE_FUNC static const type& run (const TransformType& x) { return x.matrix(); }
|
||||
};
|
||||
|
||||
template<typename MatrixType,typename Lhs>
|
||||
@@ -238,15 +257,15 @@ struct homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs>
|
||||
typedef typename traits<homogeneous_left_product_impl>::LhsMatrixType LhsMatrixType;
|
||||
typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
|
||||
typedef typename remove_all<typename LhsMatrixTypeCleaned::Nested>::type LhsMatrixTypeNested;
|
||||
homogeneous_left_product_impl(const Lhs& lhs, const MatrixType& rhs)
|
||||
EIGEN_DEVICE_FUNC homogeneous_left_product_impl(const Lhs& lhs, const MatrixType& rhs)
|
||||
: m_lhs(take_matrix_for_product<Lhs>::run(lhs)),
|
||||
m_rhs(rhs)
|
||||
{}
|
||||
|
||||
inline Index rows() const { return m_lhs.rows(); }
|
||||
inline Index cols() const { return m_rhs.cols(); }
|
||||
EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); }
|
||||
EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); }
|
||||
|
||||
template<typename Dest> void evalTo(Dest& dst) const
|
||||
template<typename Dest> EIGEN_DEVICE_FUNC void evalTo(Dest& dst) const
|
||||
{
|
||||
// FIXME investigate how to allow lazy evaluation of this product when possible
|
||||
dst = Block<const LhsMatrixTypeNested,
|
||||
@@ -277,14 +296,14 @@ struct homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs>
|
||||
: public ReturnByValue<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
|
||||
{
|
||||
typedef typename remove_all<typename Rhs::Nested>::type RhsNested;
|
||||
homogeneous_right_product_impl(const MatrixType& lhs, const Rhs& rhs)
|
||||
EIGEN_DEVICE_FUNC homogeneous_right_product_impl(const MatrixType& lhs, const Rhs& rhs)
|
||||
: m_lhs(lhs), m_rhs(rhs)
|
||||
{}
|
||||
|
||||
inline Index rows() const { return m_lhs.rows(); }
|
||||
inline Index cols() const { return m_rhs.cols(); }
|
||||
EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); }
|
||||
EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); }
|
||||
|
||||
template<typename Dest> void evalTo(Dest& dst) const
|
||||
template<typename Dest> EIGEN_DEVICE_FUNC void evalTo(Dest& dst) const
|
||||
{
|
||||
// FIXME investigate how to allow lazy evaluation of this product when possible
|
||||
dst = m_lhs * Block<const RhsNested,
|
||||
@@ -317,7 +336,7 @@ struct unary_evaluator<Homogeneous<ArgType,Direction>, IndexBased>
|
||||
typedef typename XprType::PlainObject PlainObject;
|
||||
typedef evaluator<PlainObject> Base;
|
||||
|
||||
explicit unary_evaluator(const XprType& op)
|
||||
EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
|
||||
: Base(), m_temp(op)
|
||||
{
|
||||
::new (static_cast<Base*>(this)) Base(m_temp);
|
||||
@@ -332,8 +351,13 @@ template< typename DstXprType, typename ArgType, typename Scalar>
|
||||
struct Assignment<DstXprType, Homogeneous<ArgType,Vertical>, internal::assign_op<Scalar,typename ArgType::Scalar>, Dense2Dense>
|
||||
{
|
||||
typedef Homogeneous<ArgType,Vertical> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename ArgType::Scalar> &)
|
||||
EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename ArgType::Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
dst.template topRows<ArgType::RowsAtCompileTime>(src.nestedExpression().rows()) = src.nestedExpression();
|
||||
dst.row(dst.rows()-1).setOnes();
|
||||
}
|
||||
@@ -344,8 +368,13 @@ template< typename DstXprType, typename ArgType, typename Scalar>
|
||||
struct Assignment<DstXprType, Homogeneous<ArgType,Horizontal>, internal::assign_op<Scalar,typename ArgType::Scalar>, Dense2Dense>
|
||||
{
|
||||
typedef Homogeneous<ArgType,Horizontal> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename ArgType::Scalar> &)
|
||||
EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename ArgType::Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
dst.template leftCols<ArgType::ColsAtCompileTime>(src.nestedExpression().cols()) = src.nestedExpression();
|
||||
dst.col(dst.cols()-1).setOnes();
|
||||
}
|
||||
@@ -355,7 +384,7 @@ template<typename LhsArg, typename Rhs, int ProductTag>
|
||||
struct generic_product_impl<Homogeneous<LhsArg,Horizontal>, Rhs, HomogeneousShape, DenseShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Homogeneous<LhsArg,Horizontal>& lhs, const Rhs& rhs)
|
||||
EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const Homogeneous<LhsArg,Horizontal>& lhs, const Rhs& rhs)
|
||||
{
|
||||
homogeneous_right_product_impl<Homogeneous<LhsArg,Horizontal>, Rhs>(lhs.nestedExpression(), rhs).evalTo(dst);
|
||||
}
|
||||
@@ -396,12 +425,24 @@ template<typename Lhs, typename RhsArg, int ProductTag>
|
||||
struct generic_product_impl<Lhs, Homogeneous<RhsArg,Vertical>, DenseShape, HomogeneousShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
|
||||
EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const Lhs& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
|
||||
{
|
||||
homogeneous_left_product_impl<Homogeneous<RhsArg,Vertical>, Lhs>(lhs, rhs.nestedExpression()).evalTo(dst);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: the following specialization is to address a regression from 3.2 to 3.3
|
||||
// In the future, this path should be optimized.
|
||||
template<typename Lhs, typename RhsArg, int ProductTag>
|
||||
struct generic_product_impl<Lhs, Homogeneous<RhsArg,Vertical>, TriangularShape, HomogeneousShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
|
||||
{
|
||||
dst.noalias() = lhs * rhs.eval();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs,typename Rhs>
|
||||
struct homogeneous_left_product_refactoring_helper
|
||||
{
|
||||
@@ -438,7 +479,7 @@ struct generic_product_impl<Transform<Scalar,Dim,Mode,Options>, Homogeneous<RhsA
|
||||
{
|
||||
typedef Transform<Scalar,Dim,Mode,Options> TransformType;
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const TransformType& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
|
||||
EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const TransformType& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
|
||||
{
|
||||
homogeneous_left_product_impl<Homogeneous<RhsArg,Vertical>, TransformType>(lhs, rhs.nestedExpression()).evalTo(dst);
|
||||
}
|
||||
|
||||
@@ -50,21 +50,21 @@ public:
|
||||
typedef const Block<const Coefficients,AmbientDimAtCompileTime,1> ConstNormalReturnType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline Hyperplane() {}
|
||||
EIGEN_DEVICE_FUNC inline Hyperplane() {}
|
||||
|
||||
template<int OtherOptions>
|
||||
Hyperplane(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
EIGEN_DEVICE_FUNC Hyperplane(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
: m_coeffs(other.coeffs())
|
||||
{}
|
||||
|
||||
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit Hyperplane(Index _dim) : m_coeffs(_dim+1) {}
|
||||
EIGEN_DEVICE_FUNC inline explicit Hyperplane(Index _dim) : m_coeffs(_dim+1) {}
|
||||
|
||||
/** Construct a plane from its normal \a n and a point \a e onto the plane.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const VectorType& e)
|
||||
EIGEN_DEVICE_FUNC inline Hyperplane(const VectorType& n, const VectorType& e)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
* such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const Scalar& d)
|
||||
EIGEN_DEVICE_FUNC inline Hyperplane(const VectorType& n, const Scalar& d)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
/** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
|
||||
* is greater than 2, then there isn't uniqueness, so an arbitrary choice is made.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
|
||||
EIGEN_DEVICE_FUNC static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
|
||||
{
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p1 - p0).unitOrthogonal();
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
||||
* is required to be exactly 3.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
|
||||
EIGEN_DEVICE_FUNC static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
|
||||
Hyperplane result(p0.size());
|
||||
@@ -120,19 +120,19 @@ public:
|
||||
* so an arbitrary choice is made.
|
||||
*/
|
||||
// FIXME to be consitent with the rest this could be implemented as a static Through function ??
|
||||
explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
|
||||
EIGEN_DEVICE_FUNC explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
|
||||
{
|
||||
normal() = parametrized.direction().unitOrthogonal();
|
||||
offset() = -parametrized.origin().dot(normal());
|
||||
}
|
||||
|
||||
~Hyperplane() {}
|
||||
EIGEN_DEVICE_FUNC ~Hyperplane() {}
|
||||
|
||||
/** \returns the dimension in which the plane holds */
|
||||
inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : Index(AmbientDimAtCompileTime); }
|
||||
EIGEN_DEVICE_FUNC inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : Index(AmbientDimAtCompileTime); }
|
||||
|
||||
/** normalizes \c *this */
|
||||
void normalize(void)
|
||||
EIGEN_DEVICE_FUNC void normalize(void)
|
||||
{
|
||||
m_coeffs /= normal().norm();
|
||||
}
|
||||
@@ -140,45 +140,45 @@ public:
|
||||
/** \returns the signed distance between the plane \c *this and a point \a p.
|
||||
* \sa absDistance()
|
||||
*/
|
||||
inline Scalar signedDistance(const VectorType& p) const { return normal().dot(p) + offset(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar signedDistance(const VectorType& p) const { return normal().dot(p) + offset(); }
|
||||
|
||||
/** \returns the absolute distance between the plane \c *this and a point \a p.
|
||||
* \sa signedDistance()
|
||||
*/
|
||||
inline Scalar absDistance(const VectorType& p) const { using std::abs; return abs(signedDistance(p)); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar absDistance(const VectorType& p) const { return numext::abs(signedDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the plane \c *this.
|
||||
*/
|
||||
inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
|
||||
EIGEN_DEVICE_FUNC inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
|
||||
|
||||
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline ConstNormalReturnType normal() const { return ConstNormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
EIGEN_DEVICE_FUNC inline ConstNormalReturnType normal() const { return ConstNormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
EIGEN_DEVICE_FUNC inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns the distance to the origin, which is also the "constant term" of the implicit equation
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
|
||||
EIGEN_DEVICE_FUNC inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
|
||||
|
||||
/** \returns a non-constant reference to the distance to the origin, which is also the constant part
|
||||
* of the implicit equation */
|
||||
inline Scalar& offset() { return m_coeffs(dim()); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& offset() { return m_coeffs(dim()); }
|
||||
|
||||
/** \returns a constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a non-constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** \returns the intersection of *this with \a other.
|
||||
*
|
||||
@@ -186,16 +186,15 @@ public:
|
||||
*
|
||||
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
||||
*/
|
||||
VectorType intersection(const Hyperplane& other) const
|
||||
EIGEN_DEVICE_FUNC VectorType intersection(const Hyperplane& other) const
|
||||
{
|
||||
using std::abs;
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
||||
// since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
|
||||
// whether the two lines are approximately parallel.
|
||||
if(internal::isMuchSmallerThan(det, Scalar(1)))
|
||||
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
|
||||
if(abs(coeffs().coeff(1))>abs(coeffs().coeff(0)))
|
||||
if(numext::abs(coeffs().coeff(1))>numext::abs(coeffs().coeff(0)))
|
||||
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
|
||||
else
|
||||
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
|
||||
@@ -215,7 +214,7 @@ public:
|
||||
* or a more generic #Affine transformation. The default is #Affine.
|
||||
*/
|
||||
template<typename XprType>
|
||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
EIGEN_DEVICE_FUNC inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
{
|
||||
if (traits==Affine)
|
||||
normal() = mat.inverse().transpose() * normal();
|
||||
@@ -236,7 +235,7 @@ public:
|
||||
* Other kind of transformations are not supported.
|
||||
*/
|
||||
template<int TrOptions>
|
||||
inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime,Affine,TrOptions>& t,
|
||||
EIGEN_DEVICE_FUNC inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime,Affine,TrOptions>& t,
|
||||
TransformTraits traits = Affine)
|
||||
{
|
||||
transform(t.linear(), traits);
|
||||
@@ -250,7 +249,7 @@ public:
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Hyperplane,
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<Hyperplane,
|
||||
@@ -259,7 +258,7 @@ public:
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType,int OtherOptions>
|
||||
inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
@@ -267,7 +266,7 @@ public:
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
template<int OtherOptions>
|
||||
bool isApprox(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Eigen {
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
inline typename MatrixBase<Derived>::template cross_product_return_type<OtherDerived>::type
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::template cross_product_return_type<OtherDerived>::type
|
||||
#else
|
||||
inline typename MatrixBase<Derived>::PlainObject
|
||||
#endif
|
||||
@@ -53,7 +53,7 @@ template< int Arch,typename VectorLhs,typename VectorRhs,
|
||||
typename Scalar = typename VectorLhs::Scalar,
|
||||
bool Vectorizable = bool((VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit)>
|
||||
struct cross3_impl {
|
||||
static inline typename internal::plain_matrix_type<VectorLhs>::type
|
||||
EIGEN_DEVICE_FUNC static inline typename internal::plain_matrix_type<VectorLhs>::type
|
||||
run(const VectorLhs& lhs, const VectorRhs& rhs)
|
||||
{
|
||||
return typename internal::plain_matrix_type<VectorLhs>::type(
|
||||
@@ -78,7 +78,7 @@ struct cross3_impl {
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline typename MatrixBase<Derived>::PlainObject
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::PlainObject
|
||||
MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,4)
|
||||
@@ -105,6 +105,7 @@ MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
|
||||
* \sa MatrixBase::cross() */
|
||||
template<typename ExpressionType, int Direction>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
const typename VectorwiseOp<ExpressionType,Direction>::CrossReturnType
|
||||
VectorwiseOp<ExpressionType,Direction>::cross(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
@@ -221,7 +222,7 @@ struct unitOrthogonal_selector<Derived,2>
|
||||
* \sa cross()
|
||||
*/
|
||||
template<typename Derived>
|
||||
typename MatrixBase<Derived>::PlainObject
|
||||
EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::PlainObject
|
||||
MatrixBase<Derived>::unitOrthogonal() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
|
||||
@@ -41,45 +41,45 @@ public:
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1,Options> VectorType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline ParametrizedLine() {}
|
||||
EIGEN_DEVICE_FUNC inline ParametrizedLine() {}
|
||||
|
||||
template<int OtherOptions>
|
||||
ParametrizedLine(const ParametrizedLine<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
EIGEN_DEVICE_FUNC ParametrizedLine(const ParametrizedLine<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
: m_origin(other.origin()), m_direction(other.direction())
|
||||
{}
|
||||
|
||||
/** Constructs a dynamic-size line with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit ParametrizedLine(Index _dim) : m_origin(_dim), m_direction(_dim) {}
|
||||
EIGEN_DEVICE_FUNC inline explicit ParametrizedLine(Index _dim) : m_origin(_dim), m_direction(_dim) {}
|
||||
|
||||
/** Initializes a parametrized line of direction \a direction and origin \a origin.
|
||||
* \warning the vector direction is assumed to be normalized.
|
||||
*/
|
||||
ParametrizedLine(const VectorType& origin, const VectorType& direction)
|
||||
EIGEN_DEVICE_FUNC ParametrizedLine(const VectorType& origin, const VectorType& direction)
|
||||
: m_origin(origin), m_direction(direction) {}
|
||||
|
||||
template <int OtherOptions>
|
||||
explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane);
|
||||
EIGEN_DEVICE_FUNC explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane);
|
||||
|
||||
/** Constructs a parametrized line going from \a p0 to \a p1. */
|
||||
static inline ParametrizedLine Through(const VectorType& p0, const VectorType& p1)
|
||||
EIGEN_DEVICE_FUNC static inline ParametrizedLine Through(const VectorType& p0, const VectorType& p1)
|
||||
{ return ParametrizedLine(p0, (p1-p0).normalized()); }
|
||||
|
||||
~ParametrizedLine() {}
|
||||
EIGEN_DEVICE_FUNC ~ParametrizedLine() {}
|
||||
|
||||
/** \returns the dimension in which the line holds */
|
||||
inline Index dim() const { return m_direction.size(); }
|
||||
EIGEN_DEVICE_FUNC inline Index dim() const { return m_direction.size(); }
|
||||
|
||||
const VectorType& origin() const { return m_origin; }
|
||||
VectorType& origin() { return m_origin; }
|
||||
EIGEN_DEVICE_FUNC const VectorType& origin() const { return m_origin; }
|
||||
EIGEN_DEVICE_FUNC VectorType& origin() { return m_origin; }
|
||||
|
||||
const VectorType& direction() const { return m_direction; }
|
||||
VectorType& direction() { return m_direction; }
|
||||
EIGEN_DEVICE_FUNC const VectorType& direction() const { return m_direction; }
|
||||
EIGEN_DEVICE_FUNC VectorType& direction() { return m_direction; }
|
||||
|
||||
/** \returns the squared distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa distance()
|
||||
*/
|
||||
RealScalar squaredDistance(const VectorType& p) const
|
||||
EIGEN_DEVICE_FUNC RealScalar squaredDistance(const VectorType& p) const
|
||||
{
|
||||
VectorType diff = p - origin();
|
||||
return (diff - direction().dot(diff) * direction()).squaredNorm();
|
||||
@@ -87,22 +87,22 @@ public:
|
||||
/** \returns the distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa squaredDistance()
|
||||
*/
|
||||
RealScalar distance(const VectorType& p) const { using std::sqrt; return sqrt(squaredDistance(p)); }
|
||||
EIGEN_DEVICE_FUNC RealScalar distance(const VectorType& p) const { EIGEN_USING_STD_MATH(sqrt) return sqrt(squaredDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the line \c *this. */
|
||||
VectorType projection(const VectorType& p) const
|
||||
EIGEN_DEVICE_FUNC VectorType projection(const VectorType& p) const
|
||||
{ return origin() + direction().dot(p-origin()) * direction(); }
|
||||
|
||||
VectorType pointAt(const Scalar& t) const;
|
||||
EIGEN_DEVICE_FUNC VectorType pointAt(const Scalar& t) const;
|
||||
|
||||
template <int OtherOptions>
|
||||
Scalar intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
EIGEN_DEVICE_FUNC Scalar intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
|
||||
template <int OtherOptions>
|
||||
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
EIGEN_DEVICE_FUNC Scalar intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
|
||||
template <int OtherOptions>
|
||||
VectorType intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
EIGEN_DEVICE_FUNC VectorType intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<ParametrizedLine,
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<ParametrizedLine,
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType,int OtherOptions>
|
||||
inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
{
|
||||
m_origin = other.origin().template cast<Scalar>();
|
||||
m_direction = other.direction().template cast<Scalar>();
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const ParametrizedLine& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const ParametrizedLine& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||
|
||||
protected:
|
||||
@@ -143,7 +143,7 @@ protected:
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim,OtherOptions>& hyperplane)
|
||||
EIGEN_DEVICE_FUNC inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim,OtherOptions>& hyperplane)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
direction() = hyperplane.normal().unitOrthogonal();
|
||||
@@ -153,7 +153,7 @@ inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const H
|
||||
/** \returns the point at \a t along this line
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType
|
||||
EIGEN_DEVICE_FUNC inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType
|
||||
ParametrizedLine<_Scalar, _AmbientDim,_Options>::pointAt(const _Scalar& t) const
|
||||
{
|
||||
return origin() + (direction()*t);
|
||||
@@ -163,7 +163,7 @@ ParametrizedLine<_Scalar, _AmbientDim,_Options>::pointAt(const _Scalar& t) const
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
EIGEN_DEVICE_FUNC inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
{
|
||||
return -(hyperplane.offset()+hyperplane.normal().dot(origin()))
|
||||
/ hyperplane.normal().dot(direction());
|
||||
@@ -175,7 +175,7 @@ inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionPara
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
EIGEN_DEVICE_FUNC inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
{
|
||||
return intersectionParameter(hyperplane);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(con
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType
|
||||
EIGEN_DEVICE_FUNC inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType
|
||||
ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
{
|
||||
return pointAt(intersectionParameter(hyperplane));
|
||||
|
||||
@@ -58,37 +58,37 @@ class QuaternionBase : public RotationBase<Derived, 3>
|
||||
|
||||
|
||||
/** \returns the \c x coefficient */
|
||||
inline Scalar x() const { return this->derived().coeffs().coeff(0); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar x() const { return this->derived().coeffs().coeff(0); }
|
||||
/** \returns the \c y coefficient */
|
||||
inline Scalar y() const { return this->derived().coeffs().coeff(1); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar y() const { return this->derived().coeffs().coeff(1); }
|
||||
/** \returns the \c z coefficient */
|
||||
inline Scalar z() const { return this->derived().coeffs().coeff(2); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar z() const { return this->derived().coeffs().coeff(2); }
|
||||
/** \returns the \c w coefficient */
|
||||
inline Scalar w() const { return this->derived().coeffs().coeff(3); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar w() const { return this->derived().coeffs().coeff(3); }
|
||||
|
||||
/** \returns a reference to the \c x coefficient */
|
||||
inline Scalar& x() { return this->derived().coeffs().coeffRef(0); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& x() { return this->derived().coeffs().coeffRef(0); }
|
||||
/** \returns a reference to the \c y coefficient */
|
||||
inline Scalar& y() { return this->derived().coeffs().coeffRef(1); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& y() { return this->derived().coeffs().coeffRef(1); }
|
||||
/** \returns a reference to the \c z coefficient */
|
||||
inline Scalar& z() { return this->derived().coeffs().coeffRef(2); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& z() { return this->derived().coeffs().coeffRef(2); }
|
||||
/** \returns a reference to the \c w coefficient */
|
||||
inline Scalar& w() { return this->derived().coeffs().coeffRef(3); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& w() { return this->derived().coeffs().coeffRef(3); }
|
||||
|
||||
/** \returns a read-only vector expression of the imaginary part (x,y,z) */
|
||||
inline const VectorBlock<const Coefficients,3> vec() const { return coeffs().template head<3>(); }
|
||||
EIGEN_DEVICE_FUNC inline const VectorBlock<const Coefficients,3> vec() const { return coeffs().template head<3>(); }
|
||||
|
||||
/** \returns a vector expression of the imaginary part (x,y,z) */
|
||||
inline VectorBlock<Coefficients,3> vec() { return coeffs().template head<3>(); }
|
||||
EIGEN_DEVICE_FUNC inline VectorBlock<Coefficients,3> vec() { return coeffs().template head<3>(); }
|
||||
|
||||
/** \returns a read-only vector expression of the coefficients (x,y,z,w) */
|
||||
inline const typename internal::traits<Derived>::Coefficients& coeffs() const { return derived().coeffs(); }
|
||||
EIGEN_DEVICE_FUNC inline const typename internal::traits<Derived>::Coefficients& coeffs() const { return derived().coeffs(); }
|
||||
|
||||
/** \returns a vector expression of the coefficients (x,y,z,w) */
|
||||
inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
|
||||
EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
|
||||
|
||||
EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
|
||||
template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
|
||||
template<class OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
|
||||
|
||||
// disabled this copy operator as it is giving very strange compilation errors when compiling
|
||||
// test_stdvector with GCC 4.4.2. This looks like a GCC bug though, so feel free to re-enable it if it's
|
||||
@@ -97,72 +97,72 @@ class QuaternionBase : public RotationBase<Derived, 3>
|
||||
// Derived& operator=(const QuaternionBase& other)
|
||||
// { return operator=<Derived>(other); }
|
||||
|
||||
Derived& operator=(const AngleAxisType& aa);
|
||||
template<class OtherDerived> Derived& operator=(const MatrixBase<OtherDerived>& m);
|
||||
EIGEN_DEVICE_FUNC Derived& operator=(const AngleAxisType& aa);
|
||||
template<class OtherDerived> EIGEN_DEVICE_FUNC Derived& operator=(const MatrixBase<OtherDerived>& m);
|
||||
|
||||
/** \returns a quaternion representing an identity rotation
|
||||
* \sa MatrixBase::Identity()
|
||||
*/
|
||||
static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
|
||||
EIGEN_DEVICE_FUNC static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
|
||||
|
||||
/** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
|
||||
*/
|
||||
inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
|
||||
EIGEN_DEVICE_FUNC inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
|
||||
|
||||
/** \returns the squared norm of the quaternion's coefficients
|
||||
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
|
||||
*/
|
||||
inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
|
||||
|
||||
/** \returns the norm of the quaternion's coefficients
|
||||
* \sa QuaternionBase::squaredNorm(), MatrixBase::norm()
|
||||
*/
|
||||
inline Scalar norm() const { return coeffs().norm(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar norm() const { return coeffs().norm(); }
|
||||
|
||||
/** Normalizes the quaternion \c *this
|
||||
* \sa normalized(), MatrixBase::normalize() */
|
||||
inline void normalize() { coeffs().normalize(); }
|
||||
EIGEN_DEVICE_FUNC inline void normalize() { coeffs().normalize(); }
|
||||
/** \returns a normalized copy of \c *this
|
||||
* \sa normalize(), MatrixBase::normalized() */
|
||||
inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
|
||||
EIGEN_DEVICE_FUNC inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
|
||||
|
||||
/** \returns the dot product of \c *this and \a other
|
||||
* Geometrically speaking, the dot product of two unit quaternions
|
||||
* corresponds to the cosine of half the angle between the two rotations.
|
||||
* \sa angularDistance()
|
||||
*/
|
||||
template<class OtherDerived> inline Scalar dot(const QuaternionBase<OtherDerived>& other) const { return coeffs().dot(other.coeffs()); }
|
||||
template<class OtherDerived> EIGEN_DEVICE_FUNC inline Scalar dot(const QuaternionBase<OtherDerived>& other) const { return coeffs().dot(other.coeffs()); }
|
||||
|
||||
template<class OtherDerived> Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
|
||||
template<class OtherDerived> EIGEN_DEVICE_FUNC Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
|
||||
|
||||
/** \returns an equivalent 3x3 rotation matrix */
|
||||
Matrix3 toRotationMatrix() const;
|
||||
EIGEN_DEVICE_FUNC Matrix3 toRotationMatrix() const;
|
||||
|
||||
/** \returns the quaternion which transform \a a into \a b through a rotation */
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
EIGEN_DEVICE_FUNC Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
|
||||
template<class OtherDerived> EIGEN_STRONG_INLINE Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const;
|
||||
template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator*= (const QuaternionBase<OtherDerived>& q);
|
||||
template<class OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const;
|
||||
template<class OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*= (const QuaternionBase<OtherDerived>& q);
|
||||
|
||||
/** \returns the quaternion describing the inverse rotation */
|
||||
Quaternion<Scalar> inverse() const;
|
||||
EIGEN_DEVICE_FUNC Quaternion<Scalar> inverse() const;
|
||||
|
||||
/** \returns the conjugated quaternion */
|
||||
Quaternion<Scalar> conjugate() const;
|
||||
EIGEN_DEVICE_FUNC Quaternion<Scalar> conjugate() const;
|
||||
|
||||
template<class OtherDerived> Quaternion<Scalar> slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const;
|
||||
template<class OtherDerived> EIGEN_DEVICE_FUNC Quaternion<Scalar> slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const;
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
template<class OtherDerived>
|
||||
bool isApprox(const QuaternionBase<OtherDerived>& other, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const QuaternionBase<OtherDerived>& other, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return coeffs().isApprox(other.coeffs(), prec); }
|
||||
|
||||
/** return the result vector of \a v through the rotation*/
|
||||
EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
@@ -170,7 +170,7 @@ class QuaternionBase : public RotationBase<Derived, 3>
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type(derived());
|
||||
}
|
||||
@@ -239,7 +239,7 @@ public:
|
||||
typedef typename Base::AngleAxisType AngleAxisType;
|
||||
|
||||
/** Default constructor leaving the quaternion uninitialized. */
|
||||
inline Quaternion() {}
|
||||
EIGEN_DEVICE_FUNC inline Quaternion() {}
|
||||
|
||||
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
|
||||
* its four coefficients \a w, \a x, \a y and \a z.
|
||||
@@ -248,36 +248,36 @@ public:
|
||||
* while internally the coefficients are stored in the following order:
|
||||
* [\c x, \c y, \c z, \c w]
|
||||
*/
|
||||
inline Quaternion(const Scalar& w, const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, w){}
|
||||
EIGEN_DEVICE_FUNC inline Quaternion(const Scalar& w, const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, w){}
|
||||
|
||||
/** Constructs and initialize a quaternion from the array data */
|
||||
explicit inline Quaternion(const Scalar* data) : m_coeffs(data) {}
|
||||
EIGEN_DEVICE_FUNC explicit inline Quaternion(const Scalar* data) : m_coeffs(data) {}
|
||||
|
||||
/** Copy constructor */
|
||||
template<class Derived> EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) { this->Base::operator=(other); }
|
||||
template<class Derived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) { this->Base::operator=(other); }
|
||||
|
||||
/** Constructs and initializes a quaternion from the angle-axis \a aa */
|
||||
explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
|
||||
EIGEN_DEVICE_FUNC explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
|
||||
|
||||
/** Constructs and initializes a quaternion from either:
|
||||
* - a rotation matrix expression,
|
||||
* - a 4D vector expression representing quaternion coefficients.
|
||||
*/
|
||||
template<typename Derived>
|
||||
explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
|
||||
EIGEN_DEVICE_FUNC explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
|
||||
|
||||
/** Explicit copy constructor with scalar conversion */
|
||||
template<typename OtherScalar, int OtherOptions>
|
||||
explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
|
||||
EIGEN_DEVICE_FUNC explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
static Quaternion UnitRandom();
|
||||
EIGEN_DEVICE_FUNC static Quaternion UnitRandom();
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
EIGEN_DEVICE_FUNC static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
|
||||
inline Coefficients& coeffs() { return m_coeffs;}
|
||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||
EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs;}
|
||||
EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(NeedsAlignment))
|
||||
|
||||
@@ -357,9 +357,9 @@ class Map<const Quaternion<_Scalar>, _Options >
|
||||
* \code *coeffs == {x, y, z, w} \endcode
|
||||
*
|
||||
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
||||
explicit EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||
EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||
|
||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||
EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||
|
||||
protected:
|
||||
const Coefficients m_coeffs;
|
||||
@@ -394,10 +394,10 @@ class Map<Quaternion<_Scalar>, _Options >
|
||||
* \code *coeffs == {x, y, z, w} \endcode
|
||||
*
|
||||
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
||||
explicit EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||
EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
protected:
|
||||
Coefficients m_coeffs;
|
||||
@@ -425,7 +425,7 @@ typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
|
||||
namespace internal {
|
||||
template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options> struct quat_product
|
||||
{
|
||||
static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
|
||||
return Quaternion<Scalar>
|
||||
(
|
||||
a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
|
||||
@@ -440,7 +440,7 @@ template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options
|
||||
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
|
||||
@@ -453,7 +453,7 @@ QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) c
|
||||
/** \sa operator*(Quaternion) */
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const QuaternionBase<OtherDerived>& other)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const QuaternionBase<OtherDerived>& other)
|
||||
{
|
||||
derived() = derived() * other.derived();
|
||||
return derived();
|
||||
@@ -467,7 +467,7 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const Quaterni
|
||||
* - Via a Matrix3: 24 + 15n
|
||||
*/
|
||||
template <class Derived>
|
||||
EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
|
||||
QuaternionBase<Derived>::_transformVector(const Vector3& v) const
|
||||
{
|
||||
// Note that this algorithm comes from the optimization by hand
|
||||
@@ -481,7 +481,7 @@ QuaternionBase<Derived>::_transformVector(const Vector3& v) const
|
||||
}
|
||||
|
||||
template<class Derived>
|
||||
EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<Derived>& other)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<Derived>& other)
|
||||
{
|
||||
coeffs() = other.coeffs();
|
||||
return derived();
|
||||
@@ -489,7 +489,7 @@ EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(
|
||||
|
||||
template<class Derived>
|
||||
template<class OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
|
||||
{
|
||||
coeffs() = other.coeffs();
|
||||
return derived();
|
||||
@@ -498,10 +498,10 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const Quaternion
|
||||
/** Set \c *this from an angle-axis \a aa and returns a reference to \c *this
|
||||
*/
|
||||
template<class Derived>
|
||||
EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
|
||||
{
|
||||
using std::cos;
|
||||
using std::sin;
|
||||
EIGEN_USING_STD_MATH(cos)
|
||||
EIGEN_USING_STD_MATH(sin)
|
||||
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
|
||||
this->w() = cos(ha);
|
||||
this->vec() = sin(ha) * aa.axis();
|
||||
@@ -516,7 +516,7 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisT
|
||||
|
||||
template<class Derived>
|
||||
template<class MatrixDerived>
|
||||
inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
|
||||
EIGEN_DEVICE_FUNC inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
@@ -528,7 +528,7 @@ inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerive
|
||||
* be normalized, otherwise the result is undefined.
|
||||
*/
|
||||
template<class Derived>
|
||||
inline typename QuaternionBase<Derived>::Matrix3
|
||||
EIGEN_DEVICE_FUNC inline typename QuaternionBase<Derived>::Matrix3
|
||||
QuaternionBase<Derived>::toRotationMatrix(void) const
|
||||
{
|
||||
// NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
|
||||
@@ -575,9 +575,9 @@ QuaternionBase<Derived>::toRotationMatrix(void) const
|
||||
*/
|
||||
template<class Derived>
|
||||
template<typename Derived1, typename Derived2>
|
||||
inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
EIGEN_DEVICE_FUNC inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
{
|
||||
using std::sqrt;
|
||||
EIGEN_USING_STD_MATH(sqrt)
|
||||
Vector3 v0 = a.normalized();
|
||||
Vector3 v1 = b.normalized();
|
||||
Scalar c = v1.dot(v0);
|
||||
@@ -616,11 +616,11 @@ inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Deri
|
||||
* \note The implementation is based on http://planning.cs.uiuc.edu/node198.html
|
||||
*/
|
||||
template<typename Scalar, int Options>
|
||||
Quaternion<Scalar,Options> Quaternion<Scalar,Options>::UnitRandom()
|
||||
EIGEN_DEVICE_FUNC Quaternion<Scalar,Options> Quaternion<Scalar,Options>::UnitRandom()
|
||||
{
|
||||
using std::sqrt;
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
EIGEN_USING_STD_MATH(sqrt)
|
||||
EIGEN_USING_STD_MATH(sin)
|
||||
EIGEN_USING_STD_MATH(cos)
|
||||
const Scalar u1 = internal::random<Scalar>(0, 1),
|
||||
u2 = internal::random<Scalar>(0, 2*EIGEN_PI),
|
||||
u3 = internal::random<Scalar>(0, 2*EIGEN_PI);
|
||||
@@ -642,7 +642,7 @@ Quaternion<Scalar,Options> Quaternion<Scalar,Options>::UnitRandom()
|
||||
*/
|
||||
template<typename Scalar, int Options>
|
||||
template<typename Derived1, typename Derived2>
|
||||
Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
EIGEN_DEVICE_FUNC Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
{
|
||||
Quaternion quat;
|
||||
quat.setFromTwoVectors(a, b);
|
||||
@@ -657,7 +657,7 @@ Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const Matr
|
||||
* \sa QuaternionBase::conjugate()
|
||||
*/
|
||||
template <class Derived>
|
||||
inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
|
||||
EIGEN_DEVICE_FUNC inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
|
||||
{
|
||||
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
||||
Scalar n2 = this->squaredNorm();
|
||||
@@ -674,7 +674,7 @@ inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Der
|
||||
namespace internal {
|
||||
template<int Arch, class Derived, typename Scalar, int _Options> struct quat_conj
|
||||
{
|
||||
static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived>& q){
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived>& q){
|
||||
return Quaternion<Scalar>(q.w(),-q.x(),-q.y(),-q.z());
|
||||
}
|
||||
};
|
||||
@@ -687,7 +687,7 @@ template<int Arch, class Derived, typename Scalar, int _Options> struct quat_con
|
||||
* \sa Quaternion2::inverse()
|
||||
*/
|
||||
template <class Derived>
|
||||
inline Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
EIGEN_DEVICE_FUNC inline Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
QuaternionBase<Derived>::conjugate() const
|
||||
{
|
||||
return internal::quat_conj<Architecture::Target, Derived,
|
||||
@@ -701,13 +701,12 @@ QuaternionBase<Derived>::conjugate() const
|
||||
*/
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
inline typename internal::traits<Derived>::Scalar
|
||||
EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar
|
||||
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
|
||||
{
|
||||
using std::atan2;
|
||||
using std::abs;
|
||||
EIGEN_USING_STD_MATH(atan2)
|
||||
Quaternion<Scalar> d = (*this) * other.conjugate();
|
||||
return Scalar(2) * atan2( d.vec().norm(), abs(d.w()) );
|
||||
return Scalar(2) * atan2( d.vec().norm(), numext::abs(d.w()) );
|
||||
}
|
||||
|
||||
|
||||
@@ -720,15 +719,14 @@ QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& oth
|
||||
*/
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
EIGEN_DEVICE_FUNC Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const
|
||||
{
|
||||
using std::acos;
|
||||
using std::sin;
|
||||
using std::abs;
|
||||
EIGEN_USING_STD_MATH(acos)
|
||||
EIGEN_USING_STD_MATH(sin)
|
||||
const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
|
||||
Scalar d = this->dot(other);
|
||||
Scalar absD = abs(d);
|
||||
Scalar absD = numext::abs(d);
|
||||
|
||||
Scalar scale0;
|
||||
Scalar scale1;
|
||||
@@ -759,10 +757,10 @@ template<typename Other>
|
||||
struct quaternionbase_assign_impl<Other,3,3>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
template<class Derived> static inline void run(QuaternionBase<Derived>& q, const Other& a_mat)
|
||||
template<class Derived> EIGEN_DEVICE_FUNC static inline void run(QuaternionBase<Derived>& q, const Other& a_mat)
|
||||
{
|
||||
const typename internal::nested_eval<Other,2>::type mat(a_mat);
|
||||
using std::sqrt;
|
||||
EIGEN_USING_STD_MATH(sqrt)
|
||||
// This algorithm comes from "Quaternion Calculus and Fast Animation",
|
||||
// Ken Shoemake, 1987 SIGGRAPH course notes
|
||||
Scalar t = mat.trace();
|
||||
@@ -800,7 +798,7 @@ template<typename Other>
|
||||
struct quaternionbase_assign_impl<Other,4,1>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
template<class Derived> static inline void run(QuaternionBase<Derived>& q, const Other& vec)
|
||||
template<class Derived> EIGEN_DEVICE_FUNC static inline void run(QuaternionBase<Derived>& q, const Other& vec)
|
||||
{
|
||||
q.coeffs() = vec;
|
||||
}
|
||||
|
||||
@@ -59,35 +59,35 @@ protected:
|
||||
public:
|
||||
|
||||
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
|
||||
explicit inline Rotation2D(const Scalar& a) : m_angle(a) {}
|
||||
EIGEN_DEVICE_FUNC explicit inline Rotation2D(const Scalar& a) : m_angle(a) {}
|
||||
|
||||
/** Default constructor wihtout initialization. The represented rotation is undefined. */
|
||||
Rotation2D() {}
|
||||
EIGEN_DEVICE_FUNC Rotation2D() {}
|
||||
|
||||
/** Construct a 2D rotation from a 2x2 rotation matrix \a mat.
|
||||
*
|
||||
* \sa fromRotationMatrix()
|
||||
*/
|
||||
template<typename Derived>
|
||||
explicit Rotation2D(const MatrixBase<Derived>& m)
|
||||
EIGEN_DEVICE_FUNC explicit Rotation2D(const MatrixBase<Derived>& m)
|
||||
{
|
||||
fromRotationMatrix(m.derived());
|
||||
}
|
||||
|
||||
/** \returns the rotation angle */
|
||||
inline Scalar angle() const { return m_angle; }
|
||||
EIGEN_DEVICE_FUNC inline Scalar angle() const { return m_angle; }
|
||||
|
||||
/** \returns a read-write reference to the rotation angle */
|
||||
inline Scalar& angle() { return m_angle; }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& angle() { return m_angle; }
|
||||
|
||||
/** \returns the rotation angle in [0,2pi] */
|
||||
inline Scalar smallestPositiveAngle() const {
|
||||
EIGEN_DEVICE_FUNC inline Scalar smallestPositiveAngle() const {
|
||||
Scalar tmp = numext::fmod(m_angle,Scalar(2*EIGEN_PI));
|
||||
return tmp<Scalar(0) ? tmp + Scalar(2*EIGEN_PI) : tmp;
|
||||
}
|
||||
|
||||
/** \returns the rotation angle in [-pi,pi] */
|
||||
inline Scalar smallestAngle() const {
|
||||
EIGEN_DEVICE_FUNC inline Scalar smallestAngle() const {
|
||||
Scalar tmp = numext::fmod(m_angle,Scalar(2*EIGEN_PI));
|
||||
if(tmp>Scalar(EIGEN_PI)) tmp -= Scalar(2*EIGEN_PI);
|
||||
else if(tmp<-Scalar(EIGEN_PI)) tmp += Scalar(2*EIGEN_PI);
|
||||
@@ -95,23 +95,23 @@ public:
|
||||
}
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Rotation2D inverse() const { return Rotation2D(-m_angle); }
|
||||
EIGEN_DEVICE_FUNC inline Rotation2D inverse() const { return Rotation2D(-m_angle); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D operator*(const Rotation2D& other) const
|
||||
EIGEN_DEVICE_FUNC inline Rotation2D operator*(const Rotation2D& other) const
|
||||
{ return Rotation2D(m_angle + other.m_angle); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D& operator*=(const Rotation2D& other)
|
||||
EIGEN_DEVICE_FUNC inline Rotation2D& operator*=(const Rotation2D& other)
|
||||
{ m_angle += other.m_angle; return *this; }
|
||||
|
||||
/** Applies the rotation to a 2D vector */
|
||||
Vector2 operator* (const Vector2& vec) const
|
||||
EIGEN_DEVICE_FUNC Vector2 operator* (const Vector2& vec) const
|
||||
{ return toRotationMatrix() * vec; }
|
||||
|
||||
template<typename Derived>
|
||||
Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix2 toRotationMatrix() const;
|
||||
EIGEN_DEVICE_FUNC Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
EIGEN_DEVICE_FUNC Matrix2 toRotationMatrix() const;
|
||||
|
||||
/** Set \c *this from a 2x2 rotation matrix \a mat.
|
||||
* In other words, this function extract the rotation angle from the rotation matrix.
|
||||
@@ -121,13 +121,13 @@ public:
|
||||
* \sa fromRotationMatrix()
|
||||
*/
|
||||
template<typename Derived>
|
||||
Rotation2D& operator=(const MatrixBase<Derived>& m)
|
||||
EIGEN_DEVICE_FUNC Rotation2D& operator=(const MatrixBase<Derived>& m)
|
||||
{ return fromRotationMatrix(m.derived()); }
|
||||
|
||||
/** \returns the spherical interpolation between \c *this and \a other using
|
||||
* parameter \a t. It is in fact equivalent to a linear interpolation.
|
||||
*/
|
||||
inline Rotation2D slerp(const Scalar& t, const Rotation2D& other) const
|
||||
EIGEN_DEVICE_FUNC inline Rotation2D slerp(const Scalar& t, const Rotation2D& other) const
|
||||
{
|
||||
Scalar dist = Rotation2D(other.m_angle-m_angle).smallestAngle();
|
||||
return Rotation2D(m_angle + dist*t);
|
||||
@@ -139,23 +139,23 @@ public:
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
|
||||
{
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
static inline Rotation2D Identity() { return Rotation2D(0); }
|
||||
EIGEN_DEVICE_FUNC static inline Rotation2D Identity() { return Rotation2D(0); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Rotation2D& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const Rotation2D& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return internal::isApprox(m_angle,other.m_angle, prec); }
|
||||
|
||||
};
|
||||
@@ -173,9 +173,9 @@ typedef Rotation2D<double> Rotation2Dd;
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
EIGEN_DEVICE_FUNC Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
using std::atan2;
|
||||
EIGEN_USING_STD_MATH(atan2)
|
||||
EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_angle = atan2(mat.coeff(1,0), mat.coeff(0,0));
|
||||
return *this;
|
||||
@@ -185,10 +185,10 @@ Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Deri
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename Rotation2D<Scalar>::Matrix2
|
||||
Rotation2D<Scalar>::toRotationMatrix(void) const
|
||||
EIGEN_DEVICE_FUNC Rotation2D<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
EIGEN_USING_STD_MATH(sin)
|
||||
EIGEN_USING_STD_MATH(cos)
|
||||
Scalar sinA = sin(m_angle);
|
||||
Scalar cosA = cos(m_angle);
|
||||
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
|
||||
|
||||
@@ -38,26 +38,26 @@ class RotationBase
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
|
||||
public:
|
||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
|
||||
/** \returns an equivalent rotation matrix */
|
||||
inline RotationMatrixType toRotationMatrix() const { return derived().toRotationMatrix(); }
|
||||
EIGEN_DEVICE_FUNC inline RotationMatrixType toRotationMatrix() const { return derived().toRotationMatrix(); }
|
||||
|
||||
/** \returns an equivalent rotation matrix
|
||||
* This function is added to be conform with the Transform class' naming scheme.
|
||||
*/
|
||||
inline RotationMatrixType matrix() const { return derived().toRotationMatrix(); }
|
||||
EIGEN_DEVICE_FUNC inline RotationMatrixType matrix() const { return derived().toRotationMatrix(); }
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Derived inverse() const { return derived().inverse(); }
|
||||
EIGEN_DEVICE_FUNC inline Derived inverse() const { return derived().inverse(); }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a translation \a t */
|
||||
inline Transform<Scalar,Dim,Isometry> operator*(const Translation<Scalar,Dim>& t) const
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Isometry> operator*(const Translation<Scalar,Dim>& t) const
|
||||
{ return Transform<Scalar,Dim,Isometry>(*this) * t; }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a uniform scaling \a s */
|
||||
inline RotationMatrixType operator*(const UniformScaling<Scalar>& s) const
|
||||
EIGEN_DEVICE_FUNC inline RotationMatrixType operator*(const UniformScaling<Scalar>& s) const
|
||||
{ return toRotationMatrix() * s.factor(); }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a generic expression \a e
|
||||
@@ -67,17 +67,17 @@ class RotationBase
|
||||
* - a vector of size Dim
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE typename internal::rotation_base_generic_product_selector<Derived,OtherDerived,OtherDerived::IsVectorAtCompileTime>::ReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::rotation_base_generic_product_selector<Derived,OtherDerived,OtherDerived::IsVectorAtCompileTime>::ReturnType
|
||||
operator*(const EigenBase<OtherDerived>& e) const
|
||||
{ return internal::rotation_base_generic_product_selector<Derived,OtherDerived>::run(derived(), e.derived()); }
|
||||
|
||||
/** \returns the concatenation of a linear transformation \a l with the rotation \a r */
|
||||
template<typename OtherDerived> friend
|
||||
inline RotationMatrixType operator*(const EigenBase<OtherDerived>& l, const Derived& r)
|
||||
EIGEN_DEVICE_FUNC inline RotationMatrixType operator*(const EigenBase<OtherDerived>& l, const Derived& r)
|
||||
{ return l.derived() * r.toRotationMatrix(); }
|
||||
|
||||
/** \returns the concatenation of a scaling \a l with the rotation \a r */
|
||||
friend inline Transform<Scalar,Dim,Affine> operator*(const DiagonalMatrix<Scalar,Dim>& l, const Derived& r)
|
||||
EIGEN_DEVICE_FUNC friend inline Transform<Scalar,Dim,Affine> operator*(const DiagonalMatrix<Scalar,Dim>& l, const Derived& r)
|
||||
{
|
||||
Transform<Scalar,Dim,Affine> res(r);
|
||||
res.linear().applyOnTheLeft(l);
|
||||
@@ -86,11 +86,11 @@ class RotationBase
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a transformation \a t */
|
||||
template<int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode> operator*(const Transform<Scalar,Dim,Mode,Options>& t) const
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode> operator*(const Transform<Scalar,Dim,Mode,Options>& t) const
|
||||
{ return toRotationMatrix() * t; }
|
||||
|
||||
template<typename OtherVectorType>
|
||||
inline VectorType _transformVector(const OtherVectorType& v) const
|
||||
EIGEN_DEVICE_FUNC inline VectorType _transformVector(const OtherVectorType& v) const
|
||||
{ return toRotationMatrix() * v; }
|
||||
};
|
||||
|
||||
@@ -102,7 +102,7 @@ struct rotation_base_generic_product_selector<RotationDerived,MatrixType,false>
|
||||
{
|
||||
enum { Dim = RotationDerived::Dim };
|
||||
typedef Matrix<typename RotationDerived::Scalar,Dim,Dim> ReturnType;
|
||||
static inline ReturnType run(const RotationDerived& r, const MatrixType& m)
|
||||
EIGEN_DEVICE_FUNC static inline ReturnType run(const RotationDerived& r, const MatrixType& m)
|
||||
{ return r.toRotationMatrix() * m; }
|
||||
};
|
||||
|
||||
@@ -110,7 +110,7 @@ template<typename RotationDerived, typename Scalar, int Dim, int MaxDim>
|
||||
struct rotation_base_generic_product_selector< RotationDerived, DiagonalMatrix<Scalar,Dim,MaxDim>, false >
|
||||
{
|
||||
typedef Transform<Scalar,Dim,Affine> ReturnType;
|
||||
static inline ReturnType run(const RotationDerived& r, const DiagonalMatrix<Scalar,Dim,MaxDim>& m)
|
||||
EIGEN_DEVICE_FUNC static inline ReturnType run(const RotationDerived& r, const DiagonalMatrix<Scalar,Dim,MaxDim>& m)
|
||||
{
|
||||
ReturnType res(r);
|
||||
res.linear() *= m;
|
||||
@@ -123,7 +123,7 @@ struct rotation_base_generic_product_selector<RotationDerived,OtherVectorType,tr
|
||||
{
|
||||
enum { Dim = RotationDerived::Dim };
|
||||
typedef Matrix<typename RotationDerived::Scalar,Dim,1> ReturnType;
|
||||
static EIGEN_STRONG_INLINE ReturnType run(const RotationDerived& r, const OtherVectorType& v)
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE ReturnType run(const RotationDerived& r, const OtherVectorType& v)
|
||||
{
|
||||
return r._transformVector(v);
|
||||
}
|
||||
@@ -137,7 +137,7 @@ struct rotation_base_generic_product_selector<RotationDerived,OtherVectorType,tr
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
EIGEN_DEVICE_FUNC Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
@@ -150,7 +150,7 @@ Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>&
|
||||
EIGEN_DEVICE_FUNC Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
@@ -179,20 +179,20 @@ namespace internal {
|
||||
* \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
static inline Matrix<Scalar,2,2> toRotationMatrix(const Scalar& s)
|
||||
EIGEN_DEVICE_FUNC static inline Matrix<Scalar,2,2> toRotationMatrix(const Scalar& s)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return Rotation2D<Scalar>(s).toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline Matrix<Scalar,Dim,Dim> toRotationMatrix(const RotationBase<OtherDerived,Dim>& r)
|
||||
EIGEN_DEVICE_FUNC static inline Matrix<Scalar,Dim,Dim> toRotationMatrix(const RotationBase<OtherDerived,Dim>& r)
|
||||
{
|
||||
return r.toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline const MatrixBase<OtherDerived>& toRotationMatrix(const MatrixBase<OtherDerived>& mat)
|
||||
EIGEN_DEVICE_FUNC static inline const MatrixBase<OtherDerived>& toRotationMatrix(const MatrixBase<OtherDerived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim,
|
||||
YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
|
||||
12
Eigen/src/Geometry/Scaling.h
Normal file → Executable file
12
Eigen/src/Geometry/Scaling.h
Normal file → Executable file
@@ -118,28 +118,28 @@ operator*(const MatrixBase<Derived>& matrix, const UniformScaling<Scalar>& s)
|
||||
{ return matrix.derived() * s.factor(); }
|
||||
|
||||
/** Constructs a uniform scaling from scale factor \a s */
|
||||
static inline UniformScaling<float> Scaling(float s) { return UniformScaling<float>(s); }
|
||||
inline UniformScaling<float> Scaling(float s) { return UniformScaling<float>(s); }
|
||||
/** Constructs a uniform scaling from scale factor \a s */
|
||||
static inline UniformScaling<double> Scaling(double s) { return UniformScaling<double>(s); }
|
||||
inline UniformScaling<double> Scaling(double s) { return UniformScaling<double>(s); }
|
||||
/** Constructs a uniform scaling from scale factor \a s */
|
||||
template<typename RealScalar>
|
||||
static inline UniformScaling<std::complex<RealScalar> > Scaling(const std::complex<RealScalar>& s)
|
||||
inline UniformScaling<std::complex<RealScalar> > Scaling(const std::complex<RealScalar>& s)
|
||||
{ return UniformScaling<std::complex<RealScalar> >(s); }
|
||||
|
||||
/** Constructs a 2D axis aligned scaling */
|
||||
template<typename Scalar>
|
||||
static inline DiagonalMatrix<Scalar,2> Scaling(const Scalar& sx, const Scalar& sy)
|
||||
inline DiagonalMatrix<Scalar,2> Scaling(const Scalar& sx, const Scalar& sy)
|
||||
{ return DiagonalMatrix<Scalar,2>(sx, sy); }
|
||||
/** Constructs a 3D axis aligned scaling */
|
||||
template<typename Scalar>
|
||||
static inline DiagonalMatrix<Scalar,3> Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
inline DiagonalMatrix<Scalar,3> Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{ return DiagonalMatrix<Scalar,3>(sx, sy, sz); }
|
||||
|
||||
/** Constructs an axis aligned scaling expression from vector expression \a coeffs
|
||||
* This is an alias for coeffs.asDiagonal()
|
||||
*/
|
||||
template<typename Derived>
|
||||
static inline const DiagonalWrapper<const Derived> Scaling(const MatrixBase<Derived>& coeffs)
|
||||
inline const DiagonalWrapper<const Derived> Scaling(const MatrixBase<Derived>& coeffs)
|
||||
{ return coeffs.asDiagonal(); }
|
||||
|
||||
/** \deprecated */
|
||||
|
||||
@@ -193,7 +193,7 @@ template<int Mode> struct transform_make_affine;
|
||||
* preprocessor token EIGEN_QT_SUPPORT is defined.
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_TRANSFORM_PLUGIN.
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_TRANSFORM_PLUGIN.
|
||||
*
|
||||
* \sa class Matrix, class Quaternion
|
||||
*/
|
||||
@@ -253,43 +253,43 @@ public:
|
||||
|
||||
/** Default constructor without initialization of the meaningful coefficients.
|
||||
* If Mode==Affine, then the last row is set to [0 ... 0 1] */
|
||||
inline Transform()
|
||||
EIGEN_DEVICE_FUNC inline Transform()
|
||||
{
|
||||
check_template_params();
|
||||
internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix);
|
||||
}
|
||||
|
||||
inline Transform(const Transform& other)
|
||||
EIGEN_DEVICE_FUNC inline Transform(const Transform& other)
|
||||
{
|
||||
check_template_params();
|
||||
m_matrix = other.m_matrix;
|
||||
}
|
||||
|
||||
inline explicit Transform(const TranslationType& t)
|
||||
EIGEN_DEVICE_FUNC inline explicit Transform(const TranslationType& t)
|
||||
{
|
||||
check_template_params();
|
||||
*this = t;
|
||||
}
|
||||
inline explicit Transform(const UniformScaling<Scalar>& s)
|
||||
EIGEN_DEVICE_FUNC inline explicit Transform(const UniformScaling<Scalar>& s)
|
||||
{
|
||||
check_template_params();
|
||||
*this = s;
|
||||
}
|
||||
template<typename Derived>
|
||||
inline explicit Transform(const RotationBase<Derived, Dim>& r)
|
||||
EIGEN_DEVICE_FUNC inline explicit Transform(const RotationBase<Derived, Dim>& r)
|
||||
{
|
||||
check_template_params();
|
||||
*this = r;
|
||||
}
|
||||
|
||||
inline Transform& operator=(const Transform& other)
|
||||
EIGEN_DEVICE_FUNC inline Transform& operator=(const Transform& other)
|
||||
{ m_matrix = other.m_matrix; return *this; }
|
||||
|
||||
typedef internal::transform_take_affine_part<Transform> take_affine_part;
|
||||
|
||||
/** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */
|
||||
template<typename OtherDerived>
|
||||
inline explicit Transform(const EigenBase<OtherDerived>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit Transform(const EigenBase<OtherDerived>& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
|
||||
@@ -300,7 +300,7 @@ public:
|
||||
|
||||
/** Set \c *this from a Dim^2 or (Dim+1)^2 matrix. */
|
||||
template<typename OtherDerived>
|
||||
inline Transform& operator=(const EigenBase<OtherDerived>& other)
|
||||
EIGEN_DEVICE_FUNC inline Transform& operator=(const EigenBase<OtherDerived>& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
|
||||
@@ -310,7 +310,7 @@ public:
|
||||
}
|
||||
|
||||
template<int OtherOptions>
|
||||
inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other)
|
||||
EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other)
|
||||
{
|
||||
check_template_params();
|
||||
// only the options change, we can directly copy the matrices
|
||||
@@ -318,7 +318,7 @@ public:
|
||||
}
|
||||
|
||||
template<int OtherMode,int OtherOptions>
|
||||
inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
|
||||
EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
|
||||
{
|
||||
check_template_params();
|
||||
// prevent conversions as:
|
||||
@@ -359,14 +359,14 @@ public:
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
Transform(const ReturnByValue<OtherDerived>& other)
|
||||
EIGEN_DEVICE_FUNC Transform(const ReturnByValue<OtherDerived>& other)
|
||||
{
|
||||
check_template_params();
|
||||
other.evalTo(*this);
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
Transform& operator=(const ReturnByValue<OtherDerived>& other)
|
||||
EIGEN_DEVICE_FUNC Transform& operator=(const ReturnByValue<OtherDerived>& other)
|
||||
{
|
||||
other.evalTo(*this);
|
||||
return *this;
|
||||
@@ -381,35 +381,35 @@ public:
|
||||
inline QTransform toQTransform(void) const;
|
||||
#endif
|
||||
|
||||
Index rows() const { return int(Mode)==int(Projective) ? m_matrix.cols() : (m_matrix.cols()-1); }
|
||||
Index cols() const { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC Index rows() const { return int(Mode)==int(Projective) ? m_matrix.cols() : (m_matrix.cols()-1); }
|
||||
EIGEN_DEVICE_FUNC Index cols() const { return m_matrix.cols(); }
|
||||
|
||||
/** shortcut for m_matrix(row,col);
|
||||
* \sa MatrixBase::operator(Index,Index) const */
|
||||
inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
|
||||
/** shortcut for m_matrix(row,col);
|
||||
* \sa MatrixBase::operator(Index,Index) */
|
||||
inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
|
||||
|
||||
/** \returns a read-only expression of the transformation matrix */
|
||||
inline const MatrixType& matrix() const { return m_matrix; }
|
||||
EIGEN_DEVICE_FUNC inline const MatrixType& matrix() const { return m_matrix; }
|
||||
/** \returns a writable expression of the transformation matrix */
|
||||
inline MatrixType& matrix() { return m_matrix; }
|
||||
EIGEN_DEVICE_FUNC inline MatrixType& matrix() { return m_matrix; }
|
||||
|
||||
/** \returns a read-only expression of the linear part of the transformation */
|
||||
inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
|
||||
EIGEN_DEVICE_FUNC inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
|
||||
/** \returns a writable expression of the linear part of the transformation */
|
||||
inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
|
||||
EIGEN_DEVICE_FUNC inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
|
||||
|
||||
/** \returns a read-only expression of the Dim x HDim affine part of the transformation */
|
||||
inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
|
||||
EIGEN_DEVICE_FUNC inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
|
||||
/** \returns a writable expression of the Dim x HDim affine part of the transformation */
|
||||
inline AffinePart affine() { return take_affine_part::run(m_matrix); }
|
||||
EIGEN_DEVICE_FUNC inline AffinePart affine() { return take_affine_part::run(m_matrix); }
|
||||
|
||||
/** \returns a read-only expression of the translation vector of the transformation */
|
||||
inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
|
||||
EIGEN_DEVICE_FUNC inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
|
||||
/** \returns a writable expression of the translation vector of the transformation */
|
||||
inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
|
||||
EIGEN_DEVICE_FUNC inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
|
||||
|
||||
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other.
|
||||
*
|
||||
@@ -437,7 +437,7 @@ public:
|
||||
*/
|
||||
// note: this function is defined here because some compilers cannot find the respective declaration
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
|
||||
operator * (const EigenBase<OtherDerived> &other) const
|
||||
{ return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
|
||||
|
||||
@@ -449,7 +449,7 @@ public:
|
||||
* \li a general transformation matrix of size Dim+1 x Dim+1.
|
||||
*/
|
||||
template<typename OtherDerived> friend
|
||||
inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
|
||||
EIGEN_DEVICE_FUNC inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
|
||||
operator * (const EigenBase<OtherDerived> &a, const Transform &b)
|
||||
{ return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
|
||||
|
||||
@@ -460,11 +460,11 @@ public:
|
||||
* mode is no isometry. In that case, the returned transform is an affinity.
|
||||
*/
|
||||
template<typename DiagonalDerived>
|
||||
inline const TransformTimeDiagonalReturnType
|
||||
EIGEN_DEVICE_FUNC inline const TransformTimeDiagonalReturnType
|
||||
operator * (const DiagonalBase<DiagonalDerived> &b) const
|
||||
{
|
||||
TransformTimeDiagonalReturnType res(*this);
|
||||
res.linear() *= b;
|
||||
res.linearExt() *= b;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -475,7 +475,7 @@ public:
|
||||
* mode is no isometry. In that case, the returned transform is an affinity.
|
||||
*/
|
||||
template<typename DiagonalDerived>
|
||||
friend inline TransformTimeDiagonalReturnType
|
||||
EIGEN_DEVICE_FUNC friend inline TransformTimeDiagonalReturnType
|
||||
operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
|
||||
{
|
||||
TransformTimeDiagonalReturnType res;
|
||||
@@ -487,10 +487,10 @@ public:
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
|
||||
EIGEN_DEVICE_FUNC inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
|
||||
|
||||
/** Concatenates two transformations */
|
||||
inline const Transform operator * (const Transform& other) const
|
||||
EIGEN_DEVICE_FUNC inline const Transform operator * (const Transform& other) const
|
||||
{
|
||||
return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
|
||||
}
|
||||
@@ -522,7 +522,7 @@ public:
|
||||
#else
|
||||
/** Concatenates two different transformations */
|
||||
template<int OtherMode,int OtherOptions>
|
||||
inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
|
||||
EIGEN_DEVICE_FUNC inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
|
||||
operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
|
||||
{
|
||||
return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
|
||||
@@ -530,47 +530,61 @@ public:
|
||||
#endif
|
||||
|
||||
/** \sa MatrixBase::setIdentity() */
|
||||
void setIdentity() { m_matrix.setIdentity(); }
|
||||
EIGEN_DEVICE_FUNC void setIdentity() { m_matrix.setIdentity(); }
|
||||
|
||||
/**
|
||||
* \brief Returns an identity transformation.
|
||||
* \todo In the future this function should be returning a Transform expression.
|
||||
*/
|
||||
static const Transform Identity()
|
||||
EIGEN_DEVICE_FUNC static const Transform Identity()
|
||||
{
|
||||
return Transform(MatrixType::Identity());
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& scale(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& prescale(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
inline Transform& scale(const Scalar& s);
|
||||
inline Transform& prescale(const Scalar& s);
|
||||
EIGEN_DEVICE_FUNC inline Transform& scale(const Scalar& s);
|
||||
EIGEN_DEVICE_FUNC inline Transform& prescale(const Scalar& s);
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& translate(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename RotationType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& rotate(const RotationType& rotation);
|
||||
|
||||
template<typename RotationType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& prerotate(const RotationType& rotation);
|
||||
|
||||
Transform& shear(const Scalar& sx, const Scalar& sy);
|
||||
Transform& preshear(const Scalar& sx, const Scalar& sy);
|
||||
EIGEN_DEVICE_FUNC Transform& shear(const Scalar& sx, const Scalar& sy);
|
||||
EIGEN_DEVICE_FUNC Transform& preshear(const Scalar& sx, const Scalar& sy);
|
||||
|
||||
inline Transform& operator=(const TranslationType& t);
|
||||
EIGEN_DEVICE_FUNC inline Transform& operator=(const TranslationType& t);
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
|
||||
inline Transform operator*(const TranslationType& t) const;
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Transform operator*(const TranslationType& t) const;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& operator=(const UniformScaling<Scalar>& t);
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const
|
||||
{
|
||||
TransformTimeDiagonalReturnType res = *this;
|
||||
@@ -578,31 +592,36 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linearExt() *= s; return *this; }
|
||||
|
||||
template<typename Derived>
|
||||
inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
||||
EIGEN_DEVICE_FUNC inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
||||
template<typename Derived>
|
||||
inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
|
||||
EIGEN_DEVICE_FUNC inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
|
||||
template<typename Derived>
|
||||
inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
|
||||
EIGEN_DEVICE_FUNC inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
|
||||
|
||||
const LinearMatrixType rotation() const;
|
||||
EIGEN_DEVICE_FUNC const LinearMatrixType rotation() const;
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
|
||||
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
|
||||
|
||||
/** \returns a const pointer to the column major internal matrix */
|
||||
const Scalar* data() const { return m_matrix.data(); }
|
||||
EIGEN_DEVICE_FUNC const Scalar* data() const { return m_matrix.data(); }
|
||||
/** \returns a non-const pointer to the column major internal matrix */
|
||||
Scalar* data() { return m_matrix.data(); }
|
||||
EIGEN_DEVICE_FUNC Scalar* data() { return m_matrix.data(); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
@@ -610,12 +629,12 @@ public:
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
|
||||
{
|
||||
check_template_params();
|
||||
m_matrix = other.matrix().template cast<Scalar>();
|
||||
@@ -625,12 +644,12 @@ public:
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_matrix.isApprox(other.m_matrix, prec); }
|
||||
|
||||
/** Sets the last row to [0 ... 0 1]
|
||||
*/
|
||||
void makeAffine()
|
||||
EIGEN_DEVICE_FUNC void makeAffine()
|
||||
{
|
||||
internal::transform_make_affine<int(Mode)>::run(m_matrix);
|
||||
}
|
||||
@@ -639,26 +658,26 @@ public:
|
||||
* \returns the Dim x Dim linear part if the transformation is affine,
|
||||
* and the HDim x Dim part for projective transformations.
|
||||
*/
|
||||
inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
|
||||
EIGEN_DEVICE_FUNC inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
|
||||
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
|
||||
/** \internal
|
||||
* \returns the Dim x Dim linear part if the transformation is affine,
|
||||
* and the HDim x Dim part for projective transformations.
|
||||
*/
|
||||
inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
|
||||
EIGEN_DEVICE_FUNC inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
|
||||
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
|
||||
|
||||
/** \internal
|
||||
* \returns the translation part if the transformation is affine,
|
||||
* and the last column for projective transformations.
|
||||
*/
|
||||
inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
|
||||
EIGEN_DEVICE_FUNC inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
|
||||
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
|
||||
/** \internal
|
||||
* \returns the translation part if the transformation is affine,
|
||||
* and the last column for projective transformations.
|
||||
*/
|
||||
inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
|
||||
EIGEN_DEVICE_FUNC inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
|
||||
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
|
||||
|
||||
|
||||
@@ -668,7 +687,7 @@ public:
|
||||
|
||||
protected:
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
static EIGEN_STRONG_INLINE void check_template_params()
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void check_template_params()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
|
||||
}
|
||||
@@ -821,7 +840,7 @@ QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
@@ -835,7 +854,7 @@ Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
|
||||
* \sa prescale(Scalar)
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s)
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
||||
linearExt() *= s;
|
||||
@@ -848,12 +867,12 @@ inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::s
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
||||
m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
|
||||
affine().noalias() = (other.asDiagonal() * affine());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -862,7 +881,7 @@ Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &oth
|
||||
* \sa scale(Scalar)
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s)
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
||||
m_matrix.template topRows<Dim>() *= s;
|
||||
@@ -875,7 +894,7 @@ inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::p
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
@@ -889,7 +908,7 @@ Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &ot
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
@@ -919,7 +938,7 @@ Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived>
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename RotationType>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
|
||||
{
|
||||
linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
|
||||
@@ -935,7 +954,7 @@ Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename RotationType>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
|
||||
{
|
||||
m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
|
||||
@@ -949,7 +968,7 @@ Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
|
||||
* \sa preshear()
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
@@ -965,7 +984,7 @@ Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
|
||||
* \sa shear()
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
@@ -979,7 +998,7 @@ Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
|
||||
******************************************************/
|
||||
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
|
||||
{
|
||||
linear().setIdentity();
|
||||
translation() = t.vector();
|
||||
@@ -988,7 +1007,7 @@ inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::o
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.translate(t.vector());
|
||||
@@ -996,7 +1015,7 @@ inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::op
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
|
||||
{
|
||||
m_matrix.setZero();
|
||||
linear().diagonal().fill(s.factor());
|
||||
@@ -1006,7 +1025,7 @@ inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::o
|
||||
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
|
||||
{
|
||||
linear() = internal::toRotationMatrix<Scalar,Dim>(r);
|
||||
translation().setZero();
|
||||
@@ -1016,7 +1035,7 @@ inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::o
|
||||
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.rotate(r.derived());
|
||||
@@ -1035,7 +1054,7 @@ inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::op
|
||||
* \sa computeRotationScaling(), computeScalingRotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
|
||||
EIGEN_DEVICE_FUNC const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
|
||||
Transform<Scalar,Dim,Mode,Options>::rotation() const
|
||||
{
|
||||
LinearMatrixType result;
|
||||
@@ -1057,7 +1076,7 @@ Transform<Scalar,Dim,Mode,Options>::rotation() const
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
|
||||
EIGEN_DEVICE_FUNC void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
|
||||
{
|
||||
JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
|
||||
|
||||
@@ -1073,7 +1092,7 @@ void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixTy
|
||||
}
|
||||
}
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
/** decomposes the linear part of the transformation as a product scaling x rotation, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
@@ -1086,7 +1105,7 @@ void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixTy
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
|
||||
EIGEN_DEVICE_FUNC void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
|
||||
{
|
||||
JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
|
||||
|
||||
@@ -1107,7 +1126,7 @@ void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixTyp
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
Transform<Scalar,Dim,Mode,Options>&
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
|
||||
Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
|
||||
{
|
||||
@@ -1124,7 +1143,7 @@ template<int Mode>
|
||||
struct transform_make_affine
|
||||
{
|
||||
template<typename MatrixType>
|
||||
static void run(MatrixType &mat)
|
||||
EIGEN_DEVICE_FUNC static void run(MatrixType &mat)
|
||||
{
|
||||
static const int Dim = MatrixType::ColsAtCompileTime-1;
|
||||
mat.template block<1,Dim>(Dim,0).setZero();
|
||||
@@ -1135,21 +1154,21 @@ struct transform_make_affine
|
||||
template<>
|
||||
struct transform_make_affine<AffineCompact>
|
||||
{
|
||||
template<typename MatrixType> static void run(MatrixType &) { }
|
||||
template<typename MatrixType> EIGEN_DEVICE_FUNC static void run(MatrixType &) { }
|
||||
};
|
||||
|
||||
// selector needed to avoid taking the inverse of a 3x4 matrix
|
||||
template<typename TransformType, int Mode=TransformType::Mode>
|
||||
struct projective_transform_inverse
|
||||
{
|
||||
static inline void run(const TransformType&, TransformType&)
|
||||
EIGEN_DEVICE_FUNC static inline void run(const TransformType&, TransformType&)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename TransformType>
|
||||
struct projective_transform_inverse<TransformType, Projective>
|
||||
{
|
||||
static inline void run(const TransformType& m, TransformType& res)
|
||||
EIGEN_DEVICE_FUNC static inline void run(const TransformType& m, TransformType& res)
|
||||
{
|
||||
res.matrix() = m.matrix().inverse();
|
||||
}
|
||||
@@ -1179,7 +1198,7 @@ struct projective_transform_inverse<TransformType, Projective>
|
||||
* \sa MatrixBase::inverse()
|
||||
*/
|
||||
template<typename Scalar, int Dim, int Mode, int Options>
|
||||
Transform<Scalar,Dim,Mode,Options>
|
||||
EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>
|
||||
Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
|
||||
{
|
||||
Transform res;
|
||||
|
||||
@@ -51,16 +51,16 @@ protected:
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
Translation() {}
|
||||
EIGEN_DEVICE_FUNC Translation() {}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy)
|
||||
EIGEN_DEVICE_FUNC inline Translation(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
eigen_assert(Dim==2);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
EIGEN_DEVICE_FUNC inline Translation(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{
|
||||
eigen_assert(Dim==3);
|
||||
m_coeffs.x() = sx;
|
||||
@@ -68,48 +68,48 @@ public:
|
||||
m_coeffs.z() = sz;
|
||||
}
|
||||
/** Constructs and initialize the translation transformation from a vector of translation coefficients */
|
||||
explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}
|
||||
EIGEN_DEVICE_FUNC explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}
|
||||
|
||||
/** \brief Retruns the x-translation by value. **/
|
||||
inline Scalar x() const { return m_coeffs.x(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar x() const { return m_coeffs.x(); }
|
||||
/** \brief Retruns the y-translation by value. **/
|
||||
inline Scalar y() const { return m_coeffs.y(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar y() const { return m_coeffs.y(); }
|
||||
/** \brief Retruns the z-translation by value. **/
|
||||
inline Scalar z() const { return m_coeffs.z(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar z() const { return m_coeffs.z(); }
|
||||
|
||||
/** \brief Retruns the x-translation as a reference. **/
|
||||
inline Scalar& x() { return m_coeffs.x(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& x() { return m_coeffs.x(); }
|
||||
/** \brief Retruns the y-translation as a reference. **/
|
||||
inline Scalar& y() { return m_coeffs.y(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& y() { return m_coeffs.y(); }
|
||||
/** \brief Retruns the z-translation as a reference. **/
|
||||
inline Scalar& z() { return m_coeffs.z(); }
|
||||
EIGEN_DEVICE_FUNC inline Scalar& z() { return m_coeffs.z(); }
|
||||
|
||||
const VectorType& vector() const { return m_coeffs; }
|
||||
VectorType& vector() { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC const VectorType& vector() const { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC VectorType& vector() { return m_coeffs; }
|
||||
|
||||
const VectorType& translation() const { return m_coeffs; }
|
||||
VectorType& translation() { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC const VectorType& translation() const { return m_coeffs; }
|
||||
EIGEN_DEVICE_FUNC VectorType& translation() { return m_coeffs; }
|
||||
|
||||
/** Concatenates two translation */
|
||||
inline Translation operator* (const Translation& other) const
|
||||
EIGEN_DEVICE_FUNC inline Translation operator* (const Translation& other) const
|
||||
{ return Translation(m_coeffs + other.m_coeffs); }
|
||||
|
||||
/** Concatenates a translation and a uniform scaling */
|
||||
inline AffineTransformType operator* (const UniformScaling<Scalar>& other) const;
|
||||
EIGEN_DEVICE_FUNC inline AffineTransformType operator* (const UniformScaling<Scalar>& other) const;
|
||||
|
||||
/** Concatenates a translation and a linear transformation */
|
||||
template<typename OtherDerived>
|
||||
inline AffineTransformType operator* (const EigenBase<OtherDerived>& linear) const;
|
||||
EIGEN_DEVICE_FUNC inline AffineTransformType operator* (const EigenBase<OtherDerived>& linear) const;
|
||||
|
||||
/** Concatenates a translation and a rotation */
|
||||
template<typename Derived>
|
||||
inline IsometryTransformType operator*(const RotationBase<Derived,Dim>& r) const
|
||||
EIGEN_DEVICE_FUNC inline IsometryTransformType operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{ return *this * IsometryTransformType(r); }
|
||||
|
||||
/** \returns the concatenation of a linear transformation \a l with the translation \a t */
|
||||
// its a nightmare to define a templated friend function outside its declaration
|
||||
template<typename OtherDerived> friend
|
||||
inline AffineTransformType operator*(const EigenBase<OtherDerived>& linear, const Translation& t)
|
||||
EIGEN_DEVICE_FUNC inline AffineTransformType operator*(const EigenBase<OtherDerived>& linear, const Translation& t)
|
||||
{
|
||||
AffineTransformType res;
|
||||
res.matrix().setZero();
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
|
||||
/** Concatenates a translation and a transformation */
|
||||
template<int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode> operator* (const Transform<Scalar,Dim,Mode,Options>& t) const
|
||||
EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode> operator* (const Transform<Scalar,Dim,Mode,Options>& t) const
|
||||
{
|
||||
Transform<Scalar,Dim,Mode> res = t;
|
||||
res.pretranslate(m_coeffs);
|
||||
@@ -130,8 +130,10 @@ public:
|
||||
}
|
||||
|
||||
/** Applies translation to vector */
|
||||
inline VectorType operator* (const VectorType& other) const
|
||||
{ return m_coeffs + other; }
|
||||
template<typename Derived>
|
||||
inline typename internal::enable_if<Derived::IsVectorAtCompileTime,VectorType>::type
|
||||
operator* (const MatrixBase<Derived>& vec) const
|
||||
{ return m_coeffs + vec.derived(); }
|
||||
|
||||
/** \returns the inverse translation (opposite) */
|
||||
Translation inverse() const { return Translation(-m_coeffs); }
|
||||
@@ -150,19 +152,19 @@ public:
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
|
||||
EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
|
||||
EIGEN_DEVICE_FUNC inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.vector().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Translation& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
EIGEN_DEVICE_FUNC bool isApprox(const Translation& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
@@ -176,7 +178,7 @@ typedef Translation<double,3> Translation3d;
|
||||
//@}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::AffineTransformType
|
||||
EIGEN_DEVICE_FUNC inline typename Translation<Scalar,Dim>::AffineTransformType
|
||||
Translation<Scalar,Dim>::operator* (const UniformScaling<Scalar>& other) const
|
||||
{
|
||||
AffineTransformType res;
|
||||
@@ -189,7 +191,7 @@ Translation<Scalar,Dim>::operator* (const UniformScaling<Scalar>& other) const
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
inline typename Translation<Scalar,Dim>::AffineTransformType
|
||||
EIGEN_DEVICE_FUNC inline typename Translation<Scalar,Dim>::AffineTransformType
|
||||
Translation<Scalar,Dim>::operator* (const EigenBase<OtherDerived>& linear) const
|
||||
{
|
||||
AffineTransformType res;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Geometry_arch_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Geometry_arch_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Geometry/arch COMPONENT Devel
|
||||
)
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Householder_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Householder_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Householder COMPONENT Devel
|
||||
)
|
||||
@@ -119,7 +119,7 @@ void MatrixBase<Derived>::applyHouseholderOnTheLeft(
|
||||
{
|
||||
*this *= Scalar(1)-tau;
|
||||
}
|
||||
else
|
||||
else if(tau!=Scalar(0))
|
||||
{
|
||||
Map<typename internal::plain_row_type<PlainObject>::type> tmp(workspace,cols());
|
||||
Block<Derived, EssentialPart::SizeAtCompileTime, Derived::ColsAtCompileTime> bottom(derived(), 1, 0, rows()-1, cols());
|
||||
@@ -156,7 +156,7 @@ void MatrixBase<Derived>::applyHouseholderOnTheRight(
|
||||
{
|
||||
*this *= Scalar(1)-tau;
|
||||
}
|
||||
else
|
||||
else if(tau!=Scalar(0))
|
||||
{
|
||||
Map<typename internal::plain_col_type<PlainObject>::type> tmp(workspace,rows());
|
||||
Block<Derived, Derived::RowsAtCompileTime, EssentialPart::SizeAtCompileTime> right(derived(), 0, 1, rows(), cols()-1);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user