mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
400 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eeac81b8c0 | ||
|
|
e80bc2ddb0 | ||
|
|
db3903498d | ||
|
|
dcc14bee64 | ||
|
|
b88c1117d4 | ||
|
|
912cb3d660 | ||
|
|
1b345b0895 | ||
|
|
1b95717358 | ||
|
|
d57430dd73 | ||
|
|
73985ead27 | ||
|
|
436a111792 | ||
|
|
afc55b1885 | ||
|
|
a5c2d8a3cc | ||
|
|
f8bfe10613 | ||
|
|
fc7180cda8 | ||
|
|
4d226ab5b5 | ||
|
|
ad086b03e4 | ||
|
|
dad177be01 | ||
|
|
55b4fd1d40 | ||
|
|
a354c3ca59 | ||
|
|
d46a36cc84 | ||
|
|
0ebe3808ca | ||
|
|
47d1b4a609 | ||
|
|
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)
|
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. ")
|
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()
|
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
|
# guard against bad build-type strings
|
||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
@@ -93,9 +98,11 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(EIGEN_BUILD_BTL "Build benchmark suite" OFF)
|
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)
|
option(EIGEN_BUILD_PKGCONFIG "Build pkg-config .pc file for Eigen" ON)
|
||||||
endif(NOT WIN32)
|
endif()
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
@@ -126,7 +133,6 @@ if(NOT MSVC)
|
|||||||
if(COMPILER_SUPPORT_WERROR)
|
if(COMPILER_SUPPORT_WERROR)
|
||||||
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ei_add_cxx_compiler_flag("-pedantic")
|
ei_add_cxx_compiler_flag("-pedantic")
|
||||||
ei_add_cxx_compiler_flag("-Wall")
|
ei_add_cxx_compiler_flag("-Wall")
|
||||||
ei_add_cxx_compiler_flag("-Wextra")
|
ei_add_cxx_compiler_flag("-Wextra")
|
||||||
@@ -224,6 +230,12 @@ if(NOT MSVC)
|
|||||||
message(STATUS "Enabling FMA in tests/examples")
|
message(STATUS "Enabling FMA in tests/examples")
|
||||||
endif()
|
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)
|
option(EIGEN_TEST_F16C "Enable/Disable F16C in tests/examples" OFF)
|
||||||
if(EIGEN_TEST_F16C)
|
if(EIGEN_TEST_F16C)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mf16c")
|
||||||
@@ -398,7 +410,7 @@ if(EIGEN_BUILD_PKGCONFIG)
|
|||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen3.pc
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen3.pc
|
||||||
DESTINATION ${PKGCONFIG_INSTALL_DIR}
|
DESTINATION ${PKGCONFIG_INSTALL_DIR}
|
||||||
)
|
)
|
||||||
endif(EIGEN_BUILD_PKGCONFIG)
|
endif()
|
||||||
|
|
||||||
add_subdirectory(Eigen)
|
add_subdirectory(Eigen)
|
||||||
|
|
||||||
@@ -424,6 +436,13 @@ else()
|
|||||||
add_subdirectory(lapack EXCLUDE_FROM_ALL)
|
add_subdirectory(lapack EXCLUDE_FROM_ALL)
|
||||||
endif()
|
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(unsupported)
|
||||||
|
|
||||||
add_subdirectory(demos EXCLUDE_FROM_ALL)
|
add_subdirectory(demos EXCLUDE_FROM_ALL)
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ install(FILES
|
|||||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen COMPONENT Devel
|
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen COMPONENT Devel
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(src)
|
install(DIRECTORY src DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen COMPONENT Devel FILES_MATCHING PATTERN "*.h")
|
||||||
|
|||||||
54
Eigen/Core
54
Eigen/Core
@@ -14,9 +14,9 @@
|
|||||||
// first thing Eigen does: stop the compiler from committing suicide
|
// first thing Eigen does: stop the compiler from committing suicide
|
||||||
#include "src/Core/util/DisableStupidWarnings.h"
|
#include "src/Core/util/DisableStupidWarnings.h"
|
||||||
|
|
||||||
// Handle NVCC/CUDA
|
// Handle NVCC/CUDA/SYCL
|
||||||
#ifdef __CUDACC__
|
#if defined(__CUDACC__) || defined(__SYCL_DEVICE_ONLY__)
|
||||||
// Do not try asserts on CUDA!
|
// Do not try asserts on CUDA and SYCL!
|
||||||
#ifndef EIGEN_NO_DEBUG
|
#ifndef EIGEN_NO_DEBUG
|
||||||
#define EIGEN_NO_DEBUG
|
#define EIGEN_NO_DEBUG
|
||||||
#endif
|
#endif
|
||||||
@@ -25,17 +25,24 @@
|
|||||||
#undef EIGEN_INTERNAL_DEBUGGING
|
#undef EIGEN_INTERNAL_DEBUGGING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Do not try to vectorize on CUDA!
|
|
||||||
#ifndef EIGEN_DONT_VECTORIZE
|
|
||||||
#define EIGEN_DONT_VECTORIZE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EIGEN_EXCEPTIONS
|
#ifdef EIGEN_EXCEPTIONS
|
||||||
#undef EIGEN_EXCEPTIONS
|
#undef EIGEN_EXCEPTIONS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// All functions callable from CUDA code must be qualified with __device__
|
// 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
|
#else
|
||||||
#define EIGEN_DEVICE_FUNC
|
#define EIGEN_DEVICE_FUNC
|
||||||
@@ -51,7 +58,7 @@
|
|||||||
#define EIGEN_USING_STD_MATH(FUNC) using std::FUNC;
|
#define EIGEN_USING_STD_MATH(FUNC) using std::FUNC;
|
||||||
#endif
|
#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
|
#define EIGEN_EXCEPTIONS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -140,6 +147,15 @@
|
|||||||
#ifdef __FMA__
|
#ifdef __FMA__
|
||||||
#define EIGEN_VECTORIZE_FMA
|
#define EIGEN_VECTORIZE_FMA
|
||||||
#endif
|
#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
|
// include files
|
||||||
|
|
||||||
@@ -171,7 +187,7 @@
|
|||||||
#ifdef EIGEN_VECTORIZE_SSE4_2
|
#ifdef EIGEN_VECTORIZE_SSE4_2
|
||||||
#include <nmmintrin.h>
|
#include <nmmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef EIGEN_VECTORIZE_AVX
|
#if defined(EIGEN_VECTORIZE_AVX) || defined(EIGEN_VECTORIZE_AVX512)
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -271,7 +287,9 @@
|
|||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
inline static const char *SimdInstructionSetsInUse(void) {
|
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";
|
return "AVX SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
|
||||||
#elif defined(EIGEN_VECTORIZE_SSE4_2)
|
#elif defined(EIGEN_VECTORIZE_SSE4_2)
|
||||||
return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
|
return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
|
||||||
@@ -329,8 +347,14 @@ using std::ptrdiff_t;
|
|||||||
#include "src/Core/NumTraits.h"
|
#include "src/Core/NumTraits.h"
|
||||||
#include "src/Core/MathFunctions.h"
|
#include "src/Core/MathFunctions.h"
|
||||||
#include "src/Core/GenericPacketMath.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
|
// Use AVX for floats and doubles, SSE for integers
|
||||||
#include "src/Core/arch/SSE/PacketMath.h"
|
#include "src/Core/arch/SSE/PacketMath.h"
|
||||||
#include "src/Core/arch/SSE/Complex.h"
|
#include "src/Core/arch/SSE/Complex.h"
|
||||||
@@ -377,6 +401,10 @@ using std::ptrdiff_t;
|
|||||||
#include "src/Core/functors/StlFunctors.h"
|
#include "src/Core/functors/StlFunctors.h"
|
||||||
#include "src/Core/functors/AssignmentFunctors.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/DenseCoeffsBase.h"
|
||||||
#include "src/Core/DenseBase.h"
|
#include "src/Core/DenseBase.h"
|
||||||
#include "src/Core/MatrixBase.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
|
ComputationInfo info() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
return Success;
|
return m_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
@@ -281,6 +281,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
TmpMatrixType m_temporary;
|
TmpMatrixType m_temporary;
|
||||||
internal::SignMatrix m_sign;
|
internal::SignMatrix m_sign;
|
||||||
bool m_isInitialized;
|
bool m_isInitialized;
|
||||||
|
ComputationInfo m_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@@ -298,6 +299,8 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
typedef typename TranspositionType::StorageIndex IndexType;
|
typedef typename TranspositionType::StorageIndex IndexType;
|
||||||
eigen_assert(mat.rows()==mat.cols());
|
eigen_assert(mat.rows()==mat.cols());
|
||||||
const Index size = mat.rows();
|
const Index size = mat.rows();
|
||||||
|
bool found_zero_pivot = false;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
if (size <= 1)
|
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.
|
// we should only make sure that we do not introduce INF or NaN values.
|
||||||
// Remark that LAPACK also uses 0 as the cutoff value.
|
// Remark that LAPACK also uses 0 as the cutoff value.
|
||||||
RealScalar realAkk = numext::real(mat.coeffRef(k,k));
|
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;
|
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 (sign == PositiveSemiDef) {
|
||||||
if (realAkk < static_cast<RealScalar>(0)) sign = Indefinite;
|
if (realAkk < static_cast<RealScalar>(0)) sign = Indefinite;
|
||||||
} else if (sign == NegativeSemiDef) {
|
} 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
|
// 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_temporary.resize(size);
|
||||||
m_sign = internal::ZeroSign;
|
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;
|
m_isInitialized = true;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -621,7 +642,6 @@ MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __CUDACC__
|
|
||||||
/** \cholesky_module
|
/** \cholesky_module
|
||||||
* \returns the Cholesky decomposition with full pivoting without square root of \c *this
|
* \returns the Cholesky decomposition with full pivoting without square root of \c *this
|
||||||
* \sa MatrixBase::ldlt()
|
* \sa MatrixBase::ldlt()
|
||||||
@@ -643,7 +663,6 @@ MatrixBase<Derived>::ldlt() const
|
|||||||
{
|
{
|
||||||
return LDLT<PlainObject>(derived());
|
return LDLT<PlainObject>(derived());
|
||||||
}
|
}
|
||||||
#endif // __CUDACC__
|
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ template<typename Scalar> struct llt_inplace<Scalar, Lower>
|
|||||||
Index ret;
|
Index ret;
|
||||||
if((ret=unblocked(A11))>=0) return k+ret;
|
if((ret=unblocked(A11))>=0) return k+ret;
|
||||||
if(rs>0) A11.adjoint().template triangularView<Upper>().template solveInPlace<OnTheRight>(A21);
|
if(rs>0) A11.adjoint().template triangularView<Upper>().template solveInPlace<OnTheRight>(A21);
|
||||||
if(rs>0) A22.template selfadjointView<Lower>().rankUpdate(A21,-1); // bottleneck
|
if(rs>0) A22.template selfadjointView<Lower>().rankUpdate(A21,typename NumTraits<RealScalar>::Literal(-1)); // bottleneck
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -507,7 +507,6 @@ MatrixType LLT<MatrixType,_UpLo>::reconstructedMatrix() const
|
|||||||
return matrixL() * matrixL().adjoint().toDenseMatrix();
|
return matrixL() * matrixL().adjoint().toDenseMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __CUDACC__
|
|
||||||
/** \cholesky_module
|
/** \cholesky_module
|
||||||
* \returns the LLT decomposition of \c *this
|
* \returns the LLT decomposition of \c *this
|
||||||
* \sa SelfAdjointView::llt()
|
* \sa SelfAdjointView::llt()
|
||||||
@@ -529,7 +528,6 @@ SelfAdjointView<MatrixType, UpLo>::llt() const
|
|||||||
{
|
{
|
||||||
return LLT<PlainObject,UpLo>(m_matrix);
|
return LLT<PlainObject,UpLo>(m_matrix);
|
||||||
}
|
}
|
||||||
#endif // __CUDACC__
|
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // 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 {
|
namespace internal {
|
||||||
|
|
||||||
template<typename Scalar, typename CholmodType>
|
template<typename Scalar> struct cholmod_configure_matrix;
|
||||||
void cholmod_configure_matrix(CholmodType& mat)
|
|
||||||
{
|
template<> struct cholmod_configure_matrix<double> {
|
||||||
if (internal::is_same<Scalar,float>::value)
|
template<typename CholmodType>
|
||||||
{
|
static void run(CholmodType& mat) {
|
||||||
mat.xtype = CHOLMOD_REAL;
|
|
||||||
mat.dtype = CHOLMOD_SINGLE;
|
|
||||||
}
|
|
||||||
else if (internal::is_same<Scalar,double>::value)
|
|
||||||
{
|
|
||||||
mat.xtype = CHOLMOD_REAL;
|
mat.xtype = CHOLMOD_REAL;
|
||||||
mat.dtype = CHOLMOD_DOUBLE;
|
mat.dtype = CHOLMOD_DOUBLE;
|
||||||
}
|
}
|
||||||
else if (internal::is_same<Scalar,std::complex<float> >::value)
|
};
|
||||||
{
|
|
||||||
mat.xtype = CHOLMOD_COMPLEX;
|
template<> struct cholmod_configure_matrix<std::complex<double> > {
|
||||||
mat.dtype = CHOLMOD_SINGLE;
|
template<typename CholmodType>
|
||||||
}
|
static void run(CholmodType& mat) {
|
||||||
else if (internal::is_same<Scalar,std::complex<double> >::value)
|
|
||||||
{
|
|
||||||
mat.xtype = CHOLMOD_COMPLEX;
|
mat.xtype = CHOLMOD_COMPLEX;
|
||||||
mat.dtype = CHOLMOD_DOUBLE;
|
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
|
} // namespace internal
|
||||||
|
|
||||||
@@ -49,11 +55,11 @@ void cholmod_configure_matrix(CholmodType& mat)
|
|||||||
* Note that the data are shared.
|
* Note that the data are shared.
|
||||||
*/
|
*/
|
||||||
template<typename _Scalar, int _Options, typename _StorageIndex>
|
template<typename _Scalar, int _Options, typename _StorageIndex>
|
||||||
cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_StorageIndex>& mat)
|
cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> > mat)
|
||||||
{
|
{
|
||||||
cholmod_sparse res;
|
cholmod_sparse res;
|
||||||
res.nzmax = mat.nonZeros();
|
res.nzmax = mat.nonZeros();
|
||||||
res.nrow = mat.rows();;
|
res.nrow = mat.rows();
|
||||||
res.ncol = mat.cols();
|
res.ncol = mat.cols();
|
||||||
res.p = mat.outerIndexPtr();
|
res.p = mat.outerIndexPtr();
|
||||||
res.i = mat.innerIndexPtr();
|
res.i = mat.innerIndexPtr();
|
||||||
@@ -88,7 +94,7 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_StorageIndex>& mat)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup res.xtype
|
// setup res.xtype
|
||||||
internal::cholmod_configure_matrix<_Scalar>(res);
|
internal::cholmod_configure_matrix<_Scalar>::run(res);
|
||||||
|
|
||||||
res.stype = 0;
|
res.stype = 0;
|
||||||
|
|
||||||
@@ -98,7 +104,14 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_StorageIndex>& mat)
|
|||||||
template<typename _Scalar, int _Options, typename _Index>
|
template<typename _Scalar, int _Options, typename _Index>
|
||||||
const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
|
const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
|
||||||
{
|
{
|
||||||
cholmod_sparse res = viewAsCholmod(mat.const_cast_derived());
|
cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Scalar, int _Options, typename _Index>
|
||||||
|
const cholmod_sparse viewAsCholmod(const SparseVector<_Scalar,_Options,_Index>& mat)
|
||||||
|
{
|
||||||
|
cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +120,7 @@ const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>&
|
|||||||
template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
|
template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
|
||||||
cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat)
|
cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat)
|
||||||
{
|
{
|
||||||
cholmod_sparse res = viewAsCholmod(mat.matrix().const_cast_derived());
|
cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived()));
|
||||||
|
|
||||||
if(UpLo==Upper) res.stype = 1;
|
if(UpLo==Upper) res.stype = 1;
|
||||||
if(UpLo==Lower) res.stype = -1;
|
if(UpLo==Lower) res.stype = -1;
|
||||||
@@ -131,7 +144,7 @@ cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
|
|||||||
res.x = (void*)(mat.derived().data());
|
res.x = (void*)(mat.derived().data());
|
||||||
res.z = 0;
|
res.z = 0;
|
||||||
|
|
||||||
internal::cholmod_configure_matrix<Scalar>(res);
|
internal::cholmod_configure_matrix<Scalar>::run(res);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -180,14 +193,16 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||||||
CholmodBase()
|
CholmodBase()
|
||||||
: m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
|
: 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);
|
cholmod_start(&m_cholmod);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit CholmodBase(const MatrixType& matrix)
|
explicit CholmodBase(const MatrixType& matrix)
|
||||||
: m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
|
: 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);
|
cholmod_start(&m_cholmod);
|
||||||
compute(matrix);
|
compute(matrix);
|
||||||
}
|
}
|
||||||
@@ -254,7 +269,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||||||
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
||||||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
||||||
cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
|
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.
|
// 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);
|
this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
|
||||||
m_factorizationIsOk = true;
|
m_factorizationIsOk = true;
|
||||||
@@ -290,8 +305,8 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \internal */
|
/** \internal */
|
||||||
template<typename RhsScalar, int RhsOptions, typename RhsIndex, typename DestScalar, int DestOptions, typename DestIndex>
|
template<typename RhsDerived, typename DestDerived>
|
||||||
void _solve_impl(const SparseMatrix<RhsScalar,RhsOptions,RhsIndex> &b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const
|
void _solve_impl(const SparseMatrixBase<RhsDerived> &b, SparseMatrixBase<DestDerived> &dest) const
|
||||||
{
|
{
|
||||||
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
|
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
|
||||||
const Index size = m_cholmodFactor->n;
|
const Index size = m_cholmodFactor->n;
|
||||||
@@ -299,7 +314,8 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||||||
eigen_assert(size==b.rows());
|
eigen_assert(size==b.rows());
|
||||||
|
|
||||||
// note: cs stands for Cholmod Sparse
|
// note: cs stands for Cholmod Sparse
|
||||||
cholmod_sparse b_cs = viewAsCholmod(b);
|
Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived());
|
||||||
|
cholmod_sparse b_cs = viewAsCholmod(b_ref);
|
||||||
cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
|
cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
|
||||||
if(!x_cs)
|
if(!x_cs)
|
||||||
{
|
{
|
||||||
@@ -307,7 +323,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
||||||
dest = viewAsEigen<DestScalar,DestOptions,DestIndex>(*x_cs);
|
dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
|
||||||
cholmod_free_sparse(&x_cs, &m_cholmod);
|
cholmod_free_sparse(&x_cs, &m_cholmod);
|
||||||
}
|
}
|
||||||
#endif // EIGEN_PARSED_BY_DOXYGEN
|
#endif // EIGEN_PARSED_BY_DOXYGEN
|
||||||
@@ -324,7 +340,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||||||
*/
|
*/
|
||||||
Derived& setShift(const RealScalar& offset)
|
Derived& setShift(const RealScalar& offset)
|
||||||
{
|
{
|
||||||
m_shiftOffset[0] = offset;
|
m_shiftOffset[0] = double(offset);
|
||||||
return derived();
|
return derived();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +402,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||||||
protected:
|
protected:
|
||||||
mutable cholmod_common m_cholmod;
|
mutable cholmod_common m_cholmod;
|
||||||
cholmod_factor* m_cholmodFactor;
|
cholmod_factor* m_cholmodFactor;
|
||||||
RealScalar m_shiftOffset[2];
|
double m_shiftOffset[2];
|
||||||
mutable ComputationInfo m_info;
|
mutable ComputationInfo m_info;
|
||||||
int m_factorizationIsOk;
|
int m_factorizationIsOk;
|
||||||
int m_analysisIsOk;
|
int m_analysisIsOk;
|
||||||
@@ -410,6 +426,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.
|
* 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
|
* \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLLT
|
||||||
*/
|
*/
|
||||||
template<typename _MatrixType, int _UpLo = Lower>
|
template<typename _MatrixType, int _UpLo = Lower>
|
||||||
@@ -459,6 +477,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.
|
* 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
|
* \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLDLT
|
||||||
*/
|
*/
|
||||||
template<typename _MatrixType, int _UpLo = Lower>
|
template<typename _MatrixType, int _UpLo = Lower>
|
||||||
@@ -506,6 +526,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.
|
* 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
|
* \sa \ref TutorialSparseSolverConcept
|
||||||
*/
|
*/
|
||||||
template<typename _MatrixType, int _UpLo = Lower>
|
template<typename _MatrixType, int _UpLo = Lower>
|
||||||
@@ -555,6 +577,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.
|
* 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
|
* \sa \ref TutorialSparseSolverConcept
|
||||||
*/
|
*/
|
||||||
template<typename _MatrixType, int _UpLo = Lower>
|
template<typename _MatrixType, int _UpLo = Lower>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ struct traits<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > : tra
|
|||||||
* storage layout.
|
* storage layout.
|
||||||
*
|
*
|
||||||
* This class can be extended with the help of the plugin mechanism described on the page
|
* 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
|
* \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.
|
* \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
|
* 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
|
* \sa class MatrixBase, \ref TopicClassHierarchy
|
||||||
*/
|
*/
|
||||||
@@ -87,6 +87,7 @@ template<typename Derived> class ArrayBase
|
|||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
|
||||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::ArrayBase
|
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::ArrayBase
|
||||||
|
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
|
||||||
# include "../plugins/CommonCwiseUnaryOps.h"
|
# include "../plugins/CommonCwiseUnaryOps.h"
|
||||||
# include "../plugins/MatrixCwiseUnaryOps.h"
|
# include "../plugins/MatrixCwiseUnaryOps.h"
|
||||||
# include "../plugins/ArrayCwiseUnaryOps.h"
|
# include "../plugins/ArrayCwiseUnaryOps.h"
|
||||||
@@ -97,6 +98,7 @@ template<typename Derived> class ArrayBase
|
|||||||
# include EIGEN_ARRAYBASE_PLUGIN
|
# include EIGEN_ARRAYBASE_PLUGIN
|
||||||
# endif
|
# endif
|
||||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
||||||
|
#undef EIGEN_DOC_UNARY_ADDONS
|
||||||
|
|
||||||
/** Special case of the template operator=, in order to prevent the compiler
|
/** Special case of the template operator=, in order to prevent the compiler
|
||||||
* from generating a default operator= (issue hit with g++ 4.1)
|
* 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;
|
typedef typename internal::ref_selector<ExpressionType>::non_const_type NestedExpressionType;
|
||||||
|
|
||||||
|
using Base::coeffRef;
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
explicit EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
explicit EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||||
|
|
||||||
@@ -71,66 +73,18 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
|||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
inline const Scalar* data() const { return m_expression.data(); }
|
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
|
EIGEN_DEVICE_FUNC
|
||||||
inline const Scalar& coeffRef(Index rowId, Index colId) const
|
inline const Scalar& coeffRef(Index rowId, Index colId) const
|
||||||
{
|
{
|
||||||
return m_expression.coeffRef(rowId, colId);
|
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
|
EIGEN_DEVICE_FUNC
|
||||||
inline const Scalar& coeffRef(Index index) const
|
inline const Scalar& coeffRef(Index index) const
|
||||||
{
|
{
|
||||||
return m_expression.coeffRef(index);
|
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>
|
template<typename Dest>
|
||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
inline void evalTo(Dest& dst) const { dst = m_expression; }
|
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;
|
typedef typename internal::ref_selector<ExpressionType>::non_const_type NestedExpressionType;
|
||||||
|
|
||||||
|
using Base::coeffRef;
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
explicit inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
explicit inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||||
|
|
||||||
@@ -214,66 +170,18 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
|||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
inline const Scalar* data() const { return m_expression.data(); }
|
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
|
EIGEN_DEVICE_FUNC
|
||||||
inline const Scalar& coeffRef(Index rowId, Index colId) const
|
inline const Scalar& coeffRef(Index rowId, Index colId) const
|
||||||
{
|
{
|
||||||
return m_expression.derived().coeffRef(rowId, colId);
|
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
|
EIGEN_DEVICE_FUNC
|
||||||
inline const Scalar& coeffRef(Index index) const
|
inline const Scalar& coeffRef(Index index) const
|
||||||
{
|
{
|
||||||
return m_expression.coeffRef(index);
|
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
|
EIGEN_DEVICE_FUNC
|
||||||
const typename internal::remove_all<NestedExpressionType>::type&
|
const typename internal::remove_all<NestedExpressionType>::type&
|
||||||
nestedExpression() const
|
nestedExpression() const
|
||||||
|
|||||||
@@ -88,10 +88,11 @@ private:
|
|||||||
/* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
|
/* 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. */
|
so it's only good for large enough sizes. */
|
||||||
MaySliceVectorize = bool(MightVectorize) && bool(DstHasDirectAccess)
|
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
|
/* 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
|
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:
|
public:
|
||||||
@@ -136,6 +137,11 @@ public:
|
|||||||
: int(Traversal) == int(LinearTraversal)
|
: int(Traversal) == int(LinearTraversal)
|
||||||
? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
|
? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
|
||||||
: int(NoUnrolling) )
|
: int(NoUnrolling) )
|
||||||
|
#if EIGEN_UNALIGNED_VECTORIZE
|
||||||
|
: int(Traversal) == int(SliceVectorizedTraversal)
|
||||||
|
? ( bool(MayUnrollInner) ? int(InnerUnrolling)
|
||||||
|
: int(NoUnrolling) )
|
||||||
|
#endif
|
||||||
: int(NoUnrolling)
|
: 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&) { }
|
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
|
struct copy_using_evaluator_innervec_InnerUnrolling
|
||||||
{
|
{
|
||||||
typedef typename Kernel::PacketType PacketType;
|
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)
|
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
|
||||||
{
|
{
|
||||||
kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, Index_);
|
kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, Index_);
|
||||||
enum { NextIndex = Index_ + unpacket_traits<PacketType>::size };
|
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>
|
template<typename Kernel, int Stop, int SrcAlignment, int DstAlignment>
|
||||||
struct copy_using_evaluator_innervec_InnerUnrolling<Kernel, Stop, Stop>
|
struct copy_using_evaluator_innervec_InnerUnrolling<Kernel, Stop, Stop, SrcAlignment, DstAlignment>
|
||||||
{
|
{
|
||||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &, Index) { }
|
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)
|
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
|
||||||
{
|
{
|
||||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||||
|
typedef typename Kernel::PacketType PacketType;
|
||||||
|
|
||||||
enum { size = DstXprType::SizeAtCompileTime,
|
enum { size = DstXprType::SizeAtCompileTime,
|
||||||
packetSize = packet_traits<typename Kernel::Scalar>::size,
|
packetSize =unpacket_traits<PacketType>::size,
|
||||||
alignedSize = (size/packetSize)*packetSize };
|
alignedSize = (size/packetSize)*packetSize };
|
||||||
|
|
||||||
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, alignedSize>::run(kernel);
|
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)
|
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
|
||||||
{
|
{
|
||||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||||
|
typedef typename Kernel::AssignmentTraits Traits;
|
||||||
const Index outerSize = kernel.outerSize();
|
const Index outerSize = kernel.outerSize();
|
||||||
for(Index outer = 0; outer < outerSize; ++outer)
|
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)
|
for(Index inner = alignedEnd; inner<innerSize ; ++inner)
|
||||||
kernel.assignCoeffByOuterInner(outer, 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
|
* Part 4 : Generic dense assignment kernel
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
@@ -669,24 +697,30 @@ protected:
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType, typename Functor>
|
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<DstXprType> DstEvaluatorType;
|
||||||
typedef evaluator<SrcXprType> SrcEvaluatorType;
|
typedef evaluator<SrcXprType> SrcEvaluatorType;
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
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;
|
typedef generic_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
|
||||||
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
|
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
|
||||||
|
|
||||||
dense_assignment_loop<Kernel>::run(kernel);
|
dense_assignment_loop<Kernel>::run(kernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
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>());
|
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
|
) && 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 ActualDstTypeCleaned;
|
||||||
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst&>::type ActualDstType;
|
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst&>::type ActualDstType;
|
||||||
ActualDstType actualDst(dst);
|
ActualDstType actualDst(dst);
|
||||||
@@ -795,15 +824,11 @@ template<typename Dst, typename Src, typename Func>
|
|||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src, const Func& func)
|
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:
|
// TODO check whether this is the right place to perform these checks:
|
||||||
EIGEN_STATIC_ASSERT_LVALUE(Dst)
|
EIGEN_STATIC_ASSERT_LVALUE(Dst)
|
||||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Dst,Src)
|
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);
|
Assignment<Dst,Src,Func>::run(dst, src, func);
|
||||||
}
|
}
|
||||||
template<typename Dst, typename Src>
|
template<typename Dst, typename Src>
|
||||||
@@ -825,8 +850,6 @@ struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Weak>
|
|||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const Functor &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
|
#ifndef EIGEN_NO_DEBUG
|
||||||
internal::check_for_aliasing(dst, src);
|
internal::check_for_aliasing(dst, src);
|
||||||
#endif
|
#endif
|
||||||
@@ -845,6 +868,11 @@ struct Assignment<DstXprType, SrcXprType, Functor, EigenBase2EigenBase, Weak>
|
|||||||
EIGEN_DEVICE_FUNC
|
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*/)
|
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());
|
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||||
src.evalTo(dst);
|
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
|
EIGEN_DEVICE_FUNC
|
||||||
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
||||||
{
|
{
|
||||||
if(other.rows()==0)
|
if (m_col==m_xpr.cols() && (other.cols()!=0 || other.rows()!=m_currentBlockRows))
|
||||||
{
|
|
||||||
m_col += other.cols();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
if (m_col==m_xpr.cols())
|
|
||||||
{
|
{
|
||||||
m_row+=m_currentBlockRows;
|
m_row+=m_currentBlockRows;
|
||||||
m_col = 0;
|
m_col = 0;
|
||||||
@@ -93,15 +88,11 @@ struct CommaInitializer
|
|||||||
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
||||||
&& "Too many rows passed to comma initializer (operator<<)");
|
&& "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<<)");
|
&& "Too many coefficients passed to comma initializer (operator<<)");
|
||||||
eigen_assert(m_currentBlockRows==other.rows());
|
eigen_assert(m_currentBlockRows==other.rows());
|
||||||
if (OtherDerived::SizeAtCompileTime != Dynamic)
|
m_xpr.template block<OtherDerived::RowsAtCompileTime, OtherDerived::ColsAtCompileTime>
|
||||||
m_xpr.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
|
(m_row, m_col, other.rows(), other.cols()) = other;
|
||||||
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_col += other.cols();
|
m_col += other.cols();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -112,9 +103,7 @@ struct CommaInitializer
|
|||||||
EIGEN_EXCEPTION_SPEC(Eigen::eigen_assert_exception)
|
EIGEN_EXCEPTION_SPEC(Eigen::eigen_assert_exception)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows()
|
finished();
|
||||||
&& m_col == m_xpr.cols()
|
|
||||||
&& "Too few coefficients passed to comma initializer (operator<<)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the built matrix once all its coefficients have been set.
|
/** \returns the built matrix once all its coefficients have been set.
|
||||||
@@ -125,7 +114,12 @@ struct CommaInitializer
|
|||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
EIGEN_DEVICE_FUNC
|
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
|
XprType& m_xpr; // target expression
|
||||||
Index m_row; // current row id
|
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.
|
// 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.
|
// 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>
|
template<typename NullaryOp, typename PlainObjectType>
|
||||||
struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
||||||
: evaluator_base<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)
|
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& n)
|
||||||
: m_functor(n.functor())
|
: m_functor(n.functor()), m_wrapper()
|
||||||
{
|
{
|
||||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||||
|
|
||||||
|
template <typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
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
|
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
|
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
|
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:
|
protected:
|
||||||
const NullaryOp m_functor;
|
const NullaryOp m_functor;
|
||||||
|
const internal::nullary_wrapper<CoeffReturnType,NullaryOp> m_wrapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------- CwiseUnaryOp --------------------
|
// -------------------- CwiseUnaryOp --------------------
|
||||||
@@ -700,73 +817,79 @@ struct mapbase_evaluator : evaluator_base<Derived>
|
|||||||
ColsAtCompileTime = XprType::ColsAtCompileTime,
|
ColsAtCompileTime = XprType::ColsAtCompileTime,
|
||||||
CoeffReadCost = NumTraits<Scalar>::ReadCost
|
CoeffReadCost = NumTraits<Scalar>::ReadCost
|
||||||
};
|
};
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC explicit mapbase_evaluator(const XprType& map)
|
EIGEN_DEVICE_FUNC explicit mapbase_evaluator(const XprType& map)
|
||||||
: m_data(const_cast<PointerType>(map.data())),
|
: m_data(const_cast<PointerType>(map.data())),
|
||||||
m_xpr(map)
|
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),
|
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);
|
PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
|
||||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
CoeffReturnType coeff(Index row, Index col) const
|
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
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
CoeffReturnType coeff(Index index) const
|
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
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
Scalar& coeffRef(Index row, Index col)
|
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
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
Scalar& coeffRef(Index index)
|
Scalar& coeffRef(Index index)
|
||||||
{
|
{
|
||||||
return m_data[index * m_xpr.innerStride()];
|
return m_data[index * m_innerStride.value()];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int LoadMode, typename PacketType>
|
template<int LoadMode, typename PacketType>
|
||||||
EIGEN_STRONG_INLINE
|
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);
|
return internal::ploadt<PacketType, LoadMode>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int LoadMode, typename PacketType>
|
template<int LoadMode, typename PacketType>
|
||||||
EIGEN_STRONG_INLINE
|
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>
|
template<int StoreMode, typename PacketType>
|
||||||
EIGEN_STRONG_INLINE
|
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);
|
return internal::pstoret<Scalar, PacketType, StoreMode>(ptr, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int StoreMode, typename PacketType>
|
template<int StoreMode, typename PacketType>
|
||||||
EIGEN_STRONG_INLINE
|
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:
|
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;
|
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>
|
template<typename PlainObjectType, int MapOptions, typename StrideType>
|
||||||
@@ -1179,7 +1302,7 @@ struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const ArgTypeNested m_arg;
|
typename internal::add_const_on_value_type<ArgTypeNested>::type m_arg;
|
||||||
const MemberOp m_functor;
|
const MemberOp m_functor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType> > : traits<PlainObjectT
|
|||||||
Flags = traits<PlainObjectType>::Flags & RowMajorBit
|
Flags = traits<PlainObjectType>::Flags & RowMajorBit
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
/** \class CwiseNullaryOp
|
/** \class CwiseNullaryOp
|
||||||
* \ingroup Core_Module
|
* \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
|
* However, if you want to write a function returning such an expression, you
|
||||||
* will need to use this class.
|
* 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>
|
template<typename NullaryOp, typename PlainObjectType>
|
||||||
class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp, PlainObjectType> >::type, internal::no_assignment_operator
|
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_DEVICE_FUNC
|
||||||
EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); }
|
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 */
|
/** \returns the functor representing the nullary operation */
|
||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
const NullaryOp& functor() const { return m_functor; }
|
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));
|
return DenseBase<Derived>::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_constant_op<Scalar>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(Index,const Scalar&,const Scalar&)
|
||||||
* \brief Sets a linearly spaced vector.
|
|
||||||
*
|
*
|
||||||
* The function generates 'size' equally spaced values in the closed interval [low,high].
|
* \sa LinSpaced(Index,Scalar,Scalar), setLinSpaced(Index,const Scalar&,const Scalar&)
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
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)
|
DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(const Scalar&,const Scalar&)
|
||||||
* \copydoc DenseBase::LinSpaced(Sequential_t, Index, const Scalar&, const Scalar&)
|
*
|
||||||
* Special version for fixed size types which does not require the size parameter.
|
* \sa LinSpaced(Scalar,Scalar)
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
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)
|
DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(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
|
* Example: \include DenseBase_LinSpaced.cpp
|
||||||
* Output: \verbinclude DenseBase_LinSpaced.out
|
* 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>
|
template<typename Derived>
|
||||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||||
DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high)
|
DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
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_VECTOR_ONLY(Derived)
|
||||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(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 */
|
/** \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
|
* Example: \include DenseBase_setLinSpaced.cpp
|
||||||
* Output: \verbinclude DenseBase_setLinSpaced.out
|
* 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>
|
template<typename Derived>
|
||||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high)
|
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
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.
|
* \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.
|
* When size is set to 1, a vector of length 1 containing 'high' is returned.
|
||||||
*
|
*
|
||||||
* \only_for_vectors
|
* \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>
|
template<typename Derived>
|
||||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low, const Scalar& high)
|
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)
|
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
|
||||||
{
|
{
|
||||||
m.setZero();
|
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);
|
for(Index i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1);
|
||||||
return m;
|
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.
|
* \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
|
* 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
|
* \sa \blank \ref TopicClassHierarchy
|
||||||
*/
|
*/
|
||||||
@@ -260,10 +260,10 @@ template<typename Derived> class DenseBase
|
|||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
/** \internal Represents a matrix with all coefficients equal to one another*/
|
/** \internal Represents a matrix with all coefficients equal to one another*/
|
||||||
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,PlainObject> ConstantReturnType;
|
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,PlainObject> ConstantReturnType;
|
||||||
/** \internal Represents a vector with linearly spaced coefficients that allows sequential access only. */
|
/** \internal \deprecated Represents a vector with linearly spaced coefficients that allows sequential access only. */
|
||||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar,false>,PlainObject> SequentialLinSpacedReturnType;
|
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar>,PlainObject> SequentialLinSpacedReturnType;
|
||||||
/** \internal Represents a vector with linearly spaced coefficients that allows random access. */
|
/** \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() */
|
/** \internal the return type of MatrixBase::eigenvalues() */
|
||||||
typedef Matrix<typename NumTraits<typename internal::traits<Derived>::Scalar>::Real, internal::traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType;
|
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();
|
EIGEN_DEVICE_FUNC void reverseInPlace();
|
||||||
|
|
||||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase
|
#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"
|
# include "../plugins/BlockMethods.h"
|
||||||
# ifdef EIGEN_DENSEBASE_PLUGIN
|
# ifdef EIGEN_DENSEBASE_PLUGIN
|
||||||
# include EIGEN_DENSEBASE_PLUGIN
|
# include EIGEN_DENSEBASE_PLUGIN
|
||||||
# endif
|
# endif
|
||||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
#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
|
// disable the use of evalTo for dense objects with a nice compilation error
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
|
|||||||
@@ -624,7 +624,7 @@ struct first_aligned_impl<Alignment, Derived, false>
|
|||||||
{
|
{
|
||||||
static inline Index run(const Derived& m)
|
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>
|
template<typename Derived>
|
||||||
bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const
|
bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const
|
||||||
{
|
{
|
||||||
using std::abs;
|
|
||||||
if(cols() != rows()) return false;
|
if(cols() != rows()) return false;
|
||||||
RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
|
RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
|
||||||
for(Index j = 0; j < cols(); ++j)
|
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;
|
if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
|
||||||
}
|
}
|
||||||
for(Index j = 0; j < cols(); ++j)
|
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*/)
|
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.setZero();
|
||||||
dst.diagonal() = src.diagonal();
|
dst.diagonal() = src.diagonal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,20 +159,20 @@ struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
|
|||||||
template<typename Scalar,int Size,int MaxSize>
|
template<typename Scalar,int Size,int MaxSize>
|
||||||
struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
|
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 {
|
enum {
|
||||||
ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
|
ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
|
||||||
PacketSize = internal::packet_traits<Scalar>::size
|
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() {
|
EIGEN_STRONG_INLINE Scalar* data() {
|
||||||
return ForceAlignment
|
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;
|
: m_data.array;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -207,7 +207,7 @@ template<> struct gemv_dense_selector<OnTheRight,ColMajor,true>
|
|||||||
typedef internal::blas_traits<Rhs> RhsBlasTraits;
|
typedef internal::blas_traits<Rhs> RhsBlasTraits;
|
||||||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
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);
|
ActualLhsType actualLhs = LhsBlasTraits::extract(lhs);
|
||||||
ActualRhsType actualRhs = RhsBlasTraits::extract(rhs);
|
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
|
template<typename Packet> EIGEN_DEVICE_FUNC inline
|
||||||
typename conditional<(unpacket_traits<Packet>::size%8)==0,typename unpacket_traits<Packet>::half,Packet>::type
|
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; }
|
{ return a; }
|
||||||
|
|
||||||
/** \internal \returns the product of the elements of \a 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;
|
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 internal
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
typedef typename internal::ref_selector<Inverse>::type Nested;
|
typedef typename internal::ref_selector<Inverse>::type Nested;
|
||||||
typedef typename internal::remove_all<XprType>::type NestedExpression;
|
typedef typename internal::remove_all<XprType>::type NestedExpression;
|
||||||
|
|
||||||
explicit Inverse(const XprType &xpr)
|
explicit EIGEN_DEVICE_FUNC Inverse(const XprType &xpr)
|
||||||
: m_xpr(xpr)
|
: m_xpr(xpr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Eigen {
|
|||||||
* Typical users do not have to directly deal with this class.
|
* 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.
|
* 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:
|
* The \c Derived class has to provide the following two methods describing the memory layout:
|
||||||
* \code Index innerStride() const; \endcode
|
* \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> {};
|
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>
|
template<typename Scalar>
|
||||||
struct real_retval
|
struct real_retval
|
||||||
{
|
{
|
||||||
@@ -132,6 +145,19 @@ struct imag_default_impl<Scalar,true>
|
|||||||
|
|
||||||
template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {};
|
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>
|
template<typename Scalar>
|
||||||
struct imag_retval
|
struct imag_retval
|
||||||
{
|
{
|
||||||
@@ -459,30 +485,33 @@ struct arg_retval
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of log1p *
|
* Implementation of log1p *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
template<typename Scalar, bool isComplex = NumTraits<Scalar>::IsComplex >
|
|
||||||
struct log1p_impl
|
namespace std_fallback {
|
||||||
{
|
// fallback log1p implementation in case there is no log1p(Scalar) function in namespace of Scalar,
|
||||||
static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x)
|
// 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)
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
EIGEN_USING_STD_MATH(log);
|
EIGEN_USING_STD_MATH(log);
|
||||||
Scalar x1p = RealScalar(1) + x;
|
Scalar x1p = RealScalar(1) + x;
|
||||||
return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) );
|
return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) );
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
#if EIGEN_HAS_CXX11_MATH && !defined(__CUDACC__)
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct log1p_impl<Scalar, false> {
|
struct log1p_impl {
|
||||||
static inline Scalar run(const Scalar& x)
|
static inline Scalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||||
|
#if EIGEN_HAS_CXX11_MATH
|
||||||
using std::log1p;
|
using std::log1p;
|
||||||
|
#endif
|
||||||
|
using std_fallback::log1p;
|
||||||
return log1p(x);
|
return log1p(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct log1p_retval
|
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;
|
typedef typename conditional<NumTraits<Scalar>::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX;
|
||||||
if(y<x)
|
if(y<x)
|
||||||
return 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 range = ScalarX(y)-ScalarX(x);
|
||||||
std::size_t offset = 0;
|
std::size_t offset = 0;
|
||||||
// rejection sampling
|
// rejection sampling
|
||||||
std::size_t divisor = (range+RAND_MAX-1)/(range+1);
|
std::size_t divisor = 1;
|
||||||
std::size_t multiplier = (range+RAND_MAX-1)/std::size_t(RAND_MAX);
|
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 {
|
do {
|
||||||
offset = ( (std::size_t(std::rand()) * multiplier) / divisor );
|
offset = (std::size_t(std::rand()) * multiplier) / divisor;
|
||||||
} while (offset > range);
|
} while (offset > range);
|
||||||
|
|
||||||
return Scalar(ScalarX(x) + offset);
|
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 isnan_impl(const std::complex<T>& x);
|
||||||
template<typename T> EIGEN_DEVICE_FUNC bool isinf_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
|
} // 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);
|
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>
|
template<typename ScalarX,typename ScalarY>
|
||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
inline typename internal::pow_impl<ScalarX,ScalarY>::result_type pow(const ScalarX& x, const ScalarY& y)
|
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
|
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||||
double abs(const double &x) { return ::fabs(x); }
|
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
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -1176,6 +1227,11 @@ T tanh(const T &x) {
|
|||||||
return tanh(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__
|
#ifdef __CUDACC__
|
||||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||||
float tanh(const float &x) { return ::tanhf(x); }
|
float tanh(const float &x) { return ::tanhf(x); }
|
||||||
@@ -1282,11 +1338,12 @@ template<typename Scalar>
|
|||||||
struct scalar_fuzzy_default_impl<Scalar, true, false>
|
struct scalar_fuzzy_default_impl<Scalar, true, false>
|
||||||
{
|
{
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
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)
|
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
|
||||||
{
|
{
|
||||||
return numext::abs2(x) <= numext::abs2(y) * prec * 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)
|
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;
|
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
|
* \endcode
|
||||||
*
|
*
|
||||||
* This class can be extended with the help of the plugin mechanism described on the page
|
* 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>
|
* <i><b>Some notes:</b></i>
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Eigen {
|
|||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* This class can be extended with the help of the plugin mechanism described on the page
|
* 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
|
* \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()).
|
/** \returns the size of the main diagonal, which is min(rows(),cols()).
|
||||||
* \sa rows(), cols(), SizeAtCompileTime. */
|
* \sa rows(), cols(), SizeAtCompileTime. */
|
||||||
EIGEN_DEVICE_FUNC
|
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;
|
typedef typename Base::PlainObject PlainObject;
|
||||||
|
|
||||||
@@ -121,6 +121,7 @@ template<typename Derived> class MatrixBase
|
|||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
|
||||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::MatrixBase
|
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::MatrixBase
|
||||||
|
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
|
||||||
# include "../plugins/CommonCwiseUnaryOps.h"
|
# include "../plugins/CommonCwiseUnaryOps.h"
|
||||||
# include "../plugins/CommonCwiseBinaryOps.h"
|
# include "../plugins/CommonCwiseBinaryOps.h"
|
||||||
# include "../plugins/MatrixCwiseUnaryOps.h"
|
# include "../plugins/MatrixCwiseUnaryOps.h"
|
||||||
@@ -129,6 +130,7 @@ template<typename Derived> class MatrixBase
|
|||||||
# include EIGEN_MATRIXBASE_PLUGIN
|
# include EIGEN_MATRIXBASE_PLUGIN
|
||||||
# endif
|
# endif
|
||||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
||||||
|
#undef EIGEN_DOC_UNARY_ADDONS
|
||||||
|
|
||||||
/** Special case of the template operator=, in order to prevent the compiler
|
/** Special case of the template operator=, in order to prevent the compiler
|
||||||
* from generating a default operator= (issue hit with g++ 4.1)
|
* from generating a default operator= (issue hit with g++ 4.1)
|
||||||
@@ -328,15 +330,11 @@ template<typename Derived> class MatrixBase
|
|||||||
|
|
||||||
/////////// LU module ///////////
|
/////////// LU module ///////////
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
inline const FullPivLU<PlainObject> fullPivLu() const;
|
inline const FullPivLU<PlainObject> fullPivLu() const;
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
inline const PartialPivLU<PlainObject> partialPivLu() const;
|
inline const PartialPivLU<PlainObject> partialPivLu() const;
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
inline const PartialPivLU<PlainObject> lu() const;
|
inline const PartialPivLU<PlainObject> lu() const;
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC
|
|
||||||
inline const Inverse<Derived> inverse() const;
|
inline const Inverse<Derived> inverse() const;
|
||||||
|
|
||||||
template<typename ResultType>
|
template<typename ResultType>
|
||||||
@@ -401,12 +399,14 @@ template<typename Derived> class MatrixBase
|
|||||||
EIGEN_DEVICE_FUNC
|
EIGEN_DEVICE_FUNC
|
||||||
inline PlainObject unitOrthogonal(void) const;
|
inline PlainObject unitOrthogonal(void) const;
|
||||||
|
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Matrix<Scalar,3,1> eulerAngles(Index a0, Index a1, Index a2) const;
|
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 (?)
|
// 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)
|
enum { HomogeneousReturnTypeDirection = ColsAtCompileTime==1&&RowsAtCompileTime==1 ? ((internal::traits<Derived>::Flags&RowMajorBit)==RowMajorBit ? Horizontal : Vertical)
|
||||||
: ColsAtCompileTime==1 ? Vertical : Horizontal };
|
: ColsAtCompileTime==1 ? Vertical : Horizontal };
|
||||||
typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType;
|
typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType;
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline HomogeneousReturnType homogeneous() const;
|
inline HomogeneousReturnType homogeneous() const;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -416,7 +416,7 @@ template<typename Derived> class MatrixBase
|
|||||||
internal::traits<Derived>::ColsAtCompileTime==1 ? SizeMinusOne : 1,
|
internal::traits<Derived>::ColsAtCompileTime==1 ? SizeMinusOne : 1,
|
||||||
internal::traits<Derived>::ColsAtCompileTime==1 ? 1 : SizeMinusOne> ConstStartMinusOne;
|
internal::traits<Derived>::ColsAtCompileTime==1 ? 1 : SizeMinusOne> ConstStartMinusOne;
|
||||||
typedef EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(ConstStartMinusOne,Scalar,quotient) HNormalizedReturnType;
|
typedef EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(ConstStartMinusOne,Scalar,quotient) HNormalizedReturnType;
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline const HNormalizedReturnType hnormalized() const;
|
inline const HNormalizedReturnType hnormalized() const;
|
||||||
|
|
||||||
////////// Householder module ///////////
|
////////// Householder module ///////////
|
||||||
|
|||||||
@@ -97,23 +97,6 @@ template<typename T> struct GenericNumTraits
|
|||||||
MulCost = 1
|
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 T Real;
|
||||||
typedef typename internal::conditional<
|
typedef typename internal::conditional<
|
||||||
IsInteger,
|
IsInteger,
|
||||||
@@ -255,6 +238,9 @@ private:
|
|||||||
static inline std::string quiet_NaN();
|
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
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_NUMTRAITS_H
|
#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.
|
* \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
|
* 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
|
* \sa \ref TopicClassHierarchy
|
||||||
*/
|
*/
|
||||||
@@ -916,8 +916,8 @@ struct conservative_resize_like_impl
|
|||||||
{
|
{
|
||||||
// The storage order does not allow us to use reallocation.
|
// The storage order does not allow us to use reallocation.
|
||||||
typename Derived::PlainObject tmp(rows,cols);
|
typename Derived::PlainObject tmp(rows,cols);
|
||||||
const Index common_rows = (std::min)(rows, _this.rows());
|
const Index common_rows = numext::mini(rows, _this.rows());
|
||||||
const Index common_cols = (std::min)(cols, _this.cols());
|
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);
|
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||||
_this.derived().swap(tmp);
|
_this.derived().swap(tmp);
|
||||||
}
|
}
|
||||||
@@ -950,8 +950,8 @@ struct conservative_resize_like_impl
|
|||||||
{
|
{
|
||||||
// The storage order does not allow us to use reallocation.
|
// The storage order does not allow us to use reallocation.
|
||||||
typename Derived::PlainObject tmp(other);
|
typename Derived::PlainObject tmp(other);
|
||||||
const Index common_rows = (std::min)(tmp.rows(), _this.rows());
|
const Index common_rows = numext::mini(tmp.rows(), _this.rows());
|
||||||
const Index common_cols = (std::min)(tmp.cols(), _this.cols());
|
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);
|
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||||
_this.derived().swap(tmp);
|
_this.derived().swap(tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,10 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::assign_op<Scal
|
|||||||
static EIGEN_STRONG_INLINE
|
static EIGEN_STRONG_INLINE
|
||||||
void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
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?
|
// FIXME shall we handle nested_eval here?
|
||||||
generic_product_impl<Lhs, Rhs>::evalTo(dst, src.lhs(), src.rhs());
|
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
|
static EIGEN_STRONG_INLINE
|
||||||
void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<Scalar,Scalar> &)
|
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?
|
// FIXME shall we handle nested_eval here?
|
||||||
generic_product_impl<Lhs, Rhs>::addTo(dst, src.lhs(), src.rhs());
|
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
|
static EIGEN_STRONG_INLINE
|
||||||
void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<Scalar,Scalar> &)
|
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?
|
// FIXME shall we handle nested_eval here?
|
||||||
generic_product_impl<Lhs, Rhs>::subTo(dst, src.lhs(), src.rhs());
|
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
|
// 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
|
// 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>
|
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,
|
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>
|
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 SrcXprType, typename InitialFunc>
|
||||||
template<typename InitialFunc>
|
|
||||||
static EIGEN_STRONG_INLINE
|
static EIGEN_STRONG_INLINE
|
||||||
void run(DstXprType &dst, const SrcXprType &src, const InitialFunc& /*func*/)
|
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>
|
#define EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(ASSIGN_OP,BINOP,ASSIGN_OP2) \
|
||||||
struct Assignment<DstXprType, CwiseBinaryOp<internal::scalar_sum_op<OtherScalar,ProdScalar>, const OtherXpr,
|
template< typename DstXprType, typename OtherXpr, typename Lhs, typename Rhs, typename DstScalar, typename SrcScalar, typename OtherScalar,typename ProdScalar> \
|
||||||
const Product<Lhs,Rhs,DefaultProduct> >, internal::assign_op<DstScalar,SrcScalar>, Dense2Dense>
|
struct Assignment<DstXprType, CwiseBinaryOp<internal::BINOP<OtherScalar,ProdScalar>, const OtherXpr, \
|
||||||
: assignment_from_xpr_plus_product<DstXprType, OtherXpr, Product<Lhs,Rhs,DefaultProduct>, internal::assign_op<DstScalar,OtherScalar>, internal::add_assign_op<DstScalar,ProdScalar> >
|
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> > \
|
||||||
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>
|
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_sum_op,add_assign_op);
|
||||||
: assignment_from_xpr_plus_product<DstXprType, OtherXpr, Product<Lhs,Rhs,DefaultProduct>, internal::add_assign_op<DstScalar,OtherScalar>, internal::add_assign_op<DstScalar,ProdScalar> >
|
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);
|
||||||
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,
|
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_difference_op,sub_assign_op);
|
||||||
const Product<Lhs,Rhs,DefaultProduct> >, internal::sub_assign_op<DstScalar,SrcScalar>, Dense2Dense>
|
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op,scalar_difference_op,sub_assign_op);
|
||||||
: assignment_from_xpr_plus_product<DstXprType, OtherXpr, Product<Lhs,Rhs,DefaultProduct>, internal::sub_assign_op<DstScalar,OtherScalar>, internal::sub_assign_op<DstScalar,ProdScalar> >
|
EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op,scalar_difference_op,add_assign_op);
|
||||||
{};
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
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
|
// FIXME not very good if rhs is real and lhs complex while alpha is real too
|
||||||
const Index cols = dst.cols();
|
const Index cols = dst.cols();
|
||||||
for (Index j=0; j<cols; ++j)
|
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
|
// 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
|
// FIXME not very good if lhs is real and rhs complex while alpha is real too
|
||||||
const Index rows = dst.rows();
|
const Index rows = dst.rows();
|
||||||
for (Index i=0; i<rows; ++i)
|
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>
|
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>::MulCost);
|
||||||
EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::AddCost);
|
EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::AddCost);
|
||||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
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
|
// 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,
|
SameType = is_same<typename LhsNestedCleaned::Scalar,typename RhsNestedCleaned::Scalar>::value,
|
||||||
|
|
||||||
CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags & PacketAccessBit)
|
CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags & PacketAccessBit) && (ColsAtCompileTime!=1),
|
||||||
&& (ColsAtCompileTime == Dynamic || ((ColsAtCompileTime % RhsVecPacketSize) == 0) ),
|
CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit) && (RowsAtCompileTime!=1),
|
||||||
|
|
||||||
CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit)
|
|
||||||
&& (RowsAtCompileTime == Dynamic || ((RowsAtCompileTime % LhsVecPacketSize) == 0) ),
|
|
||||||
|
|
||||||
EvalToRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
EvalToRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
: (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)),
|
LhsOuterStrideBytes = int(LhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename LhsNestedCleaned::Scalar)),
|
||||||
RhsOuterStrideBytes = int(RhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename RhsNestedCleaned::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)
|
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)
|
: bool(CanVectorizeRhs) ? (RhsOuterStrideBytes<=0 || (int(RhsOuterStrideBytes) % EIGEN_PLAIN_ENUM_MAX(1,RhsAlignment))!=0 ? 0 : RhsAlignment)
|
||||||
: 0,
|
: 0,
|
||||||
|
|
||||||
/* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside
|
/* 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
|
EIGEN_DEVICE_FUNC const CoeffReturnType coeff(Index index) const
|
||||||
{
|
{
|
||||||
const Index row = RowsAtCompileTime == 1 ? 0 : index;
|
const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? 0 : index;
|
||||||
const Index col = RowsAtCompileTime == 1 ? index : 0;
|
const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? index : 0;
|
||||||
return (m_lhs.row(row).transpose().cwiseProduct( m_rhs.col(col) )).sum();
|
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>
|
template<int LoadMode, typename PacketType>
|
||||||
const PacketType packet(Index index) const
|
const PacketType packet(Index index) const
|
||||||
{
|
{
|
||||||
const Index row = RowsAtCompileTime == 1 ? 0 : index;
|
const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? 0 : index;
|
||||||
const Index col = RowsAtCompileTime == 1 ? index : 0;
|
const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? index : 0;
|
||||||
return packet<LoadMode,PacketType>(row,col);
|
return packet<LoadMode,PacketType>(row,col);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const LhsNested m_lhs;
|
typename internal::add_const_on_value_type<LhsNested>::type m_lhs;
|
||||||
const RhsNested m_rhs;
|
typename internal::add_const_on_value_type<RhsNested>::type m_rhs;
|
||||||
|
|
||||||
LhsEtorType m_lhsImpl;
|
LhsEtorType m_lhsImpl;
|
||||||
RhsEtorType m_rhsImpl;
|
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)
|
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);
|
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)
|
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);
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
for(Index i = 0; i < innerDim; ++i)
|
||||||
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode,Packet>(i, col), res);
|
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)
|
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)
|
for(Index i = 0; i < innerDim; ++i)
|
||||||
res = pmadd(lhs.template packet<LoadMode,Packet>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
|
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 {
|
template<typename Scalar> struct scalar_random_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_random_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_random_op)
|
||||||
template<typename Index>
|
inline const Scalar operator() () const { return random<Scalar>(); }
|
||||||
inline const Scalar operator() (Index, Index = 0) const { return random<Scalar>(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
|
|||||||
@@ -35,7 +35,13 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
|
|||||||
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
|
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
|
||||||
OuterStrideMatch = Derived::IsVectorAtCompileTime
|
OuterStrideMatch = Derived::IsVectorAtCompileTime
|
||||||
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
|
|| 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,
|
ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
|
||||||
MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
|
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;
|
typedef Solve<DecType,RhsType> SrcXprType;
|
||||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
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);
|
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;
|
typedef Solve<Transpose<const DecType>,RhsType> SrcXprType;
|
||||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
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);
|
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;
|
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> &)
|
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);
|
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&
|
typename internal::remove_reference<MatrixTypeNested>::type&
|
||||||
nestedExpression() { return m_matrix; }
|
nestedExpression() { return m_matrix; }
|
||||||
|
|
||||||
|
/** \internal */
|
||||||
|
void resize(Index nrows, Index ncols) {
|
||||||
|
m_matrix.resize(ncols,nrows);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typename internal::ref_selector<MatrixType>::non_const_type m_matrix;
|
typename internal::ref_selector<MatrixType>::non_const_type m_matrix;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -641,21 +641,20 @@ MatrixBase<Derived>::triangularView() const
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const
|
bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const
|
||||||
{
|
{
|
||||||
using std::abs;
|
|
||||||
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
|
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
|
||||||
for(Index j = 0; j < cols(); ++j)
|
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)
|
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;
|
if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RealScalar threshold = maxAbsOnUpperPart * prec;
|
RealScalar threshold = maxAbsOnUpperPart * prec;
|
||||||
for(Index j = 0; j < cols(); ++j)
|
for(Index j = 0; j < cols(); ++j)
|
||||||
for(Index i = j+1; i < rows(); ++i)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,20 +666,19 @@ bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const
|
bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const
|
||||||
{
|
{
|
||||||
using std::abs;
|
|
||||||
RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
|
RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
|
||||||
for(Index j = 0; j < cols(); ++j)
|
for(Index j = 0; j < cols(); ++j)
|
||||||
for(Index i = j; i < rows(); ++i)
|
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;
|
if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
|
||||||
}
|
}
|
||||||
RealScalar threshold = maxAbsOnLowerPart * prec;
|
RealScalar threshold = maxAbsOnLowerPart * prec;
|
||||||
for(Index j = 1; j < cols(); ++j)
|
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)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -777,15 +775,18 @@ public:
|
|||||||
|
|
||||||
template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType, typename Functor>
|
template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType, typename Functor>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
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<DstXprType> DstEvaluatorType;
|
||||||
typedef evaluator<SrcXprType> SrcEvaluatorType;
|
typedef evaluator<SrcXprType> SrcEvaluatorType;
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
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,
|
typedef triangular_dense_assignment_kernel< Mode&(Lower|Upper),Mode&(UnitDiag|ZeroDiag|SelfAdjoint),SetOpposite,
|
||||||
DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
|
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>
|
template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
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>());
|
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)
|
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;
|
Index i = 0;
|
||||||
if (((Mode&Lower) && SetOpposite) || (Mode&Upper))
|
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;
|
typedef Product<Lhs,Rhs,DefaultProduct> SrcXprType;
|
||||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename SrcXprType::Scalar> &)
|
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.setZero();
|
||||||
dst._assignProduct(src, 1);
|
dst._assignProduct(src, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -602,7 +602,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
|||||||
return m_matrix / extendedTo(other.derived());
|
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.
|
* The referenced matrix is \b not modified.
|
||||||
* \sa MatrixBase::normalized(), normalize()
|
* \sa MatrixBase::normalized(), normalize()
|
||||||
*/
|
*/
|
||||||
@@ -625,6 +625,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
|||||||
/////////// Geometry module ///////////
|
/////////// Geometry module ///////////
|
||||||
|
|
||||||
typedef Homogeneous<ExpressionType,Direction> HomogeneousReturnType;
|
typedef Homogeneous<ExpressionType,Direction> HomogeneousReturnType;
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
HomogeneousReturnType homogeneous() const;
|
HomogeneousReturnType homogeneous() const;
|
||||||
|
|
||||||
typedef typename ExpressionType::PlainObject CrossReturnType;
|
typedef typename ExpressionType::PlainObject CrossReturnType;
|
||||||
@@ -654,6 +655,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
|||||||
Direction==Horizontal ? HNormalized_SizeMinusOne : 1> >
|
Direction==Horizontal ? HNormalized_SizeMinusOne : 1> >
|
||||||
HNormalizedReturnType;
|
HNormalizedReturnType;
|
||||||
|
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
const HNormalizedReturnType hnormalized() const;
|
const HNormalizedReturnType hnormalized() const;
|
||||||
|
|
||||||
protected:
|
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;
|
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 internal
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -266,52 +266,10 @@ pexp<Packet8f>(const Packet8f& _x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hyperbolic Tangent function.
|
// 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 <>
|
template <>
|
||||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8f
|
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8f
|
||||||
ptanh<Packet8f>(const Packet8f& _x) {
|
ptanh<Packet8f>(const Packet8f& x) {
|
||||||
// Clamp the inputs to the range [-9, 9] since anything outside
|
return internal::generic_fast_tanh_float(x);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@@ -397,30 +355,27 @@ pexp<Packet4d>(const Packet4d& _x) {
|
|||||||
// Functions for sqrt.
|
// Functions for sqrt.
|
||||||
// The EIGEN_FAST_MATH version uses the _mm_rsqrt_ps approximation and one step
|
// 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
|
// 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
|
// exact solution. It does not handle +inf, or denormalized numbers correctly.
|
||||||
// also the fact that it can be inlined and pipelined with other computations,
|
// The main advantage of this approach is not just speed, but also the fact that
|
||||||
// further reducing its effective latency.
|
// 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
|
#if EIGEN_FAST_MATH
|
||||||
template <>
|
template <>
|
||||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8f
|
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8f
|
||||||
psqrt<Packet8f>(const Packet8f& _x) {
|
psqrt<Packet8f>(const Packet8f& _x) {
|
||||||
_EIGEN_DECLARE_CONST_Packet8f(one_point_five, 1.5f);
|
Packet8f half = pmul(_x, pset1<Packet8f>(.5f));
|
||||||
_EIGEN_DECLARE_CONST_Packet8f(minus_half, -0.5f);
|
Packet8f denormal_mask = _mm256_and_ps(
|
||||||
_EIGEN_DECLARE_CONST_Packet8f_FROM_INT(flt_min, 0x00800000);
|
_mm256_cmp_ps(_x, pset1<Packet8f>((std::numeric_limits<float>::min)()),
|
||||||
|
_CMP_LT_OQ),
|
||||||
Packet8f neg_half = pmul(_x, p8f_minus_half);
|
_mm256_cmp_ps(_x, _mm256_setzero_ps(), _CMP_GE_OQ));
|
||||||
|
|
||||||
// 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));
|
|
||||||
|
|
||||||
|
// Compute approximate reciprocal sqrt.
|
||||||
|
Packet8f x = _mm256_rsqrt_ps(_x);
|
||||||
// Do a single step of Newton's iteration.
|
// Do a single step of Newton's iteration.
|
||||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p8f_one_point_five));
|
x = pmul(x, psub(pset1<Packet8f>(1.5f), pmul(half, pmul(x,x))));
|
||||||
|
// Flush results for denormals to zero.
|
||||||
// Multiply the original _x by it's reciprocal square root to extract the
|
return _mm256_andnot_ps(denormal_mask, pmul(_x,x));
|
||||||
// square root.
|
|
||||||
return pmul(_x, x);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template <> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
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) \
|
#define _EIGEN_DECLARE_CONST_Packet8i(NAME,X) \
|
||||||
const Packet8i p8i_##NAME = pset1<Packet8i>(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
|
template<> struct packet_traits<float> : default_packet_traits
|
||||||
{
|
{
|
||||||
typedef Packet8f type;
|
typedef Packet8f type;
|
||||||
@@ -93,6 +95,10 @@ template<> struct packet_traits<double> : default_packet_traits
|
|||||||
HasCeil = 1
|
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
|
/* Proper support for integers is only provided by AVX2. In the meantime, we'll
|
||||||
use SSE instructions and packets to deal with integers.
|
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__
|
#ifdef __FMA__
|
||||||
template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f& b, const Packet8f& c) {
|
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,
|
// clang stupidly generates a vfmadd213ps instruction plus some vmovaps on registers,
|
||||||
// and gcc stupidly generates a vfmadd132ps instruction,
|
// 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
|
// 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
|
#endif
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet4d pmadd(const Packet4d& a, const Packet4d& b, const Packet4d& c) {
|
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
|
// see above
|
||||||
Packet4d res = c;
|
Packet4d res = c;
|
||||||
__asm__("vfmadd231pd %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b));
|
__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);
|
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<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<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); }
|
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) {
|
template<> EIGEN_STRONG_INLINE float pfirst<Packet8f>(const Packet8f& a) {
|
||||||
return _mm_cvtss_f32(_mm256_castps256_ps128(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));
|
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));
|
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);
|
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 internal
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // 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 {
|
namespace Eigen {
|
||||||
|
|
||||||
|
struct half;
|
||||||
|
|
||||||
namespace half_impl {
|
namespace half_impl {
|
||||||
|
|
||||||
#if !defined(EIGEN_HAS_CUDA_FP16)
|
#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 __half float_to_half_rtne(float ff);
|
||||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half h);
|
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.
|
// 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() {}
|
||||||
|
|
||||||
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(h) {}
|
EIGEN_DEVICE_FUNC half(const half& h) : half_impl::half_base(h) {}
|
||||||
|
|
||||||
explicit EIGEN_DEVICE_FUNC half(bool b)
|
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>
|
template<class T>
|
||||||
explicit EIGEN_DEVICE_FUNC half(const T& val)
|
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)
|
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 {
|
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(bool) const {
|
||||||
// +0.0 and -0.0 become false, everything else becomes true.
|
// +0.0 and -0.0 become false, everything else becomes true.
|
||||||
return (x & 0x7fff) != 0;
|
return (x & 0x7fff) != 0;
|
||||||
}
|
}
|
||||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(signed char) const {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(unsigned long long) const {
|
||||||
return static_cast<unsigned long long>(half_to_float(*this));
|
return static_cast<unsigned long long>(half_to_float(*this));
|
||||||
}
|
}
|
||||||
EIGEN_DEVICE_FUNC EIGEN_EXPLICIT_CAST(float) const {
|
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 {
|
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) {
|
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
|
#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530
|
||||||
|
|
||||||
// Intrinsics for native fp16 support. Note that on current hardware,
|
// 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)));
|
return half(::expf(float(a)));
|
||||||
}
|
}
|
||||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log(const half& 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)));
|
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) {
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log10(const half& a) {
|
||||||
return half(::log10f(float(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
|
} // end namespace half_impl
|
||||||
|
|
||||||
// import Eigen::half_impl::half into Eigen namespace
|
// import Eigen::half_impl::half into Eigen namespace
|
||||||
using half_impl::half;
|
// using half_impl::half;
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template<>
|
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)
|
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
|
} // end namespace internal
|
||||||
|
|
||||||
template<> struct NumTraits<Eigen::half_impl::half>
|
template<> struct NumTraits<Eigen::half>
|
||||||
: GenericNumTraits<Eigen::half_impl::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);
|
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 dummy_precision() { return Eigen::half(1e-2f); }
|
||||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half_impl::half highest() {
|
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half highest() {
|
||||||
return half_impl::raw_uint16_to_half(0x7bff);
|
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);
|
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);
|
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);
|
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)));
|
return Eigen::half(::expf(float(a)));
|
||||||
}
|
}
|
||||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half logh(const Eigen::half& 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)));
|
return Eigen::half(::logf(float(a)));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half sqrth(const Eigen::half& a) {
|
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half sqrth(const Eigen::half& a) {
|
||||||
return Eigen::half(::sqrtf(float(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.
|
// ldg() has an overload for __half, but we also need one for Eigen::half.
|
||||||
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 350
|
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 350
|
||||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half __ldg(const Eigen::half* ptr) {
|
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)));
|
__ldg(reinterpret_cast<const unsigned short*>(ptr)));
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#endif // EIGEN_HALF_CUDA_H
|
||||||
|
|||||||
@@ -31,6 +31,18 @@ double2 plog<double2>(const double2& a)
|
|||||||
return make_double2(log(a.x), log(a.y));
|
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
|
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
float4 pexp<float4>(const float4& a)
|
float4 pexp<float4>(const float4& a)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Eigen {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Most of the following operations require arch >= 3.0
|
// 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 }; };
|
template<> struct is_arithmetic<half2> { enum { value = true }; };
|
||||||
|
|
||||||
@@ -34,21 +34,22 @@ template<> struct packet_traits<Eigen::half> : default_packet_traits
|
|||||||
HasSqrt = 1,
|
HasSqrt = 1,
|
||||||
HasRsqrt = 1,
|
HasRsqrt = 1,
|
||||||
HasExp = 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<> 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);
|
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);
|
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]);
|
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]);
|
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;
|
*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[0] = __low2half(from);
|
||||||
to[1] = __high2half(from);
|
to[1] = __high2half(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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
|
#if __CUDA_ARCH__ >= 350
|
||||||
return __ldg((const half2*)from);
|
return __ldg((const half2*)from);
|
||||||
#else
|
#else
|
||||||
@@ -75,7 +76,7 @@ template<>
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
#if __CUDA_ARCH__ >= 350
|
||||||
return __halves2half2(__ldg(from+0), __ldg(from+1));
|
return __halves2half2(__ldg(from+0), __ldg(from+1));
|
||||||
#else
|
#else
|
||||||
@@ -83,27 +84,27 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro<half2, Unaligned>(const Ei
|
|||||||
#endif
|
#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]);
|
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*0] = __low2half(from);
|
||||||
to[stride*1] = __high2half(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);
|
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;
|
half2 result;
|
||||||
result.x = a.x & 0x7FFF7FFF;
|
result.x = a.x & 0x7FFF7FFF;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
|
__device__ EIGEN_STRONG_INLINE void
|
||||||
ptranspose(PacketBlock<half2,2>& kernel) {
|
ptranspose(PacketBlock<half2,2>& kernel) {
|
||||||
__half a1 = __low2half(kernel.packet[0]);
|
__half a1 = __low2half(kernel.packet[0]);
|
||||||
__half a2 = __high2half(kernel.packet[0]);
|
__half a2 = __high2half(kernel.packet[0]);
|
||||||
@@ -113,7 +114,7 @@ ptranspose(PacketBlock<half2,2>& kernel) {
|
|||||||
kernel.packet[1] = __halves2half2(a2, b2);
|
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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __halves2half2(a, __hadd(a, __float2half(1.0f)));
|
return __halves2half2(a, __hadd(a, __float2half(1.0f)));
|
||||||
#else
|
#else
|
||||||
@@ -122,7 +123,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset<half2>(const Eigen:
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __hadd2(a, b);
|
return __hadd2(a, b);
|
||||||
#else
|
#else
|
||||||
@@ -136,7 +137,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd<half2>(const half2&
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __hsub2(a, b);
|
return __hsub2(a, b);
|
||||||
#else
|
#else
|
||||||
@@ -150,7 +151,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psub<half2>(const half2&
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __hneg2(a);
|
return __hneg2(a);
|
||||||
#else
|
#else
|
||||||
@@ -160,9 +161,9 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pnegate(const half2& a) {
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __hmul2(a, b);
|
return __hmul2(a, b);
|
||||||
#else
|
#else
|
||||||
@@ -176,7 +177,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul<half2>(const half2&
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __hfma2(a, b, c);
|
return __hfma2(a, b, c);
|
||||||
#else
|
#else
|
||||||
@@ -192,7 +193,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmadd<half2>(const half2&
|
|||||||
#endif
|
#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 a1 = __low2float(a);
|
||||||
float a2 = __high2float(a);
|
float a2 = __high2float(a);
|
||||||
float b1 = __low2float(b);
|
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);
|
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 a1 = __low2float(a);
|
||||||
float a2 = __high2float(a);
|
float a2 = __high2float(a);
|
||||||
float b1 = __low2float(b);
|
float b1 = __low2float(b);
|
||||||
@@ -212,7 +213,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin<half2>(const half2&
|
|||||||
return __halves2half2(r1, r2);
|
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 a1 = __low2float(a);
|
||||||
float a2 = __high2float(a);
|
float a2 = __high2float(a);
|
||||||
float b1 = __low2float(b);
|
float b1 = __low2float(b);
|
||||||
@@ -222,7 +223,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax<half2>(const half2&
|
|||||||
return __halves2half2(r1, r2);
|
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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __hadd(__low2half(a), __high2half(a));
|
return __hadd(__low2half(a), __high2half(a));
|
||||||
#else
|
#else
|
||||||
@@ -232,7 +233,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux<half2>(const
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
__half first = __low2half(a);
|
__half first = __low2half(a);
|
||||||
__half second = __high2half(a);
|
__half second = __high2half(a);
|
||||||
@@ -244,7 +245,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max<half2>(c
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
__half first = __low2half(a);
|
__half first = __low2half(a);
|
||||||
__half second = __high2half(a);
|
__half second = __high2half(a);
|
||||||
@@ -256,7 +257,7 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min<half2>(c
|
|||||||
#endif
|
#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
|
#if __CUDA_ARCH__ >= 530
|
||||||
return __hmul(__low2half(a), __high2half(a));
|
return __hmul(__low2half(a), __high2half(a));
|
||||||
#else
|
#else
|
||||||
@@ -266,31 +267,39 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul<half2>(c
|
|||||||
#endif
|
#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
|
#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) {
|
half2 plog<half2>(const half2& a) {
|
||||||
return h2log(a);
|
return h2log(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template<> __device__ EIGEN_STRONG_INLINE
|
||||||
half2 pexp<half2>(const half2& a) {
|
half2 pexp<half2>(const half2& a) {
|
||||||
return h2exp(a);
|
return h2exp(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template<> __device__ EIGEN_STRONG_INLINE
|
||||||
half2 psqrt<half2>(const half2& a) {
|
half2 psqrt<half2>(const half2& a) {
|
||||||
return h2sqrt(a);
|
return h2sqrt(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template<> __device__ EIGEN_STRONG_INLINE
|
||||||
half2 prsqrt<half2>(const half2& a) {
|
half2 prsqrt<half2>(const half2& a) {
|
||||||
return h2rsqrt(a);
|
return h2rsqrt(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#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 a1 = __low2float(a);
|
||||||
float a2 = __high2float(a);
|
float a2 = __high2float(a);
|
||||||
float r1 = logf(a1);
|
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);
|
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 a1 = __low2float(a);
|
||||||
float a2 = __high2float(a);
|
float a2 = __high2float(a);
|
||||||
float r1 = expf(a1);
|
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);
|
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 a1 = __low2float(a);
|
||||||
float a2 = __high2float(a);
|
float a2 = __high2float(a);
|
||||||
float r1 = sqrtf(a1);
|
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);
|
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 a1 = __low2float(a);
|
||||||
float a2 = __high2float(a);
|
float a2 = __high2float(a);
|
||||||
float r1 = rsqrtf(a1);
|
float r1 = rsqrtf(a1);
|
||||||
@@ -324,6 +333,374 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 prsqrt<half2>(const half2
|
|||||||
|
|
||||||
#endif
|
#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
|
#elif defined EIGEN_VECTORIZE_AVX
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -483,6 +860,30 @@ template<> EIGEN_STRONG_INLINE void pscatter<Eigen::half, Packet8h>(Eigen::half*
|
|||||||
to[stride*7].x = aux[7].x;
|
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
|
EIGEN_STRONG_INLINE void
|
||||||
ptranspose(PacketBlock<Packet8h,8>& kernel) {
|
ptranspose(PacketBlock<Packet8h,8>& kernel) {
|
||||||
__m128i a = kernel.packet[0].x;
|
__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) {
|
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; }
|
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 h[4];
|
||||||
|
|
||||||
Eigen::half ha = raw_uint16_to_half(static_cast<unsigned short>(a64));
|
Eigen::half ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64));
|
||||||
Eigen::half hb = raw_uint16_to_half(static_cast<unsigned short>(b64));
|
Eigen::half hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64));
|
||||||
h[0] = ha + hb;
|
h[0] = ha + hb;
|
||||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
||||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
||||||
h[1] = ha + hb;
|
h[1] = ha + hb;
|
||||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
||||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
||||||
h[2] = ha + hb;
|
h[2] = ha + hb;
|
||||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
||||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
||||||
h[3] = ha + hb;
|
h[3] = ha + hb;
|
||||||
Packet4h result;
|
Packet4h result;
|
||||||
result.x = _mm_set_pi16(h[3].x, h[2].x, h[1].x, h[0].x);
|
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 h[4];
|
||||||
|
|
||||||
Eigen::half ha = raw_uint16_to_half(static_cast<unsigned short>(a64));
|
Eigen::half ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64));
|
||||||
Eigen::half hb = raw_uint16_to_half(static_cast<unsigned short>(b64));
|
Eigen::half hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64));
|
||||||
h[0] = ha * hb;
|
h[0] = ha * hb;
|
||||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 16));
|
||||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 16));
|
||||||
h[1] = ha * hb;
|
h[1] = ha * hb;
|
||||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 32));
|
||||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 32));
|
||||||
h[2] = ha * hb;
|
h[2] = ha * hb;
|
||||||
ha = raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
ha = half_impl::raw_uint16_to_half(static_cast<unsigned short>(a64 >> 48));
|
||||||
hb = raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
hb = half_impl::raw_uint16_to_half(static_cast<unsigned short>(b64 >> 48));
|
||||||
h[3] = ha * hb;
|
h[3] = ha * hb;
|
||||||
Packet4h result;
|
Packet4h result;
|
||||||
result.x = _mm_set_pi16(h[3].x, h[2].x, h[1].x, h[0].x);
|
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);
|
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
|
#elif defined EIGEN_VECTORIZE_AVX
|
||||||
|
|
||||||
template <>
|
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 {
|
namespace internal {
|
||||||
|
|
||||||
inline uint32x4_t p4ui_CONJ_XOR() {
|
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 };
|
static const uint32_t conj_XOR_DATA[] = { 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
|
||||||
return vld1q_u32( conj_XOR_DATA );
|
return vld1q_u32( conj_XOR_DATA );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32x2_t p2ui_CONJ_XOR() {
|
inline uint32x2_t p2ui_CONJ_XOR() {
|
||||||
@@ -282,8 +288,13 @@ ptranspose(PacketBlock<Packet2cf,2>& kernel) {
|
|||||||
//---------- double ----------
|
//---------- double ----------
|
||||||
#if EIGEN_ARCH_ARM64 && !EIGEN_APPLE_DOUBLE_NEON_BUG
|
#if EIGEN_ARCH_ARM64 && !EIGEN_APPLE_DOUBLE_NEON_BUG
|
||||||
|
|
||||||
const uint64_t p2ul_conj_XOR_DATA[] = { 0x0, 0x8000000000000000 };
|
// See bug 1325, clang fails to call vld1q_u64.
|
||||||
static uint64x2_t p2ul_CONJ_XOR = vld1q_u64( p2ul_conj_XOR_DATA );
|
#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
|
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));
|
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 internal
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
|
|||||||
/* the smallest non denormalized float number */
|
/* the smallest non denormalized float number */
|
||||||
_EIGEN_DECLARE_CONST_Packet4f_FROM_INT(min_norm_pos, 0x00800000);
|
_EIGEN_DECLARE_CONST_Packet4f_FROM_INT(min_norm_pos, 0x00800000);
|
||||||
_EIGEN_DECLARE_CONST_Packet4f_FROM_INT(minus_inf, 0xff800000);//-1.f/0.f);
|
_EIGEN_DECLARE_CONST_Packet4f_FROM_INT(minus_inf, 0xff800000);//-1.f/0.f);
|
||||||
|
|
||||||
/* natural logarithm computed for 4 simultaneous float
|
/* natural logarithm computed for 4 simultaneous float
|
||||||
return NaN for x <= 0
|
return NaN for x <= 0
|
||||||
*/
|
*/
|
||||||
@@ -444,25 +444,33 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
|
|||||||
|
|
||||||
#if EIGEN_FAST_MATH
|
#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/
|
// 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
|
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||||
Packet4f psqrt<Packet4f>(const Packet4f& _x)
|
Packet4f psqrt<Packet4f>(const Packet4f& _x)
|
||||||
{
|
{
|
||||||
Packet4f half = pmul(_x, pset1<Packet4f>(.5f));
|
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 */
|
// Compute approximate reciprocal sqrt.
|
||||||
Packet4f non_zero_mask = _mm_cmpge_ps(_x, pset1<Packet4f>((std::numeric_limits<float>::min)()));
|
Packet4f x = _mm_rsqrt_ps(_x);
|
||||||
Packet4f x = _mm_and_ps(non_zero_mask, _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))));
|
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
|
#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); }
|
Packet4f psqrt<Packet4f>(const Packet4f& x) { return _mm_sqrt_ps(x); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -491,7 +499,7 @@ Packet4f prsqrt<Packet4f>(const Packet4f& _x) {
|
|||||||
Packet4f neg_mask = _mm_cmplt_ps(_x, _mm_setzero_ps());
|
Packet4f neg_mask = _mm_cmplt_ps(_x, _mm_setzero_ps());
|
||||||
Packet4f zero_mask = _mm_andnot_ps(neg_mask, le_zero_mask);
|
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),
|
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.
|
// Do a single step of Newton's iteration.
|
||||||
x = pmul(x, pmadd(neg_half, pmul(x, x), p4f_one_point_five));
|
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.
|
// 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 <>
|
template <>
|
||||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet4f
|
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet4f
|
||||||
ptanh<Packet4f>(const Packet4f& _x) {
|
ptanh<Packet4f>(const Packet4f& x) {
|
||||||
// Clamp the inputs to the range [-9, 9] since anything outside
|
return internal::generic_fast_tanh_float(x);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // 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<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; };
|
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
|
#if EIGEN_COMP_MSVC==1500
|
||||||
// Workaround MSVC 9 internal compiler error.
|
// 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
|
// 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
|
#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 internal
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // 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;
|
// typedef typename NumTraits<Scalar>::Real result_type;
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
|
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;
|
Scalar p, qp;
|
||||||
if(_x>_y)
|
if(_x>_y)
|
||||||
{
|
{
|
||||||
@@ -287,7 +287,7 @@ struct functor_traits<scalar_hypot_op<Scalar,Scalar> > {
|
|||||||
{
|
{
|
||||||
Cost = 3 * NumTraits<Scalar>::AddCost +
|
Cost = 3 * NumTraits<Scalar>::AddCost +
|
||||||
2 * NumTraits<Scalar>::MulCost +
|
2 * NumTraits<Scalar>::MulCost +
|
||||||
2 * NumTraits<Scalar>::template Div<false>::Cost,
|
2 * scalar_div_cost<Scalar,false>::value,
|
||||||
PacketAccess = false
|
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;
|
typedef typename scalar_quotient_op<LhsScalar,RhsScalar>::result_type result_type;
|
||||||
enum {
|
enum {
|
||||||
PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv,
|
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
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
// for linear algebra.
|
// 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
|
// 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
|
// 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 {
|
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_constant_op& other) : m_other(other.m_other) { }
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(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() () const { return m_other; }
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; }
|
template<typename PacketType>
|
||||||
template<typename Index, typename PacketType>
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetOp() const { return internal::pset1<PacketType>(m_other); }
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetOp(Index, Index = 0) const { return internal::pset1<PacketType>(m_other); }
|
|
||||||
const Scalar m_other;
|
const Scalar m_other;
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
@@ -31,94 +30,85 @@ struct functor_traits<scalar_constant_op<Scalar> >
|
|||||||
|
|
||||||
template<typename Scalar> struct scalar_identity_op {
|
template<typename Scalar> struct scalar_identity_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
|
||||||
template<typename Index>
|
template<typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); }
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType row, IndexType col) const { return row==col ? Scalar(1) : Scalar(0); }
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct functor_traits<scalar_identity_op<Scalar> >
|
struct functor_traits<scalar_identity_op<Scalar> >
|
||||||
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
|
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
|
||||||
|
|
||||||
template <typename Scalar, typename Packet, bool RandomAccess, bool IsInteger> struct linspaced_op_impl;
|
template <typename Scalar, typename Packet, 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>
|
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) :
|
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>
|
template<typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType i) const {
|
||||||
const Scalar operator() (Index i) const {
|
if(m_flip)
|
||||||
return m_low + (m_length*Scalar(i))/m_divisor;
|
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>
|
template<typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(IndexType i) const
|
||||||
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)),
|
// Principle:
|
||||||
pset1<Packet>(m_divisor))); }
|
// [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_low;
|
||||||
const Scalar m_length;
|
const Scalar m_high;
|
||||||
const Scalar m_divisor;
|
const Index m_size1;
|
||||||
|
const Scalar m_step;
|
||||||
const Packet m_interPacket;
|
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 ----------------------------------------------------------------
|
// ----- 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
|
// 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
|
// us a speed gain when using packet access but it allows to use the functor in
|
||||||
// nested expressions).
|
// nested expressions).
|
||||||
template <typename Scalar, typename PacketType, bool RandomAccess = true> struct linspaced_op;
|
template <typename Scalar, typename PacketType> struct linspaced_op;
|
||||||
template <typename Scalar, typename PacketType, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,PacketType,RandomAccess> >
|
template <typename Scalar, typename PacketType> struct functor_traits< linspaced_op<Scalar,PacketType> >
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Cost = 1,
|
Cost = 1,
|
||||||
PacketAccess = packet_traits<Scalar>::HasSetLinear
|
PacketAccess = (!NumTraits<Scalar>::IsInteger) && packet_traits<Scalar>::HasSetLinear && packet_traits<Scalar>::HasBlend,
|
||||||
&& ((!NumTraits<Scalar>::IsInteger) || packet_traits<Scalar>::HasDiv),
|
/*&& ((!NumTraits<Scalar>::IsInteger) || packet_traits<Scalar>::HasDiv),*/ // <- vectorization for integer is currently disabled
|
||||||
IsRepeatable = true
|
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)
|
linspaced_op(const Scalar& low, const Scalar& high, Index num_steps)
|
||||||
: impl((num_steps==1 ? high : low),high,num_steps)
|
: impl((num_steps==1 ? high : low),high,num_steps)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename Index>
|
template<typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
|
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
|
template<typename Packet,typename IndexType>
|
||||||
// there row==0 and col is used for the actual iteration.
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(IndexType i) const { return impl.packetOp(i); }
|
||||||
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 Index, typename Packet>
|
// This proxy object handles the actual required temporaries and the different
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); }
|
// implementations (integer vs. floating point).
|
||||||
|
const linspaced_op_impl<Scalar,PacketType,NumTraits<Scalar>::IsInteger> impl;
|
||||||
// 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// all functors allow linear access, except scalar_identity_op. So we fix here a quick meta
|
// Linear access is automatically determined from the operator() prototypes available for the given functor.
|
||||||
// to indicate whether a functor allows linear access, just always answering 'yes' except for
|
// If it exposes an operator()(i,j), then we assume the i and j coefficients are required independently
|
||||||
// scalar_identity_op.
|
// and linear access is not possible. In all other cases, linear access is enabled.
|
||||||
template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
|
// Users should not have to deal with this structure.
|
||||||
template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
|
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
|
} // end namespace internal
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// This file is part of Eigen, a lightweight C++ template library
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
// for linear algebra.
|
// 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
|
// 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
|
// 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
|
// double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
|
||||||
: (14 * NumTraits<Scalar>::AddCost +
|
: (14 * NumTraits<Scalar>::AddCost +
|
||||||
6 * NumTraits<Scalar>::MulCost +
|
6 * NumTraits<Scalar>::MulCost +
|
||||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost))
|
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value))
|
||||||
#else
|
#else
|
||||||
Cost =
|
Cost =
|
||||||
(sizeof(Scalar) == 4
|
(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
|
// double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
|
||||||
: (23 * NumTraits<Scalar>::AddCost +
|
: (23 * NumTraits<Scalar>::AddCost +
|
||||||
12 * NumTraits<Scalar>::MulCost +
|
12 * NumTraits<Scalar>::MulCost +
|
||||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost))
|
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value))
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -321,7 +321,7 @@ struct functor_traits<scalar_log1p_op<Scalar> > {
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar> struct scalar_log10_op {
|
template<typename Scalar> struct scalar_log10_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(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>
|
template <typename Packet>
|
||||||
EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog10(a); }
|
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
|
/** \internal
|
||||||
* \brief Template functor to compute the tanh of a scalar
|
* \brief Template functor to compute the tanh of a scalar
|
||||||
* \sa class CwiseUnaryOp, ArrayBase::tanh()
|
* \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_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>
|
template <typename Packet>
|
||||||
EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& _x) const {
|
EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const { return ptanh(x); }
|
||||||
/** \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);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
|
||||||
struct functor_traits<scalar_tanh_op<Scalar> >
|
template <typename Scalar>
|
||||||
{
|
struct functor_traits<scalar_tanh_op<Scalar> > {
|
||||||
enum {
|
enum {
|
||||||
PacketAccess = packet_traits<Scalar>::HasTanh,
|
PacketAccess = packet_traits<Scalar>::HasTanh,
|
||||||
Cost =
|
Cost = ( (EIGEN_FAST_MATH && is_same<Scalar,float>::value)
|
||||||
(PacketAccess
|
// The following numbers are based on the AVX implementation,
|
||||||
// The following numbers are based on the AVX implementation,
|
|
||||||
#ifdef EIGEN_VECTORIZE_FMA
|
#ifdef EIGEN_VECTORIZE_FMA
|
||||||
// Haswell can issue 2 add/mul/madd per cycle.
|
// Haswell can issue 2 add/mul/madd per cycle.
|
||||||
// 9 pmadd, 2 pmul, 1 div, 2 other
|
// 9 pmadd, 2 pmul, 1 div, 2 other
|
||||||
? (2 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost +
|
? (2 * NumTraits<Scalar>::AddCost +
|
||||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost)
|
6 * NumTraits<Scalar>::MulCost +
|
||||||
|
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)
|
||||||
#else
|
#else
|
||||||
? (11 * NumTraits<Scalar>::AddCost +
|
? (11 * NumTraits<Scalar>::AddCost +
|
||||||
11 * NumTraits<Scalar>::MulCost +
|
11 * NumTraits<Scalar>::MulCost +
|
||||||
NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost)
|
scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)
|
||||||
#endif
|
#endif
|
||||||
// This number assumes a naive implementation of tanh
|
// This number assumes a naive implementation of tanh
|
||||||
: (6 * NumTraits<Scalar>::AddCost + 3 * NumTraits<Scalar>::MulCost +
|
: (6 * NumTraits<Scalar>::AddCost +
|
||||||
2 * NumTraits<Scalar>::template Div<packet_traits<Scalar>::HasDiv>::Cost +
|
3 * NumTraits<Scalar>::MulCost +
|
||||||
functor_traits<scalar_exp_op<Scalar> >::Cost))
|
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>
|
template<typename LhsPacketType, typename RhsPacketType, typename AccPacketType>
|
||||||
EIGEN_STRONG_INLINE void madd(const LhsPacketType& a, const RhsPacketType& b, AccPacketType& c, AccPacketType& tmp) const
|
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
|
// 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
|
// 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
|
// (in the case where there is no FMA) gcc fails to figure out how to avoid
|
||||||
// spilling register.
|
// spilling register.
|
||||||
#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||||
EIGEN_UNUSED_VARIABLE(tmp);
|
EIGEN_UNUSED_VARIABLE(tmp);
|
||||||
c = pmadd(a,b,c);
|
c = cj.pmadd(a,b,c);
|
||||||
#else
|
#else
|
||||||
tmp = b; tmp = pmul(a,tmp); c = padd(c,tmp);
|
tmp = b; tmp = cj.pmul(a,tmp); c = padd(c,tmp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,9 +458,6 @@ public:
|
|||||||
r = pmadd(c,alpha,r);
|
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>
|
template<typename RealScalar, bool _ConjLhs>
|
||||||
@@ -582,7 +580,7 @@ DoublePacket<Packet> padd(const DoublePacket<Packet> &a, const DoublePacket<Pack
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Packet>
|
template<typename Packet>
|
||||||
const DoublePacket<Packet>& predux4(const DoublePacket<Packet> &a)
|
const DoublePacket<Packet>& predux_downto4(const DoublePacket<Packet> &a)
|
||||||
{
|
{
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@@ -1583,10 +1581,10 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
|||||||
if(SwappedTraits::LhsProgress==8)
|
if(SwappedTraits::LhsProgress==8)
|
||||||
{
|
{
|
||||||
// Special case where we have to first reduce the accumulation register C0
|
// 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<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,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<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<SAccPacket>::half,SAccPacket>::type SAccPacketHalf;
|
||||||
|
|
||||||
SResPacketHalf R = res.template gatherPacket<SResPacketHalf>(i, j2);
|
SResPacketHalf R = res.template gatherPacket<SResPacketHalf>(i, j2);
|
||||||
SResPacketHalf alphav = pset1<SResPacketHalf>(alpha);
|
SResPacketHalf alphav = pset1<SResPacketHalf>(alpha);
|
||||||
@@ -1598,13 +1596,13 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
|||||||
SRhsPacketHalf b0;
|
SRhsPacketHalf b0;
|
||||||
straits.loadLhsUnaligned(blB, a0);
|
straits.loadLhsUnaligned(blB, a0);
|
||||||
straits.loadRhs(blA, b0);
|
straits.loadRhs(blA, b0);
|
||||||
SAccPacketHalf c0 = predux4(C0);
|
SAccPacketHalf c0 = predux_downto4(C0);
|
||||||
straits.madd(a0,b0,c0,b0);
|
straits.madd(a0,b0,c0,b0);
|
||||||
straits.acc(c0, alphav, R);
|
straits.acc(c0, alphav, R);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
straits.acc(predux4(C0), alphav, R);
|
straits.acc(predux_downto4(C0), alphav, R);
|
||||||
}
|
}
|
||||||
res.scatterPacket(i, j2, R);
|
res.scatterPacket(i, j2, R);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#ifndef EIGEN_GENERAL_MATRIX_MATRIX_H
|
#ifndef EIGEN_GENERAL_MATRIX_MATRIX_H
|
||||||
#define EIGEN_GENERAL_MATRIX_MATRIX_H
|
#define EIGEN_GENERAL_MATRIX_MATRIX_H
|
||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ template<
|
|||||||
struct general_matrix_matrix_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,RowMajor>
|
struct general_matrix_matrix_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,RowMajor>
|
||||||
{
|
{
|
||||||
typedef gebp_traits<RhsScalar,LhsScalar> Traits;
|
typedef gebp_traits<RhsScalar,LhsScalar> Traits;
|
||||||
|
|
||||||
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
||||||
static EIGEN_STRONG_INLINE void run(
|
static EIGEN_STRONG_INLINE void run(
|
||||||
Index rows, Index cols, Index depth,
|
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 gebp_traits<LhsScalar,RhsScalar> Traits;
|
||||||
|
|
||||||
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
||||||
static void run(Index rows, Index cols, Index depth,
|
static void run(Index rows, Index cols, Index depth,
|
||||||
const LhsScalar* _lhs, Index lhsStride,
|
const LhsScalar* _lhs, Index lhsStride,
|
||||||
@@ -85,13 +85,13 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
// this is the parallel version!
|
// this is the parallel version!
|
||||||
Index tid = omp_get_thread_num();
|
Index tid = omp_get_thread_num();
|
||||||
Index threads = omp_get_num_threads();
|
Index threads = omp_get_num_threads();
|
||||||
|
|
||||||
LhsScalar* blockA = blocking.blockA();
|
LhsScalar* blockA = blocking.blockA();
|
||||||
eigen_internal_assert(blockA!=0);
|
eigen_internal_assert(blockA!=0);
|
||||||
|
|
||||||
std::size_t sizeB = kc*nc;
|
std::size_t sizeB = kc*nc;
|
||||||
ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, 0);
|
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 each horizontal panel of the rhs, and corresponding vertical panel of the lhs...
|
||||||
for(Index k=0; k<depth; k+=kc)
|
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.
|
// Notify the other threads that the part A'_i is ready to go.
|
||||||
info[tid].sync = k;
|
info[tid].sync = k;
|
||||||
|
|
||||||
// Computes C_i += A' * B' per A'_i
|
// Computes C_i += A' * B' per A'_i
|
||||||
for(Index shift=0; shift<threads; ++shift)
|
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(LhsScalar, blockA, sizeA, blocking.blockA());
|
||||||
ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, blocking.blockB());
|
ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, blocking.blockB());
|
||||||
|
|
||||||
const bool pack_rhs_once = mc!=rows && kc==depth && nc==cols;
|
const bool pack_rhs_once = mc!=rows && kc==depth && nc==cols;
|
||||||
|
|
||||||
// For each horizontal panel of the rhs, and corresponding panel of the lhs...
|
// 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)
|
for(Index k2=0; k2<depth; k2+=kc)
|
||||||
{
|
{
|
||||||
const Index actual_kc = (std::min)(k2+kc,depth)-k2;
|
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.
|
// 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)
|
// => 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
|
// 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.
|
// horizontal panel which is, in practice, a very low number.
|
||||||
pack_lhs(blockA, lhs.getSubMapper(i2,k2), actual_kc, actual_mc);
|
pack_lhs(blockA, lhs.getSubMapper(i2,k2), actual_kc, actual_mc);
|
||||||
|
|
||||||
// For each kc x nc block of the rhs's horizontal panel...
|
// For each kc x nc block of the rhs's horizontal panel...
|
||||||
for(Index j2=0; j2<cols; j2+=nc)
|
for(Index j2=0; j2<cols; j2+=nc)
|
||||||
{
|
{
|
||||||
const Index actual_nc = (std::min)(j2+nc,cols)-j2;
|
const Index actual_nc = (std::min)(j2+nc,cols)-j2;
|
||||||
|
|
||||||
// We pack the rhs's block into a sequential chunk of memory (L2 caching)
|
// 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
|
// 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).
|
// micro horizontal panel of the large rhs's panel (e.g., rows/12 times).
|
||||||
if((!pack_rhs_once) || i2==0)
|
if((!pack_rhs_once) || i2==0)
|
||||||
pack_rhs(blockB, rhs.getSubMapper(k2,j2), actual_kc, actual_nc);
|
pack_rhs(blockB, rhs.getSubMapper(k2,j2), actual_kc, actual_nc);
|
||||||
|
|
||||||
// Everything is packed, we can now call the panel * block kernel:
|
// 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);
|
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(),
|
(Scalar*)&(m_dest.coeffRef(row,col)), m_dest.outerStride(),
|
||||||
m_actualAlpha, m_blocking, info);
|
m_actualAlpha, m_blocking, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef typename Gemm::Traits Traits;
|
typedef typename Gemm::Traits Traits;
|
||||||
|
|
||||||
protected:
|
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));
|
this->m_blockB = reinterpret_cast<RhsScalar*>((internal::UIntPtr(m_staticB) + (EIGEN_DEFAULT_ALIGN_BYTES-1)) & ~std::size_t(EIGEN_DEFAULT_ALIGN_BYTES-1));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void initParallel(Index, Index, Index, Index)
|
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_sizeA = this->m_mc * this->m_kc;
|
||||||
m_sizeB = this->m_kc * this->m_nc;
|
m_sizeB = this->m_kc * this->m_nc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initParallel(Index rows, Index cols, Index depth, Index num_threads)
|
void initParallel(Index rows, Index cols, Index depth, Index num_threads)
|
||||||
{
|
{
|
||||||
this->m_mc = Transpose ? cols : rows;
|
this->m_mc = Transpose ? cols : rows;
|
||||||
this->m_nc = Transpose ? rows : cols;
|
this->m_nc = Transpose ? rows : cols;
|
||||||
this->m_kc = depth;
|
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;
|
Index m = this->m_mc;
|
||||||
computeProductBlockingSizes<LhsScalar,RhsScalar,KcFactor>(this->m_kc, m, this->m_nc, num_threads);
|
computeProductBlockingSizes<LhsScalar,RhsScalar,KcFactor>(this->m_kc, m, this->m_nc, num_threads);
|
||||||
m_sizeA = this->m_mc * this->m_kc;
|
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
|
} // end namespace internal
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct>
|
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct>
|
||||||
: generic_product_impl_base<Lhs,Rhs,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 Product<Lhs,Rhs>::Scalar Scalar;
|
||||||
typedef typename Lhs::Scalar LhsScalar;
|
typedef typename Lhs::Scalar LhsScalar;
|
||||||
typedef typename Rhs::Scalar RhsScalar;
|
typedef typename Rhs::Scalar RhsScalar;
|
||||||
|
|
||||||
typedef internal::blas_traits<Lhs> LhsBlasTraits;
|
typedef internal::blas_traits<Lhs> LhsBlasTraits;
|
||||||
typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType;
|
typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType;
|
||||||
typedef typename internal::remove_all<ActualLhsType>::type ActualLhsTypeCleaned;
|
typedef typename internal::remove_all<ActualLhsType>::type ActualLhsTypeCleaned;
|
||||||
|
|
||||||
typedef internal::blas_traits<Rhs> RhsBlasTraits;
|
typedef internal::blas_traits<Rhs> RhsBlasTraits;
|
||||||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
||||||
typedef typename internal::remove_all<ActualRhsType>::type ActualRhsTypeCleaned;
|
typedef typename internal::remove_all<ActualRhsType>::type ActualRhsTypeCleaned;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MaxDepthAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(Lhs::MaxColsAtCompileTime,Rhs::MaxRowsAtCompileTime)
|
MaxDepthAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(Lhs::MaxColsAtCompileTime,Rhs::MaxRowsAtCompileTime)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode> lazyproduct;
|
typedef generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode> lazyproduct;
|
||||||
|
|
||||||
template<typename Dst>
|
template<typename Dst>
|
||||||
static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
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
|
else
|
||||||
scaleAndAddTo(dst, lhs, rhs, Scalar(-1));
|
scaleAndAddTo(dst, lhs, rhs, Scalar(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
static void scaleAndAddTo(Dest& dst, const Lhs& a_lhs, const Rhs& a_rhs, const Scalar& alpha)
|
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);
|
BlockingType blocking(dst.rows(), dst.cols(), lhs.cols(), 1, true);
|
||||||
internal::parallelize_gemm<(Dest::MaxRowsAtCompileTime>32 || Dest::MaxRowsAtCompileTime==Dynamic)>
|
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;
|
alignmentPattern = AllAligned;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Index offset1 = (FirstAligned && alignmentStep==1?3:1);
|
const Index offset1 = (FirstAligned && alignmentStep==1)?3:1;
|
||||||
const Index offset3 = (FirstAligned && alignmentStep==1?1:3);
|
const Index offset3 = (FirstAligned && alignmentStep==1)?1:3;
|
||||||
|
|
||||||
Index columnBound = ((cols-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
|
Index columnBound = ((cols-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
|
||||||
for (Index i=skipColumns; i<columnBound; i+=columnsAtOnce)
|
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;
|
alignmentPattern = AllAligned;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Index offset1 = (FirstAligned && alignmentStep==1?3:1);
|
const Index offset1 = (FirstAligned && alignmentStep==1)?3:1;
|
||||||
const Index offset3 = (FirstAligned && alignmentStep==1?1:3);
|
const Index offset3 = (FirstAligned && alignmentStep==1)?1:3;
|
||||||
|
|
||||||
Index rowBound = ((rows-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
|
Index rowBound = ((rows-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
|
||||||
for (Index i=skipRows; i<rowBound; i+=rowsAtOnce)
|
for (Index i=skipRows; i<rowBound; i+=rowsAtOnce)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#ifndef EIGEN_PARALLELIZER_H
|
#ifndef EIGEN_PARALLELIZER_H
|
||||||
#define EIGEN_PARALLELIZER_H
|
#define EIGEN_PARALLELIZER_H
|
||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ template<typename Index> struct GemmParallelInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<bool Condition, typename Functor, typename Index>
|
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,
|
// TODO when EIGEN_USE_BLAS is defined,
|
||||||
// we should still enable OMP for other scalar types
|
// 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
|
// the matrix product when multithreading is enabled. This is a temporary
|
||||||
// fix to support row-major destination matrices. This whole
|
// fix to support row-major destination matrices. This whole
|
||||||
// parallelizer mechanism has to be redisigned anyway.
|
// parallelizer mechanism has to be redisigned anyway.
|
||||||
|
EIGEN_UNUSED_VARIABLE(depth);
|
||||||
EIGEN_UNUSED_VARIABLE(transpose);
|
EIGEN_UNUSED_VARIABLE(transpose);
|
||||||
func(0,rows, 0,cols);
|
func(0,rows, 0,cols);
|
||||||
#else
|
#else
|
||||||
@@ -106,6 +107,12 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos
|
|||||||
// FIXME this has to be fine tuned
|
// FIXME this has to be fine tuned
|
||||||
Index size = transpose ? rows : cols;
|
Index size = transpose ? rows : cols;
|
||||||
Index pb_max_threads = std::max<Index>(1,size / 32);
|
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
|
// compute the number of threads we are going to use
|
||||||
Index threads = std::min<Index>(nbThreads(), pb_max_threads);
|
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)
|
if(transpose)
|
||||||
std::swap(rows,cols);
|
std::swap(rows,cols);
|
||||||
|
|
||||||
ei_declare_aligned_stack_constructed_variable(GemmParallelInfo<Index>,info,threads,0);
|
ei_declare_aligned_stack_constructed_variable(GemmParallelInfo<Index>,info,threads,0);
|
||||||
|
|
||||||
#pragma omp parallel num_threads(threads)
|
#pragma omp parallel num_threads(threads)
|
||||||
{
|
{
|
||||||
Index i = omp_get_thread_num();
|
Index i = omp_get_thread_num();
|
||||||
// Note that the actual number of threads might be lower than the number of request ones.
|
// Note that the actual number of threads might be lower than the number of request ones.
|
||||||
Index actual_threads = omp_get_num_threads();
|
Index actual_threads = omp_get_num_threads();
|
||||||
|
|
||||||
Index blockCols = (cols / actual_threads) & ~Index(0x3);
|
Index blockCols = (cols / actual_threads) & ~Index(0x3);
|
||||||
Index blockRows = (rows / actual_threads);
|
Index blockRows = (rows / actual_threads);
|
||||||
blockRows = (blockRows/Functor::Traits::mr)*Functor::Traits::mr;
|
blockRows = (blockRows/Functor::Traits::mr)*Functor::Traits::mr;
|
||||||
|
|
||||||
Index r0 = i*blockRows;
|
Index r0 = i*blockRows;
|
||||||
Index actualBlockRows = (i+1==actual_threads) ? rows-r0 : 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 Dest::Scalar ResScalar;
|
||||||
typedef typename Rhs::Scalar RhsScalar;
|
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());
|
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 internal::blas_traits<Rhs> RhsBlasTraits;
|
||||||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
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<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(lhs);
|
||||||
typename internal::add_const_on_value_type<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(rhs);
|
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<> struct conj_if<true> {
|
||||||
template<typename T>
|
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>
|
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<> struct conj_if<false> {
|
||||||
template<typename T>
|
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>
|
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>
|
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)
|
static inline Scalar extractScalarFactor(const XprType& x)
|
||||||
{ return Base::extractScalarFactor(x.lhs()) * x.rhs().functor().m_other; }
|
{ 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
|
// pop opposite
|
||||||
template<typename Scalar, typename NestedXpr>
|
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
|
// 4512 - assignment operator could not be generated
|
||||||
// 4522 - 'class' : multiple assignment operators specified
|
// 4522 - 'class' : multiple assignment operators specified
|
||||||
// 4700 - uninitialized local variable 'xyz' used
|
// 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
|
// 4717 - 'function' : recursive on all control paths, function will cause runtime stack overflow
|
||||||
// 4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning)
|
// 4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning)
|
||||||
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
||||||
#pragma warning( push )
|
#pragma warning( push )
|
||||||
#endif
|
#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
|
#elif defined __INTEL_COMPILER
|
||||||
// 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
|
// 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
|
||||||
@@ -56,13 +57,19 @@
|
|||||||
#pragma diag_suppress code_is_unreachable
|
#pragma diag_suppress code_is_unreachable
|
||||||
// Disable the "dynamic initialization in unreachable code" message
|
// Disable the "dynamic initialization in unreachable code" message
|
||||||
#pragma diag_suppress initialization_not_reachable
|
#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 2651
|
||||||
#pragma diag_suppress 2653
|
#pragma diag_suppress 2653
|
||||||
#pragma diag_suppress 2668
|
#pragma diag_suppress 2668
|
||||||
#pragma diag_suppress 2669
|
#pragma diag_suppress 2669
|
||||||
#pragma diag_suppress 2670
|
#pragma diag_suppress 2670
|
||||||
#pragma diag_suppress 2671
|
#pragma diag_suppress 2671
|
||||||
|
#pragma diag_suppress 2735
|
||||||
|
#pragma diag_suppress 2737
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // not EIGEN_WARNINGS_DISABLED
|
#endif // not EIGEN_WARNINGS_DISABLED
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
#define EIGEN_MACROS_H
|
#define EIGEN_MACROS_H
|
||||||
|
|
||||||
#define EIGEN_WORLD_VERSION 3
|
#define EIGEN_WORLD_VERSION 3
|
||||||
#define EIGEN_MAJOR_VERSION 2
|
#define EIGEN_MAJOR_VERSION 3
|
||||||
#define EIGEN_MINOR_VERSION 93
|
#define EIGEN_MINOR_VERSION 0
|
||||||
|
|
||||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||||
@@ -28,9 +28,9 @@
|
|||||||
#define EIGEN_COMP_GNUC 0
|
#define EIGEN_COMP_GNUC 0
|
||||||
#endif
|
#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__)
|
#if defined(__clang__)
|
||||||
#define EIGEN_COMP_CLANG 1
|
#define EIGEN_COMP_CLANG (__clang_major__*100+__clang_minor__)
|
||||||
#else
|
#else
|
||||||
#define EIGEN_COMP_CLANG 0
|
#define EIGEN_COMP_CLANG 0
|
||||||
#endif
|
#endif
|
||||||
@@ -356,6 +356,13 @@
|
|||||||
#define EIGEN_MAX_CPP_VER 99
|
#define EIGEN_MAX_CPP_VER 99
|
||||||
#endif
|
#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?
|
// Do we support r-value references?
|
||||||
#ifndef EIGEN_HAS_RVALUE_REFERENCES
|
#ifndef EIGEN_HAS_RVALUE_REFERENCES
|
||||||
#if EIGEN_MAX_CPP_VER>=11 && \
|
#if EIGEN_MAX_CPP_VER>=11 && \
|
||||||
@@ -392,8 +399,8 @@
|
|||||||
// Does the compiler support variadic templates?
|
// Does the compiler support variadic templates?
|
||||||
#ifndef EIGEN_HAS_VARIADIC_TEMPLATES
|
#ifndef EIGEN_HAS_VARIADIC_TEMPLATES
|
||||||
#if EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) \
|
#if EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) \
|
||||||
&& ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 )
|
&& ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000) )
|
||||||
// ^^ Disable the use of variadic templates when compiling with nvcc on ARM devices:
|
// ^^ 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
|
// this prevents nvcc from crashing when compiling Eigen on Tegra X1
|
||||||
#define EIGEN_HAS_VARIADIC_TEMPLATES 1
|
#define EIGEN_HAS_VARIADIC_TEMPLATES 1
|
||||||
#else
|
#else
|
||||||
@@ -652,6 +659,9 @@ namespace Eigen {
|
|||||||
// If the user explicitly disable vectorization, then we also disable alignment
|
// If the user explicitly disable vectorization, then we also disable alignment
|
||||||
#if defined(EIGEN_DONT_VECTORIZE)
|
#if defined(EIGEN_DONT_VECTORIZE)
|
||||||
#define EIGEN_IDEAL_MAX_ALIGN_BYTES 0
|
#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__)
|
#elif defined(__AVX__)
|
||||||
// 32 bytes static alignmeent is preferred only if really required
|
// 32 bytes static alignmeent is preferred only if really required
|
||||||
#define EIGEN_IDEAL_MAX_ALIGN_BYTES 32
|
#define EIGEN_IDEAL_MAX_ALIGN_BYTES 32
|
||||||
@@ -801,7 +811,7 @@ namespace Eigen {
|
|||||||
// just an empty macro !
|
// just an empty macro !
|
||||||
#define EIGEN_EMPTY
|
#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) \
|
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
||||||
using Base::operator =;
|
using Base::operator =;
|
||||||
#elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
#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)
|
# define EIGEN_CATCH(X) catch (X)
|
||||||
#else
|
#else
|
||||||
# ifdef __CUDA_ARCH__
|
# ifdef __CUDA_ARCH__
|
||||||
# define EIGEN_THROW_X(X) asm("trap;") return {}
|
# define EIGEN_THROW_X(X) asm("trap;")
|
||||||
# define EIGEN_THROW asm("trap;"); return {}
|
# define EIGEN_THROW asm("trap;")
|
||||||
# else
|
# else
|
||||||
# define EIGEN_THROW_X(X) std::abort()
|
# define EIGEN_THROW_X(X) std::abort()
|
||||||
# define EIGEN_THROW 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);
|
destruct_elements_of_array(ptr, i);
|
||||||
EIGEN_THROW;
|
EIGEN_THROW;
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@@ -305,6 +306,7 @@ template<typename T> EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size)
|
|||||||
aligned_free(result);
|
aligned_free(result);
|
||||||
EIGEN_THROW;
|
EIGEN_THROW;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(size_t size)
|
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);
|
conditional_aligned_free<Align>(result);
|
||||||
EIGEN_THROW;
|
EIGEN_THROW;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \internal Deletes objects constructed with aligned_new
|
/** \internal Deletes objects constructed with aligned_new
|
||||||
|
|||||||
@@ -22,6 +22,16 @@
|
|||||||
|
|
||||||
namespace Eigen {
|
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 {
|
namespace internal {
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
@@ -358,17 +368,46 @@ struct result_of<Func(ArgType0,ArgType1,ArgType2)> {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct meta_yes { char a[1]; };
|
||||||
|
struct meta_no { char a[2]; };
|
||||||
|
|
||||||
// Check whether T::ReturnType does exist
|
// Check whether T::ReturnType does exist
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_ReturnType
|
struct has_ReturnType
|
||||||
{
|
{
|
||||||
typedef char yes[1];
|
template <typename C> static meta_yes testFunctor(typename C::ReturnType const *);
|
||||||
typedef char no[2];
|
template <typename C> static meta_no testFunctor(...);
|
||||||
|
|
||||||
template <typename C> static yes& testFunctor(C const *, typename C::ReturnType const * = 0);
|
enum { value = sizeof(testFunctor<T>(0)) == sizeof(meta_yes) };
|
||||||
static no& testFunctor(...);
|
};
|
||||||
|
|
||||||
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.
|
/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#if defined __NVCC__
|
#if defined __NVCC__
|
||||||
// Don't reenable the diagnostic messages, as it turns out these messages need
|
// 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)
|
// 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 code_is_unreachable
|
||||||
// #pragma diag_default initialization_not_reachable
|
// #pragma diag_default initialization_not_reachable
|
||||||
// #pragma diag_default 2651
|
// #pragma diag_default 2651
|
||||||
|
|||||||
@@ -100,7 +100,8 @@
|
|||||||
MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY,
|
MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY,
|
||||||
THIS_TYPE_IS_NOT_SUPPORTED,
|
THIS_TYPE_IS_NOT_SUPPORTED,
|
||||||
STORAGE_KIND_MUST_MATCH,
|
STORAGE_KIND_MUST_MATCH,
|
||||||
STORAGE_INDEX_MUST_MATCH
|
STORAGE_INDEX_MUST_MATCH,
|
||||||
|
CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,16 +24,6 @@
|
|||||||
|
|
||||||
namespace Eigen {
|
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 {
|
namespace internal {
|
||||||
|
|
||||||
template<typename IndexDest, typename IndexSrc>
|
template<typename IndexDest, typename IndexSrc>
|
||||||
@@ -201,7 +191,7 @@ struct find_best_packet
|
|||||||
#if EIGEN_MAX_STATIC_ALIGN_BYTES>0
|
#if EIGEN_MAX_STATIC_ALIGN_BYTES>0
|
||||||
template<int ArrayBytes, int AlignmentBytes,
|
template<int ArrayBytes, int AlignmentBytes,
|
||||||
bool Match = bool((ArrayBytes%AlignmentBytes)==0),
|
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
|
struct compute_default_alignment_helper
|
||||||
{
|
{
|
||||||
enum { value = 0 };
|
enum { value = 0 };
|
||||||
@@ -674,6 +664,28 @@ bool is_same_dense(const T1 &, const T2 &, typename enable_if<!(has_direct_acces
|
|||||||
return false;
|
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
|
#ifdef EIGEN_DEBUG_ASSIGN
|
||||||
std::string demangle_traversal(int t)
|
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.
|
* 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.
|
* 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
|
\code
|
||||||
template<typename BinaryOp>
|
template<typename BinaryOp>
|
||||||
struct ScalarBinaryOpTraits<U1,U2,BinaryOp> { typedef U3 ReturnType; };
|
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; };
|
struct ScalarBinaryOpTraits<U1,U2,internal::scalar_sum_op<U1,U2> > { typedef U1 ReturnType; };
|
||||||
\endcode
|
\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
|
* \sa CwiseBinaryOp
|
||||||
*/
|
*/
|
||||||
template<typename ScalarA, typename ScalarB, typename BinaryOp=internal::scalar_product_op<ScalarA,ScalarB> >
|
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;
|
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
|
// For Matrix * Permutation
|
||||||
template<typename T, typename BinaryOp>
|
template<typename T, typename BinaryOp>
|
||||||
struct ScalarBinaryOpTraits<T,void,BinaryOp>
|
struct ScalarBinaryOpTraits<T,void,BinaryOp>
|
||||||
@@ -772,18 +803,6 @@ struct ScalarBinaryOpTraits<void,void,BinaryOp>
|
|||||||
typedef void ReturnType;
|
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.
|
// 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.
|
// 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
|
// 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
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
// for linear algebra.
|
// 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) 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
|
// 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
|
// 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;
|
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.
|
* This is a column vector with entries of type #ComplexScalar.
|
||||||
* The length of the vector is the size of #MatrixType.
|
* The length of the vector is the size of #MatrixType.
|
||||||
@@ -114,7 +115,14 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
*
|
*
|
||||||
* \sa compute() for an example.
|
* \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
|
/** \brief Default constructor with memory preallocation
|
||||||
*
|
*
|
||||||
@@ -126,10 +134,9 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
: m_eivec(size, size),
|
: m_eivec(size, size),
|
||||||
m_alphas(size),
|
m_alphas(size),
|
||||||
m_betas(size),
|
m_betas(size),
|
||||||
m_isInitialized(false),
|
m_valuesOkay(false),
|
||||||
m_eigenvectorsOk(false),
|
m_vectorsOkay(false),
|
||||||
m_realQZ(size),
|
m_realQZ(size),
|
||||||
m_matS(size, size),
|
|
||||||
m_tmp(size)
|
m_tmp(size)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -149,10 +156,9 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
: m_eivec(A.rows(), A.cols()),
|
: m_eivec(A.rows(), A.cols()),
|
||||||
m_alphas(A.cols()),
|
m_alphas(A.cols()),
|
||||||
m_betas(A.cols()),
|
m_betas(A.cols()),
|
||||||
m_isInitialized(false),
|
m_valuesOkay(false),
|
||||||
m_eigenvectorsOk(false),
|
m_vectorsOkay(false),
|
||||||
m_realQZ(A.cols()),
|
m_realQZ(A.cols()),
|
||||||
m_matS(A.rows(), A.cols()),
|
|
||||||
m_tmp(A.cols())
|
m_tmp(A.cols())
|
||||||
{
|
{
|
||||||
compute(A, B, computeEigenvectors);
|
compute(A, B, computeEigenvectors);
|
||||||
@@ -160,22 +166,20 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
|
|
||||||
/* \brief Returns the computed generalized eigenvectors.
|
/* \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
|
* \pre Either the constructor
|
||||||
* GeneralizedEigenSolver(const MatrixType&,const MatrixType&, bool) or the member function
|
* GeneralizedEigenSolver(const MatrixType&,const MatrixType&, bool) or the member function
|
||||||
* compute(const MatrixType&, const MatrixType& bool) has been called before, and
|
* compute(const MatrixType&, const MatrixType& bool) has been called before, and
|
||||||
* \p computeEigenvectors was set to true (the default).
|
* \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()
|
* \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.
|
/** \brief Returns an expression of the computed generalized eigenvalues.
|
||||||
*
|
*
|
||||||
@@ -197,7 +201,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
*/
|
*/
|
||||||
EigenvalueType eigenvalues() const
|
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);
|
return EigenvalueType(m_alphas,m_betas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +212,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
* \sa betas(), eigenvalues() */
|
* \sa betas(), eigenvalues() */
|
||||||
ComplexVectorType alphas() const
|
ComplexVectorType alphas() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
|
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||||
return m_alphas;
|
return m_alphas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +223,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
* \sa alphas(), eigenvalues() */
|
* \sa alphas(), eigenvalues() */
|
||||||
VectorType betas() const
|
VectorType betas() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "GeneralizedEigenSolver is not initialized.");
|
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||||
return m_betas;
|
return m_betas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +254,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
|
|
||||||
ComputationInfo info() const
|
ComputationInfo info() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
|
eigen_assert(m_valuesOkay && "EigenSolver is not initialized.");
|
||||||
return m_realQZ.info();
|
return m_realQZ.info();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,29 +274,14 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
|
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
MatrixType m_eivec;
|
EigenvectorsType m_eivec;
|
||||||
ComplexVectorType m_alphas;
|
ComplexVectorType m_alphas;
|
||||||
VectorType m_betas;
|
VectorType m_betas;
|
||||||
bool m_isInitialized;
|
bool m_valuesOkay, m_vectorsOkay;
|
||||||
bool m_eigenvectorsOk;
|
|
||||||
RealQZ<MatrixType> m_realQZ;
|
RealQZ<MatrixType> m_realQZ;
|
||||||
MatrixType m_matS;
|
ComplexVectorType m_tmp;
|
||||||
|
|
||||||
typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ColumnVectorType;
|
|
||||||
ColumnVectorType 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>
|
template<typename MatrixType>
|
||||||
GeneralizedEigenSolver<MatrixType>&
|
GeneralizedEigenSolver<MatrixType>&
|
||||||
GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
|
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::sqrt;
|
||||||
using std::abs;
|
using std::abs;
|
||||||
eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
|
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:
|
// Reduce to generalized real Schur form:
|
||||||
// A = Q S Z and B = Q T Z
|
// A = Q S Z and B = Q T Z
|
||||||
m_realQZ.compute(A, B, computeEigenvectors);
|
m_realQZ.compute(A, B, computeEigenvectors);
|
||||||
|
|
||||||
if (m_realQZ.info() == Success)
|
if (m_realQZ.info() == Success)
|
||||||
{
|
{
|
||||||
m_matS = m_realQZ.matrixS();
|
// Resize storage
|
||||||
const MatrixType &matT = m_realQZ.matrixT();
|
m_alphas.resize(size);
|
||||||
|
m_betas.resize(size);
|
||||||
if (computeEigenvectors)
|
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);
|
// Real eigenvalue
|
||||||
m_betas.coeffRef(i) = matT.coeff(i,i);
|
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;
|
++i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -333,27 +364,53 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
|
|||||||
|
|
||||||
// T = [a 0]
|
// T = [a 0]
|
||||||
// [0 b]
|
// [0 b]
|
||||||
RealScalar a = matT.diagonal().coeff(i),
|
RealScalar a = mT.diagonal().coeff(i),
|
||||||
b = matT.diagonal().coeff(i+1);
|
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.
|
// ^^ 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 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)));
|
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);
|
const ComplexScalar alpha = ComplexScalar(S2.coeff(1,1) + p, (beta > 0) ? z : -z);
|
||||||
m_alphas.coeffRef(i+1) = ComplexScalar(S2.coeff(1,1) + p, -z);
|
m_alphas.coeffRef(i) = conj(alpha);
|
||||||
|
m_alphas.coeffRef(i+1) = alpha;
|
||||||
|
|
||||||
m_betas.coeffRef(i) =
|
if (computeEigenvectors) {
|
||||||
m_betas.coeffRef(i+1) = a*b;
|
// 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;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_valuesOkay = true;
|
||||||
|
m_vectorsOkay = computeEigenvectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isInitialized = true;
|
|
||||||
m_eigenvectorsOk = false;//computeEigenvectors;
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ template<typename _MatrixType> class RealSchur
|
|||||||
typedef Matrix<Scalar,3,1> Vector3s;
|
typedef Matrix<Scalar,3,1> Vector3s;
|
||||||
|
|
||||||
Scalar computeNormOfT();
|
Scalar computeNormOfT();
|
||||||
Index findSmallSubdiagEntry(Index iu, const Scalar& maxDiagEntry);
|
Index findSmallSubdiagEntry(Index iu);
|
||||||
void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift);
|
void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift);
|
||||||
void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo);
|
void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo);
|
||||||
void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector);
|
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)
|
if(norm!=0)
|
||||||
{
|
{
|
||||||
Scalar maxDiagEntry = m_matT.cwiseAbs().diagonal().maxCoeff();
|
|
||||||
|
|
||||||
while (iu >= 0)
|
while (iu >= 0)
|
||||||
{
|
{
|
||||||
Index il = findSmallSubdiagEntry(iu,maxDiagEntry);
|
Index il = findSmallSubdiagEntry(iu);
|
||||||
|
|
||||||
// Check for convergence
|
// Check for convergence
|
||||||
if (il == iu) // One root found
|
if (il == iu) // One root found
|
||||||
{
|
{
|
||||||
m_matT.coeffRef(iu,iu) = m_matT.coeff(iu,iu) + exshift;
|
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)
|
if (iu > 0)
|
||||||
m_matT.coeffRef(iu, iu-1) = Scalar(0);
|
m_matT.coeffRef(iu, iu-1) = Scalar(0);
|
||||||
iu--;
|
iu--;
|
||||||
@@ -313,8 +309,6 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMa
|
|||||||
else if (il == iu-1) // Two roots found
|
else if (il == iu-1) // Two roots found
|
||||||
{
|
{
|
||||||
splitOffTwoRows(iu, computeU, exshift);
|
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;
|
iu -= 2;
|
||||||
iter = 0;
|
iter = 0;
|
||||||
}
|
}
|
||||||
@@ -329,8 +323,6 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMa
|
|||||||
Index im;
|
Index im;
|
||||||
initFrancisQRStep(il, iu, shiftInfo, im, firstHouseholderVector);
|
initFrancisQRStep(il, iu, shiftInfo, im, firstHouseholderVector);
|
||||||
performFrancisQRStep(il, im, iu, computeU, firstHouseholderVector, workspace);
|
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 */
|
/** \internal Look for single small sub-diagonal element and returns its index */
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
inline Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu, const Scalar& maxDiagEntry)
|
inline Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu)
|
||||||
{
|
{
|
||||||
using std::abs;
|
using std::abs;
|
||||||
Index res = iu;
|
Index res = iu;
|
||||||
while (res > 0)
|
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;
|
break;
|
||||||
res--;
|
res--;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -501,7 +501,7 @@ ComputationInfo computeFromTridiagonal_impl(DiagType& diag, SubDiagType& subdiag
|
|||||||
subdiag[i] = 0;
|
subdiag[i] = 0;
|
||||||
|
|
||||||
// find the largest unreduced block
|
// find the largest unreduced block
|
||||||
while (end>0 && subdiag[end-1]==0)
|
while (end>0 && subdiag[end-1]==RealScalar(0))
|
||||||
{
|
{
|
||||||
end--;
|
end--;
|
||||||
}
|
}
|
||||||
@@ -569,8 +569,8 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
|
|||||||
EIGEN_USING_STD_MATH(atan2)
|
EIGEN_USING_STD_MATH(atan2)
|
||||||
EIGEN_USING_STD_MATH(cos)
|
EIGEN_USING_STD_MATH(cos)
|
||||||
EIGEN_USING_STD_MATH(sin)
|
EIGEN_USING_STD_MATH(sin)
|
||||||
const Scalar s_inv3 = Scalar(1.0)/Scalar(3.0);
|
const Scalar s_inv3 = Scalar(1)/Scalar(3);
|
||||||
const Scalar s_sqrt3 = sqrt(Scalar(3.0));
|
const Scalar s_sqrt3 = sqrt(Scalar(3));
|
||||||
|
|
||||||
// The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The
|
// 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
|
// 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));
|
// RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2));
|
||||||
// This explain the following, somewhat more complicated, version:
|
// This explain the following, somewhat more complicated, version:
|
||||||
RealScalar mu = diag[end];
|
RealScalar mu = diag[end];
|
||||||
if(td==0)
|
if(td==RealScalar(0))
|
||||||
mu -= abs(e);
|
mu -= abs(e);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RealScalar e2 = numext::abs2(subdiag[end-1]);
|
RealScalar e2 = numext::abs2(subdiag[end-1]);
|
||||||
RealScalar h = numext::hypot(td,e);
|
RealScalar h = numext::hypot(td,e);
|
||||||
if(e2==0) mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h);
|
if(e2==RealScalar(0)) mu -= (e / (td + (td>RealScalar(0) ? RealScalar(1) : RealScalar(-1)))) * (e / h);
|
||||||
else mu -= e2 / (td + (td>0 ? h : -h));
|
else mu -= e2 / (td + (td>RealScalar(0) ? h : -h));
|
||||||
}
|
}
|
||||||
|
|
||||||
RealScalar x = diag[start] - mu;
|
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. */
|
/** Default constructor initializing a null box. */
|
||||||
inline AlignedBox()
|
EIGEN_DEVICE_FUNC inline AlignedBox()
|
||||||
{ if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
|
{ if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
|
||||||
|
|
||||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
/** 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(); }
|
{ setEmpty(); }
|
||||||
|
|
||||||
/** Constructs a box with extremities \a _min and \a _max.
|
/** 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. */
|
* \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>
|
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. */
|
/** Constructs a box containing a single point \a p. */
|
||||||
template<typename Derived>
|
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 */
|
/** \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() */
|
/** \deprecated use isEmpty() */
|
||||||
inline bool isNull() const { return isEmpty(); }
|
EIGEN_DEVICE_FUNC inline bool isNull() const { return isEmpty(); }
|
||||||
|
|
||||||
/** \deprecated use setEmpty() */
|
/** \deprecated use setEmpty() */
|
||||||
inline void setNull() { setEmpty(); }
|
EIGEN_DEVICE_FUNC inline void setNull() { setEmpty(); }
|
||||||
|
|
||||||
/** \returns true if the box is empty.
|
/** \returns true if the box is empty.
|
||||||
* \sa setEmpty */
|
* \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.
|
/** Makes \c *this an empty box.
|
||||||
* \sa isEmpty */
|
* \sa isEmpty */
|
||||||
inline void setEmpty()
|
EIGEN_DEVICE_FUNC inline void setEmpty()
|
||||||
{
|
{
|
||||||
m_min.setConstant( ScalarTraits::highest() );
|
m_min.setConstant( ScalarTraits::highest() );
|
||||||
m_max.setConstant( ScalarTraits::lowest() );
|
m_max.setConstant( ScalarTraits::lowest() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the minimal corner */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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
|
center() const
|
||||||
{ return (m_min+m_max)/RealScalar(2); }
|
{ 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
|
* Note that this function does not get the same
|
||||||
* result for integral or floating scalar types: see
|
* 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; }
|
{ return m_max - m_min; }
|
||||||
|
|
||||||
/** \returns the volume of the bounding box */
|
/** \returns the volume of the bounding box */
|
||||||
inline Scalar volume() const
|
EIGEN_DEVICE_FUNC inline Scalar volume() const
|
||||||
{ return sizes().prod(); }
|
{ return sizes().prod(); }
|
||||||
|
|
||||||
/** \returns an expression for the bounding box diagonal vector
|
/** \returns an expression for the bounding box diagonal vector
|
||||||
* if the length of the diagonal is needed: diagonal().norm()
|
* if the length of the diagonal is needed: diagonal().norm()
|
||||||
* will provide it.
|
* 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(); }
|
{ return sizes(); }
|
||||||
|
|
||||||
/** \returns the vertex of the bounding box at the corner defined by
|
/** \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:
|
* For 3D bounding boxes, the following names are added:
|
||||||
* BottomLeftCeil, BottomRightCeil, TopLeftCeil, TopRightCeil.
|
* 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);
|
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
|
/** \returns a random point inside the bounding box sampled with
|
||||||
* a uniform distribution */
|
* a uniform distribution */
|
||||||
inline VectorType sample() const
|
EIGEN_DEVICE_FUNC inline VectorType sample() const
|
||||||
{
|
{
|
||||||
VectorType r(dim());
|
VectorType r(dim());
|
||||||
for(Index d=0; d<dim(); ++d)
|
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. */
|
/** \returns true if the point \a p is inside the box \c *this. */
|
||||||
template<typename Derived>
|
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());
|
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();
|
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. */
|
/** \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(); }
|
{ 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.
|
/** \returns true if the box \a b is intersecting the box \c *this.
|
||||||
* \sa intersection, clamp */
|
* \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(); }
|
{ 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.
|
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this.
|
||||||
* \sa extend(const AlignedBox&) */
|
* \sa extend(const AlignedBox&) */
|
||||||
template<typename Derived>
|
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());
|
typename internal::nested_eval<Derived,2>::type p_n(p.derived());
|
||||||
m_min = m_min.cwiseMin(p_n);
|
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.
|
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this.
|
||||||
* \sa merged, extend(const MatrixBase&) */
|
* \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_min = m_min.cwiseMin(b.m_min);
|
||||||
m_max = m_max.cwiseMax(b.m_max);
|
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.
|
/** 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.
|
* \note If the boxes don't intersect, the resulting box is empty.
|
||||||
* \sa intersection(), intersects() */
|
* \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_min = m_min.cwiseMax(b.m_min);
|
||||||
m_max = m_max.cwiseMin(b.m_max);
|
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
|
/** 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.
|
* \note If the boxes don't intersect, the resulting box is empty.
|
||||||
* \sa intersects(), clamp, contains() */
|
* \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)); }
|
{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.
|
/** 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.
|
* \note Merging with an empty box may result in a box bigger than \c *this.
|
||||||
* \sa extend(const AlignedBox&) */
|
* \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)); }
|
{ 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. */
|
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
||||||
template<typename Derived>
|
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());
|
const typename internal::nested_eval<Derived,2>::type t(a_t.derived());
|
||||||
m_min += t;
|
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&)
|
* \sa exteriorDistance(const MatrixBase&), squaredExteriorDistance(const AlignedBox&)
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
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,
|
/** \returns the squared distance between the boxes \a b and \c *this,
|
||||||
* and zero if the boxes intersect.
|
* and zero if the boxes intersect.
|
||||||
* \sa exteriorDistance(const AlignedBox&), squaredExteriorDistance(const MatrixBase&)
|
* \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,
|
/** \returns the distance between the point \a p and the box \c *this,
|
||||||
* and zero if \a p is inside the box.
|
* and zero if \a p is inside the box.
|
||||||
* \sa squaredExteriorDistance(const MatrixBase&), exteriorDistance(const AlignedBox&)
|
* \sa squaredExteriorDistance(const MatrixBase&), exteriorDistance(const AlignedBox&)
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
|
EIGEN_DEVICE_FUNC inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
|
||||||
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(p))); }
|
{ EIGEN_USING_STD_MATH(sqrt) return sqrt(NonInteger(squaredExteriorDistance(p))); }
|
||||||
|
|
||||||
/** \returns the distance between the boxes \a b and \c *this,
|
/** \returns the distance between the boxes \a b and \c *this,
|
||||||
* and zero if the boxes intersect.
|
* and zero if the boxes intersect.
|
||||||
* \sa squaredExteriorDistance(const AlignedBox&), exteriorDistance(const MatrixBase&)
|
* \sa squaredExteriorDistance(const AlignedBox&), exteriorDistance(const MatrixBase&)
|
||||||
*/
|
*/
|
||||||
inline NonInteger exteriorDistance(const AlignedBox& b) const
|
EIGEN_DEVICE_FUNC inline NonInteger exteriorDistance(const AlignedBox& b) const
|
||||||
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(b))); }
|
{ EIGEN_USING_STD_MATH(sqrt) return sqrt(NonInteger(squaredExteriorDistance(b))); }
|
||||||
|
|
||||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
/** \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.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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
|
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||||
{
|
{
|
||||||
return typename internal::cast_return_type<AlignedBox,
|
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 */
|
/** Copy constructor with scalar type conversion */
|
||||||
template<typename OtherScalarType>
|
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_min = (other.min)().template cast<Scalar>();
|
||||||
m_max = (other.max)().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.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \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); }
|
{ return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -311,7 +311,7 @@ protected:
|
|||||||
|
|
||||||
template<typename Scalar,int AmbientDim>
|
template<typename Scalar,int AmbientDim>
|
||||||
template<typename Derived>
|
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());
|
typename internal::nested_eval<Derived,2*AmbientDim>::type p(a_p.derived());
|
||||||
Scalar dist2(0);
|
Scalar dist2(0);
|
||||||
@@ -333,7 +333,7 @@ inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const Matri
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar,int AmbientDim>
|
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 dist2(0);
|
||||||
Scalar aux;
|
Scalar aux;
|
||||||
|
|||||||
@@ -69,59 +69,61 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Default constructor without initialization. */
|
/** Default constructor without initialization. */
|
||||||
AngleAxis() {}
|
EIGEN_DEVICE_FUNC AngleAxis() {}
|
||||||
/** Constructs and initialize the angle-axis rotation from an \a angle in radian
|
/** Constructs and initialize the angle-axis rotation from an \a angle in radian
|
||||||
* and an \a axis which \b must \b be \b normalized.
|
* 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
|
* \warning If the \a axis vector is not normalized, then the angle-axis object
|
||||||
* represents an invalid rotation. */
|
* represents an invalid rotation. */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline AngleAxis(const Scalar& angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
|
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.
|
/** Constructs and initialize the angle-axis rotation from a quaternion \a q.
|
||||||
* This function implicitly normalizes the 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. */
|
/** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
|
||||||
template<typename Derived>
|
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 */
|
/** \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 */
|
/** \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 */
|
/** \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.
|
/** \returns a read-write reference to the stored rotation axis.
|
||||||
*
|
*
|
||||||
* \warning The rotation axis must remain a \b unit vector.
|
* \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 */
|
/** 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); }
|
{ return QuaternionType(*this) * QuaternionType(other); }
|
||||||
|
|
||||||
/** Concatenates two rotations */
|
/** Concatenates two rotations */
|
||||||
inline QuaternionType operator* (const QuaternionType& other) const
|
EIGEN_DEVICE_FUNC inline QuaternionType operator* (const QuaternionType& other) const
|
||||||
{ return QuaternionType(*this) * other; }
|
{ return QuaternionType(*this) * other; }
|
||||||
|
|
||||||
/** Concatenates two rotations */
|
/** 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); }
|
{ return a * QuaternionType(b); }
|
||||||
|
|
||||||
/** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */
|
/** \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); }
|
{ return AngleAxis(-m_angle, m_axis); }
|
||||||
|
|
||||||
template<class QuatDerived>
|
template<class QuatDerived>
|
||||||
AngleAxis& operator=(const QuaternionBase<QuatDerived>& q);
|
EIGEN_DEVICE_FUNC AngleAxis& operator=(const QuaternionBase<QuatDerived>& q);
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
AngleAxis& operator=(const MatrixBase<Derived>& m);
|
EIGEN_DEVICE_FUNC AngleAxis& operator=(const MatrixBase<Derived>& m);
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
EIGEN_DEVICE_FUNC AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||||
Matrix3 toRotationMatrix(void) const;
|
EIGEN_DEVICE_FUNC Matrix3 toRotationMatrix(void) const;
|
||||||
|
|
||||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
/** \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.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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); }
|
{ return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
|
||||||
|
|
||||||
/** Copy constructor with scalar type conversion */
|
/** Copy constructor with scalar type conversion */
|
||||||
template<typename OtherScalarType>
|
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_axis = other.axis().template cast<Scalar>();
|
||||||
m_angle = Scalar(other.angle());
|
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
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \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); }
|
{ 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;
|
typedef AngleAxis<double> AngleAxisd;
|
||||||
|
|
||||||
/** Set \c *this from a \b unit quaternion.
|
/** 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.
|
* This function implicitly normalizes the quaternion \a q.
|
||||||
*/
|
*/
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
template<typename QuatDerived>
|
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();
|
Scalar n = q.vec().norm();
|
||||||
if(n<NumTraits<Scalar>::epsilon())
|
if(n<NumTraits<Scalar>::epsilon())
|
||||||
n = q.vec().stableNorm();
|
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;
|
m_axis = q.vec() / n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -187,7 +194,7 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
template<typename Derived>
|
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,
|
// Since a direct conversion would not be really faster,
|
||||||
// let's use the robust Quaternion implementation:
|
// 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 Scalar>
|
||||||
template<typename Derived>
|
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);
|
return *this = QuaternionType(mat);
|
||||||
}
|
}
|
||||||
@@ -208,10 +215,10 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derive
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
typename AngleAxis<Scalar>::Matrix3
|
typename AngleAxis<Scalar>::Matrix3
|
||||||
AngleAxis<Scalar>::toRotationMatrix(void) const
|
EIGEN_DEVICE_FUNC AngleAxis<Scalar>::toRotationMatrix(void) const
|
||||||
{
|
{
|
||||||
using std::sin;
|
EIGEN_USING_STD_MATH(sin)
|
||||||
using std::cos;
|
EIGEN_USING_STD_MATH(cos)
|
||||||
Matrix3 res;
|
Matrix3 res;
|
||||||
Vector3 sin_axis = sin(m_angle) * m_axis;
|
Vector3 sin_axis = sin(m_angle) * m_axis;
|
||||||
Scalar c = cos(m_angle);
|
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
|
* \sa class AngleAxis
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
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
|
MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
|
||||||
{
|
{
|
||||||
using std::atan2;
|
EIGEN_USING_STD_MATH(atan2)
|
||||||
using std::sin;
|
EIGEN_USING_STD_MATH(sin)
|
||||||
using std::cos;
|
EIGEN_USING_STD_MATH(cos)
|
||||||
/* Implemented from Graphics Gems IV */
|
/* Implemented from Graphics Gems IV */
|
||||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
|
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));
|
res[0] = atan2(coeff(j,i), coeff(k,i));
|
||||||
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0)))
|
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();
|
Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
|
||||||
res[1] = -atan2(s2, coeff(i,i));
|
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));
|
res[0] = atan2(coeff(j,k), coeff(k,k));
|
||||||
Scalar c2 = Vector2(coeff(i,i), coeff(i,j)).norm();
|
Scalar c2 = Vector2(coeff(i,i), coeff(i,j)).norm();
|
||||||
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0))) {
|
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);
|
res[1] = atan2(-coeff(i,k), -c2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -68,17 +68,17 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
|||||||
typedef MatrixBase<Homogeneous> Base;
|
typedef MatrixBase<Homogeneous> Base;
|
||||||
EIGEN_DENSE_PUBLIC_INTERFACE(Homogeneous)
|
EIGEN_DENSE_PUBLIC_INTERFACE(Homogeneous)
|
||||||
|
|
||||||
explicit inline Homogeneous(const MatrixType& matrix)
|
EIGEN_DEVICE_FUNC explicit inline Homogeneous(const MatrixType& matrix)
|
||||||
: m_matrix(matrix)
|
: m_matrix(matrix)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
EIGEN_DEVICE_FUNC 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 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>
|
template<typename Rhs>
|
||||||
inline const Product<Homogeneous,Rhs>
|
EIGEN_DEVICE_FUNC inline const Product<Homogeneous,Rhs>
|
||||||
operator* (const MatrixBase<Rhs>& rhs) const
|
operator* (const MatrixBase<Rhs>& rhs) const
|
||||||
{
|
{
|
||||||
eigen_assert(int(Direction)==Horizontal);
|
eigen_assert(int(Direction)==Horizontal);
|
||||||
@@ -86,7 +86,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Lhs> friend
|
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)
|
operator* (const MatrixBase<Lhs>& lhs, const Homogeneous& rhs)
|
||||||
{
|
{
|
||||||
eigen_assert(int(Direction)==Vertical);
|
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
|
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)
|
operator* (const Transform<Scalar,Dim,Mode,Options>& lhs, const Homogeneous& rhs)
|
||||||
{
|
{
|
||||||
eigen_assert(int(Direction)==Vertical);
|
eigen_assert(int(Direction)==Vertical);
|
||||||
@@ -102,7 +102,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func>
|
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
|
redux(const Func& func) const
|
||||||
{
|
{
|
||||||
return func(m_matrix.redux(func), Scalar(1));
|
return func(m_matrix.redux(func), Scalar(1));
|
||||||
@@ -114,7 +114,9 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
|||||||
|
|
||||||
/** \geometry_module \ingroup Geometry_Module
|
/** \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
|
* \only_for_vectors
|
||||||
*
|
*
|
||||||
@@ -124,7 +126,7 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
|||||||
* \sa VectorwiseOp::homogeneous(), class Homogeneous
|
* \sa VectorwiseOp::homogeneous(), class Homogeneous
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline typename MatrixBase<Derived>::HomogeneousReturnType
|
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::HomogeneousReturnType
|
||||||
MatrixBase<Derived>::homogeneous() const
|
MatrixBase<Derived>::homogeneous() const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||||
@@ -133,14 +135,16 @@ MatrixBase<Derived>::homogeneous() const
|
|||||||
|
|
||||||
/** \geometry_module \ingroup Geometry_Module
|
/** \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
|
* Example: \include VectorwiseOp_homogeneous.cpp
|
||||||
* Output: \verbinclude VectorwiseOp_homogeneous.out
|
* Output: \verbinclude VectorwiseOp_homogeneous.out
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::homogeneous(), class Homogeneous */
|
* \sa MatrixBase::homogeneous(), class Homogeneous */
|
||||||
template<typename ExpressionType, int Direction>
|
template<typename ExpressionType, int Direction>
|
||||||
inline Homogeneous<ExpressionType,Direction>
|
EIGEN_DEVICE_FUNC inline Homogeneous<ExpressionType,Direction>
|
||||||
VectorwiseOp<ExpressionType,Direction>::homogeneous() const
|
VectorwiseOp<ExpressionType,Direction>::homogeneous() const
|
||||||
{
|
{
|
||||||
return HomogeneousReturnType(_expression());
|
return HomogeneousReturnType(_expression());
|
||||||
@@ -148,14 +152,23 @@ VectorwiseOp<ExpressionType,Direction>::homogeneous() const
|
|||||||
|
|
||||||
/** \geometry_module \ingroup Geometry_Module
|
/** \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
|
* Example: \include MatrixBase_hnormalized.cpp
|
||||||
* Output: \verbinclude MatrixBase_hnormalized.out
|
* Output: \verbinclude MatrixBase_hnormalized.out
|
||||||
*
|
*
|
||||||
* \sa VectorwiseOp::hnormalized() */
|
* \sa VectorwiseOp::hnormalized() */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline const typename MatrixBase<Derived>::HNormalizedReturnType
|
EIGEN_DEVICE_FUNC inline const typename MatrixBase<Derived>::HNormalizedReturnType
|
||||||
MatrixBase<Derived>::hnormalized() const
|
MatrixBase<Derived>::hnormalized() const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||||
@@ -166,14 +179,20 @@ MatrixBase<Derived>::hnormalized() const
|
|||||||
|
|
||||||
/** \geometry_module \ingroup Geometry_Module
|
/** \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
|
* Example: \include DirectionWise_hnormalized.cpp
|
||||||
* Output: \verbinclude DirectionWise_hnormalized.out
|
* Output: \verbinclude DirectionWise_hnormalized.out
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::hnormalized() */
|
* \sa MatrixBase::hnormalized() */
|
||||||
template<typename ExpressionType, int Direction>
|
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
|
VectorwiseOp<ExpressionType,Direction>::hnormalized() const
|
||||||
{
|
{
|
||||||
return HNormalized_Block(_expression(),0,0,
|
return HNormalized_Block(_expression(),0,0,
|
||||||
@@ -197,7 +216,7 @@ template<typename MatrixOrTransformType>
|
|||||||
struct take_matrix_for_product
|
struct take_matrix_for_product
|
||||||
{
|
{
|
||||||
typedef MatrixOrTransformType type;
|
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>
|
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 Transform<Scalar, Dim, Mode, Options> TransformType;
|
||||||
typedef typename internal::add_const<typename TransformType::ConstAffinePart>::type type;
|
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>
|
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 Transform<Scalar, Dim, Projective, Options> TransformType;
|
||||||
typedef typename TransformType::MatrixType type;
|
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>
|
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 traits<homogeneous_left_product_impl>::LhsMatrixType LhsMatrixType;
|
||||||
typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
|
typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
|
||||||
typedef typename remove_all<typename LhsMatrixTypeCleaned::Nested>::type LhsMatrixTypeNested;
|
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_lhs(take_matrix_for_product<Lhs>::run(lhs)),
|
||||||
m_rhs(rhs)
|
m_rhs(rhs)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline Index rows() const { return m_lhs.rows(); }
|
EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); }
|
||||||
inline Index cols() const { return m_rhs.cols(); }
|
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
|
// FIXME investigate how to allow lazy evaluation of this product when possible
|
||||||
dst = Block<const LhsMatrixTypeNested,
|
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> >
|
: public ReturnByValue<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
|
||||||
{
|
{
|
||||||
typedef typename remove_all<typename Rhs::Nested>::type RhsNested;
|
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)
|
: m_lhs(lhs), m_rhs(rhs)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline Index rows() const { return m_lhs.rows(); }
|
EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); }
|
||||||
inline Index cols() const { return m_rhs.cols(); }
|
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
|
// FIXME investigate how to allow lazy evaluation of this product when possible
|
||||||
dst = m_lhs * Block<const RhsNested,
|
dst = m_lhs * Block<const RhsNested,
|
||||||
@@ -317,7 +336,7 @@ struct unary_evaluator<Homogeneous<ArgType,Direction>, IndexBased>
|
|||||||
typedef typename XprType::PlainObject PlainObject;
|
typedef typename XprType::PlainObject PlainObject;
|
||||||
typedef evaluator<PlainObject> Base;
|
typedef evaluator<PlainObject> Base;
|
||||||
|
|
||||||
explicit unary_evaluator(const XprType& op)
|
EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
|
||||||
: Base(), m_temp(op)
|
: Base(), m_temp(op)
|
||||||
{
|
{
|
||||||
::new (static_cast<Base*>(this)) Base(m_temp);
|
::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>
|
struct Assignment<DstXprType, Homogeneous<ArgType,Vertical>, internal::assign_op<Scalar,typename ArgType::Scalar>, Dense2Dense>
|
||||||
{
|
{
|
||||||
typedef Homogeneous<ArgType,Vertical> SrcXprType;
|
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.template topRows<ArgType::RowsAtCompileTime>(src.nestedExpression().rows()) = src.nestedExpression();
|
||||||
dst.row(dst.rows()-1).setOnes();
|
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>
|
struct Assignment<DstXprType, Homogeneous<ArgType,Horizontal>, internal::assign_op<Scalar,typename ArgType::Scalar>, Dense2Dense>
|
||||||
{
|
{
|
||||||
typedef Homogeneous<ArgType,Horizontal> SrcXprType;
|
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.template leftCols<ArgType::ColsAtCompileTime>(src.nestedExpression().cols()) = src.nestedExpression();
|
||||||
dst.col(dst.cols()-1).setOnes();
|
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>
|
struct generic_product_impl<Homogeneous<LhsArg,Horizontal>, Rhs, HomogeneousShape, DenseShape, ProductTag>
|
||||||
{
|
{
|
||||||
template<typename Dest>
|
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);
|
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>
|
struct generic_product_impl<Lhs, Homogeneous<RhsArg,Vertical>, DenseShape, HomogeneousShape, ProductTag>
|
||||||
{
|
{
|
||||||
template<typename Dest>
|
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);
|
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>
|
template<typename Lhs,typename Rhs>
|
||||||
struct homogeneous_left_product_refactoring_helper
|
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;
|
typedef Transform<Scalar,Dim,Mode,Options> TransformType;
|
||||||
template<typename Dest>
|
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);
|
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;
|
typedef const Block<const Coefficients,AmbientDimAtCompileTime,1> ConstNormalReturnType;
|
||||||
|
|
||||||
/** Default constructor without initialization */
|
/** Default constructor without initialization */
|
||||||
inline Hyperplane() {}
|
EIGEN_DEVICE_FUNC inline Hyperplane() {}
|
||||||
|
|
||||||
template<int OtherOptions>
|
template<int OtherOptions>
|
||||||
Hyperplane(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
EIGEN_DEVICE_FUNC Hyperplane(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||||
: m_coeffs(other.coeffs())
|
: m_coeffs(other.coeffs())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
||||||
* of the ambient space */
|
* 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.
|
/** 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.
|
* \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)
|
: m_coeffs(n.size()+1)
|
||||||
{
|
{
|
||||||
normal() = n;
|
normal() = n;
|
||||||
@@ -75,7 +75,7 @@ public:
|
|||||||
* such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
|
* 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.
|
* \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)
|
: m_coeffs(n.size()+1)
|
||||||
{
|
{
|
||||||
normal() = n;
|
normal() = n;
|
||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
/** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
|
/** 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.
|
* 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());
|
Hyperplane result(p0.size());
|
||||||
result.normal() = (p1 - p0).unitOrthogonal();
|
result.normal() = (p1 - p0).unitOrthogonal();
|
||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
||||||
* is required to be exactly 3.
|
* 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)
|
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
|
||||||
Hyperplane result(p0.size());
|
Hyperplane result(p0.size());
|
||||||
@@ -120,19 +120,19 @@ public:
|
|||||||
* so an arbitrary choice is made.
|
* so an arbitrary choice is made.
|
||||||
*/
|
*/
|
||||||
// FIXME to be consitent with the rest this could be implemented as a static Through function ??
|
// 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();
|
normal() = parametrized.direction().unitOrthogonal();
|
||||||
offset() = -parametrized.origin().dot(normal());
|
offset() = -parametrized.origin().dot(normal());
|
||||||
}
|
}
|
||||||
|
|
||||||
~Hyperplane() {}
|
EIGEN_DEVICE_FUNC ~Hyperplane() {}
|
||||||
|
|
||||||
/** \returns the dimension in which the plane holds */
|
/** \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 */
|
/** normalizes \c *this */
|
||||||
void normalize(void)
|
EIGEN_DEVICE_FUNC void normalize(void)
|
||||||
{
|
{
|
||||||
m_coeffs /= normal().norm();
|
m_coeffs /= normal().norm();
|
||||||
}
|
}
|
||||||
@@ -140,45 +140,45 @@ public:
|
|||||||
/** \returns the signed distance between the plane \c *this and a point \a p.
|
/** \returns the signed distance between the plane \c *this and a point \a p.
|
||||||
* \sa absDistance()
|
* \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.
|
/** \returns the absolute distance between the plane \c *this and a point \a p.
|
||||||
* \sa signedDistance()
|
* \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.
|
/** \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
|
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
|
||||||
* to the linear part of the implicit equation.
|
* 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
|
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
|
||||||
* to the linear part of the implicit equation.
|
* 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
|
/** \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.
|
* \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
|
/** \returns a non-constant reference to the distance to the origin, which is also the constant part
|
||||||
* of the implicit equation */
|
* 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:
|
/** \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$
|
* \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:
|
/** \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$
|
* \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.
|
/** \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.
|
* \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)
|
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
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
|
// 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.
|
// whether the two lines are approximately parallel.
|
||||||
if(internal::isMuchSmallerThan(det, Scalar(1)))
|
if(internal::isMuchSmallerThan(det, Scalar(1)))
|
||||||
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
|
{ // 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));
|
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
|
||||||
else
|
else
|
||||||
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
|
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.
|
* or a more generic #Affine transformation. The default is #Affine.
|
||||||
*/
|
*/
|
||||||
template<typename XprType>
|
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)
|
if (traits==Affine)
|
||||||
normal() = mat.inverse().transpose() * normal();
|
normal() = mat.inverse().transpose() * normal();
|
||||||
@@ -236,7 +235,7 @@ public:
|
|||||||
* Other kind of transformations are not supported.
|
* Other kind of transformations are not supported.
|
||||||
*/
|
*/
|
||||||
template<int TrOptions>
|
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)
|
TransformTraits traits = Affine)
|
||||||
{
|
{
|
||||||
transform(t.linear(), traits);
|
transform(t.linear(), traits);
|
||||||
@@ -250,7 +249,7 @@ public:
|
|||||||
* then this function smartly returns a const reference to \c *this.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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
|
Hyperplane<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
|
||||||
{
|
{
|
||||||
return typename internal::cast_return_type<Hyperplane,
|
return typename internal::cast_return_type<Hyperplane,
|
||||||
@@ -259,7 +258,7 @@ public:
|
|||||||
|
|
||||||
/** Copy constructor with scalar type conversion */
|
/** Copy constructor with scalar type conversion */
|
||||||
template<typename OtherScalarType,int OtherOptions>
|
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>(); }
|
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||||
|
|
||||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
@@ -267,7 +266,7 @@ public:
|
|||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \sa MatrixBase::isApprox() */
|
||||||
template<int OtherOptions>
|
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); }
|
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Eigen {
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
#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
|
#else
|
||||||
inline typename MatrixBase<Derived>::PlainObject
|
inline typename MatrixBase<Derived>::PlainObject
|
||||||
#endif
|
#endif
|
||||||
@@ -53,7 +53,7 @@ template< int Arch,typename VectorLhs,typename VectorRhs,
|
|||||||
typename Scalar = typename VectorLhs::Scalar,
|
typename Scalar = typename VectorLhs::Scalar,
|
||||||
bool Vectorizable = bool((VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit)>
|
bool Vectorizable = bool((VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit)>
|
||||||
struct cross3_impl {
|
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)
|
run(const VectorLhs& lhs, const VectorRhs& rhs)
|
||||||
{
|
{
|
||||||
return typename internal::plain_matrix_type<VectorLhs>::type(
|
return typename internal::plain_matrix_type<VectorLhs>::type(
|
||||||
@@ -78,7 +78,7 @@ struct cross3_impl {
|
|||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
inline typename MatrixBase<Derived>::PlainObject
|
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::PlainObject
|
||||||
MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
|
MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,4)
|
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,4)
|
||||||
@@ -105,6 +105,7 @@ MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
|
|||||||
* \sa MatrixBase::cross() */
|
* \sa MatrixBase::cross() */
|
||||||
template<typename ExpressionType, int Direction>
|
template<typename ExpressionType, int Direction>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
const typename VectorwiseOp<ExpressionType,Direction>::CrossReturnType
|
const typename VectorwiseOp<ExpressionType,Direction>::CrossReturnType
|
||||||
VectorwiseOp<ExpressionType,Direction>::cross(const MatrixBase<OtherDerived>& other) const
|
VectorwiseOp<ExpressionType,Direction>::cross(const MatrixBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
@@ -221,7 +222,7 @@ struct unitOrthogonal_selector<Derived,2>
|
|||||||
* \sa cross()
|
* \sa cross()
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
typename MatrixBase<Derived>::PlainObject
|
EIGEN_DEVICE_FUNC typename MatrixBase<Derived>::PlainObject
|
||||||
MatrixBase<Derived>::unitOrthogonal() const
|
MatrixBase<Derived>::unitOrthogonal() const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||||
|
|||||||
@@ -41,45 +41,45 @@ public:
|
|||||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1,Options> VectorType;
|
typedef Matrix<Scalar,AmbientDimAtCompileTime,1,Options> VectorType;
|
||||||
|
|
||||||
/** Default constructor without initialization */
|
/** Default constructor without initialization */
|
||||||
inline ParametrizedLine() {}
|
EIGEN_DEVICE_FUNC inline ParametrizedLine() {}
|
||||||
|
|
||||||
template<int OtherOptions>
|
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())
|
: m_origin(other.origin()), m_direction(other.direction())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/** Constructs a dynamic-size line with \a _dim the dimension
|
/** Constructs a dynamic-size line with \a _dim the dimension
|
||||||
* of the ambient space */
|
* 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.
|
/** Initializes a parametrized line of direction \a direction and origin \a origin.
|
||||||
* \warning the vector direction is assumed to be normalized.
|
* \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) {}
|
: m_origin(origin), m_direction(direction) {}
|
||||||
|
|
||||||
template <int OtherOptions>
|
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. */
|
/** 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()); }
|
{ return ParametrizedLine(p0, (p1-p0).normalized()); }
|
||||||
|
|
||||||
~ParametrizedLine() {}
|
EIGEN_DEVICE_FUNC ~ParametrizedLine() {}
|
||||||
|
|
||||||
/** \returns the dimension in which the line holds */
|
/** \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; }
|
EIGEN_DEVICE_FUNC const VectorType& origin() const { return m_origin; }
|
||||||
VectorType& origin() { return m_origin; }
|
EIGEN_DEVICE_FUNC VectorType& origin() { return m_origin; }
|
||||||
|
|
||||||
const VectorType& direction() const { return m_direction; }
|
EIGEN_DEVICE_FUNC const VectorType& direction() const { return m_direction; }
|
||||||
VectorType& direction() { 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.
|
/** \returns the squared distance of a point \a p to its projection onto the line \c *this.
|
||||||
* \sa distance()
|
* \sa distance()
|
||||||
*/
|
*/
|
||||||
RealScalar squaredDistance(const VectorType& p) const
|
EIGEN_DEVICE_FUNC RealScalar squaredDistance(const VectorType& p) const
|
||||||
{
|
{
|
||||||
VectorType diff = p - origin();
|
VectorType diff = p - origin();
|
||||||
return (diff - direction().dot(diff) * direction()).squaredNorm();
|
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.
|
/** \returns the distance of a point \a p to its projection onto the line \c *this.
|
||||||
* \sa squaredDistance()
|
* \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. */
|
/** \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(); }
|
{ 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>
|
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>
|
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>
|
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
|
/** \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.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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
|
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
|
||||||
{
|
{
|
||||||
return typename internal::cast_return_type<ParametrizedLine,
|
return typename internal::cast_return_type<ParametrizedLine,
|
||||||
@@ -119,7 +119,7 @@ public:
|
|||||||
|
|
||||||
/** Copy constructor with scalar type conversion */
|
/** Copy constructor with scalar type conversion */
|
||||||
template<typename OtherScalarType,int OtherOptions>
|
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_origin = other.origin().template cast<Scalar>();
|
||||||
m_direction = other.direction().template cast<Scalar>();
|
m_direction = other.direction().template cast<Scalar>();
|
||||||
@@ -129,7 +129,7 @@ public:
|
|||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \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); }
|
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -143,7 +143,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||||
template <int OtherOptions>
|
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)
|
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||||
direction() = hyperplane.normal().unitOrthogonal();
|
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
|
/** \returns the point at \a t along this line
|
||||||
*/
|
*/
|
||||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
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
|
ParametrizedLine<_Scalar, _AmbientDim,_Options>::pointAt(const _Scalar& t) const
|
||||||
{
|
{
|
||||||
return origin() + (direction()*t);
|
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 <typename _Scalar, int _AmbientDim, int _Options>
|
||||||
template <int OtherOptions>
|
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()))
|
return -(hyperplane.offset()+hyperplane.normal().dot(origin()))
|
||||||
/ hyperplane.normal().dot(direction());
|
/ hyperplane.normal().dot(direction());
|
||||||
@@ -175,7 +175,7 @@ inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionPara
|
|||||||
*/
|
*/
|
||||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||||
template <int OtherOptions>
|
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);
|
return intersectionParameter(hyperplane);
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(con
|
|||||||
*/
|
*/
|
||||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||||
template <int OtherOptions>
|
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
|
ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||||
{
|
{
|
||||||
return pointAt(intersectionParameter(hyperplane));
|
return pointAt(intersectionParameter(hyperplane));
|
||||||
|
|||||||
@@ -58,37 +58,37 @@ class QuaternionBase : public RotationBase<Derived, 3>
|
|||||||
|
|
||||||
|
|
||||||
/** \returns the \c x coefficient */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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) */
|
/** \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) */
|
/** \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) */
|
/** \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) */
|
/** \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);
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
|
||||||
template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& 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
|
// 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
|
// 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)
|
// Derived& operator=(const QuaternionBase& other)
|
||||||
// { return operator=<Derived>(other); }
|
// { return operator=<Derived>(other); }
|
||||||
|
|
||||||
Derived& operator=(const AngleAxisType& aa);
|
EIGEN_DEVICE_FUNC Derived& operator=(const AngleAxisType& aa);
|
||||||
template<class OtherDerived> Derived& operator=(const MatrixBase<OtherDerived>& m);
|
template<class OtherDerived> EIGEN_DEVICE_FUNC Derived& operator=(const MatrixBase<OtherDerived>& m);
|
||||||
|
|
||||||
/** \returns a quaternion representing an identity rotation
|
/** \returns a quaternion representing an identity rotation
|
||||||
* \sa MatrixBase::Identity()
|
* \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()
|
/** \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
|
/** \returns the squared norm of the quaternion's coefficients
|
||||||
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
|
* \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
|
/** \returns the norm of the quaternion's coefficients
|
||||||
* \sa QuaternionBase::squaredNorm(), MatrixBase::norm()
|
* \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
|
/** Normalizes the quaternion \c *this
|
||||||
* \sa normalized(), MatrixBase::normalize() */
|
* \sa normalized(), MatrixBase::normalize() */
|
||||||
inline void normalize() { coeffs().normalize(); }
|
EIGEN_DEVICE_FUNC inline void normalize() { coeffs().normalize(); }
|
||||||
/** \returns a normalized copy of \c *this
|
/** \returns a normalized copy of \c *this
|
||||||
* \sa normalize(), MatrixBase::normalized() */
|
* \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
|
/** \returns the dot product of \c *this and \a other
|
||||||
* Geometrically speaking, the dot product of two unit quaternions
|
* Geometrically speaking, the dot product of two unit quaternions
|
||||||
* corresponds to the cosine of half the angle between the two rotations.
|
* corresponds to the cosine of half the angle between the two rotations.
|
||||||
* \sa angularDistance()
|
* \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 */
|
/** \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 */
|
/** \returns the quaternion which transform \a a into \a b through a rotation */
|
||||||
template<typename Derived1, typename Derived2>
|
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_DEVICE_FUNC 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 Derived& operator*= (const QuaternionBase<OtherDerived>& q);
|
||||||
|
|
||||||
/** \returns the quaternion describing the inverse rotation */
|
/** \returns the quaternion describing the inverse rotation */
|
||||||
Quaternion<Scalar> inverse() const;
|
EIGEN_DEVICE_FUNC Quaternion<Scalar> inverse() const;
|
||||||
|
|
||||||
/** \returns the conjugated quaternion */
|
/** \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
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \sa MatrixBase::isApprox() */
|
||||||
template<class OtherDerived>
|
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 coeffs().isApprox(other.coeffs(), prec); }
|
||||||
|
|
||||||
/** return the result vector of \a v through the rotation*/
|
/** 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
|
/** \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.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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());
|
return typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type(derived());
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ public:
|
|||||||
typedef typename Base::AngleAxisType AngleAxisType;
|
typedef typename Base::AngleAxisType AngleAxisType;
|
||||||
|
|
||||||
/** Default constructor leaving the quaternion uninitialized. */
|
/** 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
|
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
|
||||||
* its four coefficients \a w, \a x, \a y and \a z.
|
* 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:
|
* while internally the coefficients are stored in the following order:
|
||||||
* [\c x, \c y, \c z, \c w]
|
* [\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 */
|
/** 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 */
|
/** 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 */
|
/** 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:
|
/** Constructs and initializes a quaternion from either:
|
||||||
* - a rotation matrix expression,
|
* - a rotation matrix expression,
|
||||||
* - a 4D vector expression representing quaternion coefficients.
|
* - a 4D vector expression representing quaternion coefficients.
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
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 */
|
/** Explicit copy constructor with scalar conversion */
|
||||||
template<typename OtherScalar, int OtherOptions>
|
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>(); }
|
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||||
|
|
||||||
static Quaternion UnitRandom();
|
EIGEN_DEVICE_FUNC static Quaternion UnitRandom();
|
||||||
|
|
||||||
template<typename Derived1, typename Derived2>
|
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;}
|
EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs;}
|
||||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||||
|
|
||||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(NeedsAlignment))
|
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
|
* \code *coeffs == {x, y, z, w} \endcode
|
||||||
*
|
*
|
||||||
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
* 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:
|
protected:
|
||||||
const Coefficients m_coeffs;
|
const Coefficients m_coeffs;
|
||||||
@@ -394,10 +394,10 @@ class Map<Quaternion<_Scalar>, _Options >
|
|||||||
* \code *coeffs == {x, y, z, w} \endcode
|
* \code *coeffs == {x, y, z, w} \endcode
|
||||||
*
|
*
|
||||||
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
* 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; }
|
EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs; }
|
||||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Coefficients m_coeffs;
|
Coefficients m_coeffs;
|
||||||
@@ -425,7 +425,7 @@ typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options> struct quat_product
|
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>
|
return Quaternion<Scalar>
|
||||||
(
|
(
|
||||||
a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
|
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 */
|
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
template <class OtherDerived>
|
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
|
QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
|
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) */
|
/** \sa operator*(Quaternion) */
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
template <class OtherDerived>
|
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();
|
derived() = derived() * other.derived();
|
||||||
return derived();
|
return derived();
|
||||||
@@ -467,7 +467,7 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const Quaterni
|
|||||||
* - Via a Matrix3: 24 + 15n
|
* - Via a Matrix3: 24 + 15n
|
||||||
*/
|
*/
|
||||||
template <class Derived>
|
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
|
QuaternionBase<Derived>::_transformVector(const Vector3& v) const
|
||||||
{
|
{
|
||||||
// Note that this algorithm comes from the optimization by hand
|
// Note that this algorithm comes from the optimization by hand
|
||||||
@@ -481,7 +481,7 @@ QuaternionBase<Derived>::_transformVector(const Vector3& v) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Derived>
|
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();
|
coeffs() = other.coeffs();
|
||||||
return derived();
|
return derived();
|
||||||
@@ -489,7 +489,7 @@ EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(
|
|||||||
|
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
template<class OtherDerived>
|
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();
|
coeffs() = other.coeffs();
|
||||||
return derived();
|
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
|
/** Set \c *this from an angle-axis \a aa and returns a reference to \c *this
|
||||||
*/
|
*/
|
||||||
template<class Derived>
|
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;
|
EIGEN_USING_STD_MATH(cos)
|
||||||
using std::sin;
|
EIGEN_USING_STD_MATH(sin)
|
||||||
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
|
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
|
||||||
this->w() = cos(ha);
|
this->w() = cos(ha);
|
||||||
this->vec() = sin(ha) * aa.axis();
|
this->vec() = sin(ha) * aa.axis();
|
||||||
@@ -516,7 +516,7 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisT
|
|||||||
|
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
template<class MatrixDerived>
|
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),
|
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)
|
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.
|
* be normalized, otherwise the result is undefined.
|
||||||
*/
|
*/
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
inline typename QuaternionBase<Derived>::Matrix3
|
EIGEN_DEVICE_FUNC inline typename QuaternionBase<Derived>::Matrix3
|
||||||
QuaternionBase<Derived>::toRotationMatrix(void) const
|
QuaternionBase<Derived>::toRotationMatrix(void) const
|
||||||
{
|
{
|
||||||
// NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
|
// 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<class Derived>
|
||||||
template<typename Derived1, typename Derived2>
|
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 v0 = a.normalized();
|
||||||
Vector3 v1 = b.normalized();
|
Vector3 v1 = b.normalized();
|
||||||
Scalar c = v1.dot(v0);
|
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
|
* \note The implementation is based on http://planning.cs.uiuc.edu/node198.html
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Options>
|
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;
|
EIGEN_USING_STD_MATH(sqrt)
|
||||||
using std::sin;
|
EIGEN_USING_STD_MATH(sin)
|
||||||
using std::cos;
|
EIGEN_USING_STD_MATH(cos)
|
||||||
const Scalar u1 = internal::random<Scalar>(0, 1),
|
const Scalar u1 = internal::random<Scalar>(0, 1),
|
||||||
u2 = internal::random<Scalar>(0, 2*EIGEN_PI),
|
u2 = internal::random<Scalar>(0, 2*EIGEN_PI),
|
||||||
u3 = 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 Scalar, int Options>
|
||||||
template<typename Derived1, typename Derived2>
|
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;
|
Quaternion quat;
|
||||||
quat.setFromTwoVectors(a, b);
|
quat.setFromTwoVectors(a, b);
|
||||||
@@ -657,7 +657,7 @@ Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const Matr
|
|||||||
* \sa QuaternionBase::conjugate()
|
* \sa QuaternionBase::conjugate()
|
||||||
*/
|
*/
|
||||||
template <class Derived>
|
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() ??
|
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
||||||
Scalar n2 = this->squaredNorm();
|
Scalar n2 = this->squaredNorm();
|
||||||
@@ -674,7 +674,7 @@ inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Der
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
template<int Arch, class Derived, typename Scalar, int _Options> struct quat_conj
|
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());
|
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()
|
* \sa Quaternion2::inverse()
|
||||||
*/
|
*/
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
inline Quaternion<typename internal::traits<Derived>::Scalar>
|
EIGEN_DEVICE_FUNC inline Quaternion<typename internal::traits<Derived>::Scalar>
|
||||||
QuaternionBase<Derived>::conjugate() const
|
QuaternionBase<Derived>::conjugate() const
|
||||||
{
|
{
|
||||||
return internal::quat_conj<Architecture::Target, Derived,
|
return internal::quat_conj<Architecture::Target, Derived,
|
||||||
@@ -701,13 +701,12 @@ QuaternionBase<Derived>::conjugate() const
|
|||||||
*/
|
*/
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
template <class OtherDerived>
|
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
|
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
using std::atan2;
|
EIGEN_USING_STD_MATH(atan2)
|
||||||
using std::abs;
|
|
||||||
Quaternion<Scalar> d = (*this) * other.conjugate();
|
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 Derived>
|
||||||
template <class OtherDerived>
|
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
|
QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
using std::acos;
|
EIGEN_USING_STD_MATH(acos)
|
||||||
using std::sin;
|
EIGEN_USING_STD_MATH(sin)
|
||||||
using std::abs;
|
|
||||||
const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
|
const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
|
||||||
Scalar d = this->dot(other);
|
Scalar d = this->dot(other);
|
||||||
Scalar absD = abs(d);
|
Scalar absD = numext::abs(d);
|
||||||
|
|
||||||
Scalar scale0;
|
Scalar scale0;
|
||||||
Scalar scale1;
|
Scalar scale1;
|
||||||
@@ -759,10 +757,10 @@ template<typename Other>
|
|||||||
struct quaternionbase_assign_impl<Other,3,3>
|
struct quaternionbase_assign_impl<Other,3,3>
|
||||||
{
|
{
|
||||||
typedef typename Other::Scalar Scalar;
|
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);
|
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",
|
// This algorithm comes from "Quaternion Calculus and Fast Animation",
|
||||||
// Ken Shoemake, 1987 SIGGRAPH course notes
|
// Ken Shoemake, 1987 SIGGRAPH course notes
|
||||||
Scalar t = mat.trace();
|
Scalar t = mat.trace();
|
||||||
@@ -800,7 +798,7 @@ template<typename Other>
|
|||||||
struct quaternionbase_assign_impl<Other,4,1>
|
struct quaternionbase_assign_impl<Other,4,1>
|
||||||
{
|
{
|
||||||
typedef typename Other::Scalar Scalar;
|
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;
|
q.coeffs() = vec;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,35 +59,35 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
|
/** 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. */
|
/** 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.
|
/** Construct a 2D rotation from a 2x2 rotation matrix \a mat.
|
||||||
*
|
*
|
||||||
* \sa fromRotationMatrix()
|
* \sa fromRotationMatrix()
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
explicit Rotation2D(const MatrixBase<Derived>& m)
|
EIGEN_DEVICE_FUNC explicit Rotation2D(const MatrixBase<Derived>& m)
|
||||||
{
|
{
|
||||||
fromRotationMatrix(m.derived());
|
fromRotationMatrix(m.derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the rotation angle */
|
/** \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 */
|
/** \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] */
|
/** \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));
|
Scalar tmp = numext::fmod(m_angle,Scalar(2*EIGEN_PI));
|
||||||
return tmp<Scalar(0) ? tmp + Scalar(2*EIGEN_PI) : tmp;
|
return tmp<Scalar(0) ? tmp + Scalar(2*EIGEN_PI) : tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the rotation angle in [-pi,pi] */
|
/** \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));
|
Scalar tmp = numext::fmod(m_angle,Scalar(2*EIGEN_PI));
|
||||||
if(tmp>Scalar(EIGEN_PI)) tmp -= 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);
|
else if(tmp<-Scalar(EIGEN_PI)) tmp += Scalar(2*EIGEN_PI);
|
||||||
@@ -95,23 +95,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the inverse rotation */
|
/** \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 */
|
/** 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); }
|
{ return Rotation2D(m_angle + other.m_angle); }
|
||||||
|
|
||||||
/** Concatenates two rotations */
|
/** 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; }
|
{ m_angle += other.m_angle; return *this; }
|
||||||
|
|
||||||
/** Applies the rotation to a 2D vector */
|
/** 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; }
|
{ return toRotationMatrix() * vec; }
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
|
EIGEN_DEVICE_FUNC Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||||
Matrix2 toRotationMatrix() const;
|
EIGEN_DEVICE_FUNC Matrix2 toRotationMatrix() const;
|
||||||
|
|
||||||
/** Set \c *this from a 2x2 rotation matrix \a mat.
|
/** Set \c *this from a 2x2 rotation matrix \a mat.
|
||||||
* In other words, this function extract the rotation angle from the rotation matrix.
|
* In other words, this function extract the rotation angle from the rotation matrix.
|
||||||
@@ -121,13 +121,13 @@ public:
|
|||||||
* \sa fromRotationMatrix()
|
* \sa fromRotationMatrix()
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
Rotation2D& operator=(const MatrixBase<Derived>& m)
|
EIGEN_DEVICE_FUNC Rotation2D& operator=(const MatrixBase<Derived>& m)
|
||||||
{ return fromRotationMatrix(m.derived()); }
|
{ return fromRotationMatrix(m.derived()); }
|
||||||
|
|
||||||
/** \returns the spherical interpolation between \c *this and \a other using
|
/** \returns the spherical interpolation between \c *this and \a other using
|
||||||
* parameter \a t. It is in fact equivalent to a linear interpolation.
|
* 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();
|
Scalar dist = Rotation2D(other.m_angle-m_angle).smallestAngle();
|
||||||
return Rotation2D(m_angle + dist*t);
|
return Rotation2D(m_angle + dist*t);
|
||||||
@@ -139,23 +139,23 @@ public:
|
|||||||
* then this function smartly returns a const reference to \c *this.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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); }
|
{ return typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
|
||||||
|
|
||||||
/** Copy constructor with scalar type conversion */
|
/** Copy constructor with scalar type conversion */
|
||||||
template<typename OtherScalarType>
|
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());
|
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
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \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); }
|
{ return internal::isApprox(m_angle,other.m_angle, prec); }
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -173,9 +173,9 @@ typedef Rotation2D<double> Rotation2Dd;
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
template<typename Derived>
|
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)
|
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));
|
m_angle = atan2(mat.coeff(1,0), mat.coeff(0,0));
|
||||||
return *this;
|
return *this;
|
||||||
@@ -185,10 +185,10 @@ Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Deri
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
typename Rotation2D<Scalar>::Matrix2
|
typename Rotation2D<Scalar>::Matrix2
|
||||||
Rotation2D<Scalar>::toRotationMatrix(void) const
|
EIGEN_DEVICE_FUNC Rotation2D<Scalar>::toRotationMatrix(void) const
|
||||||
{
|
{
|
||||||
using std::sin;
|
EIGEN_USING_STD_MATH(sin)
|
||||||
using std::cos;
|
EIGEN_USING_STD_MATH(cos)
|
||||||
Scalar sinA = sin(m_angle);
|
Scalar sinA = sin(m_angle);
|
||||||
Scalar cosA = cos(m_angle);
|
Scalar cosA = cos(m_angle);
|
||||||
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
|
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
|
||||||
|
|||||||
@@ -38,26 +38,26 @@ class RotationBase
|
|||||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||||
|
|
||||||
/** \returns an equivalent rotation matrix */
|
/** \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
|
/** \returns an equivalent rotation matrix
|
||||||
* This function is added to be conform with the Transform class' naming scheme.
|
* 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 */
|
/** \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 */
|
/** \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; }
|
{ return Transform<Scalar,Dim,Isometry>(*this) * t; }
|
||||||
|
|
||||||
/** \returns the concatenation of the rotation \c *this with a uniform scaling \a s */
|
/** \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(); }
|
{ return toRotationMatrix() * s.factor(); }
|
||||||
|
|
||||||
/** \returns the concatenation of the rotation \c *this with a generic expression \a e
|
/** \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
|
* - a vector of size Dim
|
||||||
*/
|
*/
|
||||||
template<typename OtherDerived>
|
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
|
operator*(const EigenBase<OtherDerived>& e) const
|
||||||
{ return internal::rotation_base_generic_product_selector<Derived,OtherDerived>::run(derived(), e.derived()); }
|
{ 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 */
|
/** \returns the concatenation of a linear transformation \a l with the rotation \a r */
|
||||||
template<typename OtherDerived> friend
|
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(); }
|
{ return l.derived() * r.toRotationMatrix(); }
|
||||||
|
|
||||||
/** \returns the concatenation of a scaling \a l with the rotation \a r */
|
/** \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);
|
Transform<Scalar,Dim,Affine> res(r);
|
||||||
res.linear().applyOnTheLeft(l);
|
res.linear().applyOnTheLeft(l);
|
||||||
@@ -86,11 +86,11 @@ class RotationBase
|
|||||||
|
|
||||||
/** \returns the concatenation of the rotation \c *this with a transformation \a t */
|
/** \returns the concatenation of the rotation \c *this with a transformation \a t */
|
||||||
template<int Mode, int Options>
|
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; }
|
{ return toRotationMatrix() * t; }
|
||||||
|
|
||||||
template<typename OtherVectorType>
|
template<typename OtherVectorType>
|
||||||
inline VectorType _transformVector(const OtherVectorType& v) const
|
EIGEN_DEVICE_FUNC inline VectorType _transformVector(const OtherVectorType& v) const
|
||||||
{ return toRotationMatrix() * v; }
|
{ return toRotationMatrix() * v; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ struct rotation_base_generic_product_selector<RotationDerived,MatrixType,false>
|
|||||||
{
|
{
|
||||||
enum { Dim = RotationDerived::Dim };
|
enum { Dim = RotationDerived::Dim };
|
||||||
typedef Matrix<typename RotationDerived::Scalar,Dim,Dim> ReturnType;
|
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; }
|
{ 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 >
|
struct rotation_base_generic_product_selector< RotationDerived, DiagonalMatrix<Scalar,Dim,MaxDim>, false >
|
||||||
{
|
{
|
||||||
typedef Transform<Scalar,Dim,Affine> ReturnType;
|
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);
|
ReturnType res(r);
|
||||||
res.linear() *= m;
|
res.linear() *= m;
|
||||||
@@ -123,7 +123,7 @@ struct rotation_base_generic_product_selector<RotationDerived,OtherVectorType,tr
|
|||||||
{
|
{
|
||||||
enum { Dim = RotationDerived::Dim };
|
enum { Dim = RotationDerived::Dim };
|
||||||
typedef Matrix<typename RotationDerived::Scalar,Dim,1> ReturnType;
|
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);
|
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 _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||||
template<typename OtherDerived>
|
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)
|
::Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
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 _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||||
template<typename OtherDerived>
|
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>
|
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||||
::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||||
{
|
{
|
||||||
@@ -179,20 +179,20 @@ namespace internal {
|
|||||||
* \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis
|
* \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim>
|
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)
|
EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||||
return Rotation2D<Scalar>(s).toRotationMatrix();
|
return Rotation2D<Scalar>(s).toRotationMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar, int Dim, typename OtherDerived>
|
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();
|
return r.toRotationMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar, int Dim, typename OtherDerived>
|
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,
|
EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim,
|
||||||
YOU_MADE_A_PROGRAMMING_MISTAKE)
|
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(); }
|
{ return matrix.derived() * s.factor(); }
|
||||||
|
|
||||||
/** Constructs a uniform scaling from scale factor \a s */
|
/** 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 */
|
/** 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 */
|
/** Constructs a uniform scaling from scale factor \a s */
|
||||||
template<typename RealScalar>
|
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); }
|
{ return UniformScaling<std::complex<RealScalar> >(s); }
|
||||||
|
|
||||||
/** Constructs a 2D axis aligned scaling */
|
/** Constructs a 2D axis aligned scaling */
|
||||||
template<typename Scalar>
|
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); }
|
{ return DiagonalMatrix<Scalar,2>(sx, sy); }
|
||||||
/** Constructs a 3D axis aligned scaling */
|
/** Constructs a 3D axis aligned scaling */
|
||||||
template<typename Scalar>
|
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); }
|
{ return DiagonalMatrix<Scalar,3>(sx, sy, sz); }
|
||||||
|
|
||||||
/** Constructs an axis aligned scaling expression from vector expression \a coeffs
|
/** Constructs an axis aligned scaling expression from vector expression \a coeffs
|
||||||
* This is an alias for coeffs.asDiagonal()
|
* This is an alias for coeffs.asDiagonal()
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
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(); }
|
{ return coeffs.asDiagonal(); }
|
||||||
|
|
||||||
/** \deprecated */
|
/** \deprecated */
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ template<int Mode> struct transform_make_affine;
|
|||||||
* preprocessor token EIGEN_QT_SUPPORT is defined.
|
* preprocessor token EIGEN_QT_SUPPORT is defined.
|
||||||
*
|
*
|
||||||
* This class can be extended with the help of the plugin mechanism described on the page
|
* 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
|
* \sa class Matrix, class Quaternion
|
||||||
*/
|
*/
|
||||||
@@ -253,43 +253,43 @@ public:
|
|||||||
|
|
||||||
/** Default constructor without initialization of the meaningful coefficients.
|
/** Default constructor without initialization of the meaningful coefficients.
|
||||||
* If Mode==Affine, then the last row is set to [0 ... 0 1] */
|
* If Mode==Affine, then the last row is set to [0 ... 0 1] */
|
||||||
inline Transform()
|
EIGEN_DEVICE_FUNC inline Transform()
|
||||||
{
|
{
|
||||||
check_template_params();
|
check_template_params();
|
||||||
internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix);
|
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();
|
check_template_params();
|
||||||
m_matrix = other.m_matrix;
|
m_matrix = other.m_matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline explicit Transform(const TranslationType& t)
|
EIGEN_DEVICE_FUNC inline explicit Transform(const TranslationType& t)
|
||||||
{
|
{
|
||||||
check_template_params();
|
check_template_params();
|
||||||
*this = t;
|
*this = t;
|
||||||
}
|
}
|
||||||
inline explicit Transform(const UniformScaling<Scalar>& s)
|
EIGEN_DEVICE_FUNC inline explicit Transform(const UniformScaling<Scalar>& s)
|
||||||
{
|
{
|
||||||
check_template_params();
|
check_template_params();
|
||||||
*this = s;
|
*this = s;
|
||||||
}
|
}
|
||||||
template<typename Derived>
|
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();
|
check_template_params();
|
||||||
*this = r;
|
*this = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Transform& operator=(const Transform& other)
|
EIGEN_DEVICE_FUNC inline Transform& operator=(const Transform& other)
|
||||||
{ m_matrix = other.m_matrix; return *this; }
|
{ m_matrix = other.m_matrix; return *this; }
|
||||||
|
|
||||||
typedef internal::transform_take_affine_part<Transform> take_affine_part;
|
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. */
|
/** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */
|
||||||
template<typename OtherDerived>
|
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),
|
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);
|
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. */
|
/** Set \c *this from a Dim^2 or (Dim+1)^2 matrix. */
|
||||||
template<typename OtherDerived>
|
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),
|
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);
|
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>
|
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();
|
check_template_params();
|
||||||
// only the options change, we can directly copy the matrices
|
// only the options change, we can directly copy the matrices
|
||||||
@@ -318,7 +318,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int OtherMode,int OtherOptions>
|
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();
|
check_template_params();
|
||||||
// prevent conversions as:
|
// prevent conversions as:
|
||||||
@@ -359,14 +359,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
Transform(const ReturnByValue<OtherDerived>& other)
|
EIGEN_DEVICE_FUNC Transform(const ReturnByValue<OtherDerived>& other)
|
||||||
{
|
{
|
||||||
check_template_params();
|
check_template_params();
|
||||||
other.evalTo(*this);
|
other.evalTo(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
Transform& operator=(const ReturnByValue<OtherDerived>& other)
|
EIGEN_DEVICE_FUNC Transform& operator=(const ReturnByValue<OtherDerived>& other)
|
||||||
{
|
{
|
||||||
other.evalTo(*this);
|
other.evalTo(*this);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -381,35 +381,35 @@ public:
|
|||||||
inline QTransform toQTransform(void) const;
|
inline QTransform toQTransform(void) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Index rows() const { return int(Mode)==int(Projective) ? m_matrix.cols() : (m_matrix.cols()-1); }
|
EIGEN_DEVICE_FUNC 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 cols() const { return m_matrix.cols(); }
|
||||||
|
|
||||||
/** shortcut for m_matrix(row,col);
|
/** shortcut for m_matrix(row,col);
|
||||||
* \sa MatrixBase::operator(Index,Index) const */
|
* \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);
|
/** shortcut for m_matrix(row,col);
|
||||||
* \sa MatrixBase::operator(Index,Index) */
|
* \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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 */
|
/** \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.
|
/** \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
|
// note: this function is defined here because some compilers cannot find the respective declaration
|
||||||
template<typename OtherDerived>
|
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
|
operator * (const EigenBase<OtherDerived> &other) const
|
||||||
{ return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
|
{ 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.
|
* \li a general transformation matrix of size Dim+1 x Dim+1.
|
||||||
*/
|
*/
|
||||||
template<typename OtherDerived> friend
|
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)
|
operator * (const EigenBase<OtherDerived> &a, const Transform &b)
|
||||||
{ return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),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.
|
* mode is no isometry. In that case, the returned transform is an affinity.
|
||||||
*/
|
*/
|
||||||
template<typename DiagonalDerived>
|
template<typename DiagonalDerived>
|
||||||
inline const TransformTimeDiagonalReturnType
|
EIGEN_DEVICE_FUNC inline const TransformTimeDiagonalReturnType
|
||||||
operator * (const DiagonalBase<DiagonalDerived> &b) const
|
operator * (const DiagonalBase<DiagonalDerived> &b) const
|
||||||
{
|
{
|
||||||
TransformTimeDiagonalReturnType res(*this);
|
TransformTimeDiagonalReturnType res(*this);
|
||||||
res.linear() *= b;
|
res.linearExt() *= b;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,7 +475,7 @@ public:
|
|||||||
* mode is no isometry. In that case, the returned transform is an affinity.
|
* mode is no isometry. In that case, the returned transform is an affinity.
|
||||||
*/
|
*/
|
||||||
template<typename DiagonalDerived>
|
template<typename DiagonalDerived>
|
||||||
friend inline TransformTimeDiagonalReturnType
|
EIGEN_DEVICE_FUNC friend inline TransformTimeDiagonalReturnType
|
||||||
operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
|
operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
|
||||||
{
|
{
|
||||||
TransformTimeDiagonalReturnType res;
|
TransformTimeDiagonalReturnType res;
|
||||||
@@ -487,10 +487,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename OtherDerived>
|
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 */
|
/** 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);
|
return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
|
||||||
}
|
}
|
||||||
@@ -522,7 +522,7 @@ public:
|
|||||||
#else
|
#else
|
||||||
/** Concatenates two different transformations */
|
/** Concatenates two different transformations */
|
||||||
template<int OtherMode,int OtherOptions>
|
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
|
operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
|
||||||
{
|
{
|
||||||
return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
|
return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
|
||||||
@@ -530,47 +530,61 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** \sa MatrixBase::setIdentity() */
|
/** \sa MatrixBase::setIdentity() */
|
||||||
void setIdentity() { m_matrix.setIdentity(); }
|
EIGEN_DEVICE_FUNC void setIdentity() { m_matrix.setIdentity(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Returns an identity transformation.
|
* \brief Returns an identity transformation.
|
||||||
* \todo In the future this function should be returning a Transform expression.
|
* \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());
|
return Transform(MatrixType::Identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform& scale(const MatrixBase<OtherDerived> &other);
|
inline Transform& scale(const MatrixBase<OtherDerived> &other);
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform& prescale(const MatrixBase<OtherDerived> &other);
|
inline Transform& prescale(const MatrixBase<OtherDerived> &other);
|
||||||
|
|
||||||
inline Transform& scale(const Scalar& s);
|
EIGEN_DEVICE_FUNC inline Transform& scale(const Scalar& s);
|
||||||
inline Transform& prescale(const Scalar& s);
|
EIGEN_DEVICE_FUNC inline Transform& prescale(const Scalar& s);
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform& translate(const MatrixBase<OtherDerived> &other);
|
inline Transform& translate(const MatrixBase<OtherDerived> &other);
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
|
inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
|
||||||
|
|
||||||
template<typename RotationType>
|
template<typename RotationType>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform& rotate(const RotationType& rotation);
|
inline Transform& rotate(const RotationType& rotation);
|
||||||
|
|
||||||
template<typename RotationType>
|
template<typename RotationType>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform& prerotate(const RotationType& rotation);
|
inline Transform& prerotate(const RotationType& rotation);
|
||||||
|
|
||||||
Transform& shear(const Scalar& sx, const Scalar& sy);
|
EIGEN_DEVICE_FUNC Transform& shear(const Scalar& sx, const Scalar& sy);
|
||||||
Transform& preshear(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) { 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);
|
inline Transform& operator=(const UniformScaling<Scalar>& t);
|
||||||
|
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
|
inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
|
||||||
|
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const
|
inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const
|
||||||
{
|
{
|
||||||
TransformTimeDiagonalReturnType res = *this;
|
TransformTimeDiagonalReturnType res = *this;
|
||||||
@@ -578,31 +592,36 @@ public:
|
|||||||
return res;
|
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>
|
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>
|
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>
|
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>
|
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
|
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
|
||||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
|
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
|
||||||
|
|
||||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
|
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
|
||||||
|
|
||||||
|
EIGEN_DEVICE_FUNC
|
||||||
inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
|
inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
|
||||||
|
|
||||||
/** \returns a const pointer to the column major internal matrix */
|
/** \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 */
|
/** \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
|
/** \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.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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); }
|
{ return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
|
||||||
|
|
||||||
/** Copy constructor with scalar type conversion */
|
/** Copy constructor with scalar type conversion */
|
||||||
template<typename OtherScalarType>
|
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();
|
check_template_params();
|
||||||
m_matrix = other.matrix().template cast<Scalar>();
|
m_matrix = other.matrix().template cast<Scalar>();
|
||||||
@@ -625,12 +644,12 @@ public:
|
|||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \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); }
|
{ return m_matrix.isApprox(other.m_matrix, prec); }
|
||||||
|
|
||||||
/** Sets the last row to [0 ... 0 1]
|
/** Sets the last row to [0 ... 0 1]
|
||||||
*/
|
*/
|
||||||
void makeAffine()
|
EIGEN_DEVICE_FUNC void makeAffine()
|
||||||
{
|
{
|
||||||
internal::transform_make_affine<int(Mode)>::run(m_matrix);
|
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,
|
* \returns the Dim x Dim linear part if the transformation is affine,
|
||||||
* and the HDim x Dim part for projective transformations.
|
* 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); }
|
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
|
||||||
/** \internal
|
/** \internal
|
||||||
* \returns the Dim x Dim linear part if the transformation is affine,
|
* \returns the Dim x Dim linear part if the transformation is affine,
|
||||||
* and the HDim x Dim part for projective transformations.
|
* 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); }
|
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* \returns the translation part if the transformation is affine,
|
* \returns the translation part if the transformation is affine,
|
||||||
* and the last column for projective transformations.
|
* 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); }
|
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
|
||||||
/** \internal
|
/** \internal
|
||||||
* \returns the translation part if the transformation is affine,
|
* \returns the translation part if the transformation is affine,
|
||||||
* and the last column for projective transformations.
|
* 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); }
|
{ return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
|
||||||
|
|
||||||
|
|
||||||
@@ -668,7 +687,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
#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)
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename OtherDerived>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
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)
|
* \sa prescale(Scalar)
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode, int Options>
|
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)
|
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
||||||
linearExt() *= s;
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename OtherDerived>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||||
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -862,7 +881,7 @@ Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &oth
|
|||||||
* \sa scale(Scalar)
|
* \sa scale(Scalar)
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode, int Options>
|
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)
|
EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
|
||||||
m_matrix.template topRows<Dim>() *= s;
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename OtherDerived>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename OtherDerived>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename RotationType>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
|
||||||
{
|
{
|
||||||
linearExt() *= internal::toRotationMatrix<Scalar,Dim>(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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename RotationType>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
|
||||||
{
|
{
|
||||||
m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(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()
|
* \sa preshear()
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode, int Options>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
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()
|
* \sa shear()
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode, int Options>
|
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)
|
Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
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>
|
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();
|
linear().setIdentity();
|
||||||
translation() = t.vector();
|
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>
|
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;
|
Transform res = *this;
|
||||||
res.translate(t.vector());
|
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>
|
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();
|
m_matrix.setZero();
|
||||||
linear().diagonal().fill(s.factor());
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename Derived>
|
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);
|
linear() = internal::toRotationMatrix<Scalar,Dim>(r);
|
||||||
translation().setZero();
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename Derived>
|
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;
|
Transform res = *this;
|
||||||
res.rotate(r.derived());
|
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
|
* \sa computeRotationScaling(), computeScalingRotation(), class SVD
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode, int Options>
|
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
|
Transform<Scalar,Dim,Mode,Options>::rotation() const
|
||||||
{
|
{
|
||||||
LinearMatrixType result;
|
LinearMatrixType result;
|
||||||
@@ -1057,7 +1076,7 @@ Transform<Scalar,Dim,Mode,Options>::rotation() const
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode, int Options>
|
template<typename Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
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);
|
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.
|
* not necessarily positive.
|
||||||
*
|
*
|
||||||
* If either pointer is zero, the corresponding computation is skipped.
|
* 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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
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);
|
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 Scalar, int Dim, int Mode, int Options>
|
||||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
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,
|
Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
|
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
|
||||||
{
|
{
|
||||||
@@ -1124,7 +1143,7 @@ template<int Mode>
|
|||||||
struct transform_make_affine
|
struct transform_make_affine
|
||||||
{
|
{
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
static void run(MatrixType &mat)
|
EIGEN_DEVICE_FUNC static void run(MatrixType &mat)
|
||||||
{
|
{
|
||||||
static const int Dim = MatrixType::ColsAtCompileTime-1;
|
static const int Dim = MatrixType::ColsAtCompileTime-1;
|
||||||
mat.template block<1,Dim>(Dim,0).setZero();
|
mat.template block<1,Dim>(Dim,0).setZero();
|
||||||
@@ -1135,21 +1154,21 @@ struct transform_make_affine
|
|||||||
template<>
|
template<>
|
||||||
struct transform_make_affine<AffineCompact>
|
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
|
// selector needed to avoid taking the inverse of a 3x4 matrix
|
||||||
template<typename TransformType, int Mode=TransformType::Mode>
|
template<typename TransformType, int Mode=TransformType::Mode>
|
||||||
struct projective_transform_inverse
|
struct projective_transform_inverse
|
||||||
{
|
{
|
||||||
static inline void run(const TransformType&, TransformType&)
|
EIGEN_DEVICE_FUNC static inline void run(const TransformType&, TransformType&)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename TransformType>
|
template<typename TransformType>
|
||||||
struct projective_transform_inverse<TransformType, Projective>
|
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();
|
res.matrix() = m.matrix().inverse();
|
||||||
}
|
}
|
||||||
@@ -1179,7 +1198,7 @@ struct projective_transform_inverse<TransformType, Projective>
|
|||||||
* \sa MatrixBase::inverse()
|
* \sa MatrixBase::inverse()
|
||||||
*/
|
*/
|
||||||
template<typename Scalar, int Dim, int Mode, int Options>
|
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<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
|
||||||
{
|
{
|
||||||
Transform res;
|
Transform res;
|
||||||
|
|||||||
@@ -51,16 +51,16 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Default constructor without initialization. */
|
/** 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);
|
eigen_assert(Dim==2);
|
||||||
m_coeffs.x() = sx;
|
m_coeffs.x() = sx;
|
||||||
m_coeffs.y() = sy;
|
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);
|
eigen_assert(Dim==3);
|
||||||
m_coeffs.x() = sx;
|
m_coeffs.x() = sx;
|
||||||
@@ -68,48 +68,48 @@ public:
|
|||||||
m_coeffs.z() = sz;
|
m_coeffs.z() = sz;
|
||||||
}
|
}
|
||||||
/** Constructs and initialize the translation transformation from a vector of translation coefficients */
|
/** 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. **/
|
/** \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. **/
|
/** \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. **/
|
/** \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. **/
|
/** \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. **/
|
/** \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. **/
|
/** \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; }
|
EIGEN_DEVICE_FUNC const VectorType& vector() const { return m_coeffs; }
|
||||||
VectorType& vector() { return m_coeffs; }
|
EIGEN_DEVICE_FUNC VectorType& vector() { return m_coeffs; }
|
||||||
|
|
||||||
const VectorType& translation() const { return m_coeffs; }
|
EIGEN_DEVICE_FUNC const VectorType& translation() const { return m_coeffs; }
|
||||||
VectorType& translation() { return m_coeffs; }
|
EIGEN_DEVICE_FUNC VectorType& translation() { return m_coeffs; }
|
||||||
|
|
||||||
/** Concatenates two translation */
|
/** 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); }
|
{ return Translation(m_coeffs + other.m_coeffs); }
|
||||||
|
|
||||||
/** Concatenates a translation and a uniform scaling */
|
/** 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 */
|
/** Concatenates a translation and a linear transformation */
|
||||||
template<typename OtherDerived>
|
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 */
|
/** Concatenates a translation and a rotation */
|
||||||
template<typename Derived>
|
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); }
|
{ return *this * IsometryTransformType(r); }
|
||||||
|
|
||||||
/** \returns the concatenation of a linear transformation \a l with the translation \a t */
|
/** \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
|
// its a nightmare to define a templated friend function outside its declaration
|
||||||
template<typename OtherDerived> friend
|
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;
|
AffineTransformType res;
|
||||||
res.matrix().setZero();
|
res.matrix().setZero();
|
||||||
@@ -122,7 +122,7 @@ public:
|
|||||||
|
|
||||||
/** Concatenates a translation and a transformation */
|
/** Concatenates a translation and a transformation */
|
||||||
template<int Mode, int Options>
|
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;
|
Transform<Scalar,Dim,Mode> res = t;
|
||||||
res.pretranslate(m_coeffs);
|
res.pretranslate(m_coeffs);
|
||||||
@@ -130,8 +130,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Applies translation to vector */
|
/** Applies translation to vector */
|
||||||
inline VectorType operator* (const VectorType& other) const
|
template<typename Derived>
|
||||||
{ return m_coeffs + other; }
|
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) */
|
/** \returns the inverse translation (opposite) */
|
||||||
Translation inverse() const { return Translation(-m_coeffs); }
|
Translation inverse() const { return Translation(-m_coeffs); }
|
||||||
@@ -150,19 +152,19 @@ public:
|
|||||||
* then this function smartly returns a const reference to \c *this.
|
* then this function smartly returns a const reference to \c *this.
|
||||||
*/
|
*/
|
||||||
template<typename NewScalarType>
|
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); }
|
{ return typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
|
||||||
|
|
||||||
/** Copy constructor with scalar type conversion */
|
/** Copy constructor with scalar type conversion */
|
||||||
template<typename OtherScalarType>
|
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>(); }
|
{ m_coeffs = other.vector().template cast<Scalar>(); }
|
||||||
|
|
||||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \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); }
|
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -176,7 +178,7 @@ typedef Translation<double,3> Translation3d;
|
|||||||
//@}
|
//@}
|
||||||
|
|
||||||
template<typename Scalar, int Dim>
|
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
|
Translation<Scalar,Dim>::operator* (const UniformScaling<Scalar>& other) const
|
||||||
{
|
{
|
||||||
AffineTransformType res;
|
AffineTransformType res;
|
||||||
@@ -189,7 +191,7 @@ Translation<Scalar,Dim>::operator* (const UniformScaling<Scalar>& other) const
|
|||||||
|
|
||||||
template<typename Scalar, int Dim>
|
template<typename Scalar, int Dim>
|
||||||
template<typename OtherDerived>
|
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
|
Translation<Scalar,Dim>::operator* (const EigenBase<OtherDerived>& linear) const
|
||||||
{
|
{
|
||||||
AffineTransformType res;
|
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;
|
*this *= Scalar(1)-tau;
|
||||||
}
|
}
|
||||||
else
|
else if(tau!=Scalar(0))
|
||||||
{
|
{
|
||||||
Map<typename internal::plain_row_type<PlainObject>::type> tmp(workspace,cols());
|
Map<typename internal::plain_row_type<PlainObject>::type> tmp(workspace,cols());
|
||||||
Block<Derived, EssentialPart::SizeAtCompileTime, Derived::ColsAtCompileTime> bottom(derived(), 1, 0, rows()-1, 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;
|
*this *= Scalar(1)-tau;
|
||||||
}
|
}
|
||||||
else
|
else if(tau!=Scalar(0))
|
||||||
{
|
{
|
||||||
Map<typename internal::plain_col_type<PlainObject>::type> tmp(workspace,rows());
|
Map<typename internal::plain_col_type<PlainObject>::type> tmp(workspace,rows());
|
||||||
Block<Derived, Derived::RowsAtCompileTime, EssentialPart::SizeAtCompileTime> right(derived(), 0, 1, rows(), cols()-1);
|
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