Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
549bf8c75b | ||
|
|
151b95d078 | ||
|
|
2e5447e620 | ||
|
|
8d7ebac6ec | ||
|
|
bea7f7c582 | ||
|
|
7292c78e18 | ||
|
|
e524488eb2 | ||
|
|
dbd25f632b | ||
|
|
027dc5bc8d | ||
|
|
4df215785b | ||
|
|
2d170aea11 | ||
|
|
ea869e183b | ||
|
|
6ef18340a1 | ||
|
|
14477c5d43 | ||
|
|
b2ec79a23c | ||
|
|
62fbd276e0 | ||
|
|
d38d669fdb | ||
|
|
4ac3e71f77 | ||
|
|
a627f72cd6 | ||
|
|
e0a59e5a66 | ||
|
|
6cd6284f7f | ||
|
|
e5f3fa2d61 | ||
|
|
f426eff949 | ||
|
|
da1a34a6ba | ||
|
|
52fc978c6f | ||
|
|
8a8fbc8f5e | ||
|
|
70d8d99d0d | ||
|
|
7f0cb638c5 | ||
|
|
1e9d7ed7d3 | ||
|
|
5d4485e767 | ||
|
|
2e8cc042a1 | ||
|
|
52f570a409 | ||
|
|
38b51d5b7e | ||
|
|
d2a70fe4e2 | ||
|
|
4ae5647355 | ||
|
|
1a45d2168e | ||
|
|
05e74b1a40 | ||
|
|
d368998120 | ||
|
|
c487a4fe9e | ||
|
|
4033cfcc1d | ||
|
|
e9dfbad618 | ||
|
|
43a65a9cbd | ||
|
|
954e21152e | ||
|
|
e15cd620a0 | ||
|
|
1c0048a08c | ||
|
|
ddce1d7d12 | ||
|
|
8b9dbcdaaf | ||
|
|
975a5aba4f | ||
|
|
4be7e6b4e0 | ||
|
|
edcf4c135f | ||
|
|
e4493233e8 | ||
|
|
f5ead2d34c | ||
|
|
1e65707aa2 | ||
|
|
abeba85356 | ||
|
|
b5bef9dcb0 | ||
|
|
97c7cc6200 | ||
|
|
efe5b6979d | ||
|
|
2cf66d4b0d | ||
|
|
d7fa5ebe0e | ||
|
|
cedf1f4c17 | ||
|
|
302fc46bc3 | ||
|
|
430e35fbd1 | ||
|
|
bd0cd1d67b | ||
|
|
6854da2ea0 | ||
|
|
ac1b29f823 | ||
|
|
849a336243 | ||
|
|
8ac2fb077d | ||
|
|
cc0be00435 | ||
|
|
f169c13d8e | ||
|
|
7fa069ef90 | ||
|
|
7c636dd5db | ||
|
|
26616fe5b8 | ||
|
|
a395ee162d | ||
|
|
0bce653efc | ||
|
|
db8bd5b825 | ||
|
|
6de0515fa6 | ||
|
|
98fbf6ed77 | ||
|
|
81044ec13d | ||
|
|
bcce88c99e | ||
|
|
ac6955ebc6 | ||
|
|
67a898a079 | ||
|
|
cdf6a1f5ed | ||
|
|
d228bcdf8f | ||
|
|
994f3d107a | ||
|
|
cda19a6255 | ||
|
|
d0b490ee09 | ||
|
|
c458d68fae | ||
|
|
3f00059beb | ||
|
|
21e89b930c | ||
|
|
4fdf87bbf5 | ||
|
|
a7f183cadb | ||
|
|
d81aa18f4d | ||
|
|
171bd08ca9 | ||
|
|
db85838ee2 | ||
|
|
6f1a143418 | ||
|
|
f3e7d64f3d | ||
|
|
434a2fc4a4 | ||
|
|
ae3aba99db | ||
|
|
ee4f86f909 | ||
|
|
6dbbf0a843 | ||
|
|
fb2fca90be | ||
|
|
d6b23a2256 | ||
|
|
7294434099 | ||
|
|
2265a5e025 | ||
|
|
619be0deb6 | ||
|
|
d2dce37767 | ||
|
|
66d8111ac1 | ||
|
|
d6689a15d7 | ||
|
|
33f5f59614 | ||
|
|
5330960900 | ||
|
|
6266d430cc | ||
|
|
e39ad8badc | ||
|
|
7aefb9f4d9 | ||
|
|
73ca849a68 | ||
|
|
28c3b26d53 | ||
|
|
cebe09110c | ||
|
|
11fd34cc1c | ||
|
|
2cd47d743e | ||
|
|
b860042263 | ||
|
|
02d9e1138a | ||
|
|
9cc9209b9b | ||
|
|
e0c99a8dd6 | ||
|
|
63a40ffb95 | ||
|
|
44fb6422be | ||
|
|
3866cbfbe8 | ||
|
|
6579e36eb4 | ||
|
|
8e32cbf7da | ||
|
|
d935916ac6 | ||
|
|
754bd24f5e | ||
|
|
ac2165c11f | ||
|
|
3143968195 | ||
|
|
70f2aead9a | ||
|
|
0259a52b0e | ||
|
|
14f845a1a8 | ||
|
|
33b04fe518 | ||
|
|
10e62ccd22 | ||
|
|
464c1d0978 | ||
|
|
21223f6bb6 | ||
|
|
350544eb01 | ||
|
|
43810fc1be | ||
|
|
d28041ed5a | ||
|
|
9a86214039 | ||
|
|
be5147b090 | ||
|
|
179a49684a | ||
|
|
dd56367554 | ||
|
|
d79bac0d3c | ||
|
|
9935396b15 | ||
|
|
72adf891d5 | ||
|
|
6aebfa9acc | ||
|
|
bddaa99e15 | ||
|
|
e42dceb3a1 | ||
|
|
5fc6fc9881 | ||
|
|
0ae7b59018 | ||
|
|
4dda5b927a | ||
|
|
66f7f51b7e | ||
|
|
151f6127df | ||
|
|
1d8b82b074 | ||
|
|
eb3f9f443d | ||
|
|
9c211430b5 | ||
|
|
22cd7307dd | ||
|
|
6b4881ad48 | ||
|
|
420d891de7 | ||
|
|
becefd59e2 | ||
|
|
809d266b49 | ||
|
|
ef475f2770 | ||
|
|
a0591cbc93 | ||
|
|
715deac188 | ||
|
|
4c38131a16 | ||
|
|
4c2611d27c | ||
|
|
c079ee5e44 | ||
|
|
74264c391a | ||
|
|
3ebe898b5f | ||
|
|
b73bb766a5 | ||
|
|
b1e74b1ccd | ||
|
|
9589cc4e7f | ||
|
|
2926b2e0a9 | ||
|
|
b6849f675d | ||
|
|
1b2e84e55a | ||
|
|
872c179f58 | ||
|
|
2a35a917be | ||
|
|
a056b93114 | ||
|
|
5d866a7a78 | ||
|
|
bc67025ba7 | ||
|
|
dc1126e762 | ||
|
|
cd511a09aa | ||
|
|
f679843dc2 | ||
|
|
f9705adabb | ||
|
|
b75895a8b6 | ||
|
|
4a6ac97d13 | ||
|
|
e986838464 | ||
|
|
c486af5ad3 | ||
|
|
abac563f5d | ||
|
|
2e76277bd0 | ||
|
|
ad13df7ea4 | ||
|
|
9836e8d035 | ||
|
|
7bb23b1e36 | ||
|
|
7bb8c58e7c | ||
|
|
24e0c2a125 | ||
|
|
a32db43966 | ||
|
|
c01ff45312 | ||
|
|
af59ada0ac | ||
|
|
4a9e32ae0b | ||
|
|
00776d1ba4 | ||
|
|
7f23778593 | ||
|
|
c30b35a310 | ||
|
|
a26ba67349 | ||
|
|
08c31c3ba6 | ||
|
|
1ac1af62ef | ||
|
|
7b6623af30 | ||
|
|
fd48fbb260 | ||
|
|
a885340ba5 | ||
|
|
45a8478d09 | ||
|
|
de4afcf414 | ||
|
|
5e8916050b | ||
|
|
77a073aaa8 | ||
|
|
41e46ed243 | ||
|
|
a0d32e40d9 | ||
|
|
d34b100c13 | ||
|
|
f19a6803c8 | ||
|
|
5064cb7d5e | ||
|
|
1ea61a5d26 | ||
|
|
8ad4344ca7 | ||
|
|
5610a13b77 | ||
|
|
6c6ce9d06b | ||
|
|
e7c799b7c9 | ||
|
|
00af47102d | ||
|
|
8ee6f8475a | ||
|
|
93ec5450cb | ||
|
|
0af6ab4b76 | ||
|
|
d5eec781b7 | ||
|
|
2fc63808e4 | ||
|
|
5133c836c0 | ||
|
|
d6e3b528b2 | ||
|
|
040180078d | ||
|
|
0fb2ed140d | ||
|
|
8b4efc8ed8 | ||
|
|
489dbbc651 | ||
|
|
283d871a3f | ||
|
|
0d366f6532 | ||
|
|
8adf43640e | ||
|
|
bc424f617a | ||
|
|
e52ac76ca3 | ||
|
|
122be167cd | ||
|
|
d49021212b | ||
|
|
bb73be8a2e | ||
|
|
7fd305ecae | ||
|
|
c8267654f2 | ||
|
|
84c446df2c | ||
|
|
a9584d8e3c | ||
|
|
dd4c2805d9 | ||
|
|
9e962d9c54 | ||
|
|
695e49d1bd | ||
|
|
dae09773fc | ||
|
|
c23ec3420e | ||
|
|
58b252e5b3 | ||
|
|
6c04d0cd68 | ||
|
|
b15ebb1c2d | ||
|
|
53b83cddf9 | ||
|
|
37563856c9 | ||
|
|
3f067c4850 | ||
|
|
4e5136d239 | ||
|
|
b396a6fbb2 | ||
|
|
820e8a45fb | ||
|
|
b55dab7f21 | ||
|
|
e0cbc55d92 | ||
|
|
7eea0a9213 | ||
|
|
78f3c654ee | ||
|
|
6d7af238fa | ||
|
|
74dcfbbd0f | ||
|
|
a097f728fe | ||
|
|
44b16f48cb | ||
|
|
12068cbcdb | ||
|
|
4e8e5e7409 | ||
|
|
8e8c319087 | ||
|
|
7ad7c1d5c5 | ||
|
|
d052b7f864 | ||
|
|
ba5183f98c | ||
|
|
3ffb4e50df | ||
|
|
b6b8b54e5e |
@@ -7,6 +7,8 @@ BasedOnStyle: Google
|
||||
ColumnLimit: 120
|
||||
StatementMacros:
|
||||
- EIGEN_STATIC_ASSERT
|
||||
- EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||
- EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
SortIncludes: false
|
||||
AttributeMacros:
|
||||
- EIGEN_STRONG_INLINE
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
*.sh eol=lf
|
||||
debug/msvc/*.dat eol=crlf
|
||||
debug/msvc/*.natvis eol=crlf
|
||||
+5
-2
@@ -11,6 +11,7 @@ stages:
|
||||
- checkformat
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
# CMake build directory.
|
||||
@@ -19,8 +20,9 @@ variables:
|
||||
EIGEN_CI_BUILD_TARGET: ""
|
||||
# If a test regex is specified, that will be selected.
|
||||
# Otherwise, we will try a label if specified.
|
||||
EIGEN_CI_TEST_REGEX: ""
|
||||
EIGEN_CI_TEST_LABEL: ""
|
||||
EIGEN_CI_CTEST_REGEX: ""
|
||||
EIGEN_CI_CTEST_LABEL: ""
|
||||
EIGEN_CI_CTEST_ARGS: ""
|
||||
|
||||
include:
|
||||
- "/ci/checkformat.gitlab-ci.yml"
|
||||
@@ -29,3 +31,4 @@ include:
|
||||
- "/ci/build.windows.gitlab-ci.yml"
|
||||
- "/ci/test.linux.gitlab-ci.yml"
|
||||
- "/ci/test.windows.gitlab-ci.yml"
|
||||
- "/ci/deploy.gitlab-ci.yml"
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
[patterns]
|
||||
*.sh = LF
|
||||
*.MINPACK = CRLF
|
||||
scripts/*.in = LF
|
||||
debug/msvc/*.dat = CRLF
|
||||
debug/msvc/*.natvis = CRLF
|
||||
unsupported/test/mpreal/*.* = CRLF
|
||||
** = native
|
||||
|
||||
[repository]
|
||||
native = LF
|
||||
+1905
File diff suppressed because it is too large
Load Diff
+95
-62
@@ -29,6 +29,11 @@ if (POLICY CMP0146)
|
||||
cmake_policy(SET CMP0146 OLD)
|
||||
endif ()
|
||||
|
||||
# Normalize DESTINATION paths
|
||||
if (POLICY CMP0177)
|
||||
cmake_policy(SET CMP0177 NEW)
|
||||
endif ()
|
||||
|
||||
#==============================================================================
|
||||
# CMake Project.
|
||||
#==============================================================================
|
||||
@@ -95,34 +100,64 @@ endif()
|
||||
# Version Info.
|
||||
#==============================================================================
|
||||
|
||||
# Automatically parse the version number from header files.
|
||||
file(READ "${PROJECT_SOURCE_DIR}/Eigen/src/Core/util/Macros.h" _eigen_version_header)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen_world_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_WORLD_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen_major_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen_minor_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||
set(EIGEN_VERSION_NUMBER ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})
|
||||
# If version information is not provided, automatically parse the version number
|
||||
# from header files.
|
||||
file(READ "${PROJECT_SOURCE_DIR}/Eigen/Version" _eigen_version_header)
|
||||
if (NOT DEFINED EIGEN_WORLD_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen_world_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_WORLD_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_MAJOR_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen_major_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_MINOR_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen_minor_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_PATCH_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_PATCH_VERSION[ \t]+([0-9]+)" _eigen_patch_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_PATCH_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_PRERELEASE_VERSION)
|
||||
set(EIGEN_PRERELEASE_VERSION "dev")
|
||||
endif()
|
||||
|
||||
# If we are in a git repo, extract a changeset.
|
||||
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/.git)
|
||||
# if the git program is absent or this will leave the EIGEN_GIT_REVNUM string empty,
|
||||
# but won't stop CMake.
|
||||
execute_process(COMMAND git ls-remote --refs -q ${CMAKE_SOURCE_DIR} HEAD OUTPUT_VARIABLE EIGEN_GIT_OUTPUT)
|
||||
execute_process(COMMAND git ls-remote -q ${CMAKE_SOURCE_DIR} HEAD OUTPUT_VARIABLE EIGEN_GIT_OUTPUT)
|
||||
endif()
|
||||
|
||||
# extract the git rev number from the git output...
|
||||
if(EIGEN_GIT_OUTPUT)
|
||||
string(REGEX MATCH "^([0-9;a-f]+).*" EIGEN_GIT_CHANGESET_MATCH "${EIGEN_GIT_OUTPUT}")
|
||||
set(EIGEN_GIT_REVNUM "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "^([0-9;a-f]+).*" EIGEN_GIT_CHANGESET_MATCH "${EIGEN_GIT_OUTPUT}")
|
||||
set(EIGEN_GIT_REVNUM "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
#...and show it next to the version number
|
||||
if(EIGEN_GIT_REVNUM)
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER} (git rev ${EIGEN_GIT_REVNUM})")
|
||||
|
||||
if (NOT DEFINED EIGEN_BUILD_VERSION AND DEFINED EIGEN_GIT_REVNUM)
|
||||
string(SUBSTRING "${EIGEN_GIT_REVNUM}" 0 8 EIGEN_BUILD_VERSION)
|
||||
else()
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
|
||||
set(EIGEN_BUILD_VERSION "")
|
||||
endif()
|
||||
|
||||
# The EIGEN_VERSION_NUMBER must be of the form <major.minor.patch>.
|
||||
# The EIGEN_VERSION_STRING can contain the preprelease/build strings.
|
||||
set(EIGEN_VERSION_NUMBER "${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION}.${EIGEN_PATCH_VERSION}")
|
||||
set(EIGEN_VERSION_STRING "${EIGEN_VERSION_NUMBER}")
|
||||
if (NOT "x${EIGEN_PRERELEASE_VERSION}" STREQUAL "x")
|
||||
set(EIGEN_VERSION_STRING "${EIGEN_VERSION_STRING}-${EIGEN_PRERELEASE_VERSION}")
|
||||
endif()
|
||||
if (NOT "x${EIGEN_BUILD_VERSION}" STREQUAL "x")
|
||||
set(EIGEN_VERSION_STRING "${EIGEN_VERSION_STRING}+${EIGEN_BUILD_VERSION}")
|
||||
endif()
|
||||
|
||||
|
||||
# Generate version file.
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Version.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/Eigen/Version")
|
||||
|
||||
#==============================================================================
|
||||
# Install Path Configuration.
|
||||
#==============================================================================
|
||||
@@ -170,11 +205,6 @@ endforeach()
|
||||
# Eigen Library.
|
||||
#==============================================================================
|
||||
|
||||
set ( EIGEN_VERSION_STRING ${EIGEN_VERSION_NUMBER} )
|
||||
set ( EIGEN_VERSION_MAJOR ${EIGEN_WORLD_VERSION} )
|
||||
set ( EIGEN_VERSION_MINOR ${EIGEN_MAJOR_VERSION} )
|
||||
set ( EIGEN_VERSION_PATCH ${EIGEN_MINOR_VERSION} )
|
||||
|
||||
# Alias Eigen_*_DIR to Eigen3_*_DIR:
|
||||
set(Eigen_SOURCE_DIR ${Eigen3_SOURCE_DIR})
|
||||
set(Eigen_BINARY_DIR ${Eigen3_BINARY_DIR})
|
||||
@@ -187,6 +217,9 @@ target_include_directories (eigen INTERFACE
|
||||
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
|
||||
)
|
||||
|
||||
# Eigen requires at least C++14
|
||||
target_compile_features (eigen INTERFACE cxx_std_14)
|
||||
|
||||
# Export as title case Eigen
|
||||
set_target_properties (eigen PROPERTIES EXPORT_NAME Eigen)
|
||||
|
||||
@@ -206,6 +239,9 @@ if(EIGEN_BUILD_PKGCONFIG)
|
||||
endif()
|
||||
|
||||
install(DIRECTORY Eigen DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel)
|
||||
# Replace the "Version" header file with the generated one.
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Eigen/Version
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/ COMPONENT Devel)
|
||||
|
||||
install(TARGETS eigen EXPORT Eigen3Targets)
|
||||
|
||||
@@ -219,25 +255,10 @@ if(EIGEN_BUILD_CMAKE_PACKAGE)
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO # Eigen does not provide components
|
||||
)
|
||||
|
||||
# NOTE Remove the first code path once the minimum required CMake version is
|
||||
# bumped to 3.14 or above.
|
||||
if (CMAKE_VERSION VERSION_LESS 3.14)
|
||||
# Remove CMAKE_SIZEOF_VOID_P from Eigen3ConfigVersion.cmake since Eigen does
|
||||
# not depend on architecture specific settings or libraries. More
|
||||
# specifically, an Eigen3Config.cmake generated from a 64 bit target can be
|
||||
# used for 32 bit targets as well (and vice versa).
|
||||
set (_Eigen3_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
|
||||
unset (CMAKE_SIZEOF_VOID_P)
|
||||
write_basic_package_version_file (Eigen3ConfigVersion.cmake
|
||||
VERSION ${EIGEN_VERSION_NUMBER}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
set (CMAKE_SIZEOF_VOID_P ${_Eigen3_CMAKE_SIZEOF_VOID_P})
|
||||
else (CMAKE_VERSION VERSION_LESS 3.14)
|
||||
write_basic_package_version_file (Eigen3ConfigVersion.cmake
|
||||
VERSION ${EIGEN_VERSION_NUMBER}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
ARCH_INDEPENDENT)
|
||||
endif (CMAKE_VERSION VERSION_LESS 3.14)
|
||||
set(CVF_VERSION "${EIGEN_VERSION_NUMBER}")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Eigen3ConfigVersion.cmake.in"
|
||||
"Eigen3ConfigVersion.cmake"
|
||||
@ONLY)
|
||||
|
||||
# The Eigen target will be located in the Eigen3 namespace. Other CMake
|
||||
# targets can refer to it using Eigen3::Eigen.
|
||||
@@ -253,7 +274,7 @@ if(EIGEN_BUILD_CMAKE_PACKAGE)
|
||||
DESTINATION ${CMAKEPACKAGE_INSTALL_DIR})
|
||||
|
||||
# Add uninstall target
|
||||
if(NOT TARGET uninstall)
|
||||
if(NOT TARGET uninstall AND PROJECT_IS_TOP_LEVEL)
|
||||
add_custom_target ( uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/EigenUninstall.cmake)
|
||||
endif()
|
||||
@@ -383,12 +404,17 @@ if (EIGEN_BUILD_TESTING)
|
||||
ei_add_cxx_compiler_flag("-Wno-psabi")
|
||||
ei_add_cxx_compiler_flag("-Wno-variadic-macros")
|
||||
ei_add_cxx_compiler_flag("-Wno-long-long")
|
||||
ei_add_cxx_compiler_flag("-fno-check-new")
|
||||
ei_add_cxx_compiler_flag("-fno-common")
|
||||
ei_add_cxx_compiler_flag("-fstrict-aliasing")
|
||||
ei_add_cxx_compiler_flag("-wd981") # disable ICC's "operands are evaluated in unspecified order" remark
|
||||
ei_add_cxx_compiler_flag("-wd2304") # disable ICC's "warning #2304: non-explicit constructor with single argument may cause implicit type conversion" produced by -Wnon-virtual-dtor
|
||||
|
||||
# Clang emits warnings about unused flag.
|
||||
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
ei_add_cxx_compiler_flag("-fno-check-new")
|
||||
endif()
|
||||
|
||||
|
||||
if(ANDROID_NDK)
|
||||
ei_add_cxx_compiler_flag("-pie")
|
||||
ei_add_cxx_compiler_flag("-fPIE")
|
||||
@@ -486,6 +512,12 @@ if (EIGEN_BUILD_TESTING)
|
||||
message(STATUS "Enabling MSA in tests/examples")
|
||||
endif()
|
||||
|
||||
option(EIGEN_TEST_LSX "Enable/Disable LSX in tests/examples" OFF)
|
||||
if(EIGEN_TEST_LSX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlsx")
|
||||
message(STATUS "Enabling LSX in tests/examples")
|
||||
endif()
|
||||
|
||||
option(EIGEN_TEST_NEON "Enable/Disable Neon in tests/examples" OFF)
|
||||
if(EIGEN_TEST_NEON)
|
||||
if(EIGEN_TEST_FMA)
|
||||
@@ -738,36 +770,37 @@ if(PROJECT_IS_TOP_LEVEL)
|
||||
else()
|
||||
message(STATUS "Available targets (use: cmake --build . --target TARGET):")
|
||||
endif()
|
||||
message(STATUS "---------+--------------------------------------------------------------")
|
||||
message(STATUS "Target | Description")
|
||||
message(STATUS "---------+--------------------------------------------------------------")
|
||||
message(STATUS "install | Install Eigen. Headers will be installed to:")
|
||||
message(STATUS " | <CMAKE_INSTALL_PREFIX>/<INCLUDE_INSTALL_DIR>")
|
||||
message(STATUS " | Using the following values:")
|
||||
message(STATUS " | CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS " | INCLUDE_INSTALL_DIR: ${INCLUDE_INSTALL_DIR}")
|
||||
message(STATUS " | Change the install location of Eigen headers using:")
|
||||
message(STATUS " | cmake . -DCMAKE_INSTALL_PREFIX=yourprefix")
|
||||
message(STATUS " | Or:")
|
||||
message(STATUS " | cmake . -DINCLUDE_INSTALL_DIR=yourdir")
|
||||
message(STATUS "uninstall| Remove files installed by the install target")
|
||||
message(STATUS "------------+--------------------------------------------------------------")
|
||||
message(STATUS "Target | Description")
|
||||
message(STATUS "------------+--------------------------------------------------------------")
|
||||
message(STATUS "install | Install Eigen. Headers will be installed to:")
|
||||
message(STATUS " | <CMAKE_INSTALL_PREFIX>/<INCLUDE_INSTALL_DIR>")
|
||||
message(STATUS " | Using the following values:")
|
||||
message(STATUS " | CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS " | INCLUDE_INSTALL_DIR: ${INCLUDE_INSTALL_DIR}")
|
||||
message(STATUS " | Change the install location of Eigen headers using:")
|
||||
message(STATUS " | cmake . -DCMAKE_INSTALL_PREFIX=yourprefix")
|
||||
message(STATUS " | Or:")
|
||||
message(STATUS " | cmake . -DINCLUDE_INSTALL_DIR=yourdir")
|
||||
message(STATUS "uninstall | Remove files installed by the install target")
|
||||
if (EIGEN_BUILD_DOC)
|
||||
message(STATUS "doc | Generate the API documentation, requires Doxygen & LaTeX")
|
||||
message(STATUS "doc | Generate the API documentation, requires Doxygen & LaTeX")
|
||||
message(STATUS "install-doc | Install the API documentation")
|
||||
endif()
|
||||
if(EIGEN_BUILD_TESTING)
|
||||
message(STATUS "check | Build and run the unit-tests. Read this page:")
|
||||
message(STATUS " | http://eigen.tuxfamily.org/index.php?title=Tests")
|
||||
message(STATUS "check | Build and run the unit-tests. Read this page:")
|
||||
message(STATUS " | http://eigen.tuxfamily.org/index.php?title=Tests")
|
||||
endif()
|
||||
if (EIGEN_BUILD_BLAS)
|
||||
message(STATUS "blas | Build BLAS library (not the same thing as Eigen)")
|
||||
message(STATUS "blas | Build BLAS library (not the same thing as Eigen)")
|
||||
endif()
|
||||
if (EIGEN_BUILD_LAPACK)
|
||||
message(STATUS "lapack | Build LAPACK subset library (not the same thing as Eigen)")
|
||||
message(STATUS "lapack | Build LAPACK subset library (not the same thing as Eigen)")
|
||||
endif()
|
||||
message(STATUS "---------+--------------------------------------------------------------")
|
||||
message(STATUS "------------+--------------------------------------------------------------")
|
||||
message(STATUS "")
|
||||
endif()
|
||||
|
||||
message(STATUS "")
|
||||
message(STATUS "Configured Eigen ${EIGEN_VERSION_NUMBER}")
|
||||
message(STATUS "Configured Eigen ${EIGEN_VERSION_STRING}")
|
||||
message(STATUS "")
|
||||
|
||||
+40
-12
@@ -11,6 +11,9 @@
|
||||
#ifndef EIGEN_CORE_MODULE_H
|
||||
#define EIGEN_CORE_MODULE_H
|
||||
|
||||
// Eigen version information.
|
||||
#include "Version"
|
||||
|
||||
// first thing Eigen does: stop the compiler from reporting useless warnings.
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
@@ -92,6 +95,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// for std::is_nothrow_move_assignable
|
||||
@@ -102,6 +106,11 @@
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
// for std::bit_cast()
|
||||
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
#include <bit>
|
||||
#endif
|
||||
|
||||
// for outputting debug info
|
||||
#ifdef EIGEN_DEBUG_ASSIGN
|
||||
#include <iostream>
|
||||
@@ -121,7 +130,6 @@
|
||||
#undef isfinite
|
||||
#include <CL/sycl.hpp>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#ifndef EIGEN_SYCL_LOCAL_THREAD_DIM0
|
||||
@@ -193,38 +201,52 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/arch/Default/GenericPacketMathFunctionsFwd.h"
|
||||
|
||||
#if defined EIGEN_VECTORIZE_AVX512
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/Reductions.h"
|
||||
#include "src/Core/arch/AVX/PacketMath.h"
|
||||
#include "src/Core/arch/AVX/Reductions.h"
|
||||
#include "src/Core/arch/AVX512/PacketMath.h"
|
||||
#include "src/Core/arch/AVX512/Reductions.h"
|
||||
#if defined EIGEN_VECTORIZE_AVX512FP16
|
||||
#include "src/Core/arch/AVX512/PacketMathFP16.h"
|
||||
#endif
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/TypeCasting.h"
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
#include "src/Core/arch/AVX/PacketMath.h"
|
||||
#include "src/Core/arch/AVX/TypeCasting.h"
|
||||
#include "src/Core/arch/AVX/Complex.h"
|
||||
#include "src/Core/arch/AVX512/PacketMath.h"
|
||||
#include "src/Core/arch/AVX512/TypeCasting.h"
|
||||
#if defined EIGEN_VECTORIZE_AVX512FP16
|
||||
#include "src/Core/arch/AVX512/TypeCastingFP16.h"
|
||||
#endif
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
#include "src/Core/arch/AVX/Complex.h"
|
||||
#include "src/Core/arch/AVX512/Complex.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX512/MathFunctions.h"
|
||||
#if defined EIGEN_VECTORIZE_AVX512FP16
|
||||
#include "src/Core/arch/AVX512/MathFunctionsFP16.h"
|
||||
#endif
|
||||
#include "src/Core/arch/AVX512/TrsmKernel.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/Reductions.h"
|
||||
#include "src/Core/arch/SSE/TypeCasting.h"
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
#include "src/Core/arch/AVX/PacketMath.h"
|
||||
#include "src/Core/arch/AVX/Reductions.h"
|
||||
#include "src/Core/arch/AVX/TypeCasting.h"
|
||||
#include "src/Core/arch/AVX/Complex.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX/MathFunctions.h"
|
||||
#elif defined EIGEN_VECTORIZE_SSE
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/Reductions.h"
|
||||
#include "src/Core/arch/SSE/TypeCasting.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
#elif defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX)
|
||||
#endif
|
||||
|
||||
#if defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX)
|
||||
#include "src/Core/arch/AltiVec/PacketMath.h"
|
||||
#include "src/Core/arch/AltiVec/TypeCasting.h"
|
||||
#include "src/Core/arch/AltiVec/MathFunctions.h"
|
||||
@@ -234,6 +256,11 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/arch/NEON/TypeCasting.h"
|
||||
#include "src/Core/arch/NEON/MathFunctions.h"
|
||||
#include "src/Core/arch/NEON/Complex.h"
|
||||
#elif defined EIGEN_VECTORIZE_LSX
|
||||
#include "src/Core/arch/LSX/PacketMath.h"
|
||||
#include "src/Core/arch/LSX/TypeCasting.h"
|
||||
#include "src/Core/arch/LSX/MathFunctions.h"
|
||||
#include "src/Core/arch/LSX/Complex.h"
|
||||
#elif defined EIGEN_VECTORIZE_SVE
|
||||
#include "src/Core/arch/SVE/PacketMath.h"
|
||||
#include "src/Core/arch/SVE/TypeCasting.h"
|
||||
@@ -300,11 +327,8 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/Product.h"
|
||||
#include "src/Core/CoreEvaluators.h"
|
||||
#include "src/Core/AssignEvaluator.h"
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874
|
||||
// at least confirmed with Doxygen 1.5.5 and 1.5.6
|
||||
#include "src/Core/RealView.h"
|
||||
#include "src/Core/Assign.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/ArrayBase.h"
|
||||
#include "src/Core/util/BlasUtil.h"
|
||||
@@ -318,6 +342,7 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/PlainObjectBase.h"
|
||||
#include "src/Core/Matrix.h"
|
||||
#include "src/Core/Array.h"
|
||||
#include "src/Core/Fill.h"
|
||||
#include "src/Core/CwiseTernaryOp.h"
|
||||
#include "src/Core/CwiseBinaryOp.h"
|
||||
#include "src/Core/CwiseUnaryOp.h"
|
||||
@@ -342,6 +367,7 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/SkewSymmetricMatrix3.h"
|
||||
#include "src/Core/Redux.h"
|
||||
#include "src/Core/Visitor.h"
|
||||
#include "src/Core/FindCoeff.h"
|
||||
#include "src/Core/Fuzzy.h"
|
||||
#include "src/Core/Swap.h"
|
||||
#include "src/Core/CommaInitializer.h"
|
||||
@@ -380,6 +406,8 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/arch/AltiVec/MatrixProduct.h"
|
||||
#elif defined EIGEN_VECTORIZE_NEON
|
||||
#include "src/Core/arch/NEON/GeneralBlockPanelKernel.h"
|
||||
#elif defined EIGEN_VECTORIZE_LSX
|
||||
#include "src/Core/arch/LSX/GeneralBlockPanelKernel.h"
|
||||
#endif
|
||||
|
||||
#if defined(EIGEN_VECTORIZE_AVX512)
|
||||
|
||||
+4
-6
@@ -22,13 +22,11 @@
|
||||
* - fixed-size homogeneous transformations
|
||||
* - translation, scaling, 2D and 3D rotations
|
||||
* - \link Quaternion quaternions \endlink
|
||||
* - cross products (\ref MatrixBase::cross, \ref MatrixBase::cross3)
|
||||
* - orthogonal vector generation (\ref MatrixBase::unitOrthogonal)
|
||||
* - some linear components: \link ParametrizedLine parametrized-lines \endlink and \link Hyperplane hyperplanes
|
||||
* \endlink
|
||||
* - cross products (\ref MatrixBase::cross(), \ref MatrixBase::cross3())
|
||||
* - orthogonal vector generation (MatrixBase::unitOrthogonal)
|
||||
* - some linear components: \link ParametrizedLine parametrized-lines \endlink and \link Hyperplane hyperplanes \endlink
|
||||
* - \link AlignedBox axis aligned bounding boxes \endlink
|
||||
* - \link umeyama least-square transformation fitting \endlink
|
||||
*
|
||||
* - \link umeyama() least-square transformation fitting \endlink
|
||||
* \code
|
||||
* #include <Eigen/Geometry>
|
||||
* \endcode
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#include "src/ThreadPool/Barrier.h"
|
||||
#include "src/ThreadPool/NonBlockingThreadPool.h"
|
||||
#include "src/ThreadPool/CoreThreadPoolDevice.h"
|
||||
#include "src/ThreadPool/ForkJoin.h"
|
||||
// IWYU pragma: end_exports
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef EIGEN_VERSION_H
|
||||
#define EIGEN_VERSION_H
|
||||
|
||||
// The "WORLD" version will forever remain "3" for the "Eigen3" library.
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
// As of Eigen3 5.0.0, we have moved to Semantic Versioning (semver.org).
|
||||
#define EIGEN_MAJOR_VERSION 5
|
||||
#define EIGEN_MINOR_VERSION 0
|
||||
#define EIGEN_PATCH_VERSION 0
|
||||
#define EIGEN_PRERELEASE_VERSION ""
|
||||
#define EIGEN_BUILD_VERSION ""
|
||||
#define EIGEN_VERSION_STRING "5.0.0"
|
||||
|
||||
#endif // EIGEN_VERSION_H
|
||||
@@ -11,7 +11,7 @@ template <typename MatrixType_, int UpLo_, SparseFactorization_t Solver_, bool E
|
||||
class AccelerateImpl;
|
||||
|
||||
/** \ingroup AccelerateSupport_Module
|
||||
* \class AccelerateLLT
|
||||
* \typedef AccelerateLLT
|
||||
* \brief A direct Cholesky (LLT) factorization and solver based on Accelerate
|
||||
*
|
||||
* \warning Only single and double precision real scalar types are supported by Accelerate
|
||||
@@ -25,7 +25,7 @@ template <typename MatrixType, int UpLo = Lower>
|
||||
using AccelerateLLT = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationCholesky, true>;
|
||||
|
||||
/** \ingroup AccelerateSupport_Module
|
||||
* \class AccelerateLDLT
|
||||
* \typedef AccelerateLDLT
|
||||
* \brief The default Cholesky (LDLT) factorization and solver based on Accelerate
|
||||
*
|
||||
* \warning Only single and double precision real scalar types are supported by Accelerate
|
||||
@@ -39,7 +39,7 @@ template <typename MatrixType, int UpLo = Lower>
|
||||
using AccelerateLDLT = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLT, true>;
|
||||
|
||||
/** \ingroup AccelerateSupport_Module
|
||||
* \class AccelerateLDLTUnpivoted
|
||||
* \typedef AccelerateLDLTUnpivoted
|
||||
* \brief A direct Cholesky-like LDL^T factorization and solver based on Accelerate with only 1x1 pivots and no pivoting
|
||||
*
|
||||
* \warning Only single and double precision real scalar types are supported by Accelerate
|
||||
@@ -53,7 +53,7 @@ template <typename MatrixType, int UpLo = Lower>
|
||||
using AccelerateLDLTUnpivoted = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTUnpivoted, true>;
|
||||
|
||||
/** \ingroup AccelerateSupport_Module
|
||||
* \class AccelerateLDLTSBK
|
||||
* \typedef AccelerateLDLTSBK
|
||||
* \brief A direct Cholesky (LDLT) factorization and solver based on Accelerate with Supernode Bunch-Kaufman and static
|
||||
* pivoting
|
||||
*
|
||||
@@ -68,7 +68,7 @@ template <typename MatrixType, int UpLo = Lower>
|
||||
using AccelerateLDLTSBK = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTSBK, true>;
|
||||
|
||||
/** \ingroup AccelerateSupport_Module
|
||||
* \class AccelerateLDLTTPP
|
||||
* \typedef AccelerateLDLTTPP
|
||||
* \brief A direct Cholesky (LDLT) factorization and solver based on Accelerate with full threshold partial pivoting
|
||||
*
|
||||
* \warning Only single and double precision real scalar types are supported by Accelerate
|
||||
@@ -82,7 +82,7 @@ template <typename MatrixType, int UpLo = Lower>
|
||||
using AccelerateLDLTTPP = AccelerateImpl<MatrixType, UpLo | Symmetric, SparseFactorizationLDLTTPP, true>;
|
||||
|
||||
/** \ingroup AccelerateSupport_Module
|
||||
* \class AccelerateQR
|
||||
* \typedef AccelerateQR
|
||||
* \brief A QR factorization and solver based on Accelerate
|
||||
*
|
||||
* \warning Only single and double precision real scalar types are supported by Accelerate
|
||||
@@ -95,7 +95,7 @@ template <typename MatrixType>
|
||||
using AccelerateQR = AccelerateImpl<MatrixType, 0, SparseFactorizationQR, false>;
|
||||
|
||||
/** \ingroup AccelerateSupport_Module
|
||||
* \class AccelerateCholeskyAtA
|
||||
* \typedef AccelerateCholeskyAtA
|
||||
* \brief A QR factorization and solver based on Accelerate without storing Q (equivalent to A^TA = R^T R)
|
||||
*
|
||||
* \warning Only single and double precision real scalar types are supported by Accelerate
|
||||
|
||||
@@ -230,8 +230,8 @@ class LDLT : public SolverBase<LDLT<MatrixType_, UpLo_> > {
|
||||
*/
|
||||
const LDLT& adjoint() const { return *this; }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); }
|
||||
|
||||
/** \brief Reports whether previous computation was successful.
|
||||
*
|
||||
|
||||
@@ -182,10 +182,10 @@ class LLT : public SolverBase<LLT<MatrixType_, UpLo_> > {
|
||||
* This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as:
|
||||
* \code x = decomposition.adjoint().solve(b) \endcode
|
||||
*/
|
||||
const LLT& adjoint() const EIGEN_NOEXCEPT { return *this; }
|
||||
const LLT& adjoint() const noexcept { return *this; }
|
||||
|
||||
inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
constexpr Index rows() const noexcept { return m_matrix.rows(); }
|
||||
constexpr Index cols() const noexcept { return m_matrix.cols(); }
|
||||
|
||||
template <typename VectorType>
|
||||
LLT& rankUpdate(const VectorType& vec, const RealScalar& sigma = 1);
|
||||
|
||||
+26
-17
@@ -102,8 +102,13 @@ class Array : public PlainObjectBase<Array<Scalar_, Rows_, Cols_, Options_, MaxR
|
||||
return Base::_set(other);
|
||||
}
|
||||
|
||||
/** This is a special case of the templated operator=. Its purpose is to
|
||||
* prevent a default operator= from hiding the templated operator=.
|
||||
/**
|
||||
* \brief Assigns arrays to each other.
|
||||
*
|
||||
* \note This is a special case of the templated operator=. Its purpose is
|
||||
* to prevent a default operator= from hiding the templated operator=.
|
||||
*
|
||||
* \callgraph
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array& operator=(const Array& other) { return Base::_set(other); }
|
||||
|
||||
@@ -117,23 +122,27 @@ class Array : public PlainObjectBase<Array<Scalar_, Rows_, Cols_, Options_, MaxR
|
||||
*
|
||||
* \sa resize(Index,Index)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array() : Base() { EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED }
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
// FIXME is it still needed ??
|
||||
/** \internal */
|
||||
EIGEN_DEVICE_FUNC Array(internal::constructor_without_unaligned_array_assert)
|
||||
: Base(internal::constructor_without_unaligned_array_assert()){EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED}
|
||||
#ifdef EIGEN_INITIALIZE_COEFFS
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Array() : Base() { EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED }
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Array() = default;
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Array(Array && other) = default;
|
||||
EIGEN_DEVICE_FUNC Array& operator=(Array&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable<Scalar>::value) {
|
||||
/** \brief Move constructor */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Array(Array&&) = default;
|
||||
EIGEN_DEVICE_FUNC Array& operator=(Array&& other) noexcept(std::is_nothrow_move_assignable<Scalar>::value) {
|
||||
Base::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \copydoc PlainObjectBase(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const
|
||||
* ArgTypes&... args)
|
||||
/** \brief Construct a row of column vector with fixed size from an arbitrary number of coefficients.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* This constructor is for 1D array or vectors with more than 4 coefficients.
|
||||
*
|
||||
* \warning To construct a column (resp. row) vector of fixed length, the number of values passed to this
|
||||
* constructor must match the the fixed number of rows (resp. columns) of \c *this.
|
||||
*
|
||||
*
|
||||
* Example: \include Array_variadic_ctor_cxx11.cpp
|
||||
* Output: \verbinclude Array_variadic_ctor_cxx11.out
|
||||
@@ -230,7 +239,7 @@ class Array : public PlainObjectBase<Array<Scalar_, Rows_, Cols_, Options_, MaxR
|
||||
}
|
||||
|
||||
/** Copy constructor */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Array(const Array& other) = default;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Array(const Array&) = default;
|
||||
|
||||
private:
|
||||
struct PrivateType {};
|
||||
@@ -244,8 +253,8 @@ class Array : public PlainObjectBase<Array<Scalar_, Rows_, Cols_, Options_, MaxR
|
||||
PrivateType())
|
||||
: Base(other.derived()) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT { return 1; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { return this->innerSize(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return 1; }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return this->innerSize(); }
|
||||
|
||||
#ifdef EIGEN_ARRAY_PLUGIN
|
||||
#include EIGEN_ARRAY_PLUGIN
|
||||
|
||||
+46
-55
@@ -81,9 +81,6 @@ class ArrayBase : public DenseBase<Derived> {
|
||||
|
||||
typedef typename Base::CoeffReturnType CoeffReturnType;
|
||||
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
typedef typename Base::PlainObject PlainObject;
|
||||
|
||||
/** \internal Represents a matrix with all coefficients equal to one another*/
|
||||
@@ -118,19 +115,57 @@ class ArrayBase : public DenseBase<Derived> {
|
||||
return derived();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const Scalar& scalar);
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const Scalar& scalar);
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::add_assign_op<Scalar, Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const ArrayBase<OtherDerived>& other);
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const ArrayBase<OtherDerived>& other);
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::sub_assign_op<Scalar, Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** replaces \c *this by \c *this + \a other.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const ArrayBase<OtherDerived>& other);
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** replaces \c *this by \c *this - \a other.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const ArrayBase<OtherDerived>& other);
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** replaces \c *this by \c *this * \a other coefficient wise.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::mul_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** replaces \c *this by \c *this / \a other coefficient wise.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::div_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
public:
|
||||
EIGEN_DEVICE_FUNC ArrayBase<Derived>& array() { return *this; }
|
||||
@@ -173,50 +208,6 @@ class ArrayBase : public DenseBase<Derived> {
|
||||
}
|
||||
};
|
||||
|
||||
/** replaces \c *this by \c *this - \a other.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator-=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** replaces \c *this by \c *this + \a other.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator+=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** replaces \c *this by \c *this * \a other coefficient wise.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator*=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::mul_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** replaces \c *this by \c *this / \a other coefficient wise.
|
||||
*
|
||||
* \returns a reference to \c *this
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator/=(const ArrayBase<OtherDerived>& other) {
|
||||
call_assignment(derived(), other.derived(), internal::div_assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ARRAYBASE_H
|
||||
|
||||
@@ -56,14 +56,10 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> > {
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT {
|
||||
return m_expression.outerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT {
|
||||
return m_expression.innerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_expression.innerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC constexpr ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
||||
EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_expression.data(); }
|
||||
@@ -135,14 +131,10 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> > {
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT {
|
||||
return m_expression.outerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT {
|
||||
return m_expression.innerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_expression.innerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC constexpr ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
||||
EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_expression.data(); }
|
||||
|
||||
+423
-317
File diff suppressed because it is too large
Load Diff
@@ -89,7 +89,7 @@ class vml_assign_traits {
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const assign_op<EIGENTYPE, EIGENTYPE> &func) { \
|
||||
resize_if_allowed(dst, src, func); \
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \
|
||||
if (vml_assign_traits<DstXprType, SrcXprNested>::Traversal == LinearTraversal) { \
|
||||
if (vml_assign_traits<DstXprType, SrcXprNested>::Traversal == (int)LinearTraversal) { \
|
||||
VMLOP(dst.size(), (const VMLTYPE *)src.nestedExpression().data(), \
|
||||
(VMLTYPE *)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE)); \
|
||||
} else { \
|
||||
|
||||
@@ -200,16 +200,16 @@ class BandMatrix : public BandMatrixBase<BandMatrix<Scalar_, Rows, Cols, Supers,
|
||||
: m_coeffs(1 + supers + subs, cols), m_rows(rows), m_supers(supers), m_subs(subs) {}
|
||||
|
||||
/** \returns the number of columns */
|
||||
inline EIGEN_CONSTEXPR Index rows() const { return m_rows.value(); }
|
||||
constexpr Index rows() const { return m_rows.value(); }
|
||||
|
||||
/** \returns the number of rows */
|
||||
inline EIGEN_CONSTEXPR Index cols() const { return m_coeffs.cols(); }
|
||||
constexpr Index cols() const { return m_coeffs.cols(); }
|
||||
|
||||
/** \returns the number of super diagonals */
|
||||
inline EIGEN_CONSTEXPR Index supers() const { return m_supers.value(); }
|
||||
constexpr Index supers() const { return m_supers.value(); }
|
||||
|
||||
/** \returns the number of sub diagonals */
|
||||
inline EIGEN_CONSTEXPR Index subs() const { return m_subs.value(); }
|
||||
constexpr Index subs() const { return m_subs.value(); }
|
||||
|
||||
inline const CoefficientsType& coeffs() const { return m_coeffs; }
|
||||
inline CoefficientsType& coeffs() { return m_coeffs; }
|
||||
@@ -260,16 +260,16 @@ class BandMatrixWrapper
|
||||
}
|
||||
|
||||
/** \returns the number of columns */
|
||||
inline EIGEN_CONSTEXPR Index rows() const { return m_rows.value(); }
|
||||
constexpr Index rows() const { return m_rows.value(); }
|
||||
|
||||
/** \returns the number of rows */
|
||||
inline EIGEN_CONSTEXPR Index cols() const { return m_coeffs.cols(); }
|
||||
constexpr Index cols() const { return m_coeffs.cols(); }
|
||||
|
||||
/** \returns the number of super diagonals */
|
||||
inline EIGEN_CONSTEXPR Index supers() const { return m_supers.value(); }
|
||||
constexpr Index supers() const { return m_supers.value(); }
|
||||
|
||||
/** \returns the number of sub diagonals */
|
||||
inline EIGEN_CONSTEXPR Index subs() const { return m_subs.value(); }
|
||||
constexpr Index subs() const { return m_subs.value(); }
|
||||
|
||||
inline const CoefficientsType& coeffs() const { return m_coeffs; }
|
||||
|
||||
|
||||
+8
-18
@@ -289,13 +289,9 @@ class BlockImpl_dense : public internal::dense_xpr_base<Block<XprType, BlockRows
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE XprType& nestedExpression() { return m_xpr; }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR StorageIndex startRow() const EIGEN_NOEXCEPT {
|
||||
return m_startRow.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR StorageIndex startCol() const EIGEN_NOEXCEPT {
|
||||
return m_startCol.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startCol() const noexcept { return m_startCol.value(); }
|
||||
|
||||
protected:
|
||||
XprTypeNested m_xpr;
|
||||
@@ -319,8 +315,7 @@ class BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel, true>
|
||||
* Adding an offset to nullptr is undefined behavior, so we must avoid it.
|
||||
*/
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE static Scalar* add_to_nullable_pointer(Scalar* base,
|
||||
Index offset) {
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE static Scalar* add_to_nullable_pointer(Scalar* base, Index offset) {
|
||||
return base != nullptr ? base + offset : nullptr;
|
||||
}
|
||||
|
||||
@@ -378,30 +373,25 @@ class BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel, true>
|
||||
init();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t<XprTypeNested>& nestedExpression() const
|
||||
EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t<XprTypeNested>& nestedExpression() const noexcept {
|
||||
return m_xpr;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE XprType& nestedExpression() { return m_xpr; }
|
||||
|
||||
/** \sa MapBase::innerStride() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index innerStride() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index innerStride() const noexcept {
|
||||
return internal::traits<BlockType>::HasSameStorageOrderAsXprType ? m_xpr.innerStride() : m_xpr.outerStride();
|
||||
}
|
||||
|
||||
/** \sa MapBase::outerStride() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index outerStride() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index outerStride() const noexcept {
|
||||
return internal::traits<BlockType>::HasSameStorageOrderAsXprType ? m_xpr.outerStride() : m_xpr.innerStride();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR StorageIndex startRow() const EIGEN_NOEXCEPT {
|
||||
return m_startRow.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR StorageIndex startCol() const EIGEN_NOEXCEPT {
|
||||
return m_startCol.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr StorageIndex startCol() const noexcept { return m_startCol.value(); }
|
||||
|
||||
#ifndef __SUNPRO_CC
|
||||
// FIXME sunstudio is not friendly with the above friend...
|
||||
|
||||
@@ -92,7 +92,7 @@ struct CommaInitializer {
|
||||
|
||||
EIGEN_DEVICE_FUNC inline ~CommaInitializer()
|
||||
#if defined VERIFY_RAISES_ASSERT && (!defined EIGEN_NO_ASSERTION_CHECKING) && defined EIGEN_EXCEPTIONS
|
||||
EIGEN_EXCEPTION_SPEC(Eigen::eigen_assert_exception)
|
||||
noexcept(false) // Eigen::eigen_assert_exception
|
||||
#endif
|
||||
{
|
||||
finished();
|
||||
|
||||
+562
-229
File diff suppressed because it is too large
Load Diff
@@ -108,12 +108,12 @@ class CwiseBinaryOp : public CwiseBinaryOpImpl<BinaryOp, LhsType, RhsType,
|
||||
eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols());
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const noexcept {
|
||||
// return the fixed size type if available to enable compile time optimizations
|
||||
return internal::traits<internal::remove_all_t<LhsNested>>::RowsAtCompileTime == Dynamic ? m_rhs.rows()
|
||||
: m_lhs.rows();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const noexcept {
|
||||
// return the fixed size type if available to enable compile time optimizations
|
||||
return internal::traits<internal::remove_all_t<LhsNested>>::ColsAtCompileTime == Dynamic ? m_rhs.cols()
|
||||
: m_lhs.cols();
|
||||
|
||||
@@ -71,9 +71,13 @@ class CwiseNullaryOp : public internal::dense_xpr_base<CwiseNullaryOp<NullaryOp,
|
||||
eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && cols >= 0 &&
|
||||
(ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC CwiseNullaryOp(Index size, const NullaryOp& func = NullaryOp())
|
||||
: CwiseNullaryOp(RowsAtCompileTime == 1 ? 1 : size, RowsAtCompileTime == 1 ? size : 1, func) {
|
||||
EIGEN_STATIC_ASSERT(CwiseNullaryOp::IsVectorAtCompileTime, YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const { return m_rows.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const { return m_cols.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const { return m_rows.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const { return m_cols.value(); }
|
||||
|
||||
/** \returns the functor representing the nullary operation */
|
||||
EIGEN_DEVICE_FUNC const NullaryOp& functor() const { return m_functor; }
|
||||
@@ -231,8 +235,7 @@ DenseBase<Derived>::Constant(const Scalar& value) {
|
||||
* \sa LinSpaced(Index,const Scalar&, const Scalar&), setLinSpaced(Index,const Scalar&,const Scalar&)
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<
|
||||
Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high) {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar>(low, high, size));
|
||||
@@ -243,8 +246,7 @@ DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const
|
||||
* \sa LinSpaced(const Scalar&, const Scalar&)
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<
|
||||
Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high) {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
@@ -283,7 +285,7 @@ DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high)
|
||||
}
|
||||
|
||||
/**
|
||||
* \copydoc DenseBase::LinSpaced(Index, const Scalar&, const Scalar&)
|
||||
* \copydoc DenseBase::LinSpaced(Index, const DenseBase::Scalar&, const DenseBase::Scalar&)
|
||||
* Special version for fixed size types which does not require the size parameter.
|
||||
*/
|
||||
template <typename Derived>
|
||||
@@ -343,7 +345,8 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& val) {
|
||||
return derived() = Constant(rows(), cols(), val);
|
||||
internal::eigen_fill_impl<Derived>::run(derived(), val);
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** Resizes to the given \a size, and sets all coefficients in this expression to the given value \a val.
|
||||
@@ -479,9 +482,9 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setEqualSpace
|
||||
* \sa Zero(), Zero(Index)
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType DenseBase<Derived>::Zero(
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ZeroReturnType DenseBase<Derived>::Zero(
|
||||
Index rows, Index cols) {
|
||||
return Constant(rows, cols, Scalar(0));
|
||||
return ZeroReturnType(rows, cols);
|
||||
}
|
||||
|
||||
/** \returns an expression of a zero vector.
|
||||
@@ -501,9 +504,9 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::Constan
|
||||
* \sa Zero(), Zero(Index,Index)
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType DenseBase<Derived>::Zero(
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ZeroReturnType DenseBase<Derived>::Zero(
|
||||
Index size) {
|
||||
return Constant(size, Scalar(0));
|
||||
return ZeroReturnType(size);
|
||||
}
|
||||
|
||||
/** \returns an expression of a fixed-size zero matrix or vector.
|
||||
@@ -517,8 +520,8 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::Constan
|
||||
* \sa Zero(Index), Zero(Index,Index)
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType DenseBase<Derived>::Zero() {
|
||||
return Constant(Scalar(0));
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ZeroReturnType DenseBase<Derived>::Zero() {
|
||||
return ZeroReturnType(RowsAtCompileTime, ColsAtCompileTime);
|
||||
}
|
||||
|
||||
/** \returns true if *this is approximately equal to the zero matrix,
|
||||
@@ -547,7 +550,8 @@ EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isZero(const RealScalar& prec) const
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero() {
|
||||
return setConstant(Scalar(0));
|
||||
internal::eigen_zero_impl<Derived>::run(derived());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** Resizes to the given \a size, and sets all coefficients in this expression to zero.
|
||||
@@ -562,7 +566,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero() {
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase<Derived>::setZero(Index newSize) {
|
||||
resize(newSize);
|
||||
return setConstant(Scalar(0));
|
||||
return setZero();
|
||||
}
|
||||
|
||||
/** Resizes to the given size, and sets all coefficients in this expression to zero.
|
||||
@@ -578,7 +582,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase<Derived>::setZero
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase<Derived>::setZero(Index rows, Index cols) {
|
||||
resize(rows, cols);
|
||||
return setConstant(Scalar(0));
|
||||
return setZero();
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of columns, and sets all
|
||||
|
||||
@@ -60,8 +60,8 @@ class CwiseUnaryOp : public CwiseUnaryOpImpl<UnaryOp, XprType, typename internal
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit CwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp())
|
||||
: m_xpr(xpr), m_functor(func) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const noexcept { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const noexcept { return m_xpr.cols(); }
|
||||
|
||||
/** \returns the functor representing the unary operation */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const UnaryOp& functor() const { return m_functor; }
|
||||
|
||||
@@ -66,13 +66,13 @@ class CwiseUnaryViewImpl<ViewOp, MatrixType, StrideType, Dense, false>
|
||||
|
||||
EIGEN_DEVICE_FUNC inline const Scalar* data() const { return &(this->coeffRef(0)); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const {
|
||||
return StrideType::InnerStrideAtCompileTime != 0 ? int(StrideType::InnerStrideAtCompileTime)
|
||||
: derived().nestedExpression().innerStride() *
|
||||
sizeof(typename traits<MatrixType>::Scalar) / sizeof(Scalar);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const {
|
||||
return StrideType::OuterStrideAtCompileTime != 0 ? int(StrideType::OuterStrideAtCompileTime)
|
||||
: derived().nestedExpression().outerStride() *
|
||||
sizeof(typename traits<MatrixType>::Scalar) / sizeof(Scalar);
|
||||
@@ -145,8 +145,8 @@ class CwiseUnaryView : public internal::CwiseUnaryViewImpl<ViewOp, MatrixType, S
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryView)
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const noexcept { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const noexcept { return m_matrix.cols(); }
|
||||
|
||||
/** \returns the functor representing unary operation */
|
||||
EIGEN_DEVICE_FUNC const ViewOp& functor() const { return m_functor; }
|
||||
|
||||
+37
-11
@@ -208,7 +208,7 @@ class DenseBase
|
||||
* \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension
|
||||
* with respect to the \ref TopicStorageOrders "storage order", i.e., the number of columns for a
|
||||
* column-major matrix, and the number of rows for a row-major matrix. */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index outerSize() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerSize() const {
|
||||
return IsVectorAtCompileTime ? 1 : int(IsRowMajor) ? this->rows() : this->cols();
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ class DenseBase
|
||||
* \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension
|
||||
* with respect to the \ref TopicStorageOrders "storage order", i.e., the number of rows for a
|
||||
* column-major matrix, and the number of columns for a row-major matrix. */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index innerSize() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerSize() const {
|
||||
return IsVectorAtCompileTime ? this->size() : int(IsRowMajor) ? this->cols() : this->rows();
|
||||
}
|
||||
|
||||
@@ -243,6 +243,8 @@ class DenseBase
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal Represents a matrix with all coefficients equal to one another*/
|
||||
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>, PlainObject> ConstantReturnType;
|
||||
/** \internal Represents a matrix with all coefficients equal to zero*/
|
||||
typedef CwiseNullaryOp<internal::scalar_zero_op<Scalar>, PlainObject> ZeroReturnType;
|
||||
/** \internal \deprecated Represents a vector with linearly spaced coefficients that allows sequential access only. */
|
||||
EIGEN_DEPRECATED typedef CwiseNullaryOp<internal::linspaced_op<Scalar>, PlainObject> SequentialLinSpacedReturnType;
|
||||
/** \internal Represents a vector with linearly spaced coefficients that allows random access. */
|
||||
@@ -304,12 +306,12 @@ class DenseBase
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Constant(Index size, const Scalar& value);
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Constant(const Scalar& value);
|
||||
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, Index size,
|
||||
const Scalar& low,
|
||||
const Scalar& high);
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t,
|
||||
const Scalar& low,
|
||||
const Scalar& high);
|
||||
EIGEN_DEPRECATED_WITH_REASON("The method may result in accuracy loss. Use .EqualSpaced() instead.")
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, Index size, const Scalar& low,
|
||||
const Scalar& high);
|
||||
EIGEN_DEPRECATED_WITH_REASON("The method may result in accuracy loss. Use .EqualSpaced() instead.")
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, const Scalar& low,
|
||||
const Scalar& high);
|
||||
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Index size, const Scalar& low,
|
||||
const Scalar& high);
|
||||
@@ -328,9 +330,9 @@ class DenseBase
|
||||
template <typename CustomNullaryOp>
|
||||
EIGEN_DEVICE_FUNC static const CwiseNullaryOp<CustomNullaryOp, PlainObject> NullaryExpr(const CustomNullaryOp& func);
|
||||
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Zero(Index rows, Index cols);
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Zero(Index size);
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Zero();
|
||||
EIGEN_DEVICE_FUNC static const ZeroReturnType Zero(Index rows, Index cols);
|
||||
EIGEN_DEVICE_FUNC static const ZeroReturnType Zero(Index size);
|
||||
EIGEN_DEVICE_FUNC static const ZeroReturnType Zero();
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(Index rows, Index cols);
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(Index size);
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Ones();
|
||||
@@ -365,7 +367,12 @@ class DenseBase
|
||||
EIGEN_DEVICE_FUNC inline bool allFinite() const;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const Scalar& other);
|
||||
template <bool Enable = !internal::is_same<Scalar, RealScalar>::value, typename = std::enable_if_t<Enable>>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const RealScalar& other);
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const Scalar& other);
|
||||
template <bool Enable = !internal::is_same<Scalar, RealScalar>::value, typename = std::enable_if_t<Enable>>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const RealScalar& other);
|
||||
|
||||
typedef internal::add_const_on_value_type_t<typename internal::eval<Derived>::type> EvalReturnType;
|
||||
/** \returns the matrix or vector obtained by evaluating this expression.
|
||||
@@ -595,6 +602,13 @@ class DenseBase
|
||||
inline const_iterator end() const;
|
||||
inline const_iterator cend() const;
|
||||
|
||||
using RealViewReturnType = std::conditional_t<NumTraits<Scalar>::IsComplex, RealView<Derived>, Derived&>;
|
||||
using ConstRealViewReturnType =
|
||||
std::conditional_t<NumTraits<Scalar>::IsComplex, RealView<const Derived>, const Derived&>;
|
||||
|
||||
EIGEN_DEVICE_FUNC RealViewReturnType realView();
|
||||
EIGEN_DEVICE_FUNC ConstRealViewReturnType realView() const;
|
||||
|
||||
#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)
|
||||
@@ -642,6 +656,18 @@ class DenseBase
|
||||
EIGEN_DEVICE_FUNC explicit DenseBase(const DenseBase<OtherDerived>&);
|
||||
};
|
||||
|
||||
/** Free-function swap.
|
||||
*/
|
||||
template <typename DerivedA, typename DerivedB>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
// Use forwarding references to capture all combinations of cv-qualified l+r-value cases.
|
||||
std::enable_if_t<std::is_base_of<DenseBase<std::decay_t<DerivedA>>, std::decay_t<DerivedA>>::value &&
|
||||
std::is_base_of<DenseBase<std::decay_t<DerivedB>>, std::decay_t<DerivedB>>::value,
|
||||
void>
|
||||
swap(DerivedA&& a, DerivedB&& b) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_DENSEBASE_H
|
||||
|
||||
@@ -45,10 +45,16 @@ class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived> {
|
||||
// - This is the return type of the coeff() method.
|
||||
// - The LvalueBit means exactly that we can offer a coeffRef() method, which means exactly that we can get references
|
||||
// to coeffs, which means exactly that we can have coeff() return a const reference (as opposed to returning a value).
|
||||
// - The DirectAccessBit means exactly that the underlying data of coefficients can be directly accessed as a plain
|
||||
// strided array, which means exactly that the underlying data of coefficients does exist in memory, which means
|
||||
// exactly that the coefficients is const-referencable, which means exactly that we can have coeff() return a const
|
||||
// reference. For example, Map<const Matrix> have DirectAccessBit but not LvalueBit, so that Map<const Matrix>.coeff()
|
||||
// does points to a const Scalar& which exists in memory, while does not allow coeffRef() as it would not provide a
|
||||
// lvalue. Notice that DirectAccessBit and LvalueBit are mutually orthogonal.
|
||||
// - The is_arithmetic check is required since "const int", "const double", etc. will cause warnings on some systems
|
||||
// while the declaration of "const T", where T is a non arithmetic type does not. Always returning "const Scalar&" is
|
||||
// not possible, since the underlying expressions might not offer a valid address the reference could be referring to.
|
||||
typedef std::conditional_t<bool(internal::traits<Derived>::Flags& LvalueBit), const Scalar&,
|
||||
typedef std::conditional_t<bool(internal::traits<Derived>::Flags&(LvalueBit | DirectAccessBit)), const Scalar&,
|
||||
std::conditional_t<internal::is_arithmetic<Scalar>::value, Scalar, const Scalar>>
|
||||
CoeffReturnType;
|
||||
|
||||
@@ -89,13 +95,12 @@ class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived> {
|
||||
*
|
||||
* \sa operator()(Index,Index) const, coeffRef(Index,Index), coeff(Index) const
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType coeff(Index row, Index col) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType coeff(Index row, Index col) const {
|
||||
eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
|
||||
return internal::evaluator<Derived>(derived()).coeff(row, col);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType coeffByOuterInner(Index outer,
|
||||
Index inner) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType coeffByOuterInner(Index outer, Index inner) const {
|
||||
return coeff(rowIndexByOuterInner(outer, inner), colIndexByOuterInner(outer, inner));
|
||||
}
|
||||
|
||||
@@ -103,7 +108,7 @@ class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived> {
|
||||
*
|
||||
* \sa operator()(Index,Index), operator[](Index)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType operator()(Index row, Index col) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType operator()(Index row, Index col) const {
|
||||
eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
|
||||
return coeff(row, col);
|
||||
}
|
||||
@@ -123,7 +128,7 @@ class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived> {
|
||||
* \sa operator[](Index) const, coeffRef(Index), coeff(Index,Index) const
|
||||
*/
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType coeff(Index index) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType coeff(Index index) const {
|
||||
EIGEN_STATIC_ASSERT(internal::evaluator<Derived>::Flags & LinearAccessBit,
|
||||
THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS)
|
||||
eigen_internal_assert(index >= 0 && index < size());
|
||||
@@ -138,7 +143,7 @@ class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived> {
|
||||
* z() const, w() const
|
||||
*/
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType operator[](Index index) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType operator[](Index index) const {
|
||||
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
|
||||
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
|
||||
eigen_assert(index >= 0 && index < size());
|
||||
@@ -155,32 +160,32 @@ class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived> {
|
||||
* z() const, w() const
|
||||
*/
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType operator()(Index index) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType operator()(Index index) const {
|
||||
eigen_assert(index >= 0 && index < size());
|
||||
return coeff(index);
|
||||
}
|
||||
|
||||
/** equivalent to operator[](0). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType x() const { return (*this)[0]; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType x() const { return (*this)[0]; }
|
||||
|
||||
/** equivalent to operator[](1). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType y() const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType y() const {
|
||||
EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 2, OUT_OF_RANGE_ACCESS);
|
||||
return (*this)[1];
|
||||
}
|
||||
|
||||
/** equivalent to operator[](2). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType z() const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType z() const {
|
||||
EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 3, OUT_OF_RANGE_ACCESS);
|
||||
return (*this)[2];
|
||||
}
|
||||
|
||||
/** equivalent to operator[](3). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR CoeffReturnType w() const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType w() const {
|
||||
EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 4, OUT_OF_RANGE_ACCESS);
|
||||
return (*this)[3];
|
||||
}
|
||||
@@ -298,7 +303,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
||||
*
|
||||
* \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index row, Index col) {
|
||||
eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
|
||||
return internal::evaluator<Derived>(derived()).coeffRef(row, col);
|
||||
}
|
||||
@@ -312,7 +317,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
||||
* \sa operator[](Index)
|
||||
*/
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index row, Index col) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& operator()(Index row, Index col) {
|
||||
eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
|
||||
return coeffRef(row, col);
|
||||
}
|
||||
@@ -332,7 +337,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
||||
* \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index)
|
||||
*/
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index index) {
|
||||
EIGEN_STATIC_ASSERT(internal::evaluator<Derived>::Flags & LinearAccessBit,
|
||||
THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS)
|
||||
eigen_internal_assert(index >= 0 && index < size());
|
||||
@@ -346,7 +351,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
||||
* \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w()
|
||||
*/
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator[](Index index) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& operator[](Index index) {
|
||||
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
|
||||
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
|
||||
eigen_assert(index >= 0 && index < size());
|
||||
@@ -362,32 +367,32 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
||||
* \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w()
|
||||
*/
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Scalar& operator()(Index index) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& operator()(Index index) {
|
||||
eigen_assert(index >= 0 && index < size());
|
||||
return coeffRef(index);
|
||||
}
|
||||
|
||||
/** equivalent to operator[](0). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Scalar& x() { return (*this)[0]; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& x() { return (*this)[0]; }
|
||||
|
||||
/** equivalent to operator[](1). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Scalar& y() {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& y() {
|
||||
EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 2, OUT_OF_RANGE_ACCESS);
|
||||
return (*this)[1];
|
||||
}
|
||||
|
||||
/** equivalent to operator[](2). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Scalar& z() {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& z() {
|
||||
EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 3, OUT_OF_RANGE_ACCESS);
|
||||
return (*this)[2];
|
||||
}
|
||||
|
||||
/** equivalent to operator[](3). */
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Scalar& w() {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& w() {
|
||||
EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 4, OUT_OF_RANGE_ACCESS);
|
||||
return (*this)[3];
|
||||
}
|
||||
@@ -421,33 +426,29 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
|
||||
*
|
||||
* \sa outerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const { return derived().innerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const { return derived().innerStride(); }
|
||||
|
||||
/** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns
|
||||
* in a column-major matrix).
|
||||
*
|
||||
* \sa innerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const { return derived().outerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const { return derived().outerStride(); }
|
||||
|
||||
// FIXME shall we remove it ?
|
||||
EIGEN_CONSTEXPR inline Index stride() const { return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); }
|
||||
constexpr Index stride() const { return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); }
|
||||
|
||||
/** \returns the pointer increment between two consecutive rows.
|
||||
*
|
||||
* \sa innerStride(), outerStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rowStride() const {
|
||||
return Derived::IsRowMajor ? outerStride() : innerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rowStride() const { return Derived::IsRowMajor ? outerStride() : innerStride(); }
|
||||
|
||||
/** \returns the pointer increment between two consecutive columns.
|
||||
*
|
||||
* \sa innerStride(), outerStride(), rowStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index colStride() const {
|
||||
return Derived::IsRowMajor ? innerStride() : outerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index colStride() const { return Derived::IsRowMajor ? innerStride() : outerStride(); }
|
||||
};
|
||||
|
||||
/** \brief Base class providing direct read/write coefficient access to matrices and arrays.
|
||||
@@ -478,25 +479,23 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors> : public DenseCoeffsBase<De
|
||||
*
|
||||
* \sa outerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT { return derived().innerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return derived().innerStride(); }
|
||||
|
||||
/** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns
|
||||
* in a column-major matrix).
|
||||
*
|
||||
* \sa innerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { return derived().outerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return derived().outerStride(); }
|
||||
|
||||
// FIXME shall we remove it ?
|
||||
EIGEN_CONSTEXPR inline Index stride() const EIGEN_NOEXCEPT {
|
||||
return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
|
||||
}
|
||||
constexpr Index stride() const noexcept { return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); }
|
||||
|
||||
/** \returns the pointer increment between two consecutive rows.
|
||||
*
|
||||
* \sa innerStride(), outerStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rowStride() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC constexpr Index rowStride() const noexcept {
|
||||
return Derived::IsRowMajor ? outerStride() : innerStride();
|
||||
}
|
||||
|
||||
@@ -504,7 +503,7 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors> : public DenseCoeffsBase<De
|
||||
*
|
||||
* \sa innerStride(), outerStride(), rowStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index colStride() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC constexpr Index colStride() const noexcept {
|
||||
return Derived::IsRowMajor ? innerStride() : outerStride();
|
||||
}
|
||||
};
|
||||
@@ -513,7 +512,7 @@ namespace internal {
|
||||
|
||||
template <int Alignment, typename Derived, bool JustReturnZero>
|
||||
struct first_aligned_impl {
|
||||
static EIGEN_CONSTEXPR inline Index run(const Derived&) EIGEN_NOEXCEPT { return 0; }
|
||||
static constexpr Index run(const Derived&) noexcept { return 0; }
|
||||
};
|
||||
|
||||
template <int Alignment, typename Derived>
|
||||
|
||||
+496
-568
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,7 @@ struct AssignmentWithDevice<DstXprType, Product<Lhs, Rhs, Options>, Functor, Dev
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, const Functor& func,
|
||||
Device&) {
|
||||
Base::run(dst, src, func);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// specialization for coeffcient-wise assignment
|
||||
@@ -87,13 +87,13 @@ template <typename Kernel, typename Device, int Traversal = Kernel::AssignmentTr
|
||||
int Unrolling = Kernel::AssignmentTraits::Unrolling>
|
||||
struct dense_assignment_loop_with_device {
|
||||
using Base = dense_assignment_loop<Kernel, Traversal, Unrolling>;
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel& kernel, Device&) { Base::run(kernel); }
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel, Device&) { Base::run(kernel); }
|
||||
};
|
||||
|
||||
// entry point for a generic expression with device
|
||||
template <typename Dst, typename Src, typename Func, typename Device>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_assignment_no_alias(DeviceWrapper<Dst, Device> dst,
|
||||
const Src& src, const Func& func) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment_no_alias(DeviceWrapper<Dst, Device> dst,
|
||||
const Src& src, const Func& func) {
|
||||
enum {
|
||||
NeedToTranspose = ((int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1) ||
|
||||
(int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1)) &&
|
||||
@@ -115,10 +115,8 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_assignment_no_al
|
||||
|
||||
// copy and pasted from AssignEvaluator except forward device to kernel
|
||||
template <typename DstXprType, typename SrcXprType, typename Functor, typename Device>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_dense_assignment_loop(DstXprType& dst,
|
||||
const SrcXprType& src,
|
||||
const Functor& func,
|
||||
Device& device) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src,
|
||||
const Functor& func, Device& device) {
|
||||
using DstEvaluatorType = evaluator<DstXprType>;
|
||||
using SrcEvaluatorType = evaluator<SrcXprType>;
|
||||
|
||||
|
||||
@@ -83,13 +83,11 @@ class Diagonal : public internal::dense_xpr_base<Diagonal<MatrixType, DiagIndex_
|
||||
: numext::mini<Index>(m_matrix.rows(), m_matrix.cols() - m_index.value());
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return 1; }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return 1; }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT {
|
||||
return m_matrix.outerStride() + 1;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_matrix.outerStride() + 1; }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { return 0; }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return 0; }
|
||||
|
||||
typedef std::conditional_t<internal::is_lvalue<MatrixType>::value, Scalar, const Scalar> ScalarWithConstIfNotLvalue;
|
||||
|
||||
@@ -134,13 +132,13 @@ class Diagonal : public internal::dense_xpr_base<Diagonal<MatrixType, DiagIndex_
|
||||
|
||||
private:
|
||||
// some compilers may fail to optimize std::max etc in case of compile-time constants...
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index absDiagIndex() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index absDiagIndex() const noexcept {
|
||||
return m_index.value() > 0 ? m_index.value() : -m_index.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rowOffset() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rowOffset() const noexcept {
|
||||
return m_index.value() > 0 ? 0 : -m_index.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index colOffset() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index colOffset() const noexcept {
|
||||
return m_index.value() > 0 ? m_index.value() : 0;
|
||||
}
|
||||
// trigger a compile-time error if someone try to call packet
|
||||
|
||||
@@ -76,9 +76,9 @@ class DiagonalBase : public EigenBase<Derived> {
|
||||
}
|
||||
|
||||
/** \returns the number of rows. */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const { return diagonal().size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const { return diagonal().size(); }
|
||||
/** \returns the number of columns. */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const { return diagonal().size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const { return diagonal().size(); }
|
||||
|
||||
/** \returns the diagonal matrix product of \c *this by the dense matrix, \a matrix */
|
||||
template <typename MatrixDerived>
|
||||
@@ -256,10 +256,13 @@ class DiagonalMatrix : public DiagonalBase<DiagonalMatrix<Scalar_, SizeAtCompile
|
||||
typedef DiagonalWrapper<const CwiseNullaryOp<internal::scalar_constant_op<Scalar>, DiagonalVectorType>>
|
||||
InitializeReturnType;
|
||||
|
||||
typedef DiagonalWrapper<const CwiseNullaryOp<internal::scalar_zero_op<Scalar>, DiagonalVectorType>>
|
||||
ZeroInitializeReturnType;
|
||||
|
||||
/** Initializes a diagonal matrix of size SizeAtCompileTime with coefficients set to zero */
|
||||
EIGEN_DEVICE_FUNC static const InitializeReturnType Zero() { return DiagonalVectorType::Zero().asDiagonal(); }
|
||||
EIGEN_DEVICE_FUNC static const ZeroInitializeReturnType Zero() { return DiagonalVectorType::Zero().asDiagonal(); }
|
||||
/** Initializes a diagonal matrix of size dim with coefficients set to zero */
|
||||
EIGEN_DEVICE_FUNC static const InitializeReturnType Zero(Index size) {
|
||||
EIGEN_DEVICE_FUNC static const ZeroInitializeReturnType Zero(Index size) {
|
||||
return DiagonalVectorType::Zero(size).asDiagonal();
|
||||
}
|
||||
/** Initializes a identity matrix of size SizeAtCompileTime */
|
||||
@@ -386,8 +389,9 @@ struct AssignmentKind<DenseShape, DiagonalShape> {
|
||||
// Diagonal matrix to Dense assignment
|
||||
template <typename DstXprType, typename SrcXprType, typename Functor>
|
||||
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 EIGEN_DEVICE_FUNC 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);
|
||||
@@ -396,13 +400,15 @@ struct Assignment<DstXprType, SrcXprType, Functor, Diagonal2Dense> {
|
||||
dst.diagonal() = src.diagonal();
|
||||
}
|
||||
|
||||
static void run(DstXprType& dst, const SrcXprType& src,
|
||||
const internal::add_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /*func*/) {
|
||||
static EIGEN_DEVICE_FUNC void run(
|
||||
DstXprType& dst, const SrcXprType& src,
|
||||
const internal::add_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /*func*/) {
|
||||
dst.diagonal() += src.diagonal();
|
||||
}
|
||||
|
||||
static void run(DstXprType& dst, const SrcXprType& src,
|
||||
const internal::sub_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /*func*/) {
|
||||
static EIGEN_DEVICE_FUNC void run(
|
||||
DstXprType& dst, const SrcXprType& src,
|
||||
const internal::sub_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>& /*func*/) {
|
||||
dst.diagonal() -= src.diagonal();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,22 +46,22 @@ struct EigenBase {
|
||||
typedef typename internal::traits<Derived>::StorageKind StorageKind;
|
||||
|
||||
/** \returns a reference to the derived object */
|
||||
EIGEN_DEVICE_FUNC Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
EIGEN_DEVICE_FUNC constexpr Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
/** \returns a const reference to the derived object */
|
||||
EIGEN_DEVICE_FUNC const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
EIGEN_DEVICE_FUNC constexpr const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Derived& const_cast_derived() const {
|
||||
EIGEN_DEVICE_FUNC inline constexpr Derived& const_cast_derived() const {
|
||||
return *static_cast<Derived*>(const_cast<EigenBase*>(this));
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline const Derived& const_derived() const { return *static_cast<const Derived*>(this); }
|
||||
|
||||
/** \returns the number of rows. \sa cols(), RowsAtCompileTime */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return derived().rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return derived().rows(); }
|
||||
/** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return derived().cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return derived().cols(); }
|
||||
/** \returns the number of coefficients, which is rows()*cols().
|
||||
* \sa rows(), cols(), SizeAtCompileTime. */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index size() const EIGEN_NOEXCEPT { return rows() * cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return rows() * cols(); }
|
||||
|
||||
/** \internal Don't use it, but do the equivalent: \code dst = *this; \endcode */
|
||||
template <typename Dest>
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2024 Charles Schlosser <cs.schlosser@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_FILL_H
|
||||
#define EIGEN_FILL_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename Xpr>
|
||||
struct eigen_fill_helper : std::false_type {};
|
||||
|
||||
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
|
||||
struct eigen_fill_helper<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>> : std::true_type {};
|
||||
|
||||
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
|
||||
struct eigen_fill_helper<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>> : std::true_type {};
|
||||
|
||||
template <typename Xpr, int BlockRows, int BlockCols>
|
||||
struct eigen_fill_helper<Block<Xpr, BlockRows, BlockCols, /*InnerPanel*/ true>> : eigen_fill_helper<Xpr> {};
|
||||
|
||||
template <typename Xpr, int BlockRows, int BlockCols>
|
||||
struct eigen_fill_helper<Block<Xpr, BlockRows, BlockCols, /*InnerPanel*/ false>>
|
||||
: std::integral_constant<bool, eigen_fill_helper<Xpr>::value &&
|
||||
(Xpr::IsRowMajor ? (BlockRows == 1) : (BlockCols == 1))> {};
|
||||
|
||||
template <typename Xpr, int Options>
|
||||
struct eigen_fill_helper<Map<Xpr, Options, Stride<0, 0>>> : eigen_fill_helper<Xpr> {};
|
||||
|
||||
template <typename Xpr, int Options, int OuterStride_>
|
||||
struct eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 0>>>
|
||||
: std::integral_constant<bool, eigen_fill_helper<Xpr>::value &&
|
||||
enum_eq_not_dynamic(OuterStride_, Xpr::InnerSizeAtCompileTime)> {};
|
||||
|
||||
template <typename Xpr, int Options, int OuterStride_>
|
||||
struct eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 1>>>
|
||||
: eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 0>>> {};
|
||||
|
||||
template <typename Xpr, int Options, int InnerStride_>
|
||||
struct eigen_fill_helper<Map<Xpr, Options, InnerStride<InnerStride_>>>
|
||||
: eigen_fill_helper<Map<Xpr, Options, Stride<0, InnerStride_>>> {};
|
||||
|
||||
template <typename Xpr, int Options, int OuterStride_>
|
||||
struct eigen_fill_helper<Map<Xpr, Options, OuterStride<OuterStride_>>>
|
||||
: eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 0>>> {};
|
||||
|
||||
template <typename Xpr>
|
||||
struct eigen_fill_impl<Xpr, /*use_fill*/ false> {
|
||||
using Scalar = typename Xpr::Scalar;
|
||||
using Func = scalar_constant_op<Scalar>;
|
||||
using PlainObject = typename Xpr::PlainObject;
|
||||
using Constant = typename PlainObject::ConstantReturnType;
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void run(Xpr& dst, const Scalar& val) {
|
||||
const Constant src(dst.rows(), dst.cols(), val);
|
||||
run(dst, src);
|
||||
}
|
||||
template <typename SrcXpr>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void run(Xpr& dst, const SrcXpr& src) {
|
||||
call_dense_assignment_loop(dst, src, assign_op<Scalar, Scalar>());
|
||||
}
|
||||
};
|
||||
|
||||
#if EIGEN_COMP_MSVC || defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
template <typename Xpr>
|
||||
struct eigen_fill_impl<Xpr, /*use_fill*/ true> : eigen_fill_impl<Xpr, /*use_fill*/ false> {};
|
||||
#else
|
||||
template <typename Xpr>
|
||||
struct eigen_fill_impl<Xpr, /*use_fill*/ true> {
|
||||
using Scalar = typename Xpr::Scalar;
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const Scalar& val) {
|
||||
const Scalar val_copy = val;
|
||||
using std::fill_n;
|
||||
fill_n(dst.data(), dst.size(), val_copy);
|
||||
}
|
||||
template <typename SrcXpr>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) {
|
||||
resize_if_allowed(dst, src, assign_op<Scalar, Scalar>());
|
||||
const Scalar& val = src.functor()();
|
||||
run(dst, val);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename Xpr>
|
||||
struct eigen_memset_helper {
|
||||
static constexpr bool value =
|
||||
std::is_trivially_copyable<typename Xpr::Scalar>::value && eigen_fill_helper<Xpr>::value;
|
||||
};
|
||||
|
||||
template <typename Xpr>
|
||||
struct eigen_zero_impl<Xpr, /*use_memset*/ false> {
|
||||
using Scalar = typename Xpr::Scalar;
|
||||
using PlainObject = typename Xpr::PlainObject;
|
||||
using Zero = typename PlainObject::ZeroReturnType;
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void run(Xpr& dst) {
|
||||
const Zero src(dst.rows(), dst.cols());
|
||||
run(dst, src);
|
||||
}
|
||||
template <typename SrcXpr>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void run(Xpr& dst, const SrcXpr& src) {
|
||||
call_dense_assignment_loop(dst, src, assign_op<Scalar, Scalar>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Xpr>
|
||||
struct eigen_zero_impl<Xpr, /*use_memset*/ true> {
|
||||
using Scalar = typename Xpr::Scalar;
|
||||
static constexpr size_t max_bytes = (std::numeric_limits<std::ptrdiff_t>::max)();
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst) {
|
||||
const size_t num_bytes = dst.size() * sizeof(Scalar);
|
||||
if (num_bytes == 0) return;
|
||||
void* dst_ptr = static_cast<void*>(dst.data());
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
if (num_bytes > max_bytes) throw_std_bad_alloc();
|
||||
eigen_assert((dst_ptr != nullptr) && "null pointer dereference error!");
|
||||
#endif
|
||||
EIGEN_USING_STD(memset);
|
||||
memset(dst_ptr, 0, num_bytes);
|
||||
}
|
||||
template <typename SrcXpr>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) {
|
||||
resize_if_allowed(dst, src, assign_op<Scalar, Scalar>());
|
||||
run(dst);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Eigen
|
||||
|
||||
#endif // EIGEN_FILL_H
|
||||
@@ -0,0 +1,464 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 Charlie Schlosser <cs.schlosser@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_FIND_COEFF_H
|
||||
#define EIGEN_FIND_COEFF_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename Scalar, int NaNPropagation, bool IsInteger = NumTraits<Scalar>::IsInteger>
|
||||
struct max_coeff_functor {
|
||||
EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const {
|
||||
return candidate > incumbent;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const {
|
||||
return pcmp_lt(incumbent, candidate);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const {
|
||||
return predux_max(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct max_coeff_functor<Scalar, PropagateNaN, false> {
|
||||
EIGEN_DEVICE_FUNC inline Scalar compareCoeff(const Scalar& incumbent, const Scalar& candidate) {
|
||||
return (candidate > incumbent) || ((candidate != candidate) && (incumbent == incumbent));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) {
|
||||
return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(incumbent));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const {
|
||||
return predux_max<PropagateNaN>(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct max_coeff_functor<Scalar, PropagateNumbers, false> {
|
||||
EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const {
|
||||
return (candidate > incumbent) || ((candidate == candidate) && (incumbent != incumbent));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const {
|
||||
return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(candidate));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const {
|
||||
return predux_max<PropagateNumbers>(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar, int NaNPropagation, bool IsInteger = NumTraits<Scalar>::IsInteger>
|
||||
struct min_coeff_functor {
|
||||
EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const {
|
||||
return candidate < incumbent;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const {
|
||||
return pcmp_lt(candidate, incumbent);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const {
|
||||
return predux_min(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct min_coeff_functor<Scalar, PropagateNaN, false> {
|
||||
EIGEN_DEVICE_FUNC inline Scalar compareCoeff(const Scalar& incumbent, const Scalar& candidate) {
|
||||
return (candidate < incumbent) || ((candidate != candidate) && (incumbent == incumbent));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) {
|
||||
return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(incumbent));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const {
|
||||
return predux_min<PropagateNaN>(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct min_coeff_functor<Scalar, PropagateNumbers, false> {
|
||||
EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const {
|
||||
return (candidate < incumbent) || ((candidate == candidate) && (incumbent != incumbent));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const {
|
||||
return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(candidate));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const {
|
||||
return predux_min<PropagateNumbers>(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct min_max_traits {
|
||||
static constexpr bool PacketAccess = packet_traits<Scalar>::Vectorizable;
|
||||
};
|
||||
template <typename Scalar, int NaNPropagation>
|
||||
struct functor_traits<max_coeff_functor<Scalar, NaNPropagation>> : min_max_traits<Scalar> {};
|
||||
template <typename Scalar, int NaNPropagation>
|
||||
struct functor_traits<min_coeff_functor<Scalar, NaNPropagation>> : min_max_traits<Scalar> {};
|
||||
|
||||
template <typename Evaluator, typename Func, bool Linear, bool Vectorize>
|
||||
struct find_coeff_loop;
|
||||
template <typename Evaluator, typename Func>
|
||||
struct find_coeff_loop<Evaluator, Func, /*Linear*/ false, /*Vectorize*/ false> {
|
||||
using Scalar = typename Evaluator::Scalar;
|
||||
static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& res, Index& outer, Index& inner) {
|
||||
Index outerSize = eval.outerSize();
|
||||
Index innerSize = eval.innerSize();
|
||||
|
||||
/* initialization performed in calling function */
|
||||
/* result = eval.coeff(0, 0); */
|
||||
/* outer = 0; */
|
||||
/* inner = 0; */
|
||||
|
||||
for (Index j = 0; j < outerSize; j++) {
|
||||
for (Index i = 0; i < innerSize; i++) {
|
||||
Scalar xprCoeff = eval.coeffByOuterInner(j, i);
|
||||
bool newRes = func.compareCoeff(res, xprCoeff);
|
||||
if (newRes) {
|
||||
outer = j;
|
||||
inner = i;
|
||||
res = xprCoeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
template <typename Evaluator, typename Func>
|
||||
struct find_coeff_loop<Evaluator, Func, /*Linear*/ true, /*Vectorize*/ false> {
|
||||
using Scalar = typename Evaluator::Scalar;
|
||||
static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& res, Index& index) {
|
||||
Index size = eval.size();
|
||||
|
||||
/* initialization performed in calling function */
|
||||
/* result = eval.coeff(0); */
|
||||
/* index = 0; */
|
||||
|
||||
for (Index k = 0; k < size; k++) {
|
||||
Scalar xprCoeff = eval.coeff(k);
|
||||
bool newRes = func.compareCoeff(res, xprCoeff);
|
||||
if (newRes) {
|
||||
index = k;
|
||||
res = xprCoeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
template <typename Evaluator, typename Func>
|
||||
struct find_coeff_loop<Evaluator, Func, /*Linear*/ false, /*Vectorize*/ true> {
|
||||
using ScalarImpl = find_coeff_loop<Evaluator, Func, false, false>;
|
||||
using Scalar = typename Evaluator::Scalar;
|
||||
using Packet = typename Evaluator::Packet;
|
||||
static constexpr int PacketSize = unpacket_traits<Packet>::size;
|
||||
static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& result, Index& outer,
|
||||
Index& inner) {
|
||||
Index outerSize = eval.outerSize();
|
||||
Index innerSize = eval.innerSize();
|
||||
Index packetEnd = numext::round_down(innerSize, PacketSize);
|
||||
|
||||
/* initialization performed in calling function */
|
||||
/* result = eval.coeff(0, 0); */
|
||||
/* outer = 0; */
|
||||
/* inner = 0; */
|
||||
|
||||
bool checkPacket = false;
|
||||
|
||||
for (Index j = 0; j < outerSize; j++) {
|
||||
Packet resultPacket = pset1<Packet>(result);
|
||||
for (Index i = 0; i < packetEnd; i += PacketSize) {
|
||||
Packet xprPacket = eval.template packetByOuterInner<Unaligned, Packet>(j, i);
|
||||
if (predux_any(func.comparePacket(resultPacket, xprPacket))) {
|
||||
outer = j;
|
||||
inner = i;
|
||||
result = func.predux(xprPacket);
|
||||
resultPacket = pset1<Packet>(result);
|
||||
checkPacket = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (Index i = packetEnd; i < innerSize; i++) {
|
||||
Scalar xprCoeff = eval.coeffByOuterInner(j, i);
|
||||
if (func.compareCoeff(result, xprCoeff)) {
|
||||
outer = j;
|
||||
inner = i;
|
||||
result = xprCoeff;
|
||||
checkPacket = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checkPacket) {
|
||||
result = eval.coeffByOuterInner(outer, inner);
|
||||
Index i_end = inner + PacketSize;
|
||||
for (Index i = inner; i < i_end; i++) {
|
||||
Scalar xprCoeff = eval.coeffByOuterInner(outer, i);
|
||||
if (func.compareCoeff(result, xprCoeff)) {
|
||||
inner = i;
|
||||
result = xprCoeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
template <typename Evaluator, typename Func>
|
||||
struct find_coeff_loop<Evaluator, Func, /*Linear*/ true, /*Vectorize*/ true> {
|
||||
using ScalarImpl = find_coeff_loop<Evaluator, Func, true, false>;
|
||||
using Scalar = typename Evaluator::Scalar;
|
||||
using Packet = typename Evaluator::Packet;
|
||||
static constexpr int PacketSize = unpacket_traits<Packet>::size;
|
||||
static constexpr int Alignment = Evaluator::Alignment;
|
||||
|
||||
static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& result, Index& index) {
|
||||
Index size = eval.size();
|
||||
Index packetEnd = numext::round_down(size, PacketSize);
|
||||
|
||||
/* initialization performed in calling function */
|
||||
/* result = eval.coeff(0); */
|
||||
/* index = 0; */
|
||||
|
||||
Packet resultPacket = pset1<Packet>(result);
|
||||
bool checkPacket = false;
|
||||
|
||||
for (Index k = 0; k < packetEnd; k += PacketSize) {
|
||||
Packet xprPacket = eval.template packet<Alignment, Packet>(k);
|
||||
if (predux_any(func.comparePacket(resultPacket, xprPacket))) {
|
||||
index = k;
|
||||
result = func.predux(xprPacket);
|
||||
resultPacket = pset1<Packet>(result);
|
||||
checkPacket = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (Index k = packetEnd; k < size; k++) {
|
||||
Scalar xprCoeff = eval.coeff(k);
|
||||
if (func.compareCoeff(result, xprCoeff)) {
|
||||
index = k;
|
||||
result = xprCoeff;
|
||||
checkPacket = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkPacket) {
|
||||
result = eval.coeff(index);
|
||||
Index k_end = index + PacketSize;
|
||||
for (Index k = index; k < k_end; k++) {
|
||||
Scalar xprCoeff = eval.coeff(k);
|
||||
if (func.compareCoeff(result, xprCoeff)) {
|
||||
index = k;
|
||||
result = xprCoeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
struct find_coeff_evaluator : public evaluator<Derived> {
|
||||
using Base = evaluator<Derived>;
|
||||
using Scalar = typename Derived::Scalar;
|
||||
using Packet = typename packet_traits<Scalar>::type;
|
||||
static constexpr int Flags = Base::Flags;
|
||||
static constexpr bool IsRowMajor = bool(Flags & RowMajorBit);
|
||||
EIGEN_DEVICE_FUNC inline find_coeff_evaluator(const Derived& xpr) : Base(xpr), m_xpr(xpr) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Scalar coeffByOuterInner(Index outer, Index inner) const {
|
||||
Index row = IsRowMajor ? outer : inner;
|
||||
Index col = IsRowMajor ? inner : outer;
|
||||
return Base::coeff(row, col);
|
||||
}
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC inline PacketType packetByOuterInner(Index outer, Index inner) const {
|
||||
Index row = IsRowMajor ? outer : inner;
|
||||
Index col = IsRowMajor ? inner : outer;
|
||||
return Base::template packet<LoadMode, PacketType>(row, col);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index innerSize() const { return m_xpr.innerSize(); }
|
||||
EIGEN_DEVICE_FUNC inline Index outerSize() const { return m_xpr.outerSize(); }
|
||||
EIGEN_DEVICE_FUNC inline Index size() const { return m_xpr.size(); }
|
||||
|
||||
const Derived& m_xpr;
|
||||
};
|
||||
|
||||
template <typename Derived, typename Func>
|
||||
struct find_coeff_impl {
|
||||
using Evaluator = find_coeff_evaluator<Derived>;
|
||||
static constexpr int Flags = Evaluator::Flags;
|
||||
static constexpr int Alignment = Evaluator::Alignment;
|
||||
static constexpr bool IsRowMajor = Derived::IsRowMajor;
|
||||
static constexpr int MaxInnerSizeAtCompileTime =
|
||||
IsRowMajor ? Derived::MaxColsAtCompileTime : Derived::MaxRowsAtCompileTime;
|
||||
static constexpr int MaxSizeAtCompileTime = Derived::MaxSizeAtCompileTime;
|
||||
|
||||
using Scalar = typename Derived::Scalar;
|
||||
using Packet = typename Evaluator::Packet;
|
||||
|
||||
static constexpr int PacketSize = unpacket_traits<Packet>::size;
|
||||
static constexpr bool Linearize = bool(Flags & LinearAccessBit);
|
||||
static constexpr bool DontVectorize =
|
||||
enum_lt_not_dynamic(Linearize ? MaxSizeAtCompileTime : MaxInnerSizeAtCompileTime, PacketSize);
|
||||
static constexpr bool Vectorize =
|
||||
!DontVectorize && bool(Flags & PacketAccessBit) && functor_traits<Func>::PacketAccess;
|
||||
|
||||
using Loop = find_coeff_loop<Evaluator, Func, Linearize, Vectorize>;
|
||||
|
||||
template <bool ForwardLinearAccess = Linearize, std::enable_if_t<!ForwardLinearAccess, bool> = true>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& outer,
|
||||
Index& inner) {
|
||||
Evaluator eval(xpr);
|
||||
Loop::run(eval, func, res, outer, inner);
|
||||
}
|
||||
template <bool ForwardLinearAccess = Linearize, std::enable_if_t<ForwardLinearAccess, bool> = true>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& outer,
|
||||
Index& inner) {
|
||||
// where possible, use the linear loop and back-calculate the outer and inner indices
|
||||
Index index = 0;
|
||||
run(xpr, func, res, index);
|
||||
outer = index / xpr.innerSize();
|
||||
inner = index % xpr.innerSize();
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& index) {
|
||||
Evaluator eval(xpr);
|
||||
Loop::run(eval, func, res, index);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived, typename IndexType, typename Func>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar findCoeff(const DenseBase<Derived>& mat, Func& func,
|
||||
IndexType* rowPtr, IndexType* colPtr) {
|
||||
eigen_assert(mat.rows() > 0 && mat.cols() > 0 && "you are using an empty matrix");
|
||||
using Scalar = typename DenseBase<Derived>::Scalar;
|
||||
using FindCoeffImpl = internal::find_coeff_impl<Derived, Func>;
|
||||
Index outer = 0;
|
||||
Index inner = 0;
|
||||
Scalar res = mat.coeff(0, 0);
|
||||
FindCoeffImpl::run(mat.derived(), func, res, outer, inner);
|
||||
*rowPtr = internal::convert_index<IndexType>(Derived::IsRowMajor ? outer : inner);
|
||||
if (colPtr) *colPtr = internal::convert_index<IndexType>(Derived::IsRowMajor ? inner : outer);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Derived, typename IndexType, typename Func>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar findCoeff(const DenseBase<Derived>& mat, Func& func,
|
||||
IndexType* indexPtr) {
|
||||
eigen_assert(mat.size() > 0 && "you are using an empty matrix");
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
using Scalar = typename DenseBase<Derived>::Scalar;
|
||||
using FindCoeffImpl = internal::find_coeff_impl<Derived, Func>;
|
||||
Index index = 0;
|
||||
Scalar res = mat.coeff(0);
|
||||
FindCoeffImpl::run(mat.derived(), func, res, index);
|
||||
*indexPtr = internal::convert_index<IndexType>(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/** \fn DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the minimum of all coefficients of *this and puts in *row and *col its location.
|
||||
*
|
||||
* If there are multiple coefficients with the same extreme value, the location of the first instance is returned.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::minCoeff(IndexType* rowPtr,
|
||||
IndexType* colPtr) const {
|
||||
using Func = internal::min_coeff_functor<Scalar, NaNPropagation>;
|
||||
Func func;
|
||||
return internal::findCoeff(derived(), func, rowPtr, colPtr);
|
||||
}
|
||||
|
||||
/** \returns the minimum of all coefficients of *this and puts in *index its location.
|
||||
*
|
||||
* If there are multiple coefficients with the same extreme value, the location of the first instance is returned.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visit(),
|
||||
* DenseBase::minCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::minCoeff(IndexType* indexPtr) const {
|
||||
using Func = internal::min_coeff_functor<Scalar, NaNPropagation>;
|
||||
Func func;
|
||||
return internal::findCoeff(derived(), func, indexPtr);
|
||||
}
|
||||
|
||||
/** \fn DenseBase<Derived>::maxCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the maximum of all coefficients of *this and puts in *row and *col its location.
|
||||
*
|
||||
* If there are multiple coefficients with the same extreme value, the location of the first instance is returned.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::maxCoeff(IndexType* rowPtr,
|
||||
IndexType* colPtr) const {
|
||||
using Func = internal::max_coeff_functor<Scalar, NaNPropagation>;
|
||||
Func func;
|
||||
return internal::findCoeff(derived(), func, rowPtr, colPtr);
|
||||
}
|
||||
|
||||
/** \returns the maximum of all coefficients of *this and puts in *index its location.
|
||||
*
|
||||
* If there are multiple coefficients with the same extreme value, the location of the first instance is returned.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(),
|
||||
* DenseBase::maxCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::maxCoeff(IndexType* indexPtr) const {
|
||||
using Func = internal::max_coeff_functor<Scalar, NaNPropagation>;
|
||||
Func func;
|
||||
return internal::findCoeff(derived(), func, indexPtr);
|
||||
}
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#endif // EIGEN_FIND_COEFF_H
|
||||
@@ -41,14 +41,10 @@ class ForceAlignedAccess : public internal::dense_xpr_base<ForceAlignedAccess<Ex
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit inline ForceAlignedAccess(const ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT {
|
||||
return m_expression.outerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT {
|
||||
return m_expression.innerStride();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_expression.innerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index row, Index col) const {
|
||||
return m_expression.coeff(row, col);
|
||||
|
||||
@@ -327,6 +327,7 @@ struct gemv_dense_selector<OnTheRight, ColMajor, true> {
|
||||
|
||||
if (!evalToDest) {
|
||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||
constexpr int Size = Dest::SizeAtCompileTime;
|
||||
Index size = dest.size();
|
||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||
#endif
|
||||
@@ -391,6 +392,7 @@ struct gemv_dense_selector<OnTheRight, RowMajor, true> {
|
||||
|
||||
if (!DirectlyUseRhs) {
|
||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||
constexpr int Size = ActualRhsTypeCleaned::SizeAtCompileTime;
|
||||
Index size = actualRhs.size();
|
||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||
#endif
|
||||
|
||||
@@ -65,13 +65,14 @@ struct default_packet_traits {
|
||||
HasAbsDiff = 0,
|
||||
HasBlend = 0,
|
||||
// This flag is used to indicate whether packet comparison is supported.
|
||||
// pcmp_eq, pcmp_lt and pcmp_le should be defined for it to be true.
|
||||
// pcmp_eq and pcmp_lt should be defined for it to be true.
|
||||
HasCmp = 0,
|
||||
|
||||
HasDiv = 0,
|
||||
HasReciprocal = 0,
|
||||
HasSqrt = 0,
|
||||
HasRsqrt = 0,
|
||||
HasCbrt = 0,
|
||||
HasExp = 0,
|
||||
HasExpm1 = 0,
|
||||
HasLog = 0,
|
||||
@@ -194,7 +195,7 @@ struct is_half {
|
||||
static constexpr int Size = unpacket_traits<Packet>::size;
|
||||
using DefaultPacket = typename packet_traits<Scalar>::type;
|
||||
static constexpr int DefaultSize = unpacket_traits<DefaultPacket>::size;
|
||||
static constexpr bool value = Size < DefaultSize;
|
||||
static constexpr bool value = Size != 1 && Size < DefaultSize;
|
||||
};
|
||||
|
||||
template <typename Src, typename Tgt>
|
||||
@@ -252,6 +253,12 @@ struct preinterpret_generic<Packet, Packet, true> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet& a) { return a; }
|
||||
};
|
||||
|
||||
template <typename ComplexPacket>
|
||||
struct preinterpret_generic<typename unpacket_traits<ComplexPacket>::as_real, ComplexPacket, false> {
|
||||
using RealPacket = typename unpacket_traits<ComplexPacket>::as_real;
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE RealPacket run(const ComplexPacket& a) { return a.v; }
|
||||
};
|
||||
|
||||
/** \internal \returns reinterpret_cast<Target>(a) */
|
||||
template <typename Target, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Target preinterpret(const Packet& a) {
|
||||
@@ -368,8 +375,13 @@ template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pdiv(const Packet& a, const Packet& b) {
|
||||
return a / b;
|
||||
}
|
||||
// Avoid compiler warning for boolean algebra.
|
||||
template <>
|
||||
EIGEN_DEVICE_FUNC inline bool pdiv(const bool& a, const bool& b) {
|
||||
return a && b;
|
||||
}
|
||||
|
||||
// In the generic case, memset to all one bits.
|
||||
// In the generic packet case, memset to all one bits.
|
||||
template <typename Packet, typename EnableIf = void>
|
||||
struct ptrue_impl {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) {
|
||||
@@ -379,19 +391,16 @@ struct ptrue_impl {
|
||||
}
|
||||
};
|
||||
|
||||
// Use a value of one for scalars.
|
||||
template <typename Scalar>
|
||||
struct ptrue_impl<Scalar, std::enable_if_t<is_scalar<Scalar>::value>> {
|
||||
static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar&) { return Scalar(1); }
|
||||
};
|
||||
|
||||
// For booleans, we can only directly set a valid `bool` value to avoid UB.
|
||||
template <>
|
||||
struct ptrue_impl<bool, void> {
|
||||
static EIGEN_DEVICE_FUNC inline bool run(const bool& /*a*/) { return true; }
|
||||
};
|
||||
|
||||
// For non-trivial scalars, set to Scalar(1) (i.e. a non-zero value).
|
||||
// Although this is technically not a valid bitmask, the scalar path for pselect
|
||||
// uses a comparison to zero, so this should still work in most cases. We don't
|
||||
// have another option, since the scalar type requires initialization.
|
||||
template <typename T>
|
||||
struct ptrue_impl<T, std::enable_if_t<is_scalar<T>::value && NumTraits<T>::RequireInitialization>> {
|
||||
static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/) { return T(1); }
|
||||
static EIGEN_DEVICE_FUNC inline bool run(const bool&) { return true; }
|
||||
};
|
||||
|
||||
/** \internal \returns one bits. */
|
||||
@@ -400,7 +409,7 @@ EIGEN_DEVICE_FUNC inline Packet ptrue(const Packet& a) {
|
||||
return ptrue_impl<Packet>::run(a);
|
||||
}
|
||||
|
||||
// In the general case, memset to zero.
|
||||
// In the general packet case, memset to zero.
|
||||
template <typename Packet, typename EnableIf = void>
|
||||
struct pzero_impl {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) {
|
||||
@@ -423,74 +432,44 @@ EIGEN_DEVICE_FUNC inline Packet pzero(const Packet& a) {
|
||||
return pzero_impl<Packet>::run(a);
|
||||
}
|
||||
|
||||
/** \internal \returns a <= b as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_le(const Packet& a, const Packet& b) {
|
||||
return a <= b ? ptrue(a) : pzero(a);
|
||||
}
|
||||
|
||||
/** \internal \returns a < b as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_lt(const Packet& a, const Packet& b) {
|
||||
return a < b ? ptrue(a) : pzero(a);
|
||||
}
|
||||
|
||||
/** \internal \returns a == b as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_eq(const Packet& a, const Packet& b) {
|
||||
return a == b ? ptrue(a) : pzero(a);
|
||||
}
|
||||
|
||||
/** \internal \returns a < b or a==NaN or b==NaN as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_lt_or_nan(const Packet& a, const Packet& b) {
|
||||
return a >= b ? pzero(a) : ptrue(a);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct bit_and {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a & b; }
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a & b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct bit_or {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a | b; }
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a | b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct bit_xor {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a ^ b; }
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a ^ b; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct bit_not {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a) const { return ~a; }
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a) const { return ~a; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bit_and<bool> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const {
|
||||
return a && b;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const { return a && b; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bit_or<bool> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const {
|
||||
return a || b;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const { return a || b; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bit_xor<bool> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const {
|
||||
return a != b;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const { return a != b; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bit_not<bool> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE bool operator()(const bool& a) const { return !a; }
|
||||
EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a) const { return !a; }
|
||||
};
|
||||
|
||||
// Use operators &, |, ^, ~.
|
||||
@@ -579,8 +558,32 @@ EIGEN_DEVICE_FUNC inline Packet pandnot(const Packet& a, const Packet& b) {
|
||||
return pand(a, pnot(b));
|
||||
}
|
||||
|
||||
/** \internal \returns a < b as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_lt(const Packet& a, const Packet& b) {
|
||||
return a < b ? ptrue(a) : pzero(a);
|
||||
}
|
||||
|
||||
/** \internal \returns a == b as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_eq(const Packet& a, const Packet& b) {
|
||||
return a == b ? ptrue(a) : pzero(a);
|
||||
}
|
||||
|
||||
/** \internal \returns a <= b as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_le(const Packet& a, const Packet& b) {
|
||||
return por(pcmp_eq(a, b), pcmp_lt(a, b));
|
||||
}
|
||||
|
||||
/** \internal \returns a < b or a==NaN or b==NaN as a bit mask */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pcmp_lt_or_nan(const Packet& a, const Packet& b) {
|
||||
return a >= b ? pzero(a) : ptrue(a);
|
||||
}
|
||||
|
||||
// In the general case, use bitwise select.
|
||||
template <typename Packet, typename EnableIf = void>
|
||||
template <typename Packet, bool is_scalar = is_scalar<Packet>::value>
|
||||
struct pselect_impl {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) {
|
||||
return por(pand(a, mask), pandnot(b, mask));
|
||||
@@ -589,9 +592,9 @@ struct pselect_impl {
|
||||
|
||||
// For scalars, use ternary select.
|
||||
template <typename Packet>
|
||||
struct pselect_impl<Packet, std::enable_if_t<is_scalar<Packet>::value>> {
|
||||
struct pselect_impl<Packet, true> {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) {
|
||||
return numext::equal_strict(mask, Packet(0)) ? b : a;
|
||||
return numext::select(mask, a, b);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -608,7 +611,7 @@ EIGEN_DEVICE_FUNC inline bool pselect<bool>(const bool& cond, const bool& a, con
|
||||
|
||||
/** \internal \returns the min or of \a a and \a b (coeff-wise)
|
||||
If either \a a or \a b are NaN, the result is implementation defined. */
|
||||
template <int NaNPropagation>
|
||||
template <int NaNPropagation, bool IsInteger>
|
||||
struct pminmax_impl {
|
||||
template <typename Packet, typename Op>
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
|
||||
@@ -619,7 +622,7 @@ struct pminmax_impl {
|
||||
/** \internal \returns the min or max of \a a and \a b (coeff-wise)
|
||||
If either \a a or \a b are NaN, NaN is returned. */
|
||||
template <>
|
||||
struct pminmax_impl<PropagateNaN> {
|
||||
struct pminmax_impl<PropagateNaN, false> {
|
||||
template <typename Packet, typename Op>
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
|
||||
Packet not_nan_mask_a = pcmp_eq(a, a);
|
||||
@@ -632,7 +635,7 @@ struct pminmax_impl<PropagateNaN> {
|
||||
If both \a a and \a b are NaN, NaN is returned.
|
||||
Equivalent to std::fmin(a, b). */
|
||||
template <>
|
||||
struct pminmax_impl<PropagateNumbers> {
|
||||
struct pminmax_impl<PropagateNumbers, false> {
|
||||
template <typename Packet, typename Op>
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
|
||||
Packet not_nan_mask_a = pcmp_eq(a, a);
|
||||
@@ -641,7 +644,7 @@ struct pminmax_impl<PropagateNumbers> {
|
||||
}
|
||||
};
|
||||
|
||||
#define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) [](const Type& a, const Type& b) { return Func(a, b); }
|
||||
#define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) [](const Type& aa, const Type& bb) { return Func(aa, bb); }
|
||||
|
||||
/** \internal \returns the min of \a a and \a b (coeff-wise).
|
||||
If \a a or \b b is NaN, the return value is implementation defined. */
|
||||
@@ -654,7 +657,8 @@ EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) {
|
||||
NaNPropagation determines the NaN propagation semantics. */
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) {
|
||||
return pminmax_impl<NaNPropagation>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmin<Packet>)));
|
||||
constexpr bool IsInteger = NumTraits<typename unpacket_traits<Packet>::type>::IsInteger;
|
||||
return pminmax_impl<NaNPropagation, IsInteger>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmin<Packet>)));
|
||||
}
|
||||
|
||||
/** \internal \returns the max of \a a and \a b (coeff-wise)
|
||||
@@ -668,7 +672,8 @@ EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) {
|
||||
NaNPropagation determines the NaN propagation semantics. */
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) {
|
||||
return pminmax_impl<NaNPropagation>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmax<Packet>)));
|
||||
constexpr bool IsInteger = NumTraits<typename unpacket_traits<Packet>::type>::IsInteger;
|
||||
return pminmax_impl<NaNPropagation, IsInteger>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmax<Packet>)));
|
||||
}
|
||||
|
||||
/** \internal \returns the absolute value of \a a */
|
||||
@@ -873,17 +878,29 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet plset(const typename unpacket_trait
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename Packet, typename EnableIf = void>
|
||||
struct peven_mask_impl {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet&) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
const size_t n = unpacket_traits<Packet>::size;
|
||||
EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n];
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
memset(elements + i, ((i & 1) == 0 ? 0xff : 0), sizeof(Scalar));
|
||||
}
|
||||
return ploadu<Packet>(elements);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct peven_mask_impl<Scalar, std::enable_if_t<is_scalar<Scalar>::value>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar&) { return Scalar(1); }
|
||||
};
|
||||
|
||||
/** \internal \returns a packet with constant coefficients \a a, e.g.: (x, 0, x, 0),
|
||||
where x is the value of all 1-bits. */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet peven_mask(const Packet& /*a*/) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
const size_t n = unpacket_traits<Packet>::size;
|
||||
EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n];
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
memset(elements + i, ((i & 1) == 0 ? 0xff : 0), sizeof(Scalar));
|
||||
}
|
||||
return ploadu<Packet>(elements);
|
||||
EIGEN_DEVICE_FUNC inline Packet peven_mask(const Packet& a) {
|
||||
return peven_mask_impl<Packet>::run(a);
|
||||
}
|
||||
|
||||
/** \internal copy the packet \a from to \a *to, \a to must be properly aligned */
|
||||
@@ -1083,8 +1100,13 @@ EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh(const Packet&
|
||||
/** \internal \returns the exp of \a a (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexp(const Packet& a) {
|
||||
EIGEN_USING_STD(exp);
|
||||
return exp(a);
|
||||
return numext::exp(a);
|
||||
}
|
||||
|
||||
/** \internal \returns the exp2 of \a a (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexp2(const Packet& a) {
|
||||
return numext::exp2(a);
|
||||
}
|
||||
|
||||
/** \internal \returns the expm1 of \a a (coeff-wise) */
|
||||
@@ -1113,7 +1135,7 @@ EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog10(const Packet&
|
||||
return log10(a);
|
||||
}
|
||||
|
||||
/** \internal \returns the log10 of \a a (coeff-wise) */
|
||||
/** \internal \returns the log2 of \a a (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog2(const Packet& a) {
|
||||
using Scalar = typename internal::unpacket_traits<Packet>::type;
|
||||
@@ -1239,26 +1261,46 @@ EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_mul(const
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(const Packet& a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<PropagateFast, Scalar>)));
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<Scalar>)));
|
||||
}
|
||||
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(const Packet& a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<NaNPropagation, Scalar>)));
|
||||
}
|
||||
|
||||
/** \internal \returns the min of the elements of \a a */
|
||||
/** \internal \returns the max of the elements of \a a */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(const Packet& a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<PropagateFast, Scalar>)));
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<Scalar>)));
|
||||
}
|
||||
|
||||
template <int NaNPropagation, typename Packet>
|
||||
struct predux_min_max_helper_impl {
|
||||
using Scalar = typename unpacket_traits<Packet>::type;
|
||||
static constexpr bool UsePredux_ = NaNPropagation == PropagateFast || NumTraits<Scalar>::IsInteger;
|
||||
template <bool UsePredux = UsePredux_, std::enable_if_t<!UsePredux, bool> = true>
|
||||
static EIGEN_DEVICE_FUNC inline Scalar run_min(const Packet& a) {
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<NaNPropagation, Scalar>)));
|
||||
}
|
||||
template <bool UsePredux = UsePredux_, std::enable_if_t<!UsePredux, bool> = true>
|
||||
static EIGEN_DEVICE_FUNC inline Scalar run_max(const Packet& a) {
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<NaNPropagation, Scalar>)));
|
||||
}
|
||||
template <bool UsePredux = UsePredux_, std::enable_if_t<UsePredux, bool> = true>
|
||||
static EIGEN_DEVICE_FUNC inline Scalar run_min(const Packet& a) {
|
||||
return predux_min(a);
|
||||
}
|
||||
template <bool UsePredux = UsePredux_, std::enable_if_t<UsePredux, bool> = true>
|
||||
static EIGEN_DEVICE_FUNC inline Scalar run_max(const Packet& a) {
|
||||
return predux_max(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(const Packet& a) {
|
||||
return predux_min_max_helper_impl<NaNPropagation, Packet>::run_min(a);
|
||||
}
|
||||
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(const Packet& a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<NaNPropagation, Scalar>)));
|
||||
return predux_min_max_helper_impl<NaNPropagation, Packet>::run_max(a);
|
||||
}
|
||||
|
||||
#undef EIGEN_BINARY_OP_NAN_PROPAGATION
|
||||
@@ -1289,29 +1331,61 @@ EIGEN_DEVICE_FUNC inline bool predux_any(const Packet& a) {
|
||||
* The following functions might not have to be overwritten for vectorized types
|
||||
***************************************************************************/
|
||||
|
||||
// FMA instructions.
|
||||
template <typename Packet, typename EnableIf = void>
|
||||
struct pmadd_impl {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pmadd(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return padd(pmul(a, b), c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pmsub(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return psub(pmul(a, b), c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pnmadd(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return psub(c, pmul(a, b));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pnmsub(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return pnegate(pmadd(a, b, c));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct pmadd_impl<Scalar, std::enable_if_t<is_scalar<Scalar>::value && NumTraits<Scalar>::IsSigned>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmadd(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::madd<Scalar>(a, b, c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmsub(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::madd<Scalar>(a, b, Scalar(-c));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmadd(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::madd<Scalar>(Scalar(-a), b, c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmsub(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return -Scalar(numext::madd<Scalar>(a, b, c));
|
||||
}
|
||||
};
|
||||
|
||||
// Multiply-add instructions.
|
||||
/** \internal \returns a * b + c (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pmadd(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return padd(pmul(a, b), c);
|
||||
return pmadd_impl<Packet>::pmadd(a, b, c);
|
||||
}
|
||||
|
||||
/** \internal \returns a * b - c (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pmsub(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return psub(pmul(a, b), c);
|
||||
return pmadd_impl<Packet>::pmsub(a, b, c);
|
||||
}
|
||||
|
||||
/** \internal \returns -(a * b) + c (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pnmadd(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return psub(c, pmul(a, b));
|
||||
return pmadd_impl<Packet>::pnmadd(a, b, c);
|
||||
}
|
||||
|
||||
/** \internal \returns -((a * b + c) (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pnmsub(const Packet& a, const Packet& b, const Packet& c) {
|
||||
return pnegate(pmadd(a, b, c));
|
||||
return pmadd_impl<Packet>::pnmsub(a, b, c);
|
||||
}
|
||||
|
||||
/** \internal copy a packet with constant coefficient \a a (e.g., [a,a,a,a]) to \a *to. \a to must be 16 bytes aligned
|
||||
@@ -1520,6 +1594,107 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pcarg(const Packet& a) {
|
||||
return (Packet)pand(result, peven_mask(result)); // atan2 0 atan2 0 ...
|
||||
}
|
||||
|
||||
/** \internal \returns a packet populated with values in the range [begin, begin + count). Elements
|
||||
* outside this range are not defined. \a *from does not need to be aligned, and can be null if \a count is zero.*/
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet ploaduSegment(const typename unpacket_traits<Packet>::type* from, Index begin,
|
||||
Index count) {
|
||||
using Scalar = typename unpacket_traits<Packet>::type;
|
||||
constexpr Index PacketSize = unpacket_traits<Packet>::size;
|
||||
eigen_assert((begin >= 0 && count >= 0 && begin + count <= PacketSize) && "invalid range");
|
||||
Scalar aux[PacketSize] = {};
|
||||
for (Index k = begin; k < begin + count; k++) {
|
||||
aux[k] = from[k];
|
||||
}
|
||||
return ploadu<Packet>(aux);
|
||||
}
|
||||
|
||||
/** \internal \returns a packet populated with values in the range [begin, begin + count). Elements
|
||||
* outside this range are not defined. \a *from must be aligned, and cannot be null.*/
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet ploadSegment(const typename unpacket_traits<Packet>::type* from, Index begin,
|
||||
Index count) {
|
||||
return ploaduSegment<Packet>(from, begin, count);
|
||||
}
|
||||
|
||||
/** \internal copy the packet \a from in the range [begin, begin + count) to \a *to.
|
||||
Elements outside of the range [begin, begin + count) are not defined. \a *to does not need to be aligned, and can be
|
||||
null if \a count is zero.*/
|
||||
template <typename Scalar, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline void pstoreuSegment(Scalar* to, const Packet& from, Index begin, Index count) {
|
||||
constexpr Index PacketSize = unpacket_traits<Packet>::size;
|
||||
eigen_assert((begin >= 0 && count >= 0 && begin + count <= PacketSize) && "invalid range");
|
||||
Scalar aux[PacketSize];
|
||||
pstoreu<Scalar, Packet>(aux, from);
|
||||
for (Index k = begin; k < begin + count; k++) {
|
||||
to[k] = aux[k];
|
||||
}
|
||||
}
|
||||
|
||||
/** \internal copy the packet \a from in the range [begin, begin + count) to \a *to.
|
||||
Elements outside of the range [begin, begin + count) are not defined. \a *to must be aligned, and cannot be
|
||||
null.*/
|
||||
template <typename Scalar, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline void pstoreSegment(Scalar* to, const Packet& from, Index begin, Index count) {
|
||||
return pstoreuSegment(to, from, begin, count);
|
||||
}
|
||||
|
||||
/** \internal \returns a packet populated with values in the range [begin, begin + count). Elements
|
||||
* outside this range are not defined.*/
|
||||
template <typename Packet, int Alignment>
|
||||
EIGEN_DEVICE_FUNC inline Packet ploadtSegment(const typename unpacket_traits<Packet>::type* from, Index begin,
|
||||
Index count) {
|
||||
constexpr int RequiredAlignment = unpacket_traits<Packet>::alignment;
|
||||
if (Alignment >= RequiredAlignment) {
|
||||
return ploadSegment<Packet>(from, begin, count);
|
||||
} else {
|
||||
return ploaduSegment<Packet>(from, begin, count);
|
||||
}
|
||||
}
|
||||
|
||||
/** \internal copy the packet \a from in the range [begin, begin + count) to \a *to.
|
||||
Elements outside of the range [begin, begin + count) are not defined.*/
|
||||
template <typename Scalar, typename Packet, int Alignment>
|
||||
EIGEN_DEVICE_FUNC inline void pstoretSegment(Scalar* to, const Packet& from, Index begin, Index count) {
|
||||
constexpr int RequiredAlignment = unpacket_traits<Packet>::alignment;
|
||||
if (Alignment >= RequiredAlignment) {
|
||||
pstoreSegment<Scalar, Packet>(to, from, begin, count);
|
||||
} else {
|
||||
pstoreuSegment<Scalar, Packet>(to, from, begin, count);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef EIGEN_NO_IO
|
||||
|
||||
template <typename Packet>
|
||||
class StreamablePacket {
|
||||
public:
|
||||
using Scalar = typename unpacket_traits<Packet>::type;
|
||||
StreamablePacket(const Packet& packet) { pstoreu(v_, packet); }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const StreamablePacket& packet) {
|
||||
os << "{" << packet.v_[0];
|
||||
for (int i = 1; i < unpacket_traits<Packet>::size; ++i) {
|
||||
os << "," << packet.v_[i];
|
||||
}
|
||||
os << "}";
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
Scalar v_[unpacket_traits<Packet>::size];
|
||||
};
|
||||
|
||||
/**
|
||||
* \internal \returns an intermediary that can be used to ostream packets, e.g. for debugging.
|
||||
*/
|
||||
template <typename Packet>
|
||||
StreamablePacket<Packet> postream(const Packet& packet) {
|
||||
return StreamablePacket<Packet>(packet);
|
||||
}
|
||||
|
||||
#endif // EIGEN_NO_IO
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -76,6 +76,7 @@ EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erf, scalar_erf_op, error function,\sa ArrayBas
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erfc, scalar_erfc_op, complement error function,\sa ArrayBase::erfc)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(ndtri, scalar_ndtri_op, inverse normal distribution function,\sa ArrayBase::ndtri)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp, scalar_exp_op, exponential,\sa ArrayBase::exp)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp2, scalar_exp2_op, exponential,\sa ArrayBase::exp2)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(expm1, scalar_expm1_op, exponential of a value minus 1,\sa ArrayBase::expm1)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log, scalar_log_op, natural logarithm,\sa Eigen::log10 DOXCOMMA ArrayBase::log)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log1p, scalar_log1p_op, natural logarithm of 1 plus the value,\sa ArrayBase::log1p)
|
||||
|
||||
+2
-2
@@ -68,8 +68,8 @@ struct IOFormat {
|
||||
// TODO check if rowPrefix, rowSuffix or rowSeparator contains a newline
|
||||
// don't add rowSpacer if columns are not to be aligned
|
||||
if ((flags & DontAlignCols)) return;
|
||||
int i = int(matSuffix.length()) - 1;
|
||||
while (i >= 0 && matSuffix[i] != '\n') {
|
||||
int i = int(matPrefix.length()) - 1;
|
||||
while (i >= 0 && matPrefix[i] != '\n') {
|
||||
rowSpacer += ' ';
|
||||
i--;
|
||||
}
|
||||
|
||||
@@ -225,14 +225,14 @@ class IndexedViewImpl<XprType, RowIndices, ColIndices, StorageKind, true>
|
||||
return this->nestedExpression().data() + row_offset + col_offset;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept {
|
||||
if (traits<Derived>::InnerStrideAtCompileTime != Dynamic) {
|
||||
return traits<Derived>::InnerStrideAtCompileTime;
|
||||
}
|
||||
return innerIncrement() * this->nestedExpression().innerStride();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept {
|
||||
if (traits<Derived>::OuterStrideAtCompileTime != Dynamic) {
|
||||
return traits<Derived>::OuterStrideAtCompileTime;
|
||||
}
|
||||
@@ -308,6 +308,12 @@ struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
|
||||
const XprType& m_xpr;
|
||||
};
|
||||
|
||||
// Catch assignments to an IndexedView.
|
||||
template <typename ArgType, typename RowIndices, typename ColIndices>
|
||||
struct evaluator_assume_aliasing<IndexedView<ArgType, RowIndices, ColIndices>> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -57,16 +57,20 @@ struct inner_product_assert {
|
||||
|
||||
template <typename Func, typename Lhs, typename Rhs>
|
||||
struct inner_product_evaluator {
|
||||
static constexpr int LhsFlags = evaluator<Lhs>::Flags, RhsFlags = evaluator<Rhs>::Flags,
|
||||
SizeAtCompileTime = min_size_prefer_fixed(Lhs::SizeAtCompileTime, Rhs::SizeAtCompileTime),
|
||||
LhsAlignment = evaluator<Lhs>::Alignment, RhsAlignment = evaluator<Rhs>::Alignment;
|
||||
static constexpr int LhsFlags = evaluator<Lhs>::Flags;
|
||||
static constexpr int RhsFlags = evaluator<Rhs>::Flags;
|
||||
static constexpr int SizeAtCompileTime = size_prefer_fixed(Lhs::SizeAtCompileTime, Rhs::SizeAtCompileTime);
|
||||
static constexpr int MaxSizeAtCompileTime =
|
||||
min_size_prefer_fixed(Lhs::MaxSizeAtCompileTime, Rhs::MaxSizeAtCompileTime);
|
||||
static constexpr int LhsAlignment = evaluator<Lhs>::Alignment;
|
||||
static constexpr int RhsAlignment = evaluator<Rhs>::Alignment;
|
||||
|
||||
using Scalar = typename Func::result_type;
|
||||
using Packet = typename find_inner_product_packet<Scalar, SizeAtCompileTime>::type;
|
||||
|
||||
static constexpr bool Vectorize =
|
||||
bool(LhsFlags & RhsFlags & PacketAccessBit) && Func::PacketAccess &&
|
||||
((SizeAtCompileTime == Dynamic) || (unpacket_traits<Packet>::size <= SizeAtCompileTime));
|
||||
((MaxSizeAtCompileTime == Dynamic) || (unpacket_traits<Packet>::size <= MaxSizeAtCompileTime));
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit inner_product_evaluator(const Lhs& lhs, const Rhs& rhs,
|
||||
Func func = Func())
|
||||
@@ -85,13 +89,13 @@ struct inner_product_evaluator {
|
||||
}
|
||||
|
||||
template <typename PacketType, int LhsMode = LhsAlignment, int RhsMode = RhsAlignment>
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index index) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const {
|
||||
return m_func.packet(m_lhs.template packet<LhsMode, PacketType>(index),
|
||||
m_rhs.template packet<RhsMode, PacketType>(index));
|
||||
}
|
||||
|
||||
template <typename PacketType, int LhsMode = LhsAlignment, int RhsMode = RhsAlignment>
|
||||
EIGEN_STRONG_INLINE PacketType packet(const PacketType& value, Index index) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(const PacketType& value, Index index) const {
|
||||
return m_func.packet(value, m_lhs.template packet<LhsMode, PacketType>(index),
|
||||
m_rhs.template packet<RhsMode, PacketType>(index));
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ class Inverse : public InverseImpl<XprType, typename internal::traits<XprType>::
|
||||
|
||||
explicit EIGEN_DEVICE_FUNC Inverse(const XprType& xpr) : m_xpr(xpr) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_xpr.rows(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC const XprTypeNestedCleaned& nestedExpression() const { return m_xpr; }
|
||||
|
||||
@@ -92,7 +92,7 @@ struct unary_evaluator<Inverse<ArgType> > : public evaluator<typename Inverse<Ar
|
||||
|
||||
enum { Flags = Base::Flags | EvalBeforeNestingBit };
|
||||
|
||||
unary_evaluator(const InverseType& inv_xpr) : m_result(inv_xpr.rows(), inv_xpr.cols()) {
|
||||
EIGEN_DEVICE_FUNC unary_evaluator(const InverseType& inv_xpr) : m_result(inv_xpr.rows(), inv_xpr.cols()) {
|
||||
internal::construct_at<Base>(this, m_result);
|
||||
internal::call_assignment_no_alias(m_result, inv_xpr);
|
||||
}
|
||||
|
||||
@@ -102,11 +102,11 @@ class Map : public MapBase<Map<PlainObjectType, MapOptions, StrideType> > {
|
||||
typedef PointerType PointerArgType;
|
||||
EIGEN_DEVICE_FUNC inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const {
|
||||
return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const {
|
||||
return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
|
||||
: internal::traits<Map>::OuterStrideAtCompileTime != Dynamic
|
||||
? Index(internal::traits<Map>::OuterStrideAtCompileTime)
|
||||
|
||||
@@ -84,9 +84,9 @@ class MapBase<Derived, ReadOnlyAccessors> : public internal::dense_xpr_base<Deri
|
||||
typedef typename Base::CoeffReturnType CoeffReturnType;
|
||||
|
||||
/** \copydoc DenseBase::rows() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_rows.value(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_rows.value(); }
|
||||
/** \copydoc DenseBase::cols() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_cols.value(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_cols.value(); }
|
||||
|
||||
/** Returns a pointer to the first coefficient of the matrix or vector.
|
||||
*
|
||||
|
||||
+209
-53
@@ -170,8 +170,8 @@ struct imag_ref_default_impl {
|
||||
|
||||
template <typename Scalar>
|
||||
struct imag_ref_default_impl<Scalar, false> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline Scalar run(Scalar&) { return Scalar(0); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline const Scalar run(const Scalar&) { return Scalar(0); }
|
||||
EIGEN_DEVICE_FUNC constexpr static Scalar run(Scalar&) { return Scalar(0); }
|
||||
EIGEN_DEVICE_FUNC constexpr static const Scalar run(const Scalar&) { return Scalar(0); }
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
@@ -182,6 +182,40 @@ struct imag_ref_retval {
|
||||
typedef typename NumTraits<Scalar>::Real& type;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
namespace numext {
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline internal::add_const_on_value_type_t<EIGEN_MATHFUNC_RETVAL(real_ref, Scalar)> real_ref(
|
||||
const Scalar& x) {
|
||||
return internal::real_ref_impl<Scalar>::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar select(const Scalar& mask, const Scalar& a, const Scalar& b) {
|
||||
return numext::is_exactly_zero(mask) ? b : a;
|
||||
}
|
||||
|
||||
} // namespace numext
|
||||
|
||||
namespace internal {
|
||||
|
||||
/****************************************************************************
|
||||
* Implementation of conj *
|
||||
****************************************************************************/
|
||||
@@ -221,7 +255,9 @@ template <typename Scalar>
|
||||
struct abs2_impl_default<Scalar, true> // IsComplex
|
||||
{
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { return x.real() * x.real() + x.imag() * x.imag(); }
|
||||
EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) {
|
||||
return numext::real(x) * numext::real(x) + numext::imag(x) * numext::imag(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
@@ -250,16 +286,14 @@ struct sqrt_impl {
|
||||
};
|
||||
|
||||
// Complex sqrt defined in MathFunctionsImpl.h.
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_sqrt(const std::complex<T>& a_x);
|
||||
template <typename ComplexT>
|
||||
EIGEN_DEVICE_FUNC ComplexT complex_sqrt(const ComplexT& a_x);
|
||||
|
||||
// Custom implementation is faster than `std::sqrt`, works on
|
||||
// GPU, and correctly handles special cases (unlike MSVC).
|
||||
template <typename T>
|
||||
struct sqrt_impl<std::complex<T>> {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE std::complex<T> run(const std::complex<T>& x) {
|
||||
return complex_sqrt<T>(x);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE std::complex<T> run(const std::complex<T>& x) { return complex_sqrt(x); }
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
@@ -272,13 +306,13 @@ template <typename T>
|
||||
struct rsqrt_impl;
|
||||
|
||||
// Complex rsqrt defined in MathFunctionsImpl.h.
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_rsqrt(const std::complex<T>& a_x);
|
||||
template <typename ComplexT>
|
||||
EIGEN_DEVICE_FUNC ComplexT complex_rsqrt(const ComplexT& a_x);
|
||||
|
||||
template <typename T>
|
||||
struct rsqrt_impl<std::complex<T>> {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE std::complex<T> run(const std::complex<T>& x) {
|
||||
return complex_rsqrt<T>(x);
|
||||
return complex_rsqrt(x);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -299,7 +333,7 @@ struct norm1_default_impl<Scalar, true> {
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) {
|
||||
EIGEN_USING_STD(abs);
|
||||
return abs(x.real()) + abs(x.imag());
|
||||
return abs(numext::real(x)) + abs(numext::imag(x));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -469,8 +503,8 @@ struct expm1_retval {
|
||||
****************************************************************************/
|
||||
|
||||
// Complex log defined in MathFunctionsImpl.h.
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_log(const std::complex<T>& z);
|
||||
template <typename ComplexT>
|
||||
EIGEN_DEVICE_FUNC ComplexT complex_log(const ComplexT& z);
|
||||
|
||||
template <typename Scalar>
|
||||
struct log_impl {
|
||||
@@ -798,8 +832,8 @@ EIGEN_DEVICE_FUNC std::enable_if_t<(std::numeric_limits<T>::has_infinity && !Num
|
||||
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
std::enable_if_t<!(std::numeric_limits<T>::has_quiet_NaN || std::numeric_limits<T>::has_signaling_NaN), bool>
|
||||
isnan_impl(const T&) {
|
||||
std::enable_if_t<!(std::numeric_limits<T>::has_quiet_NaN || std::numeric_limits<T>::has_signaling_NaN), bool>
|
||||
isnan_impl(const T&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -846,7 +880,7 @@ struct sign_impl<Scalar, true, IsInteger> {
|
||||
real_type aa = abs(a);
|
||||
if (aa == real_type(0)) return Scalar(0);
|
||||
aa = real_type(1) / aa;
|
||||
return Scalar(a.real() * aa, a.imag() * aa);
|
||||
return Scalar(numext::real(a) * aa, numext::imag(a) * aa);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -907,6 +941,79 @@ struct nearest_integer_impl<Scalar, true> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_trunc(const Scalar& x) { return x; }
|
||||
};
|
||||
|
||||
// Extra namespace to prevent leaking std::fma into Eigen::internal.
|
||||
namespace has_fma_detail {
|
||||
|
||||
template <typename T, typename EnableIf = void>
|
||||
struct has_fma_impl : public std::false_type {};
|
||||
|
||||
using std::fma;
|
||||
|
||||
template <typename T>
|
||||
struct has_fma_impl<
|
||||
T, std::enable_if_t<std::is_same<T, decltype(fma(std::declval<T>(), std::declval<T>(), std::declval<T>()))>::value>>
|
||||
: public std::true_type {};
|
||||
|
||||
} // namespace has_fma_detail
|
||||
|
||||
template <typename T>
|
||||
struct has_fma : public has_fma_detail::has_fma_impl<T> {};
|
||||
|
||||
// Default implementation.
|
||||
template <typename T, typename Enable = void>
|
||||
struct fma_impl {
|
||||
static_assert(has_fma<T>::value, "No function fma(...) for type. Please provide an implementation.");
|
||||
};
|
||||
|
||||
// STD or ADL version if it exists.
|
||||
template <typename T>
|
||||
struct fma_impl<T, std::enable_if_t<has_fma<T>::value>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T run(const T& a, const T& b, const T& c) {
|
||||
using std::fma;
|
||||
return fma(a, b, c);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(EIGEN_GPUCC)
|
||||
template <>
|
||||
struct has_fma<float> : public true_type {};
|
||||
|
||||
template <>
|
||||
struct fma_impl<float, void> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float run(const float& a, const float& b, const float& c) {
|
||||
return ::fmaf(a, b, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct has_fma<double> : public true_type {};
|
||||
|
||||
template <>
|
||||
struct fma_impl<double, void> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double run(const double& a, const double& b, const double& c) {
|
||||
return ::fma(a, b, c);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Basic multiply-add.
|
||||
template <typename Scalar, typename EnableIf = void>
|
||||
struct madd_impl {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return x * y + z;
|
||||
}
|
||||
};
|
||||
|
||||
// Use FMA if there is a single CPU instruction.
|
||||
#ifdef EIGEN_VECTORIZE_FMA
|
||||
template <typename Scalar>
|
||||
struct madd_impl<Scalar, std::enable_if_t<has_fma<Scalar>::value>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return fma_impl<Scalar>::run(x, y, z);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1042,27 +1149,6 @@ SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(maxi, fmax)
|
||||
|
||||
#endif
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline internal::add_const_on_value_type_t<EIGEN_MATHFUNC_RETVAL(real_ref, Scalar)> real_ref(
|
||||
const Scalar& x) {
|
||||
return internal::real_ref_impl<Scalar>::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(arg, Scalar) arg(const Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(arg, Scalar)::run(x);
|
||||
@@ -1248,11 +1334,9 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double trunc(const double& x) {
|
||||
// Integer division with rounding up.
|
||||
// T is assumed to be an integer type with a>=0, and b>0
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_CONSTEXPR T div_ceil(T a, T b) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE constexpr T div_ceil(T a, T b) {
|
||||
using UnsignedT = typename internal::make_unsigned<T>::type;
|
||||
EIGEN_STATIC_ASSERT((NumTraits<T>::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES)
|
||||
eigen_assert(a >= 0);
|
||||
eigen_assert(b > 0);
|
||||
// Note: explicitly declaring a and b as non-negative values allows the compiler to use better optimizations
|
||||
const UnsignedT ua = UnsignedT(a);
|
||||
const UnsignedT ub = UnsignedT(b);
|
||||
@@ -1263,13 +1347,11 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_CONSTEXPR T div_ceil(T a, T b) {
|
||||
// Integer round down to nearest power of b
|
||||
// T is assumed to be an integer type with a>=0, and b>0
|
||||
template <typename T, typename U>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_CONSTEXPR T round_down(T a, U b) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE constexpr T round_down(T a, U b) {
|
||||
using UnsignedT = typename internal::make_unsigned<T>::type;
|
||||
using UnsignedU = typename internal::make_unsigned<U>::type;
|
||||
EIGEN_STATIC_ASSERT((NumTraits<T>::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES)
|
||||
EIGEN_STATIC_ASSERT((NumTraits<U>::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES)
|
||||
eigen_assert(a >= 0);
|
||||
eigen_assert(b > 0);
|
||||
// Note: explicitly declaring a and b as non-negative values allows the compiler to use better optimizations
|
||||
const UnsignedT ua = UnsignedT(a);
|
||||
const UnsignedU ub = UnsignedU(b);
|
||||
@@ -1278,8 +1360,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_CONSTEXPR T round_down(T a, U b) {
|
||||
|
||||
/** Log base 2 for 32 bits positive integers.
|
||||
* Conveniently returns 0 for x==0. */
|
||||
EIGEN_CONSTEXPR inline int log2(int x) {
|
||||
eigen_assert(x >= 0);
|
||||
constexpr int log2(int x) {
|
||||
unsigned int v(x);
|
||||
constexpr int table[32] = {0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31};
|
||||
@@ -1317,11 +1398,17 @@ SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(sqrt, sqrt)
|
||||
|
||||
/** \returns the cube root of \a x. **/
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T cbrt(const T& x) {
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::enable_if_t<!NumTraits<T>::IsComplex, T> cbrt(const T& x) {
|
||||
EIGEN_USING_STD(cbrt);
|
||||
return static_cast<T>(cbrt(x));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::enable_if_t<NumTraits<T>::IsComplex, T> cbrt(const T& x) {
|
||||
EIGEN_USING_STD(pow);
|
||||
return pow(x, typename NumTraits<T>::Real(1.0 / 3.0));
|
||||
}
|
||||
|
||||
/** \returns the reciprocal square root of \a x. **/
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T rsqrt(const T& x) {
|
||||
@@ -1350,17 +1437,17 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double log(const double& x) {
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
std::enable_if_t<NumTraits<T>::IsSigned || NumTraits<T>::IsComplex, typename NumTraits<T>::Real>
|
||||
abs(const T& x) {
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_ALWAYS_INLINE std::enable_if_t<NumTraits<T>::IsSigned || NumTraits<T>::IsComplex, typename NumTraits<T>::Real>
|
||||
abs(const T& x) {
|
||||
EIGEN_USING_STD(abs);
|
||||
return abs(x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
std::enable_if_t<!(NumTraits<T>::IsSigned || NumTraits<T>::IsComplex), typename NumTraits<T>::Real>
|
||||
abs(const T& x) {
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_ALWAYS_INLINE std::enable_if_t<!(NumTraits<T>::IsSigned || NumTraits<T>::IsComplex), typename NumTraits<T>::Real>
|
||||
abs(const T& x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -1477,6 +1564,63 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex<double> exp(const std::comple
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T exp2(const T& x) {
|
||||
EIGEN_USING_STD(exp2);
|
||||
return exp2(x);
|
||||
}
|
||||
|
||||
// MSVC screws up some edge-cases for std::exp2(complex).
|
||||
#ifdef EIGEN_COMP_MSVC
|
||||
template <typename RealScalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex<RealScalar> exp2(const std::complex<RealScalar>& x) {
|
||||
EIGEN_USING_STD(exp);
|
||||
// If z is (x,±∞) (for any finite x), the result is (NaN,NaN) and FE_INVALID is raised.
|
||||
// If z is (x,NaN) (for any finite x), the result is (NaN,NaN) and FE_INVALID may be raised.
|
||||
if ((isfinite)(real_ref(x)) && !(isfinite)(imag_ref(x))) {
|
||||
return std::complex<RealScalar>(NumTraits<RealScalar>::quiet_NaN(), NumTraits<RealScalar>::quiet_NaN());
|
||||
}
|
||||
// If z is (+∞,±∞), the result is (±∞,NaN) and FE_INVALID is raised (the sign of the real part is unspecified)
|
||||
// If z is (+∞,NaN), the result is (±∞,NaN) (the sign of the real part is unspecified)
|
||||
if ((real_ref(x) == NumTraits<RealScalar>::infinity() && !(isfinite)(imag_ref(x)))) {
|
||||
return std::complex<RealScalar>(NumTraits<RealScalar>::infinity(), NumTraits<RealScalar>::quiet_NaN());
|
||||
}
|
||||
return exp2(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SYCL_DEVICE_ONLY)
|
||||
SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(exp2, exp2)
|
||||
#endif
|
||||
|
||||
#if defined(EIGEN_GPUCC)
|
||||
template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float exp2(const float& x) {
|
||||
return ::exp2f(x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double exp2(const double& x) {
|
||||
return ::exp2(x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex<float> exp2(const std::complex<float>& x) {
|
||||
float com = ::exp2f(x.real());
|
||||
float res_real = com * ::cosf(static_cast<float>(EIGEN_LN2) * x.imag());
|
||||
float res_imag = com * ::sinf(static_cast<float>(EIGEN_LN2) * x.imag());
|
||||
return std::complex<float>(res_real, res_imag);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex<double> exp2(const std::complex<double>& x) {
|
||||
double com = ::exp2(x.real());
|
||||
double res_real = com * ::cos(static_cast<double>(EIGEN_LN2) * x.imag());
|
||||
double res_imag = com * ::sin(static_cast<double>(EIGEN_LN2) * x.imag());
|
||||
return std::complex<double>(res_real, res_imag);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(expm1, Scalar) expm1(const Scalar& x) {
|
||||
return EIGEN_MATHFUNC_IMPL(expm1, Scalar)::run(x);
|
||||
@@ -1783,6 +1927,18 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar arithmetic_shift_right(const Scalar
|
||||
return bit_cast<Scalar, SignedScalar>(bit_cast<SignedScalar, Scalar>(a) >> n);
|
||||
}
|
||||
|
||||
// Otherwise, rely on template implementation.
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar fma(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return internal::fma_impl<Scalar>::run(x, y, z);
|
||||
}
|
||||
|
||||
// Multiply-add.
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar madd(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return internal::madd_impl<Scalar>::run(x, y, z);
|
||||
}
|
||||
|
||||
} // end namespace numext
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace internal {
|
||||
2. If a is zero, approx_a_recip must be infinite with the same sign as a.
|
||||
3. If a is infinite, approx_a_recip must be zero with the same sign as a.
|
||||
|
||||
If the preconditions are satisfied, which they are for for the _*_rcp_ps
|
||||
If the preconditions are satisfied, which they are for the _*_rcp_ps
|
||||
instructions on x86, the result has a maximum relative error of 2 ulps,
|
||||
and correctly handles reciprocals of zero, infinity, and NaN.
|
||||
*/
|
||||
@@ -66,7 +66,7 @@ struct generic_reciprocal_newton_step<Packet, 0> {
|
||||
2. If a is zero, approx_a_recip must be infinite with the same sign as a.
|
||||
3. If a is infinite, approx_a_recip must be zero with the same sign as a.
|
||||
|
||||
If the preconditions are satisfied, which they are for for the _*_rcp_ps
|
||||
If the preconditions are satisfied, which they are for the _*_rcp_ps
|
||||
instructions on x86, the result has a maximum relative error of 2 ulps,
|
||||
and correctly handles zero, infinity, and NaN. Positive denormals are
|
||||
treated as zero.
|
||||
@@ -76,7 +76,7 @@ struct generic_rsqrt_newton_step {
|
||||
static_assert(Steps > 0, "Steps must be at least 1.");
|
||||
using Scalar = typename unpacket_traits<Packet>::type;
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet run(const Packet& a, const Packet& approx_rsqrt) {
|
||||
constexpr Scalar kMinusHalf = Scalar(-1) / Scalar(2);
|
||||
const Scalar kMinusHalf = Scalar(-1) / Scalar(2);
|
||||
const Packet cst_minus_half = pset1<Packet>(kMinusHalf);
|
||||
const Packet cst_minus_one = pset1<Packet>(Scalar(-1));
|
||||
|
||||
@@ -116,7 +116,7 @@ struct generic_rsqrt_newton_step<Packet, 0> {
|
||||
2. If a is zero, approx_rsqrt must be infinite.
|
||||
3. If a is infinite, approx_rsqrt must be zero.
|
||||
|
||||
If the preconditions are satisfied, which they are for for the _*_rsqrt_ps
|
||||
If the preconditions are satisfied, which they are for the _*_rsqrt_ps
|
||||
instructions on x86, the result has a maximum relative error of 2 ulps,
|
||||
and correctly handles zero and infinity, and NaN. Positive denormal inputs
|
||||
are treated as zero.
|
||||
@@ -171,8 +171,8 @@ struct hypot_impl {
|
||||
|
||||
// Generic complex sqrt implementation that correctly handles corner cases
|
||||
// according to https://en.cppreference.com/w/cpp/numeric/complex/sqrt
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_sqrt(const std::complex<T>& z) {
|
||||
template <typename ComplexT>
|
||||
EIGEN_DEVICE_FUNC ComplexT complex_sqrt(const ComplexT& z) {
|
||||
// Computes the principal sqrt of the input.
|
||||
//
|
||||
// For a complex square root of the number x + i*y. We want to find real
|
||||
@@ -194,21 +194,21 @@ EIGEN_DEVICE_FUNC std::complex<T> complex_sqrt(const std::complex<T>& z) {
|
||||
// if x == 0: u = w, v = sign(y) * w
|
||||
// if x > 0: u = w, v = y / (2 * w)
|
||||
// if x < 0: u = |y| / (2 * w), v = sign(y) * w
|
||||
|
||||
using T = typename NumTraits<ComplexT>::Real;
|
||||
const T x = numext::real(z);
|
||||
const T y = numext::imag(z);
|
||||
const T zero = T(0);
|
||||
const T w = numext::sqrt(T(0.5) * (numext::abs(x) + numext::hypot(x, y)));
|
||||
|
||||
return (numext::isinf)(y) ? std::complex<T>(NumTraits<T>::infinity(), y)
|
||||
: numext::is_exactly_zero(x) ? std::complex<T>(w, y < zero ? -w : w)
|
||||
: x > zero ? std::complex<T>(w, y / (2 * w))
|
||||
: std::complex<T>(numext::abs(y) / (2 * w), y < zero ? -w : w);
|
||||
return (numext::isinf)(y) ? ComplexT(NumTraits<T>::infinity(), y)
|
||||
: numext::is_exactly_zero(x) ? ComplexT(w, y < zero ? -w : w)
|
||||
: x > zero ? ComplexT(w, y / (2 * w))
|
||||
: ComplexT(numext::abs(y) / (2 * w), y < zero ? -w : w);
|
||||
}
|
||||
|
||||
// Generic complex rsqrt implementation.
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_rsqrt(const std::complex<T>& z) {
|
||||
template <typename ComplexT>
|
||||
EIGEN_DEVICE_FUNC ComplexT complex_rsqrt(const ComplexT& z) {
|
||||
// Computes the principal reciprocal sqrt of the input.
|
||||
//
|
||||
// For a complex reciprocal square root of the number z = x + i*y. We want to
|
||||
@@ -230,7 +230,7 @@ EIGEN_DEVICE_FUNC std::complex<T> complex_rsqrt(const std::complex<T>& z) {
|
||||
// if x == 0: u = w / |z|, v = -sign(y) * w / |z|
|
||||
// if x > 0: u = w / |z|, v = -y / (2 * w * |z|)
|
||||
// if x < 0: u = |y| / (2 * w * |z|), v = -sign(y) * w / |z|
|
||||
|
||||
using T = typename NumTraits<ComplexT>::Real;
|
||||
const T x = numext::real(z);
|
||||
const T y = numext::imag(z);
|
||||
const T zero = T(0);
|
||||
@@ -239,20 +239,21 @@ EIGEN_DEVICE_FUNC std::complex<T> complex_rsqrt(const std::complex<T>& z) {
|
||||
const T w = numext::sqrt(T(0.5) * (numext::abs(x) + abs_z));
|
||||
const T woz = w / abs_z;
|
||||
// Corner cases consistent with 1/sqrt(z) on gcc/clang.
|
||||
return numext::is_exactly_zero(abs_z) ? std::complex<T>(NumTraits<T>::infinity(), NumTraits<T>::quiet_NaN())
|
||||
: ((numext::isinf)(x) || (numext::isinf)(y)) ? std::complex<T>(zero, zero)
|
||||
: numext::is_exactly_zero(x) ? std::complex<T>(woz, y < zero ? woz : -woz)
|
||||
: x > zero ? std::complex<T>(woz, -y / (2 * w * abs_z))
|
||||
: std::complex<T>(numext::abs(y) / (2 * w * abs_z), y < zero ? woz : -woz);
|
||||
return numext::is_exactly_zero(abs_z) ? ComplexT(NumTraits<T>::infinity(), NumTraits<T>::quiet_NaN())
|
||||
: ((numext::isinf)(x) || (numext::isinf)(y)) ? ComplexT(zero, zero)
|
||||
: numext::is_exactly_zero(x) ? ComplexT(woz, y < zero ? woz : -woz)
|
||||
: x > zero ? ComplexT(woz, -y / (2 * w * abs_z))
|
||||
: ComplexT(numext::abs(y) / (2 * w * abs_z), y < zero ? woz : -woz);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_log(const std::complex<T>& z) {
|
||||
template <typename ComplexT>
|
||||
EIGEN_DEVICE_FUNC ComplexT complex_log(const ComplexT& z) {
|
||||
// Computes complex log.
|
||||
using T = typename NumTraits<ComplexT>::Real;
|
||||
T a = numext::abs(z);
|
||||
EIGEN_USING_STD(atan2);
|
||||
T b = atan2(z.imag(), z.real());
|
||||
return std::complex<T>(numext::log(a), b);
|
||||
return ComplexT(numext::log(a), b);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
+25
-17
@@ -224,8 +224,6 @@ class Matrix : public PlainObjectBase<Matrix<Scalar_, Rows_, Cols_, Options_, Ma
|
||||
return Base::_set(other);
|
||||
}
|
||||
|
||||
/* Here, doxygen failed to copy the brief information when using \copydoc */
|
||||
|
||||
/**
|
||||
* \brief Copies the generic expression \a other into *this.
|
||||
* \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other)
|
||||
@@ -250,22 +248,31 @@ class Matrix : public PlainObjectBase<Matrix<Scalar_, Rows_, Cols_, Options_, Ma
|
||||
*
|
||||
* \sa resize(Index,Index)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix()
|
||||
: Base(){EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED}
|
||||
|
||||
// FIXME is it still needed
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr explicit Matrix(
|
||||
internal::constructor_without_unaligned_array_assert)
|
||||
: Base(internal::constructor_without_unaligned_array_assert()){EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix(Matrix && other) = default;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix& operator=(Matrix&& other)
|
||||
EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable<Scalar>::value) {
|
||||
#if defined(EIGEN_INITIALIZE_COEFFS)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix() { EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED }
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix() = default;
|
||||
#endif
|
||||
/** \brief Move constructor */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix(Matrix&&) = default;
|
||||
/** \brief Moves the matrix into the other one.
|
||||
*
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix& operator=(Matrix&& other) noexcept(
|
||||
std::is_nothrow_move_assignable<Scalar>::value) {
|
||||
Base::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \copydoc PlainObjectBase(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&... args)
|
||||
/** \brief Construct a row of column vector with fixed size from an arbitrary number of coefficients.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* This constructor is for 1D array or vectors with more than 4 coefficients.
|
||||
*
|
||||
* \warning To construct a column (resp. row) vector of fixed length, the number of values passed to this
|
||||
* constructor must match the the fixed number of rows (resp. columns) of \c *this.
|
||||
*
|
||||
*
|
||||
* Example: \include Matrix_variadic_ctor_cxx11.cpp
|
||||
* Output: \verbinclude Matrix_variadic_ctor_cxx11.out
|
||||
@@ -279,6 +286,7 @@ class Matrix : public PlainObjectBase<Matrix<Scalar_, Rows_, Cols_, Options_, Ma
|
||||
|
||||
/** \brief Constructs a Matrix and initializes it from the coefficients given as initializer-lists grouped by row.
|
||||
* \cpp11
|
||||
* \anchor matrix_initializer_list
|
||||
*
|
||||
* In the general case, the constructor takes a list of rows, each row being represented as a list of coefficients:
|
||||
*
|
||||
@@ -377,7 +385,7 @@ class Matrix : public PlainObjectBase<Matrix<Scalar_, Rows_, Cols_, Options_, Ma
|
||||
}
|
||||
|
||||
/** \brief Copy constructor */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix(const Matrix& other) = default;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Matrix(const Matrix&) = default;
|
||||
|
||||
/** \brief Copy constructor for generic expressions.
|
||||
* \sa MatrixBase::operator=(const EigenBase<OtherDerived>&)
|
||||
@@ -385,8 +393,8 @@ class Matrix : public PlainObjectBase<Matrix<Scalar_, Rows_, Cols_, Options_, Ma
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix(const EigenBase<OtherDerived>& other) : Base(other.derived()) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT { return 1; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { return this->innerSize(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return 1; }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return this->innerSize(); }
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
ConstTransposeReturnType>
|
||||
AdjointReturnType;
|
||||
/** \internal Return type of eigenvalues() */
|
||||
typedef Matrix<std::complex<RealScalar>, internal::traits<Derived>::ColsAtCompileTime, 1, ColMajor>
|
||||
typedef Matrix<internal::make_complex_t<Scalar>, internal::traits<Derived>::ColsAtCompileTime, 1, ColMajor>
|
||||
EigenvaluesReturnType;
|
||||
/** \internal the return type of identity */
|
||||
typedef CwiseNullaryOp<internal::scalar_identity_op<Scalar>, PlainObject> IdentityReturnType;
|
||||
@@ -280,7 +280,7 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
* \sa isApprox(), operator!= */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC inline bool operator==(const MatrixBase<OtherDerived>& other) const {
|
||||
return cwiseEqual(other).all();
|
||||
return (this->rows() == other.rows()) && (this->cols() == other.cols()) && cwiseEqual(other).all();
|
||||
}
|
||||
|
||||
/** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other.
|
||||
@@ -289,7 +289,7 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
* \sa isApprox(), operator== */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC inline bool operator!=(const MatrixBase<OtherDerived>& other) const {
|
||||
return cwiseNotEqual(other).any();
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
NoAlias<Derived, Eigen::MatrixBase> EIGEN_DEVICE_FUNC noalias();
|
||||
@@ -373,12 +373,14 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
template <int Options = 0>
|
||||
inline JacobiSVD<PlainObject, Options> jacobiSvd() const;
|
||||
template <int Options = 0>
|
||||
EIGEN_DEPRECATED inline JacobiSVD<PlainObject, Options> jacobiSvd(unsigned int computationOptions) const;
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using method's template parameter.")
|
||||
inline JacobiSVD<PlainObject, Options> jacobiSvd(unsigned int computationOptions) const;
|
||||
|
||||
template <int Options = 0>
|
||||
inline BDCSVD<PlainObject, Options> bdcSvd() const;
|
||||
template <int Options = 0>
|
||||
EIGEN_DEPRECATED inline BDCSVD<PlainObject, Options> bdcSvd(unsigned int computationOptions) const;
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using method's template parameter.")
|
||||
inline BDCSVD<PlainObject, Options> bdcSvd(unsigned int computationOptions) const;
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
@@ -391,7 +393,8 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
|
||||
EIGEN_DEVICE_FUNC inline PlainObject unitOrthogonal(void) const;
|
||||
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline Matrix<Scalar, 3, 1> eulerAngles(Index a0, Index a1, Index a2) const;
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .canonicalEulerAngles() instead.")
|
||||
EIGEN_DEVICE_FUNC inline Matrix<Scalar, 3, 1> eulerAngles(Index a0, Index a1, Index a2) const;
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Matrix<Scalar, 3, 1> canonicalEulerAngles(Index a0, Index a1, Index a2) const;
|
||||
|
||||
@@ -468,7 +471,7 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
EIGEN_MATRIX_FUNCTION(MatrixSquareRootReturnValue, sqrt, square root)
|
||||
EIGEN_MATRIX_FUNCTION(MatrixLogarithmReturnValue, log, logarithm)
|
||||
EIGEN_MATRIX_FUNCTION_1(MatrixPowerReturnValue, pow, power to \c p, const RealScalar& p)
|
||||
EIGEN_MATRIX_FUNCTION_1(MatrixComplexPowerReturnValue, pow, power to \c p, const std::complex<RealScalar>& p)
|
||||
EIGEN_MATRIX_FUNCTION_1(MatrixComplexPowerReturnValue, pow, power to \c p, const internal::make_complex_t<Scalar>& p)
|
||||
|
||||
protected:
|
||||
EIGEN_DEFAULT_COPY_CONSTRUCTOR(MatrixBase)
|
||||
|
||||
@@ -45,8 +45,8 @@ class NestByValue : public internal::dense_xpr_base<NestByValue<ExpressionType>
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit inline NestByValue(const ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC operator const ExpressionType&() const { return m_expression; }
|
||||
|
||||
|
||||
+84
-77
@@ -22,13 +22,13 @@ namespace internal {
|
||||
template <typename T, bool use_numeric_limits = std::numeric_limits<T>::is_specialized,
|
||||
bool is_integer = NumTraits<T>::IsInteger>
|
||||
struct default_digits_impl {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() { return std::numeric_limits<T>::digits; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() { return std::numeric_limits<T>::digits; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct default_digits_impl<T, false, false> // Floating point
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() {
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() {
|
||||
using std::ceil;
|
||||
using std::log2;
|
||||
typedef typename NumTraits<T>::Real Real;
|
||||
@@ -39,7 +39,7 @@ struct default_digits_impl<T, false, false> // Floating point
|
||||
template <typename T>
|
||||
struct default_digits_impl<T, false, true> // Integer
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() { return 0; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() { return 0; }
|
||||
};
|
||||
|
||||
// default implementation of digits10(), based on numeric_limits if specialized,
|
||||
@@ -47,13 +47,13 @@ struct default_digits_impl<T, false, true> // Integer
|
||||
template <typename T, bool use_numeric_limits = std::numeric_limits<T>::is_specialized,
|
||||
bool is_integer = NumTraits<T>::IsInteger>
|
||||
struct default_digits10_impl {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() { return std::numeric_limits<T>::digits10; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() { return std::numeric_limits<T>::digits10; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct default_digits10_impl<T, false, false> // Floating point
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() {
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() {
|
||||
using std::floor;
|
||||
using std::log10;
|
||||
typedef typename NumTraits<T>::Real Real;
|
||||
@@ -64,7 +64,7 @@ struct default_digits10_impl<T, false, false> // Floating point
|
||||
template <typename T>
|
||||
struct default_digits10_impl<T, false, true> // Integer
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() { return 0; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() { return 0; }
|
||||
};
|
||||
|
||||
// default implementation of max_digits10(), based on numeric_limits if specialized,
|
||||
@@ -72,13 +72,13 @@ struct default_digits10_impl<T, false, true> // Integer
|
||||
template <typename T, bool use_numeric_limits = std::numeric_limits<T>::is_specialized,
|
||||
bool is_integer = NumTraits<T>::IsInteger>
|
||||
struct default_max_digits10_impl {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() { return std::numeric_limits<T>::max_digits10; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() { return std::numeric_limits<T>::max_digits10; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct default_max_digits10_impl<T, false, false> // Floating point
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() {
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() {
|
||||
using std::ceil;
|
||||
using std::log10;
|
||||
typedef typename NumTraits<T>::Real Real;
|
||||
@@ -89,15 +89,28 @@ struct default_max_digits10_impl<T, false, false> // Floating point
|
||||
template <typename T>
|
||||
struct default_max_digits10_impl<T, false, true> // Integer
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static int run() { return 0; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int run() { return 0; }
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
namespace numext {
|
||||
/** \internal bit-wise cast without changing the underlying bit representation. */
|
||||
|
||||
// TODO: Replace by std::bit_cast (available in C++20)
|
||||
/** \internal bit-wise cast without changing the underlying bit representation. */
|
||||
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
template <typename Tgt, typename Src>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) {
|
||||
return std::bit_cast<Tgt>(src);
|
||||
}
|
||||
#elif EIGEN_HAS_BUILTIN(__builtin_bit_cast)
|
||||
template <typename Tgt, typename Src>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) {
|
||||
EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Src>::value, THIS_TYPE_IS_NOT_SUPPORTED)
|
||||
EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Tgt>::value, THIS_TYPE_IS_NOT_SUPPORTED)
|
||||
EIGEN_STATIC_ASSERT(sizeof(Src) == sizeof(Tgt), THIS_TYPE_IS_NOT_SUPPORTED)
|
||||
return __builtin_bit_cast(Tgt, src);
|
||||
}
|
||||
#else
|
||||
template <typename Tgt, typename Src>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
|
||||
// The behaviour of memcpy is not specified for non-trivially copyable types
|
||||
@@ -113,8 +126,10 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
|
||||
memcpy(static_cast<void*>(&tgt), static_cast<const void*>(&staged), sizeof(Tgt));
|
||||
return tgt;
|
||||
}
|
||||
#endif
|
||||
} // namespace numext
|
||||
|
||||
// clang-format off
|
||||
/** \class NumTraits
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
@@ -126,48 +141,50 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
|
||||
*
|
||||
* The provided data consists of:
|
||||
* \li A typedef \c Real, giving the "real part" type of \a T. If \a T is already real,
|
||||
* then \c Real is just a typedef to \a T. If \a T is \c std::complex<U> then \c Real
|
||||
* then \c Real is just a typedef to \a T. If \a T is `std::complex<U>` then \c Real
|
||||
* is a typedef to \a U.
|
||||
* \li A typedef \c NonInteger, giving the type that should be used for operations producing non-integral values,
|
||||
* such as quotients, square roots, etc. If \a T is a floating-point type, then this typedef just gives
|
||||
* \a T again. Note however that many Eigen functions such as internal::sqrt simply refuse to
|
||||
* take integers. Outside of a few cases, Eigen doesn't do automatic type promotion. Thus, this typedef is
|
||||
* only intended as a helper for code that needs to explicitly promote types.
|
||||
* \li A typedef \c Literal giving the type to use for numeric literals such as "2" or "0.5". For instance, for \c
|
||||
* std::complex<U>, Literal is defined as \c U. Of course, this type must be fully compatible with \a T. In doubt, just
|
||||
* use \a T here. \li A typedef \a Nested giving the type to use to nest a value inside of the expression tree. If you
|
||||
* don't know what this means, just use \a T here. \li An enum value \a IsComplex. It is equal to 1 if \a T is a \c
|
||||
* std::complex type, and to 0 otherwise. \li An enum value \a IsInteger. It is equal to \c 1 if \a T is an integer type
|
||||
* such as \c int, and to \c 0 otherwise. \li Enum values ReadCost, AddCost and MulCost representing a rough estimate of
|
||||
* the number of CPU cycles needed to by move / add / mul instructions respectively, assuming the data is already stored
|
||||
* in CPU registers. Stay vague here. No need to do architecture-specific stuff. If you don't know what this means, just
|
||||
* use \c Eigen::HugeCost. \li An enum value \a IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T
|
||||
* is unsigned. \li An enum value \a RequireInitialization. It is equal to \c 1 if the constructor of the numeric type
|
||||
* \a T must be called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1
|
||||
* otherwise. \li An epsilon() function which, unlike <a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/epsilon">std::numeric_limits::epsilon()</a>, it returns a
|
||||
* \a Real instead of a \a T. \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a
|
||||
* default value by the fuzzy comparison operators. \li highest() and lowest() functions returning the highest and
|
||||
* lowest possible values respectively. \li digits() function returning the number of radix digits (non-sign digits for
|
||||
* integers, mantissa for floating-point). This is the analogue of <a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits">std::numeric_limits<T>::digits</a> which is used
|
||||
* as the default implementation if specialized. \li digits10() function returning the number of decimal digits that can
|
||||
* be represented without change. This is the analogue of <a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits10">std::numeric_limits<T>::digits10</a> which is
|
||||
* used as the default implementation if specialized. \li max_digits10() function returning the number of decimal digits
|
||||
* required to uniquely represent all distinct values of the type. This is the analogue of <a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10">std::numeric_limits<T>::max_digits10</a>
|
||||
* \li A typedef \c Literal giving the type to use for numeric literals such as "2" or "0.5". For instance, for
|
||||
* `std::complex<U>`, Literal is defined as \a U. Of course, this type must be fully compatible with \a T. In doubt,
|
||||
* just use \a T here.
|
||||
* \li A typedef \c Nested giving the type to use to nest a value inside of the expression tree. If you don't know what
|
||||
* this means, just use \a T here.
|
||||
* \li An enum value \c IsComplex. It is equal to 1 if \a T is a \c std::complex type, and to 0 otherwise.
|
||||
* \li An enum value \c IsInteger. It is equal to \c 1 if \a T is an integer type such as \c int, and to \c 0 otherwise.
|
||||
* \li Enum values \c ReadCost, \c AddCost and \c MulCost representing a rough estimate of the number of CPU cycles needed to by
|
||||
* move / add / mul instructions respectively, assuming the data is already stored in CPU registers. Stay vague here.
|
||||
* No need to do architecture-specific stuff. If you don't know what this means, just use \c Eigen::HugeCost.
|
||||
* \li An enum value \c IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T is unsigned.
|
||||
* \li An enum value \c RequireInitialization. It is equal to \c 1 if the constructor of the numeric type \a T must be
|
||||
* called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1 otherwise.
|
||||
* \li An epsilon() function which, unlike <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/epsilon">
|
||||
* `std::numeric_limits::epsilon()`</a>, it returns a \c Real instead of a \a T.
|
||||
* \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a default value by the fuzzy
|
||||
* comparison operators.
|
||||
* \li highest() and lowest() functions returning the highest and lowest possible values respectively.
|
||||
* \li digits() function returning the number of radix digits (non-sign digits for integers, mantissa for floating-point).
|
||||
* This is the analogue of <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits">
|
||||
* `std::numeric_limits<T>::digits`</a> which is used as the default implementation if specialized.
|
||||
* \li digits10() function returning the number of decimal digits that can be represented without change. This is the
|
||||
* analogue of <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits10">
|
||||
* `std::numeric_limits<T>::digits10`</a> which is used as the default implementation if specialized.
|
||||
* \li max_digits10() function returning the number of decimal digits required to uniquely represent all distinct values
|
||||
* of the type. This is the analogue of <a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10">`std::numeric_limits<T>::max_digits10`</a>
|
||||
* which is used as the default implementation if specialized.
|
||||
* \li min_exponent() and max_exponent() functions returning the highest and lowest possible values, respectively,
|
||||
* such that the radix raised to the power exponent-1 is a normalized floating-point number. These are equivalent
|
||||
* to <a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/min_exponent">std::numeric_limits<T>::min_exponent</a>/
|
||||
* <a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/max_exponent">std::numeric_limits<T>::max_exponent</a>.
|
||||
* to <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/min_exponent">
|
||||
* `std::numeric_limits<T>::min_exponent`</a>/<a
|
||||
* href="http://en.cppreference.com/w/cpp/types/numeric_limits/max_exponent">`std::numeric_limits<T>::max_exponent`</a>.
|
||||
* \li infinity() function returning a representation of positive infinity, if available.
|
||||
* \li quiet_NaN function returning a non-signaling "not-a-number", if available.
|
||||
* \li quiet_NaN() function returning a non-signaling "not-a-number", if available.
|
||||
*/
|
||||
|
||||
// clang-format on
|
||||
template <typename T>
|
||||
struct GenericNumTraits {
|
||||
enum {
|
||||
@@ -185,32 +202,30 @@ struct GenericNumTraits {
|
||||
typedef T Nested;
|
||||
typedef T Literal;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline Real epsilon() { return numext::numeric_limits<T>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static Real epsilon() { return numext::numeric_limits<T>::epsilon(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline int digits10() { return internal::default_digits10_impl<T>::run(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static int digits10() { return internal::default_digits10_impl<T>::run(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline int max_digits10() {
|
||||
return internal::default_max_digits10_impl<T>::run();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr static int max_digits10() { return internal::default_max_digits10_impl<T>::run(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline int digits() { return internal::default_digits_impl<T>::run(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static int digits() { return internal::default_digits_impl<T>::run(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline int min_exponent() { return numext::numeric_limits<T>::min_exponent; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int min_exponent() { return numext::numeric_limits<T>::min_exponent; }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline int max_exponent() { return numext::numeric_limits<T>::max_exponent; }
|
||||
EIGEN_DEVICE_FUNC constexpr static int max_exponent() { return numext::numeric_limits<T>::max_exponent; }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline Real dummy_precision() {
|
||||
EIGEN_DEVICE_FUNC constexpr static Real dummy_precision() {
|
||||
// make sure to override this for floating-point types
|
||||
return Real(0);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline T highest() { return (numext::numeric_limits<T>::max)(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static T highest() { return (numext::numeric_limits<T>::max)(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline T lowest() { return (numext::numeric_limits<T>::lowest)(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static T lowest() { return (numext::numeric_limits<T>::lowest)(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline T infinity() { return numext::numeric_limits<T>::infinity(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static T infinity() { return numext::numeric_limits<T>::infinity(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline T quiet_NaN() { return numext::numeric_limits<T>::quiet_NaN(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static T quiet_NaN() { return numext::numeric_limits<T>::quiet_NaN(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -218,25 +233,23 @@ struct NumTraits : GenericNumTraits<T> {};
|
||||
|
||||
template <>
|
||||
struct NumTraits<float> : GenericNumTraits<float> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline float dummy_precision() { return 1e-5f; }
|
||||
EIGEN_DEVICE_FUNC constexpr static float dummy_precision() { return 1e-5f; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct NumTraits<double> : GenericNumTraits<double> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline double dummy_precision() { return 1e-12; }
|
||||
EIGEN_DEVICE_FUNC constexpr static double dummy_precision() { return 1e-12; }
|
||||
};
|
||||
|
||||
// GPU devices treat `long double` as `double`.
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template <>
|
||||
struct NumTraits<long double> : GenericNumTraits<long double> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline long double dummy_precision() {
|
||||
return static_cast<long double>(1e-15l);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr static long double dummy_precision() { return static_cast<long double>(1e-15l); }
|
||||
|
||||
#if defined(EIGEN_ARCH_PPC) && (__LDBL_MANT_DIG__ == 106)
|
||||
// PowerPC double double causes issues with some values
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline long double epsilon() {
|
||||
EIGEN_DEVICE_FUNC constexpr static long double epsilon() {
|
||||
// 2^(-(__LDBL_MANT_DIG__)+1)
|
||||
return static_cast<long double>(2.4651903288156618919116517665087e-32l);
|
||||
}
|
||||
@@ -257,10 +270,10 @@ struct NumTraits<std::complex<Real_> > : GenericNumTraits<std::complex<Real_> >
|
||||
MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline Real epsilon() { return NumTraits<Real>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline Real dummy_precision() { return NumTraits<Real>::dummy_precision(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline int digits10() { return NumTraits<Real>::digits10(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline int max_digits10() { return NumTraits<Real>::max_digits10(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static Real epsilon() { return NumTraits<Real>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static Real dummy_precision() { return NumTraits<Real>::dummy_precision(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static int digits10() { return NumTraits<Real>::digits10(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static int max_digits10() { return NumTraits<Real>::max_digits10(); }
|
||||
};
|
||||
|
||||
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
|
||||
@@ -287,25 +300,19 @@ struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > {
|
||||
: ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::MulCost)
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR static inline RealScalar dummy_precision() {
|
||||
return NumTraits<RealScalar>::dummy_precision();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr static RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC constexpr static RealScalar dummy_precision() { return NumTraits<RealScalar>::dummy_precision(); }
|
||||
|
||||
EIGEN_CONSTEXPR
|
||||
static inline int digits10() { return NumTraits<Scalar>::digits10(); }
|
||||
EIGEN_CONSTEXPR
|
||||
static inline int max_digits10() { return NumTraits<Scalar>::max_digits10(); }
|
||||
constexpr static int digits10() { return NumTraits<Scalar>::digits10(); }
|
||||
constexpr static int max_digits10() { return NumTraits<Scalar>::max_digits10(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct NumTraits<std::string> : GenericNumTraits<std::string> {
|
||||
enum { RequireInitialization = 1, ReadCost = HugeCost, AddCost = HugeCost, MulCost = HugeCost };
|
||||
|
||||
EIGEN_CONSTEXPR
|
||||
static inline int digits10() { return 0; }
|
||||
EIGEN_CONSTEXPR
|
||||
static inline int max_digits10() { return 0; }
|
||||
constexpr static int digits10() { return 0; }
|
||||
constexpr static int max_digits10() { return 0; }
|
||||
|
||||
private:
|
||||
static inline std::string epsilon();
|
||||
|
||||
@@ -103,19 +103,36 @@ struct packetwise_redux_impl<Func, Evaluator, NoUnrolling> {
|
||||
EIGEN_DEVICE_FUNC static PacketType run(const Evaluator& eval, const Func& func, Index size) {
|
||||
if (size == 0) return packetwise_redux_empty_value<PacketType>(func);
|
||||
|
||||
const Index size4 = (size - 1) & (~3);
|
||||
const Index size4 = 1 + numext::round_down(size - 1, 4);
|
||||
PacketType p = eval.template packetByOuterInner<Unaligned, PacketType>(0, 0);
|
||||
Index i = 1;
|
||||
// This loop is optimized for instruction pipelining:
|
||||
// - each iteration generates two independent instructions
|
||||
// - thanks to branch prediction and out-of-order execution we have independent instructions across loops
|
||||
for (; i < size4; i += 4)
|
||||
for (Index i = 1; i < size4; i += 4)
|
||||
p = func.packetOp(
|
||||
p, func.packetOp(func.packetOp(eval.template packetByOuterInner<Unaligned, PacketType>(i + 0, 0),
|
||||
eval.template packetByOuterInner<Unaligned, PacketType>(i + 1, 0)),
|
||||
func.packetOp(eval.template packetByOuterInner<Unaligned, PacketType>(i + 2, 0),
|
||||
eval.template packetByOuterInner<Unaligned, PacketType>(i + 3, 0))));
|
||||
for (; i < size; ++i) p = func.packetOp(p, eval.template packetByOuterInner<Unaligned, PacketType>(i, 0));
|
||||
for (Index i = size4; i < size; ++i)
|
||||
p = func.packetOp(p, eval.template packetByOuterInner<Unaligned, PacketType>(i, 0));
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Func, typename Evaluator>
|
||||
struct packetwise_segment_redux_impl {
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Evaluator>::PacketType PacketScalar;
|
||||
|
||||
template <typename PacketType>
|
||||
EIGEN_DEVICE_FUNC static PacketType run(const Evaluator& eval, const Func& func, Index size, Index begin,
|
||||
Index count) {
|
||||
if (size == 0) return packetwise_redux_empty_value<PacketType>(func);
|
||||
|
||||
PacketType p = eval.template packetSegmentByOuterInner<Unaligned, PacketType>(0, 0, begin, count);
|
||||
for (Index i = 1; i < size; ++i)
|
||||
p = func.packetOp(p, eval.template packetSegmentByOuterInner<Unaligned, PacketType>(i, 0, begin, count));
|
||||
return p;
|
||||
}
|
||||
};
|
||||
@@ -174,14 +191,13 @@ struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC PacketType packet(Index idx) const {
|
||||
enum { PacketSize = internal::unpacket_traits<PacketType>::size };
|
||||
typedef Block<const ArgTypeNestedCleaned, Direction == Vertical ? int(ArgType::RowsAtCompileTime) : int(PacketSize),
|
||||
Direction == Vertical ? int(PacketSize) : int(ArgType::ColsAtCompileTime), true /* InnerPanel */>
|
||||
PanelType;
|
||||
|
||||
PanelType panel(m_arg, Direction == Vertical ? 0 : idx, Direction == Vertical ? idx : 0,
|
||||
Direction == Vertical ? m_arg.rows() : Index(PacketSize),
|
||||
Direction == Vertical ? Index(PacketSize) : m_arg.cols());
|
||||
static constexpr int PacketSize = internal::unpacket_traits<PacketType>::size;
|
||||
static constexpr int PanelRows = Direction == Vertical ? ArgType::RowsAtCompileTime : PacketSize;
|
||||
static constexpr int PanelCols = Direction == Vertical ? PacketSize : ArgType::ColsAtCompileTime;
|
||||
using PanelType = Block<const ArgTypeNestedCleaned, PanelRows, PanelCols, true /* InnerPanel */>;
|
||||
using PanelEvaluator = typename internal::redux_evaluator<PanelType>;
|
||||
using BinaryOp = typename MemberOp::BinaryOp;
|
||||
using Impl = internal::packetwise_redux_impl<BinaryOp, PanelEvaluator>;
|
||||
|
||||
// FIXME
|
||||
// See bug 1612, currently if PacketSize==1 (i.e. complex<double> with 128bits registers) then the storage-order of
|
||||
@@ -189,11 +205,39 @@ struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
// by pass "vectorization" in this case:
|
||||
if (PacketSize == 1) return internal::pset1<PacketType>(coeff(idx));
|
||||
|
||||
typedef typename internal::redux_evaluator<PanelType> PanelEvaluator;
|
||||
Index startRow = Direction == Vertical ? 0 : idx;
|
||||
Index startCol = Direction == Vertical ? idx : 0;
|
||||
Index numRows = Direction == Vertical ? m_arg.rows() : PacketSize;
|
||||
Index numCols = Direction == Vertical ? PacketSize : m_arg.cols();
|
||||
|
||||
PanelType panel(m_arg, startRow, startCol, numRows, numCols);
|
||||
PanelEvaluator panel_eval(panel);
|
||||
typedef typename MemberOp::BinaryOp BinaryOp;
|
||||
PacketType p = internal::packetwise_redux_impl<BinaryOp, PanelEvaluator>::template run<PacketType>(
|
||||
panel_eval, m_functor.binaryFunc(), m_arg.outerSize());
|
||||
PacketType p = Impl::template run<PacketType>(panel_eval, m_functor.binaryFunc(), m_arg.outerSize());
|
||||
return p;
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index i, Index j, Index begin, Index count) const {
|
||||
return packetSegment<LoadMode, PacketType>(Direction == Vertical ? j : i, begin, count);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC PacketType packetSegment(Index idx, Index begin, Index count) const {
|
||||
static constexpr int PanelRows = Direction == Vertical ? ArgType::RowsAtCompileTime : Dynamic;
|
||||
static constexpr int PanelCols = Direction == Vertical ? Dynamic : ArgType::ColsAtCompileTime;
|
||||
using PanelType = Block<const ArgTypeNestedCleaned, PanelRows, PanelCols, true /* InnerPanel */>;
|
||||
using PanelEvaluator = typename internal::redux_evaluator<PanelType>;
|
||||
using BinaryOp = typename MemberOp::BinaryOp;
|
||||
using Impl = internal::packetwise_segment_redux_impl<BinaryOp, PanelEvaluator>;
|
||||
|
||||
Index startRow = Direction == Vertical ? 0 : idx;
|
||||
Index startCol = Direction == Vertical ? idx : 0;
|
||||
Index numRows = Direction == Vertical ? m_arg.rows() : begin + count;
|
||||
Index numCols = Direction == Vertical ? begin + count : m_arg.cols();
|
||||
|
||||
PanelType panel(m_arg, startRow, startCol, numRows, numCols);
|
||||
PanelEvaluator panel_eval(panel);
|
||||
PacketType p = Impl::template run<PacketType>(panel_eval, m_functor.binaryFunc(), m_arg.outerSize(), begin, count);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -468,17 +468,17 @@ class PermutationWrapper : public PermutationBase<PermutationWrapper<IndicesType
|
||||
/** \returns the matrix with the permutation applied to the columns.
|
||||
*/
|
||||
template <typename MatrixDerived, typename PermutationDerived>
|
||||
EIGEN_DEVICE_FUNC const Product<MatrixDerived, PermutationDerived, AliasFreeProduct> operator*(
|
||||
EIGEN_DEVICE_FUNC const Product<MatrixDerived, PermutationDerived, DefaultProduct> operator*(
|
||||
const MatrixBase<MatrixDerived>& matrix, const PermutationBase<PermutationDerived>& permutation) {
|
||||
return Product<MatrixDerived, PermutationDerived, AliasFreeProduct>(matrix.derived(), permutation.derived());
|
||||
return Product<MatrixDerived, PermutationDerived, DefaultProduct>(matrix.derived(), permutation.derived());
|
||||
}
|
||||
|
||||
/** \returns the matrix with the permutation applied to the rows.
|
||||
*/
|
||||
template <typename PermutationDerived, typename MatrixDerived>
|
||||
EIGEN_DEVICE_FUNC const Product<PermutationDerived, MatrixDerived, AliasFreeProduct> operator*(
|
||||
EIGEN_DEVICE_FUNC const Product<PermutationDerived, MatrixDerived, DefaultProduct> operator*(
|
||||
const PermutationBase<PermutationDerived>& permutation, const MatrixBase<MatrixDerived>& matrix) {
|
||||
return Product<PermutationDerived, MatrixDerived, AliasFreeProduct>(permutation.derived(), matrix.derived());
|
||||
return Product<PermutationDerived, MatrixDerived, DefaultProduct>(permutation.derived(), matrix.derived());
|
||||
}
|
||||
|
||||
template <typename PermutationType>
|
||||
@@ -520,16 +520,16 @@ class InverseImpl<PermutationType, PermutationStorage> : public EigenBase<Invers
|
||||
/** \returns the matrix with the inverse permutation applied to the columns.
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
friend const Product<OtherDerived, InverseType, AliasFreeProduct> operator*(const MatrixBase<OtherDerived>& matrix,
|
||||
const InverseType& trPerm) {
|
||||
return Product<OtherDerived, InverseType, AliasFreeProduct>(matrix.derived(), trPerm.derived());
|
||||
friend const Product<OtherDerived, InverseType, DefaultProduct> operator*(const MatrixBase<OtherDerived>& matrix,
|
||||
const InverseType& trPerm) {
|
||||
return Product<OtherDerived, InverseType, DefaultProduct>(matrix.derived(), trPerm.derived());
|
||||
}
|
||||
|
||||
/** \returns the matrix with the inverse permutation applied to the rows.
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
const Product<InverseType, OtherDerived, AliasFreeProduct> operator*(const MatrixBase<OtherDerived>& matrix) const {
|
||||
return Product<InverseType, OtherDerived, AliasFreeProduct>(derived(), matrix.derived());
|
||||
const Product<InverseType, OtherDerived, DefaultProduct> operator*(const MatrixBase<OtherDerived>& matrix) const {
|
||||
return Product<InverseType, OtherDerived, DefaultProduct>(derived(), matrix.derived());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -80,27 +80,6 @@ struct matrix_swap_impl;
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
namespace doxygen {
|
||||
|
||||
// This is a workaround to doxygen not being able to understand the inheritance logic
|
||||
// when it is hidden by the dense_xpr_base helper struct.
|
||||
// Moreover, doxygen fails to include members that are not documented in the declaration body of
|
||||
// MatrixBase if we inherits MatrixBase<Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_> >,
|
||||
// this is why we simply inherits MatrixBase, though this does not make sense.
|
||||
|
||||
/** This class is just a workaround for Doxygen and it does not not actually exist. */
|
||||
template <typename Derived>
|
||||
struct dense_xpr_base_dispatcher;
|
||||
/** This class is just a workaround for Doxygen and it does not not actually exist. */
|
||||
template <typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_>
|
||||
struct dense_xpr_base_dispatcher<Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>> : public MatrixBase {};
|
||||
/** This class is just a workaround for Doxygen and it does not not actually exist. */
|
||||
template <typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_>
|
||||
struct dense_xpr_base_dispatcher<Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>> : public ArrayBase {};
|
||||
|
||||
} // namespace doxygen
|
||||
|
||||
/** \class PlainObjectBase
|
||||
* \ingroup Core_Module
|
||||
* \brief %Dense storage base class for matrices and arrays.
|
||||
@@ -113,12 +92,7 @@ struct dense_xpr_base_dispatcher<Array<Scalar_, Rows_, Cols_, Options_, MaxRows_
|
||||
* \sa \ref TopicClassHierarchy
|
||||
*/
|
||||
template <typename Derived>
|
||||
class PlainObjectBase : public doxygen::dense_xpr_base_dispatcher<Derived>
|
||||
#else
|
||||
template <typename Derived>
|
||||
class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
#endif
|
||||
{
|
||||
class PlainObjectBase : public internal::dense_xpr_base<Derived>::type {
|
||||
public:
|
||||
enum { Options = internal::traits<Derived>::Options };
|
||||
typedef typename internal::dense_xpr_base<Derived>::type Base;
|
||||
@@ -188,8 +162,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
EIGEN_DEVICE_FUNC Base& base() { return *static_cast<Base*>(this); }
|
||||
EIGEN_DEVICE_FUNC const Base& base() const { return *static_cast<const Base*>(this); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_storage.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_storage.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const noexcept { return m_storage.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const noexcept { return m_storage.cols(); }
|
||||
|
||||
/** This is an overloaded version of DenseCoeffsBase<Derived,ReadOnlyAccessors>::coeff(Index,Index) const
|
||||
* provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts.
|
||||
@@ -324,7 +298,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
*
|
||||
* \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC inline constexpr void resize(Index size) {
|
||||
EIGEN_DEVICE_FUNC constexpr void resize(Index size) {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
|
||||
eigen_assert(((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime == Dynamic || size <= MaxSizeAtCompileTime)) ||
|
||||
SizeAtCompileTime == size) &&
|
||||
@@ -349,7 +323,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
*
|
||||
* \sa resize(Index,Index)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC inline constexpr void resize(NoChange_t, Index cols) { resize(rows(), cols); }
|
||||
EIGEN_DEVICE_FUNC constexpr void resize(NoChange_t, Index cols) { resize(rows(), cols); }
|
||||
|
||||
/** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special
|
||||
* value \c NoChange as in the example below.
|
||||
@@ -359,7 +333,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
*
|
||||
* \sa resize(Index,Index)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC inline constexpr void resize(Index rows, NoChange_t) { resize(rows, cols()); }
|
||||
EIGEN_DEVICE_FUNC constexpr void resize(Index rows, NoChange_t) { resize(rows, cols()); }
|
||||
|
||||
/** Resizes \c *this to have the same dimensions as \a other.
|
||||
* Takes care of doing all the checking that's needed.
|
||||
@@ -472,32 +446,19 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
// Prevent user from trying to instantiate PlainObjectBase objects
|
||||
// by making all its constructor protected. See bug 1074.
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase() : m_storage() {
|
||||
// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
// FIXME is it still needed ?
|
||||
/** \internal */
|
||||
EIGEN_DEVICE_FUNC constexpr explicit PlainObjectBase(internal::constructor_without_unaligned_array_assert)
|
||||
: m_storage(internal::constructor_without_unaligned_array_assert()) {
|
||||
// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase(PlainObjectBase&& other) = default;
|
||||
|
||||
EIGEN_DEVICE_FUNC constexpr PlainObjectBase& operator=(PlainObjectBase&& other) EIGEN_NOEXCEPT {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase() = default;
|
||||
/** \brief Move constructor */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase(PlainObjectBase&&) = default;
|
||||
/** \brief Move assignment operator */
|
||||
EIGEN_DEVICE_FUNC constexpr PlainObjectBase& operator=(PlainObjectBase&& other) noexcept {
|
||||
m_storage = std::move(other.m_storage);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Copy constructor */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase(const PlainObjectBase& other) = default;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase(const PlainObjectBase&) = default;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
|
||||
: m_storage(size, rows, cols) {
|
||||
// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
: m_storage(size, rows, cols) {}
|
||||
|
||||
/** \brief Construct a row of column vector with fixed size from an arbitrary number of coefficients.
|
||||
*
|
||||
@@ -538,7 +499,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
eigen_assert(list_size == static_cast<size_t>(RowsAtCompileTime) || RowsAtCompileTime == Dynamic);
|
||||
resize(list_size, ColsAtCompileTime);
|
||||
if (list.begin()->begin() != nullptr) {
|
||||
std::copy(list.begin()->begin(), list.begin()->end(), m_storage.data());
|
||||
Index index = 0;
|
||||
for (const Scalar& e : *list.begin()) {
|
||||
coeffRef(index++) = e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eigen_assert(list.size() == static_cast<size_t>(RowsAtCompileTime) || RowsAtCompileTime == Dynamic);
|
||||
|
||||
@@ -224,8 +224,8 @@ class Product
|
||||
"if you wanted a coeff-wise or a dot product use the respective explicit functions");
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_lhs.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_rhs.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const noexcept { return m_lhs.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const noexcept { return m_rhs.cols(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const LhsNestedCleaned& lhs() const { return m_lhs; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const RhsNestedCleaned& rhs() const { return m_rhs; }
|
||||
|
||||
@@ -283,7 +283,7 @@ void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst, const Lhs& lhs, cons
|
||||
template <typename Lhs, typename Rhs>
|
||||
struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, OuterProduct> {
|
||||
template <typename T>
|
||||
struct is_row_major : std::conditional_t<(int(T::Flags) & RowMajorBit), internal::true_type, internal::false_type> {};
|
||||
struct is_row_major : bool_constant<(int(T::Flags) & RowMajorBit)> {};
|
||||
typedef typename Product<Lhs, Rhs>::Scalar Scalar;
|
||||
|
||||
// TODO it would be nice to be able to exploit our *_assign_op functors for that purpose
|
||||
@@ -294,6 +294,7 @@ struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, OuterProduct> {
|
||||
}
|
||||
};
|
||||
struct add {
|
||||
/** Add to dst. */
|
||||
template <typename Dst, typename Src>
|
||||
EIGEN_DEVICE_FUNC void operator()(const Dst& dst, const Src& src) const {
|
||||
dst.const_cast_derived() += src;
|
||||
@@ -305,9 +306,12 @@ struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, OuterProduct> {
|
||||
dst.const_cast_derived() -= src;
|
||||
}
|
||||
};
|
||||
/** Scaled add. */
|
||||
struct adds {
|
||||
Scalar m_scale;
|
||||
/** Constructor */
|
||||
explicit adds(const Scalar& s) : m_scale(s) {}
|
||||
/** Scaled add to dst. */
|
||||
template <typename Dst, typename Src>
|
||||
void EIGEN_DEVICE_FUNC operator()(const Dst& dst, const Src& src) const {
|
||||
dst.const_cast_derived() += m_scale * src;
|
||||
@@ -441,7 +445,7 @@ struct generic_product_impl<Lhs, Rhs, DenseShape, DenseShape, CoeffBasedProductM
|
||||
|
||||
eval_dynamic_impl(dst, blas_traits<Lhs>::extract(lhs).template conjugateIf<ConjLhs>(),
|
||||
blas_traits<Rhs>::extract(rhs).template conjugateIf<ConjRhs>(), func, actualAlpha,
|
||||
std::conditional_t<HasScalarFactor, true_type, false_type>());
|
||||
bool_constant<HasScalarFactor>());
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -631,6 +635,24 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
return packet<LoadMode, PacketType>(row, col);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetSegment(Index row, Index col, Index begin,
|
||||
Index count) const {
|
||||
PacketType res;
|
||||
typedef etor_product_packet_impl<bool(int(Flags) & RowMajorBit) ? RowMajor : ColMajor,
|
||||
Unroll ? int(InnerSize) : Dynamic, LhsEtorType, RhsEtorType, PacketType, LoadMode>
|
||||
PacketImpl;
|
||||
PacketImpl::run_segment(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res, begin, count);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetSegment(Index index, Index begin, Index count) const {
|
||||
const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index;
|
||||
const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0;
|
||||
return packetSegment<LoadMode, PacketType>(row, col, begin, count);
|
||||
}
|
||||
|
||||
protected:
|
||||
add_const_on_value_type_t<LhsNested> m_lhs;
|
||||
add_const_on_value_type_t<RhsNested> m_rhs;
|
||||
@@ -666,6 +688,13 @@ struct etor_product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, Load
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, Index(UnrollingIndex - 1))),
|
||||
rhs.template packet<LoadMode, Packet>(Index(UnrollingIndex - 1), col), res);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs,
|
||||
Index innerDim, Packet& res, Index begin, Index count) {
|
||||
etor_product_packet_impl<RowMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run_segment(
|
||||
row, col, lhs, rhs, innerDim, res, begin, count);
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, Index(UnrollingIndex - 1))),
|
||||
rhs.template packetSegment<LoadMode, Packet>(Index(UnrollingIndex - 1), col, begin, count), res);
|
||||
}
|
||||
};
|
||||
|
||||
template <int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
@@ -677,6 +706,13 @@ struct etor_product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, Load
|
||||
res = pmadd(lhs.template packet<LoadMode, Packet>(row, Index(UnrollingIndex - 1)),
|
||||
pset1<Packet>(rhs.coeff(Index(UnrollingIndex - 1), col)), res);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs,
|
||||
Index innerDim, Packet& res, Index begin, Index count) {
|
||||
etor_product_packet_impl<ColMajor, UnrollingIndex - 1, Lhs, Rhs, Packet, LoadMode>::run_segment(
|
||||
row, col, lhs, rhs, innerDim, res, begin, count);
|
||||
res = pmadd(lhs.template packetSegment<LoadMode, Packet>(row, Index(UnrollingIndex - 1), begin, count),
|
||||
pset1<Packet>(rhs.coeff(Index(UnrollingIndex - 1), col)), res);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
@@ -685,6 +721,12 @@ struct etor_product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode> {
|
||||
Index /*innerDim*/, Packet& res) {
|
||||
res = pmul(pset1<Packet>(lhs.coeff(row, Index(0))), rhs.template packet<LoadMode, Packet>(Index(0), col));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs,
|
||||
Index /*innerDim*/, Packet& res, Index begin,
|
||||
Index count) {
|
||||
res = pmul(pset1<Packet>(lhs.coeff(row, Index(0))),
|
||||
rhs.template packetSegment<LoadMode, Packet>(Index(0), col, begin, count));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
@@ -693,6 +735,12 @@ struct etor_product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode> {
|
||||
Index /*innerDim*/, Packet& res) {
|
||||
res = pmul(lhs.template packet<LoadMode, Packet>(row, Index(0)), pset1<Packet>(rhs.coeff(Index(0), col)));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs,
|
||||
Index /*innerDim*/, Packet& res, Index begin,
|
||||
Index count) {
|
||||
res = pmul(lhs.template packetSegment<LoadMode, Packet>(row, Index(0), begin, count),
|
||||
pset1<Packet>(rhs.coeff(Index(0), col)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
@@ -701,6 +749,11 @@ struct etor_product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode> {
|
||||
const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res) {
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/,
|
||||
const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res,
|
||||
Index /*begin*/, Index /*count*/) {
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
@@ -709,6 +762,11 @@ struct etor_product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode> {
|
||||
const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res) {
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/,
|
||||
const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res,
|
||||
Index /*begin*/, Index /*count*/) {
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
@@ -719,6 +777,13 @@ struct etor_product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode> {
|
||||
for (Index i = 0; i < innerDim; ++i)
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode, Packet>(i, col), res);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs,
|
||||
Index innerDim, Packet& res, Index begin, Index count) {
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
for (Index i = 0; i < innerDim; ++i)
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packetSegment<LoadMode, Packet>(i, col, begin, count),
|
||||
res);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
@@ -729,6 +794,13 @@ struct etor_product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode> {
|
||||
for (Index i = 0; i < innerDim; ++i)
|
||||
res = pmadd(lhs.template packet<LoadMode, Packet>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs,
|
||||
Index innerDim, Packet& res, Index begin, Index count) {
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
for (Index i = 0; i < innerDim; ++i)
|
||||
res = pmadd(lhs.template packetSegment<LoadMode, Packet>(row, i, begin, count), pset1<Packet>(rhs.coeff(i, col)),
|
||||
res);
|
||||
}
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
@@ -774,7 +846,7 @@ struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, DenseShape, ProductTag>
|
||||
|
||||
template <typename Dest>
|
||||
static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
|
||||
selfadjoint_product_impl<typename Lhs::MatrixType, Lhs::Mode, false, Rhs, 0, Rhs::IsVectorAtCompileTime>::run(
|
||||
selfadjoint_product_impl<typename Lhs::MatrixType, Lhs::Mode, false, Rhs, 0, Rhs::ColsAtCompileTime == 1>::run(
|
||||
dst, lhs.nestedExpression(), rhs, alpha);
|
||||
}
|
||||
};
|
||||
@@ -786,7 +858,7 @@ struct generic_product_impl<Lhs, Rhs, DenseShape, SelfAdjointShape, ProductTag>
|
||||
|
||||
template <typename Dest>
|
||||
static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
|
||||
selfadjoint_product_impl<Lhs, 0, Lhs::IsVectorAtCompileTime, typename Rhs::MatrixType, Rhs::Mode, false>::run(
|
||||
selfadjoint_product_impl<Lhs, 0, Lhs::RowsAtCompileTime == 1, typename Rhs::MatrixType, Rhs::Mode, false>::run(
|
||||
dst, lhs, rhs.nestedExpression(), alpha);
|
||||
}
|
||||
};
|
||||
@@ -867,6 +939,26 @@ struct diagonal_product_evaluator_base : evaluator_base<Derived> {
|
||||
m_diagImpl.template packet<DiagonalPacketLoadMode, PacketType>(id));
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index id, Index begin, Index count,
|
||||
internal::true_type) const {
|
||||
return internal::pmul(m_matImpl.template packetSegment<LoadMode, PacketType>(row, col, begin, count),
|
||||
internal::pset1<PacketType>(m_diagImpl.coeff(id)));
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index id, Index begin, Index count,
|
||||
internal::false_type) const {
|
||||
enum {
|
||||
InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
|
||||
DiagonalPacketLoadMode = plain_enum_min(
|
||||
LoadMode,
|
||||
((InnerSize % 16) == 0) ? int(Aligned16) : int(evaluator<DiagonalType>::Alignment)) // FIXME hardcoded 16!!
|
||||
};
|
||||
return internal::pmul(m_matImpl.template packetSegment<LoadMode, PacketType>(row, col, begin, count),
|
||||
m_diagImpl.template packetSegment<DiagonalPacketLoadMode, PacketType>(id, begin, count));
|
||||
}
|
||||
|
||||
evaluator<DiagonalType> m_diagImpl;
|
||||
evaluator<MatrixType> m_matImpl;
|
||||
};
|
||||
@@ -888,7 +980,8 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalSha
|
||||
typedef typename XprType::PlainObject PlainObject;
|
||||
typedef typename Lhs::DiagonalVectorType DiagonalType;
|
||||
|
||||
enum { StorageOrder = Base::StorageOrder_ };
|
||||
static constexpr int StorageOrder = Base::StorageOrder_;
|
||||
using IsRowMajor_t = bool_constant<StorageOrder == RowMajor>;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {}
|
||||
|
||||
@@ -901,8 +994,7 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalSha
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const {
|
||||
// FIXME: NVCC used to complain about the template keyword, but we have to check whether this is still the case.
|
||||
// See also similar calls below.
|
||||
return this->template packet_impl<LoadMode, PacketType>(
|
||||
row, col, row, std::conditional_t<int(StorageOrder) == RowMajor, internal::true_type, internal::false_type>());
|
||||
return this->template packet_impl<LoadMode, PacketType>(row, col, row, IsRowMajor_t());
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
@@ -910,6 +1002,19 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalSha
|
||||
return packet<LoadMode, PacketType>(int(StorageOrder) == ColMajor ? idx : 0,
|
||||
int(StorageOrder) == ColMajor ? 0 : idx);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const {
|
||||
// FIXME: NVCC used to complain about the template keyword, but we have to check whether this is still the case.
|
||||
// See also similar calls below.
|
||||
return this->template packet_segment_impl<LoadMode, PacketType>(row, col, row, begin, count, IsRowMajor_t());
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count) const {
|
||||
return packetSegment<LoadMode, PacketType>(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx,
|
||||
begin, count);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -929,7 +1034,8 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DenseShape,
|
||||
typedef Product<Lhs, Rhs, ProductKind> XprType;
|
||||
typedef typename XprType::PlainObject PlainObject;
|
||||
|
||||
enum { StorageOrder = Base::StorageOrder_ };
|
||||
static constexpr int StorageOrder = Base::StorageOrder_;
|
||||
using IsColMajor_t = bool_constant<StorageOrder == ColMajor>;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal()) {}
|
||||
|
||||
@@ -940,14 +1046,23 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DenseShape,
|
||||
#ifndef EIGEN_GPUCC
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const {
|
||||
return this->template packet_impl<LoadMode, PacketType>(
|
||||
row, col, col, std::conditional_t<int(StorageOrder) == ColMajor, internal::true_type, internal::false_type>());
|
||||
return this->template packet_impl<LoadMode, PacketType>(row, col, col, IsColMajor_t());
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index idx) const {
|
||||
return packet<LoadMode, PacketType>(int(StorageOrder) == ColMajor ? idx : 0,
|
||||
int(StorageOrder) == ColMajor ? 0 : idx);
|
||||
return packet<LoadMode, PacketType>(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const {
|
||||
return this->template packet_segment_impl<LoadMode, PacketType>(row, col, col, begin, count, IsColMajor_t());
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count) const {
|
||||
return packetSegment<LoadMode, PacketType>(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx,
|
||||
begin, count);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@@ -1149,6 +1264,22 @@ struct generic_product_impl<Lhs, Rhs, SkewSymmetricShape, SkewSymmetricShape, Pr
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Rhs, MatrixShape, HomogeneousShape, ProductTag>
|
||||
: generic_product_impl<Lhs, typename Rhs::PlainObject, MatrixShape, DenseShape, ProductTag> {};
|
||||
|
||||
template <typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Rhs, HomogeneousShape, MatrixShape, ProductTag>
|
||||
: generic_product_impl<typename Lhs::PlainObject, Rhs, DenseShape, MatrixShape, ProductTag> {};
|
||||
|
||||
template <typename Lhs, typename Rhs, int ProductTag>
|
||||
struct generic_product_impl<Lhs, Rhs, PermutationShape, HomogeneousShape, ProductTag>
|
||||
: generic_product_impl<Lhs, Rhs, PermutationShape, DenseShape, ProductTag> {};
|
||||
|
||||
template <typename Lhs, typename Rhs, int ProductTag>
|
||||
struct generic_product_impl<Lhs, Rhs, HomogeneousShape, PermutationShape, ProductTag>
|
||||
: generic_product_impl<Lhs, Rhs, DenseShape, PermutationShape, ProductTag> {};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -115,13 +115,14 @@ struct random_float_impl<Scalar, false> {
|
||||
}
|
||||
};
|
||||
|
||||
#if !EIGEN_COMP_NVCC
|
||||
// random implementation for long double
|
||||
// this specialization is not compatible with double-double scalars
|
||||
template <bool Specialize = (sizeof(long double) == 2 * sizeof(uint64_t)) &&
|
||||
((std::numeric_limits<long double>::digits != (2 * std::numeric_limits<double>::digits)))>
|
||||
struct random_longdouble_impl {
|
||||
static constexpr int Size = sizeof(long double);
|
||||
static constexpr EIGEN_DEVICE_FUNC inline int mantissaBits() { return NumTraits<long double>::digits() - 1; }
|
||||
static constexpr EIGEN_DEVICE_FUNC int mantissaBits() { return NumTraits<long double>::digits() - 1; }
|
||||
static EIGEN_DEVICE_FUNC inline long double run(int numRandomBits) {
|
||||
eigen_assert(numRandomBits >= 0 && numRandomBits <= mantissaBits());
|
||||
EIGEN_USING_STD(memcpy);
|
||||
@@ -130,8 +131,15 @@ struct random_longdouble_impl {
|
||||
uint64_t randomBits[2];
|
||||
long double result = 2.0L;
|
||||
memcpy(&randomBits, &result, Size);
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
randomBits[0] |= getRandomBits<uint64_t>(numLowBits);
|
||||
randomBits[1] |= getRandomBits<uint64_t>(numHighBits);
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
randomBits[0] |= getRandomBits<uint64_t>(numHighBits);
|
||||
randomBits[1] |= getRandomBits<uint64_t>(numLowBits);
|
||||
#else
|
||||
#error Unexpected or undefined __BYTE_ORDER__
|
||||
#endif
|
||||
memcpy(&result, &randomBits, Size);
|
||||
result -= 3.0L;
|
||||
return result;
|
||||
@@ -139,13 +147,14 @@ struct random_longdouble_impl {
|
||||
};
|
||||
template <>
|
||||
struct random_longdouble_impl<false> {
|
||||
static constexpr EIGEN_DEVICE_FUNC inline int mantissaBits() { return NumTraits<double>::digits() - 1; }
|
||||
static constexpr EIGEN_DEVICE_FUNC int mantissaBits() { return NumTraits<double>::digits() - 1; }
|
||||
static EIGEN_DEVICE_FUNC inline long double run(int numRandomBits) {
|
||||
return static_cast<long double>(random_float_impl<double>::run(numRandomBits));
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct random_float_impl<long double> : random_longdouble_impl<> {};
|
||||
#endif
|
||||
|
||||
template <typename Scalar>
|
||||
struct random_default_impl<Scalar, false, false> {
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 Charlie Schlosser <cs.schlosser@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_REALVIEW_H
|
||||
#define EIGEN_REALVIEW_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Vectorized assignment to RealView requires array-oriented access to the real and imaginary components.
|
||||
// From https://en.cppreference.com/w/cpp/numeric/complex.html:
|
||||
// For any pointer to an element of an array of std::complex<T> named p and any valid array index i,
|
||||
// reinterpret_cast<T*>(p)[2 * i] is the real part of the complex number p[i], and
|
||||
// reinterpret_cast<T*>(p)[2 * i + 1] is the imaginary part of the complex number p[i].
|
||||
|
||||
template <typename ComplexScalar>
|
||||
struct complex_array_access : std::false_type {};
|
||||
template <>
|
||||
struct complex_array_access<std::complex<float>> : std::true_type {};
|
||||
template <>
|
||||
struct complex_array_access<std::complex<double>> : std::true_type {};
|
||||
template <>
|
||||
struct complex_array_access<std::complex<long double>> : std::true_type {};
|
||||
|
||||
template <typename Xpr>
|
||||
struct traits<RealView<Xpr>> : public traits<Xpr> {
|
||||
template <typename T>
|
||||
static constexpr int double_size(T size, bool times_two) {
|
||||
int size_as_int = int(size);
|
||||
if (size_as_int == Dynamic) return Dynamic;
|
||||
return times_two ? (2 * size_as_int) : size_as_int;
|
||||
}
|
||||
using Base = traits<Xpr>;
|
||||
using ComplexScalar = typename Base::Scalar;
|
||||
using Scalar = typename NumTraits<ComplexScalar>::Real;
|
||||
static constexpr int ActualDirectAccessBit = complex_array_access<ComplexScalar>::value ? DirectAccessBit : 0;
|
||||
static constexpr int ActualPacketAccessBit = packet_traits<Scalar>::Vectorizable ? PacketAccessBit : 0;
|
||||
static constexpr int FlagMask =
|
||||
ActualDirectAccessBit | ActualPacketAccessBit | HereditaryBits | LinearAccessBit | LvalueBit;
|
||||
static constexpr int BaseFlags = int(evaluator<Xpr>::Flags) | int(Base::Flags);
|
||||
static constexpr int Flags = BaseFlags & FlagMask;
|
||||
static constexpr bool IsRowMajor = Flags & RowMajorBit;
|
||||
static constexpr int RowsAtCompileTime = double_size(Base::RowsAtCompileTime, !IsRowMajor);
|
||||
static constexpr int ColsAtCompileTime = double_size(Base::ColsAtCompileTime, IsRowMajor);
|
||||
static constexpr int SizeAtCompileTime = size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime);
|
||||
static constexpr int MaxRowsAtCompileTime = double_size(Base::MaxRowsAtCompileTime, !IsRowMajor);
|
||||
static constexpr int MaxColsAtCompileTime = double_size(Base::MaxColsAtCompileTime, IsRowMajor);
|
||||
static constexpr int MaxSizeAtCompileTime = size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime);
|
||||
static constexpr int OuterStrideAtCompileTime = double_size(outer_stride_at_compile_time<Xpr>::ret, true);
|
||||
static constexpr int InnerStrideAtCompileTime = inner_stride_at_compile_time<Xpr>::ret;
|
||||
};
|
||||
|
||||
template <typename Xpr>
|
||||
struct evaluator<RealView<Xpr>> : private evaluator<Xpr> {
|
||||
using BaseEvaluator = evaluator<Xpr>;
|
||||
using XprType = RealView<Xpr>;
|
||||
using ExpressionTraits = traits<XprType>;
|
||||
using ComplexScalar = typename ExpressionTraits::ComplexScalar;
|
||||
using ComplexCoeffReturnType = typename BaseEvaluator::CoeffReturnType;
|
||||
using Scalar = typename ExpressionTraits::Scalar;
|
||||
|
||||
static constexpr bool IsRowMajor = ExpressionTraits::IsRowMajor;
|
||||
static constexpr int Flags = ExpressionTraits::Flags;
|
||||
static constexpr int CoeffReadCost = BaseEvaluator::CoeffReadCost;
|
||||
static constexpr int Alignment = BaseEvaluator::Alignment;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(XprType realView) : BaseEvaluator(realView.m_xpr) {}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<!Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
|
||||
Index p = (IsRowMajor ? col : row) & 1;
|
||||
return p ? numext::real(cscalar) : numext::imag(cscalar);
|
||||
}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
|
||||
Index p = (IsRowMajor ? col : row) & 1;
|
||||
return reinterpret_cast<const Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) {
|
||||
ComplexScalar& cscalar = BaseEvaluator::coeffRef(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
|
||||
Index p = (IsRowMajor ? col : row) & 1;
|
||||
return reinterpret_cast<Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<!Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index index) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2);
|
||||
Index p = index & 1;
|
||||
return p ? numext::real(cscalar) : numext::imag(cscalar);
|
||||
}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2);
|
||||
Index p = index & 1;
|
||||
return reinterpret_cast<const Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
|
||||
ComplexScalar& cscalar = BaseEvaluator::coeffRef(index / 2);
|
||||
Index p = index & 1;
|
||||
return reinterpret_cast<Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even");
|
||||
|
||||
Index crow = IsRowMajor ? row : row / 2;
|
||||
Index ccol = IsRowMajor ? col / 2 : col;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packet<LoadMode, ComplexPacket>(crow, ccol);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert((index % 2 == 0) && "the index must be even");
|
||||
|
||||
Index cindex = index / 2;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packet<LoadMode, ComplexPacket>(cindex);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even");
|
||||
eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even");
|
||||
|
||||
Index crow = IsRowMajor ? row : row / 2;
|
||||
Index ccol = IsRowMajor ? col / 2 : col;
|
||||
Index cbegin = begin / 2;
|
||||
Index ccount = count / 2;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packetSegment<LoadMode, ComplexPacket>(crow, ccol, cbegin, ccount);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert((index % 2 == 0) && "the index must be even");
|
||||
eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even");
|
||||
|
||||
Index cindex = index / 2;
|
||||
Index cbegin = begin / 2;
|
||||
Index ccount = count / 2;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packetSegment<LoadMode, ComplexPacket>(cindex, cbegin, ccount);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename Xpr>
|
||||
class RealView : public internal::dense_xpr_base<RealView<Xpr>>::type {
|
||||
using ExpressionTraits = internal::traits<RealView>;
|
||||
EIGEN_STATIC_ASSERT(NumTraits<typename Xpr::Scalar>::IsComplex, SCALAR MUST BE COMPLEX)
|
||||
public:
|
||||
using Scalar = typename ExpressionTraits::Scalar;
|
||||
using Nested = RealView;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit RealView(Xpr& xpr) : m_xpr(xpr) {}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return Xpr::IsRowMajor ? m_xpr.rows() : 2 * m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return Xpr::IsRowMajor ? 2 * m_xpr.cols() : m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return 2 * m_xpr.size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_xpr.innerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return 2 * m_xpr.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) {
|
||||
m_xpr.resize(Xpr::IsRowMajor ? rows : rows / 2, Xpr::IsRowMajor ? cols / 2 : cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC void resize(Index size) { m_xpr.resize(size / 2); }
|
||||
EIGEN_DEVICE_FUNC Scalar* data() { return reinterpret_cast<Scalar*>(m_xpr.data()); }
|
||||
EIGEN_DEVICE_FUNC const Scalar* data() const { return reinterpret_cast<const Scalar*>(m_xpr.data()); }
|
||||
|
||||
EIGEN_DEVICE_FUNC RealView(const RealView&) = default;
|
||||
|
||||
EIGEN_DEVICE_FUNC RealView& operator=(const RealView& other);
|
||||
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView& operator=(const RealView<OtherDerived>& other);
|
||||
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView& operator=(const DenseBase<OtherDerived>& other);
|
||||
|
||||
protected:
|
||||
friend struct internal::evaluator<RealView<Xpr>>;
|
||||
Xpr& m_xpr;
|
||||
};
|
||||
|
||||
template <typename Xpr>
|
||||
EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView& other) {
|
||||
internal::call_assignment(*this, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Xpr>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView<OtherDerived>& other) {
|
||||
internal::call_assignment(*this, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Xpr>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const DenseBase<OtherDerived>& other) {
|
||||
internal::call_assignment(*this, other.derived());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC typename DenseBase<Derived>::RealViewReturnType DenseBase<Derived>::realView() {
|
||||
return RealViewReturnType(derived());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC typename DenseBase<Derived>::ConstRealViewReturnType DenseBase<Derived>::realView() const {
|
||||
return ConstRealViewReturnType(derived());
|
||||
}
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#endif // EIGEN_REALVIEW_H
|
||||
@@ -414,6 +414,13 @@ class redux_evaluator : public internal::evaluator<XprType_> {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetByOuterInner(Index outer, Index inner) const {
|
||||
return Base::template packet<LoadMode, PacketType>(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegmentByOuterInner(Index outer, Index inner, Index begin,
|
||||
Index count) const {
|
||||
return Base::template packetSegment<LoadMode, PacketType>(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer,
|
||||
begin, count);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
@@ -73,11 +73,11 @@ class RefBase : public MapBase<Derived> {
|
||||
typedef MapBase<Derived> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(RefBase)
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const {
|
||||
return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const {
|
||||
return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
|
||||
: IsVectorAtCompileTime ? this->size()
|
||||
: int(Flags) & RowMajorBit ? this->cols()
|
||||
@@ -97,11 +97,11 @@ class RefBase : public MapBase<Derived> {
|
||||
typedef Stride<StrideType::OuterStrideAtCompileTime, StrideType::InnerStrideAtCompileTime> StrideBase;
|
||||
|
||||
// Resolves inner stride if default 0.
|
||||
static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveInnerStride(Index inner) { return inner == 0 ? 1 : inner; }
|
||||
static EIGEN_DEVICE_FUNC constexpr Index resolveInnerStride(Index inner) { return inner == 0 ? 1 : inner; }
|
||||
|
||||
// Resolves outer stride if default 0.
|
||||
static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveOuterStride(Index inner, Index outer, Index rows, Index cols,
|
||||
bool isVectorAtCompileTime, bool isRowMajor) {
|
||||
static EIGEN_DEVICE_FUNC constexpr Index resolveOuterStride(Index inner, Index outer, Index rows, Index cols,
|
||||
bool isVectorAtCompileTime, bool isRowMajor) {
|
||||
return outer == 0 ? isVectorAtCompileTime ? inner * rows * cols : isRowMajor ? inner * cols : inner * rows : outer;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,8 @@ class Replicate : public internal::dense_xpr_base<Replicate<MatrixType, RowFacto
|
||||
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_matrix.rows() * m_rowFactor.value(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_matrix.cols() * m_colFactor.value(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC const MatrixTypeNested_& nestedExpression() const { return m_matrix; }
|
||||
|
||||
|
||||
@@ -215,10 +215,10 @@ class ReshapedImpl_dense<XprType, Rows, Cols, Order, true> : public MapBase<Resh
|
||||
EIGEN_DEVICE_FUNC XprType& nestedExpression() { return m_xpr; }
|
||||
|
||||
/** \sa MapBase::innerStride() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const { return m_xpr.innerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const { return m_xpr.innerStride(); }
|
||||
|
||||
/** \sa MapBase::outerStride() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const {
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const {
|
||||
return (((Flags & RowMajorBit) == RowMajorBit) ? this->cols() : this->rows()) * m_xpr.innerStride();
|
||||
}
|
||||
|
||||
|
||||
@@ -58,12 +58,8 @@ class ReturnByValue : public internal::dense_xpr_base<ReturnByValue<Derived> >::
|
||||
EIGEN_DEVICE_FUNC inline void evalTo(Dest& dst) const {
|
||||
static_cast<const Derived*>(this)->evalTo(dst);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT {
|
||||
return static_cast<const Derived*>(this)->rows();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT {
|
||||
return static_cast<const Derived*>(this)->cols();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return static_cast<const Derived*>(this)->rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return static_cast<const Derived*>(this)->cols(); }
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
#define Unusable \
|
||||
|
||||
@@ -87,8 +87,8 @@ class Reverse : public internal::dense_xpr_base<Reverse<MatrixType, Direction> >
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reverse)
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const { return -m_matrix.innerStride(); }
|
||||
|
||||
@@ -127,19 +127,25 @@ EIGEN_DEVICE_FUNC inline typename DenseBase<Derived>::ReverseReturnType DenseBas
|
||||
* \sa VectorwiseOp::reverseInPlace(), reverse() */
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline void DenseBase<Derived>::reverseInPlace() {
|
||||
constexpr int HalfRowsAtCompileTime = RowsAtCompileTime == Dynamic ? Dynamic : RowsAtCompileTime / 2;
|
||||
constexpr int HalfColsAtCompileTime = ColsAtCompileTime == Dynamic ? Dynamic : ColsAtCompileTime / 2;
|
||||
if (cols() > rows()) {
|
||||
Index half = cols() / 2;
|
||||
leftCols(half).swap(rightCols(half).reverse());
|
||||
this->template leftCols<HalfColsAtCompileTime>(half).swap(
|
||||
this->template rightCols<HalfColsAtCompileTime>(half).reverse());
|
||||
if ((cols() % 2) == 1) {
|
||||
Index half2 = rows() / 2;
|
||||
col(half).head(half2).swap(col(half).tail(half2).reverse());
|
||||
col(half).template head<HalfRowsAtCompileTime>(half2).swap(
|
||||
col(half).template tail<HalfRowsAtCompileTime>(half2).reverse());
|
||||
}
|
||||
} else {
|
||||
Index half = rows() / 2;
|
||||
topRows(half).swap(bottomRows(half).reverse());
|
||||
this->template topRows<HalfRowsAtCompileTime>(half).swap(
|
||||
this->template bottomRows<HalfRowsAtCompileTime>(half).reverse());
|
||||
if ((rows() % 2) == 1) {
|
||||
Index half2 = cols() / 2;
|
||||
row(half).head(half2).swap(row(half).tail(half2).reverse());
|
||||
row(half).template head<HalfColsAtCompileTime>(half2).swap(
|
||||
row(half).template tail<HalfColsAtCompileTime>(half2).reverse());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-78
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \class Select
|
||||
/** \typedef Select
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* \brief Expression of a coefficient wise version of the C++ ternary operator ?:
|
||||
@@ -24,73 +24,16 @@ namespace Eigen {
|
||||
* \tparam ThenMatrixType the type of the \em then expression
|
||||
* \tparam ElseMatrixType the type of the \em else expression
|
||||
*
|
||||
* This class represents an expression of a coefficient wise version of the C++ ternary operator ?:.
|
||||
* This type represents an expression of a coefficient wise version of the C++ ternary operator ?:.
|
||||
* It is the return type of DenseBase::select() and most of the time this is the only way it is used.
|
||||
*
|
||||
* \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template <typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
|
||||
struct traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> > : traits<ThenMatrixType> {
|
||||
typedef typename traits<ThenMatrixType>::Scalar Scalar;
|
||||
typedef Dense StorageKind;
|
||||
typedef typename traits<ThenMatrixType>::XprKind XprKind;
|
||||
typedef typename ConditionMatrixType::Nested ConditionMatrixNested;
|
||||
typedef typename ThenMatrixType::Nested ThenMatrixNested;
|
||||
typedef typename ElseMatrixType::Nested ElseMatrixNested;
|
||||
enum {
|
||||
RowsAtCompileTime = ConditionMatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime,
|
||||
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & RowMajorBit
|
||||
};
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
|
||||
class Select : public internal::dense_xpr_base<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >::type,
|
||||
internal::no_assignment_operator {
|
||||
public:
|
||||
typedef typename internal::dense_xpr_base<Select>::type Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Select)
|
||||
|
||||
inline EIGEN_DEVICE_FUNC Select(const ConditionMatrixType& a_conditionMatrix, const ThenMatrixType& a_thenMatrix,
|
||||
const ElseMatrixType& a_elseMatrix)
|
||||
: m_condition(a_conditionMatrix), m_then(a_thenMatrix), m_else(a_elseMatrix) {
|
||||
eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows());
|
||||
eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols());
|
||||
}
|
||||
|
||||
inline EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_condition.rows(); }
|
||||
inline EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_condition.cols(); }
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const Scalar coeff(Index i, Index j) const {
|
||||
if (m_condition.coeff(i, j))
|
||||
return m_then.coeff(i, j);
|
||||
else
|
||||
return m_else.coeff(i, j);
|
||||
}
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const Scalar coeff(Index i) const {
|
||||
if (m_condition.coeff(i))
|
||||
return m_then.coeff(i);
|
||||
else
|
||||
return m_else.coeff(i);
|
||||
}
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const ConditionMatrixType& conditionMatrix() const { return m_condition; }
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const ThenMatrixType& thenMatrix() const { return m_then; }
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const ElseMatrixType& elseMatrix() const { return m_else; }
|
||||
|
||||
protected:
|
||||
typename ConditionMatrixType::Nested m_condition;
|
||||
typename ThenMatrixType::Nested m_then;
|
||||
typename ElseMatrixType::Nested m_else;
|
||||
};
|
||||
using Select = CwiseTernaryOp<internal::scalar_boolean_select_op<typename DenseBase<ThenMatrixType>::Scalar,
|
||||
typename DenseBase<ElseMatrixType>::Scalar,
|
||||
typename DenseBase<ConditionMatrixType>::Scalar>,
|
||||
ThenMatrixType, ElseMatrixType, ConditionMatrixType>;
|
||||
|
||||
/** \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j)
|
||||
* if \c *this(i,j) != Scalar(0), and \a elseMatrix(i,j) otherwise.
|
||||
@@ -98,7 +41,7 @@ class Select : public internal::dense_xpr_base<Select<ConditionMatrixType, ThenM
|
||||
* Example: \include MatrixBase_select.cpp
|
||||
* Output: \verbinclude MatrixBase_select.out
|
||||
*
|
||||
* \sa DenseBase::bitwiseSelect(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&)
|
||||
* \sa typedef Select
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ThenDerived, typename ElseDerived>
|
||||
@@ -107,15 +50,12 @@ inline EIGEN_DEVICE_FUNC CwiseTernaryOp<
|
||||
typename DenseBase<Derived>::Scalar>,
|
||||
ThenDerived, ElseDerived, Derived>
|
||||
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix, const DenseBase<ElseDerived>& elseMatrix) const {
|
||||
using Op = internal::scalar_boolean_select_op<typename DenseBase<ThenDerived>::Scalar,
|
||||
typename DenseBase<ElseDerived>::Scalar, Scalar>;
|
||||
return CwiseTernaryOp<Op, ThenDerived, ElseDerived, Derived>(thenMatrix.derived(), elseMatrix.derived(), derived(),
|
||||
Op());
|
||||
return Select<Derived, ThenDerived, ElseDerived>(thenMatrix.derived(), elseMatrix.derived(), derived());
|
||||
}
|
||||
/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with
|
||||
* the \em else expression being a scalar value.
|
||||
*
|
||||
* \sa DenseBase::booleanSelect(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select
|
||||
* \sa typedef Select
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ThenDerived>
|
||||
@@ -126,15 +66,13 @@ inline EIGEN_DEVICE_FUNC CwiseTernaryOp<
|
||||
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
|
||||
const typename DenseBase<ThenDerived>::Scalar& elseScalar) const {
|
||||
using ElseConstantType = typename DenseBase<ThenDerived>::ConstantReturnType;
|
||||
using Op = internal::scalar_boolean_select_op<typename DenseBase<ThenDerived>::Scalar,
|
||||
typename DenseBase<ThenDerived>::Scalar, Scalar>;
|
||||
return CwiseTernaryOp<Op, ThenDerived, ElseConstantType, Derived>(
|
||||
thenMatrix.derived(), ElseConstantType(rows(), cols(), elseScalar), derived(), Op());
|
||||
return Select<Derived, ThenDerived, ElseConstantType>(thenMatrix.derived(),
|
||||
ElseConstantType(rows(), cols(), elseScalar), derived());
|
||||
}
|
||||
/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with
|
||||
* the \em then expression being a scalar value.
|
||||
*
|
||||
* \sa DenseBase::booleanSelect(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select
|
||||
* \sa typedef Select
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ElseDerived>
|
||||
@@ -145,10 +83,8 @@ inline EIGEN_DEVICE_FUNC CwiseTernaryOp<
|
||||
DenseBase<Derived>::select(const typename DenseBase<ElseDerived>::Scalar& thenScalar,
|
||||
const DenseBase<ElseDerived>& elseMatrix) const {
|
||||
using ThenConstantType = typename DenseBase<ElseDerived>::ConstantReturnType;
|
||||
using Op = internal::scalar_boolean_select_op<typename DenseBase<ElseDerived>::Scalar,
|
||||
typename DenseBase<ElseDerived>::Scalar, Scalar>;
|
||||
return CwiseTernaryOp<Op, ThenConstantType, ElseDerived, Derived>(ThenConstantType(rows(), cols(), thenScalar),
|
||||
elseMatrix.derived(), derived(), Op());
|
||||
return Select<Derived, ThenConstantType, ElseDerived>(ThenConstantType(rows(), cols(), thenScalar),
|
||||
elseMatrix.derived(), derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -73,10 +73,10 @@ class SelfAdjointView : public TriangularBase<SelfAdjointView<MatrixType_, UpLo>
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { return m_matrix.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT { return m_matrix.innerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_matrix.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_matrix.innerStride(); }
|
||||
|
||||
/** \sa MatrixBase::coeff()
|
||||
* \warning the coordinates must fit into the referenced triangular part
|
||||
|
||||
@@ -15,33 +15,33 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// TODO generalize the scalar type of 'other'
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator*=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::mul_assign_op<Scalar, Scalar>());
|
||||
using ConstantExpr = typename internal::plain_constant_type<Derived, Scalar>::type;
|
||||
using Op = internal::mul_assign_op<Scalar>;
|
||||
internal::call_assignment(derived(), ConstantExpr(rows(), cols(), other), Op());
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator+=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::add_assign_op<Scalar, Scalar>());
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator-=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::sub_assign_op<Scalar, Scalar>());
|
||||
template <bool Enable, typename>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator*=(const RealScalar& other) {
|
||||
realView() *= other;
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator/=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::div_assign_op<Scalar, Scalar>());
|
||||
using ConstantExpr = typename internal::plain_constant_type<Derived, Scalar>::type;
|
||||
using Op = internal::div_assign_op<Scalar>;
|
||||
internal::call_assignment(derived(), ConstantExpr(rows(), cols(), other), Op());
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
template <bool Enable, typename>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator/=(const RealScalar& other) {
|
||||
realView() /= other;
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class SkewSymmetricBase : public EigenBase<Derived> {
|
||||
EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); }
|
||||
|
||||
/** Determinant vanishes */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Scalar determinant() const { return 0; }
|
||||
EIGEN_DEVICE_FUNC constexpr Scalar determinant() const { return 0; }
|
||||
|
||||
/** A.transpose() = -A */
|
||||
EIGEN_DEVICE_FUNC PlainObject transpose() const { return (-vector()).asSkewSymmetric(); }
|
||||
@@ -91,9 +91,9 @@ class SkewSymmetricBase : public EigenBase<Derived> {
|
||||
EIGEN_DEVICE_FUNC inline SkewSymmetricVectorType& vector() { return derived().vector(); }
|
||||
|
||||
/** \returns the number of rows. */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const { return 3; }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const { return 3; }
|
||||
/** \returns the number of columns. */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const { return 3; }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const { return 3; }
|
||||
|
||||
/** \returns the matrix product of \c *this by the dense matrix, \a matrix */
|
||||
template <typename MatrixDerived>
|
||||
@@ -321,7 +321,7 @@ bool MatrixBase<Derived>::isSkewSymmetric(const RealScalar& prec) const {
|
||||
return (this->transpose() + *this).isZero(prec);
|
||||
}
|
||||
|
||||
/** \returns the matrix product of \c *this by the skew symmetric matrix \skew.
|
||||
/** \returns the matrix product of \c *this by the skew symmetric matrix \a skew.
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename SkewDerived>
|
||||
|
||||
@@ -66,8 +66,8 @@ class Solve : public SolveImpl<Decomposition, RhsType, typename internal::traits
|
||||
|
||||
Solve(const Decomposition &dec, const RhsType &rhs) : m_dec(dec), m_rhs(rhs) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_dec.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_rhs.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_dec.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_rhs.cols(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC const Decomposition &dec() const { return m_dec; }
|
||||
EIGEN_DEVICE_FUNC const RhsType &rhs() const { return m_rhs; }
|
||||
|
||||
@@ -216,8 +216,8 @@ struct triangular_solve_retval : public ReturnByValue<triangular_solve_retval<Si
|
||||
|
||||
triangular_solve_retval(const TriangularType& tri, const Rhs& rhs) : m_triangularMatrix(tri), m_rhs(rhs) {}
|
||||
|
||||
inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_rhs.rows(); }
|
||||
inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_rhs.cols(); }
|
||||
constexpr Index rows() const noexcept { return m_rhs.rows(); }
|
||||
constexpr Index cols() const noexcept { return m_rhs.cols(); }
|
||||
|
||||
template <typename Dest>
|
||||
inline void evalTo(Dest& dst) const {
|
||||
|
||||
@@ -78,6 +78,14 @@ class SolverBase : public EigenBase<Derived> {
|
||||
template <typename Derived_>
|
||||
friend struct internal::solve_assertion;
|
||||
|
||||
ComputationInfo info() const {
|
||||
// CRTP static dispatch: Calls the 'info()' method on the derived class.
|
||||
// Derived must implement 'ComputationInfo info() const'.
|
||||
// If not implemented, name lookup falls back to this base method, causing
|
||||
// infinite recursion (detectable by -Winfinite-recursion).
|
||||
return derived().info();
|
||||
}
|
||||
|
||||
enum {
|
||||
RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
|
||||
ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
|
||||
|
||||
@@ -36,11 +36,11 @@ class indexed_based_stl_iterator_base {
|
||||
typedef Index difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
|
||||
indexed_based_stl_iterator_base() EIGEN_NO_THROW : mp_xpr(0), m_index(0) {}
|
||||
indexed_based_stl_iterator_base(XprType& xpr, Index index) EIGEN_NO_THROW : mp_xpr(&xpr), m_index(index) {}
|
||||
indexed_based_stl_iterator_base() noexcept : mp_xpr(0), m_index(0) {}
|
||||
indexed_based_stl_iterator_base(XprType& xpr, Index index) noexcept : mp_xpr(&xpr), m_index(index) {}
|
||||
|
||||
indexed_based_stl_iterator_base(const non_const_iterator& other) EIGEN_NO_THROW : mp_xpr(other.mp_xpr),
|
||||
m_index(other.m_index) {}
|
||||
indexed_based_stl_iterator_base(const non_const_iterator& other) noexcept
|
||||
: mp_xpr(other.mp_xpr), m_index(other.m_index) {}
|
||||
|
||||
indexed_based_stl_iterator_base& operator=(const non_const_iterator& other) {
|
||||
mp_xpr = other.mp_xpr;
|
||||
@@ -325,7 +325,7 @@ class pointer_based_stl_iterator {
|
||||
public:
|
||||
typedef Index difference_type;
|
||||
typedef typename XprType::Scalar value_type;
|
||||
#if __cplusplus >= 202002L
|
||||
#if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L
|
||||
typedef std::conditional_t<XprType::InnerStrideAtCompileTime == 1, std::contiguous_iterator_tag,
|
||||
std::random_access_iterator_tag>
|
||||
iterator_category;
|
||||
@@ -335,15 +335,14 @@ class pointer_based_stl_iterator {
|
||||
typedef std::conditional_t<bool(is_lvalue), value_type*, const value_type*> pointer;
|
||||
typedef std::conditional_t<bool(is_lvalue), value_type&, const value_type&> reference;
|
||||
|
||||
pointer_based_stl_iterator() EIGEN_NO_THROW : m_ptr(0) {}
|
||||
pointer_based_stl_iterator(XprType& xpr, Index index) EIGEN_NO_THROW : m_incr(xpr.innerStride()) {
|
||||
pointer_based_stl_iterator() noexcept : m_ptr(0) {}
|
||||
pointer_based_stl_iterator(XprType& xpr, Index index) noexcept : m_incr(xpr.innerStride()) {
|
||||
m_ptr = xpr.data() + index * m_incr.value();
|
||||
}
|
||||
|
||||
pointer_based_stl_iterator(const non_const_iterator& other) EIGEN_NO_THROW : m_ptr(other.m_ptr),
|
||||
m_incr(other.m_incr) {}
|
||||
pointer_based_stl_iterator(const non_const_iterator& other) noexcept : m_ptr(other.m_ptr), m_incr(other.m_incr) {}
|
||||
|
||||
pointer_based_stl_iterator& operator=(const non_const_iterator& other) EIGEN_NO_THROW {
|
||||
pointer_based_stl_iterator& operator=(const non_const_iterator& other) noexcept {
|
||||
m_ptr = other.m_ptr;
|
||||
m_incr.setValue(other.m_incr);
|
||||
return *this;
|
||||
|
||||
@@ -78,9 +78,9 @@ class Stride {
|
||||
}
|
||||
|
||||
/** \returns the outer stride */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outer() const { return m_outer.value(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outer() const { return m_outer.value(); }
|
||||
/** \returns the inner stride */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index inner() const { return m_inner.value(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index inner() const { return m_inner.value(); }
|
||||
|
||||
protected:
|
||||
internal::variable_if_dynamic<Index, OuterStrideAtCompileTime> m_outer;
|
||||
|
||||
@@ -65,6 +65,31 @@ class generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT,
|
||||
Index col = Base::colIndexByOuterInner(outer, inner);
|
||||
assignPacket<StoreMode, LoadMode, PacketType>(row, col);
|
||||
}
|
||||
|
||||
template <int StoreMode, int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE void assignPacketSegment(Index row, Index col, Index begin, Index count) {
|
||||
PacketType tmp = m_src.template packetSegment<LoadMode, PacketType>(row, col, begin, count);
|
||||
const_cast<SrcEvaluatorTypeT &>(m_src).template writePacketSegment<LoadMode>(
|
||||
row, col, m_dst.template packetSegment<StoreMode, PacketType>(row, col, begin, count), begin, count);
|
||||
m_dst.template writePacketSegment<StoreMode>(row, col, tmp, begin, count);
|
||||
}
|
||||
|
||||
template <int StoreMode, int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE void assignPacketSegment(Index index, Index begin, Index count) {
|
||||
PacketType tmp = m_src.template packetSegment<LoadMode, PacketType>(index, begin, count);
|
||||
const_cast<SrcEvaluatorTypeT &>(m_src).template writePacketSegment<LoadMode>(
|
||||
index, m_dst.template packetSegment<StoreMode, PacketType>(index, begin, count), begin, count);
|
||||
m_dst.template writePacketSegment<StoreMode>(index, tmp, begin, count);
|
||||
}
|
||||
|
||||
// TODO find a simple way not to have to copy/paste this function from generic_dense_assignment_kernel, by simple I
|
||||
// mean no CRTP (Gael)
|
||||
template <int StoreMode, int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE void assignPacketSegmentByOuterInner(Index outer, Index inner, Index begin, Index count) {
|
||||
Index row = Base::rowIndexByOuterInner(outer, inner);
|
||||
Index col = Base::colIndexByOuterInner(outer, inner);
|
||||
assignPacketSegment<StoreMode, LoadMode, PacketType>(row, col, begin, count);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -65,8 +65,8 @@ class Transpose : public TransposeImpl<MatrixType, typename internal::traits<Mat
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const noexcept { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const noexcept { return m_matrix.rows(); }
|
||||
|
||||
/** \returns the nested expression */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t<MatrixTypeNested>& nestedExpression() const {
|
||||
|
||||
@@ -293,9 +293,9 @@ class Transpose<TranspositionsBase<TranspositionsDerived> > {
|
||||
public:
|
||||
explicit Transpose(const TranspositionType& t) : m_transpositions(t) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_transpositions.size(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_transpositions.size(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_transpositions.size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return m_transpositions.size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_transpositions.size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_transpositions.size(); }
|
||||
|
||||
/** \returns the \a matrix with the inverse transpositions applied to the columns.
|
||||
*/
|
||||
|
||||
@@ -58,10 +58,10 @@ class TriangularBase : public EigenBase<Derived> {
|
||||
eigen_assert(!((int(Mode) & int(UnitDiag)) && (int(Mode) & int(ZeroDiag))));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return derived().rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return derived().cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { return derived().outerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT { return derived().innerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return derived().rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return derived().cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return derived().outerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return derived().innerStride(); }
|
||||
|
||||
// dummy resize function
|
||||
EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) {
|
||||
@@ -194,9 +194,9 @@ class TriangularView
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView)
|
||||
|
||||
/** \copydoc EigenBase::rows() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); }
|
||||
/** \copydoc EigenBase::cols() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); }
|
||||
|
||||
/** \returns a const reference to the nested expression */
|
||||
EIGEN_DEVICE_FUNC const NestedExpression& nestedExpression() const { return m_matrix; }
|
||||
|
||||
@@ -36,6 +36,7 @@ template <typename MatrixType, typename MemberOp, int Direction>
|
||||
class PartialReduxExpr;
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename MatrixType, typename MemberOp, int Direction>
|
||||
struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> > : traits<MatrixType> {
|
||||
typedef typename MemberOp::result_type Scalar;
|
||||
@@ -63,12 +64,8 @@ class PartialReduxExpr : public internal::dense_xpr_base<PartialReduxExpr<Matrix
|
||||
EIGEN_DEVICE_FUNC explicit PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp())
|
||||
: m_matrix(mat), m_functor(func) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT {
|
||||
return (Direction == Vertical ? 1 : m_matrix.rows());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT {
|
||||
return (Direction == Horizontal ? 1 : m_matrix.cols());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return (Direction == Vertical ? 1 : m_matrix.rows()); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return (Direction == Horizontal ? 1 : m_matrix.cols()); }
|
||||
|
||||
EIGEN_DEVICE_FUNC typename MatrixType::Nested nestedExpression() const { return m_matrix; }
|
||||
|
||||
@@ -149,6 +146,22 @@ struct member_redux {
|
||||
const BinaryOp& binaryFunc() const { return m_functor; }
|
||||
const BinaryOp m_functor;
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct scalar_replace_zero_with_one_op {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& x) const {
|
||||
return numext::is_exactly_zero(x) ? Scalar(1) : x;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& x) const {
|
||||
return pselect(pcmp_eq(x, pzero(x)), pset1<Packet>(Scalar(1)), x);
|
||||
}
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_replace_zero_with_one_op<Scalar>> {
|
||||
enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasCmp };
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/** \class VectorwiseOp
|
||||
@@ -193,9 +206,7 @@ class VectorwiseOp {
|
||||
public:
|
||||
typedef typename ExpressionType::Scalar Scalar;
|
||||
typedef typename ExpressionType::RealScalar RealScalar;
|
||||
typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
|
||||
typedef typename internal::ref_selector<ExpressionType>::non_const_type ExpressionTypeNested;
|
||||
typedef internal::remove_all_t<ExpressionTypeNested> ExpressionTypeNestedCleaned;
|
||||
typedef internal::remove_all_t<ExpressionType> ExpressionTypeCleaned;
|
||||
|
||||
template <template <typename OutScalar, typename InputScalar> class Functor, typename ReturnScalar = Scalar>
|
||||
struct ReturnType {
|
||||
@@ -334,7 +345,7 @@ class VectorwiseOp {
|
||||
|
||||
typedef typename ReturnType<internal::member_minCoeff>::Type MinCoeffReturnType;
|
||||
typedef typename ReturnType<internal::member_maxCoeff>::Type MaxCoeffReturnType;
|
||||
typedef PartialReduxExpr<const CwiseUnaryOp<internal::scalar_abs2_op<Scalar>, const ExpressionTypeNestedCleaned>,
|
||||
typedef PartialReduxExpr<const CwiseUnaryOp<internal::scalar_abs2_op<Scalar>, const ExpressionTypeCleaned>,
|
||||
internal::member_sum<RealScalar, RealScalar>, Direction>
|
||||
SquaredNormReturnType;
|
||||
typedef CwiseUnaryOp<internal::scalar_sqrt_op<RealScalar>, const SquaredNormReturnType> NormReturnType;
|
||||
@@ -585,7 +596,7 @@ class VectorwiseOp {
|
||||
/** Returns the expression of the sum of the vector \a other to each subvector of \c *this */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
|
||||
CwiseBinaryOp<internal::scalar_sum_op<Scalar, typename OtherDerived::Scalar>, const ExpressionTypeNestedCleaned,
|
||||
CwiseBinaryOp<internal::scalar_sum_op<Scalar, typename OtherDerived::Scalar>, const ExpressionTypeCleaned,
|
||||
const typename ExtendedType<OtherDerived>::Type>
|
||||
operator+(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
@@ -596,7 +607,7 @@ class VectorwiseOp {
|
||||
/** Returns the expression of the difference between each subvector of \c *this and the vector \a other */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_difference_op<Scalar, typename OtherDerived::Scalar>,
|
||||
const ExpressionTypeNestedCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
const ExpressionTypeCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
operator-(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
|
||||
@@ -606,10 +617,9 @@ class VectorwiseOp {
|
||||
/** Returns the expression where each subvector is the product of the vector \a other
|
||||
* by the corresponding subvector of \c *this */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
|
||||
CwiseBinaryOp<internal::scalar_product_op<Scalar>, const ExpressionTypeNestedCleaned,
|
||||
const typename ExtendedType<OtherDerived>::Type> EIGEN_DEVICE_FUNC
|
||||
operator*(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_product_op<Scalar, typename OtherDerived::Scalar>,
|
||||
const ExpressionTypeCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
operator*(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
|
||||
EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
|
||||
@@ -619,8 +629,8 @@ class VectorwiseOp {
|
||||
/** Returns the expression where each subvector is the quotient of the corresponding
|
||||
* subvector of \c *this by the vector \a other */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const ExpressionTypeNestedCleaned,
|
||||
const typename ExtendedType<OtherDerived>::Type>
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_quotient_op<Scalar, typename OtherDerived::Scalar>,
|
||||
const ExpressionTypeCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
operator/(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
|
||||
@@ -628,18 +638,28 @@ class VectorwiseOp {
|
||||
return m_matrix / extendedTo(other.derived());
|
||||
}
|
||||
|
||||
using Normalized_NonzeroNormType =
|
||||
CwiseUnaryOp<internal::scalar_replace_zero_with_one_op<Scalar>, const NormReturnType>;
|
||||
using NormalizedReturnType = CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const ExpressionTypeCleaned,
|
||||
const typename OppositeExtendedType<Normalized_NonzeroNormType>::Type>;
|
||||
|
||||
/** \returns an expression where each column (or row) of the referenced matrix are normalized.
|
||||
* The referenced matrix is \b not modified.
|
||||
*
|
||||
* \warning If the input columns (or rows) are too small (i.e., their norm equals to 0), they remain unchanged in the
|
||||
* resulting expression.
|
||||
*
|
||||
* \sa MatrixBase::normalized(), normalize()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const ExpressionTypeNestedCleaned,
|
||||
const typename OppositeExtendedType<NormReturnType>::Type>
|
||||
normalized() const {
|
||||
return m_matrix.cwiseQuotient(extendedToOpposite(this->norm()));
|
||||
EIGEN_DEVICE_FUNC NormalizedReturnType normalized() const {
|
||||
return m_matrix.cwiseQuotient(extendedToOpposite(Normalized_NonzeroNormType(this->norm())));
|
||||
}
|
||||
|
||||
/** Normalize in-place each row or columns of the referenced matrix.
|
||||
* \sa MatrixBase::normalize(), normalized()
|
||||
*
|
||||
* \warning If the input columns (or rows) are too small (i.e., their norm equals to 0), they are left unchanged.
|
||||
*
|
||||
* \sa MatrixBase::normalized(), normalize()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC void normalize() { m_matrix = this->normalized(); }
|
||||
|
||||
@@ -683,7 +703,7 @@ class VectorwiseOp {
|
||||
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC Index redux_length() const { return Direction == Vertical ? m_matrix.rows() : m_matrix.cols(); }
|
||||
ExpressionTypeNested m_matrix;
|
||||
ExpressionType& m_matrix;
|
||||
};
|
||||
|
||||
// const colwise moved to DenseBase.h due to CUDA compiler bug
|
||||
|
||||
+17
-269
@@ -25,14 +25,12 @@ struct visitor_impl;
|
||||
template <typename Visitor, bool ShortCircuitEvaluation = false>
|
||||
struct short_circuit_eval_impl {
|
||||
// if short circuit evaluation is not used, do nothing
|
||||
static EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(const Visitor&) { return false; }
|
||||
static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(const Visitor&) { return false; }
|
||||
};
|
||||
template <typename Visitor>
|
||||
struct short_circuit_eval_impl<Visitor, true> {
|
||||
// if short circuit evaluation is used, check the visitor
|
||||
static EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(const Visitor& visitor) {
|
||||
return visitor.done();
|
||||
}
|
||||
static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(const Visitor& visitor) { return visitor.done(); }
|
||||
};
|
||||
|
||||
// unrolled inner-outer traversal
|
||||
@@ -296,9 +294,9 @@ class visitor_evaluator {
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit visitor_evaluator(const XprType& xpr) : m_evaluator(xpr), m_xpr(xpr) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_xpr.size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return m_xpr.size(); }
|
||||
// outer-inner access
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const {
|
||||
return m_evaluator.coeff(row, col);
|
||||
@@ -386,173 +384,6 @@ EIGEN_DEVICE_FUNC void DenseBase<Derived>::visit(Visitor& visitor) const {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal
|
||||
* \brief Base class to implement min and max visitors
|
||||
*/
|
||||
template <typename Derived>
|
||||
struct coeff_visitor {
|
||||
// default initialization to avoid countless invalid maybe-uninitialized warnings by gcc
|
||||
EIGEN_DEVICE_FUNC coeff_visitor() : row(-1), col(-1), res(0) {}
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
Index row, col;
|
||||
Scalar res;
|
||||
EIGEN_DEVICE_FUNC inline void init(const Scalar& value, Index i, Index j) {
|
||||
res = value;
|
||||
row = i;
|
||||
col = j;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Scalar, int NaNPropagation, bool is_min = true>
|
||||
struct minmax_compare {
|
||||
typedef typename packet_traits<Scalar>::type Packet;
|
||||
static EIGEN_DEVICE_FUNC inline bool compare(Scalar a, Scalar b) { return a < b; }
|
||||
static EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& p) { return predux_min<NaNPropagation>(p); }
|
||||
};
|
||||
|
||||
template <typename Scalar, int NaNPropagation>
|
||||
struct minmax_compare<Scalar, NaNPropagation, false> {
|
||||
typedef typename packet_traits<Scalar>::type Packet;
|
||||
static EIGEN_DEVICE_FUNC inline bool compare(Scalar a, Scalar b) { return a > b; }
|
||||
static EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& p) { return predux_max<NaNPropagation>(p); }
|
||||
};
|
||||
|
||||
// Default implementation used by non-floating types, where we do not
|
||||
// need special logic for NaN handling.
|
||||
template <typename Derived, bool is_min, int NaNPropagation,
|
||||
bool isInt = NumTraits<typename Derived::Scalar>::IsInteger>
|
||||
struct minmax_coeff_visitor : coeff_visitor<Derived> {
|
||||
using Scalar = typename Derived::Scalar;
|
||||
using Packet = typename packet_traits<Scalar>::type;
|
||||
using Comparator = minmax_compare<Scalar, NaNPropagation, is_min>;
|
||||
static constexpr Index PacketSize = packet_traits<Scalar>::size;
|
||||
|
||||
EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index i, Index j) {
|
||||
if (Comparator::compare(value, this->res)) {
|
||||
this->res = value;
|
||||
this->row = i;
|
||||
this->col = j;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index i, Index j) {
|
||||
Scalar value = Comparator::predux(p);
|
||||
if (Comparator::compare(value, this->res)) {
|
||||
const Packet range = preverse(plset<Packet>(Scalar(1)));
|
||||
Packet mask = pcmp_eq(pset1<Packet>(value), p);
|
||||
Index max_idx = PacketSize - static_cast<Index>(predux_max(pand(range, mask)));
|
||||
this->res = value;
|
||||
this->row = Derived::IsRowMajor ? i : i + max_idx;
|
||||
this->col = Derived::IsRowMajor ? j + max_idx : j;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index i, Index j) {
|
||||
Scalar value = Comparator::predux(p);
|
||||
const Packet range = preverse(plset<Packet>(Scalar(1)));
|
||||
Packet mask = pcmp_eq(pset1<Packet>(value), p);
|
||||
Index max_idx = PacketSize - static_cast<Index>(predux_max(pand(range, mask)));
|
||||
this->res = value;
|
||||
this->row = Derived::IsRowMajor ? i : i + max_idx;
|
||||
this->col = Derived::IsRowMajor ? j + max_idx : j;
|
||||
}
|
||||
};
|
||||
|
||||
// Suppress NaN. The only case in which we return NaN is if the matrix is all NaN,
|
||||
// in which case, row=0, col=0 is returned for the location.
|
||||
template <typename Derived, bool is_min>
|
||||
struct minmax_coeff_visitor<Derived, is_min, PropagateNumbers, false> : coeff_visitor<Derived> {
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
using Packet = typename packet_traits<Scalar>::type;
|
||||
using Comparator = minmax_compare<Scalar, PropagateNumbers, is_min>;
|
||||
|
||||
EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index i, Index j) {
|
||||
if ((!(numext::isnan)(value) && (numext::isnan)(this->res)) || Comparator::compare(value, this->res)) {
|
||||
this->res = value;
|
||||
this->row = i;
|
||||
this->col = j;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index i, Index j) {
|
||||
const Index PacketSize = packet_traits<Scalar>::size;
|
||||
Scalar value = Comparator::predux(p);
|
||||
if ((!(numext::isnan)(value) && (numext::isnan)(this->res)) || Comparator::compare(value, this->res)) {
|
||||
const Packet range = preverse(plset<Packet>(Scalar(1)));
|
||||
/* mask will be zero for NaNs, so they will be ignored. */
|
||||
Packet mask = pcmp_eq(pset1<Packet>(value), p);
|
||||
Index max_idx = PacketSize - static_cast<Index>(predux_max(pand(range, mask)));
|
||||
this->res = value;
|
||||
this->row = Derived::IsRowMajor ? i : i + max_idx;
|
||||
this->col = Derived::IsRowMajor ? j + max_idx : j;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index i, Index j) {
|
||||
const Index PacketSize = packet_traits<Scalar>::size;
|
||||
Scalar value = Comparator::predux(p);
|
||||
if ((numext::isnan)(value)) {
|
||||
this->res = value;
|
||||
this->row = 0;
|
||||
this->col = 0;
|
||||
return;
|
||||
}
|
||||
const Packet range = preverse(plset<Packet>(Scalar(1)));
|
||||
/* mask will be zero for NaNs, so they will be ignored. */
|
||||
Packet mask = pcmp_eq(pset1<Packet>(value), p);
|
||||
Index max_idx = PacketSize - static_cast<Index>(predux_max(pand(range, mask)));
|
||||
this->res = value;
|
||||
this->row = Derived::IsRowMajor ? i : i + max_idx;
|
||||
this->col = Derived::IsRowMajor ? j + max_idx : j;
|
||||
}
|
||||
};
|
||||
|
||||
// Propagate NaNs. If the matrix contains NaN, the location of the first NaN
|
||||
// will be returned in row and col.
|
||||
template <typename Derived, bool is_min, int NaNPropagation>
|
||||
struct minmax_coeff_visitor<Derived, is_min, NaNPropagation, false> : coeff_visitor<Derived> {
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
using Packet = typename packet_traits<Scalar>::type;
|
||||
using Comparator = minmax_compare<Scalar, PropagateNaN, is_min>;
|
||||
|
||||
EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index i, Index j) {
|
||||
const bool value_is_nan = (numext::isnan)(value);
|
||||
if ((value_is_nan && !(numext::isnan)(this->res)) || Comparator::compare(value, this->res)) {
|
||||
this->res = value;
|
||||
this->row = i;
|
||||
this->col = j;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index i, Index j) {
|
||||
const Index PacketSize = packet_traits<Scalar>::size;
|
||||
Scalar value = Comparator::predux(p);
|
||||
const bool value_is_nan = (numext::isnan)(value);
|
||||
if ((value_is_nan && !(numext::isnan)(this->res)) || Comparator::compare(value, this->res)) {
|
||||
const Packet range = preverse(plset<Packet>(Scalar(1)));
|
||||
// If the value is NaN, pick the first position of a NaN, otherwise pick the first extremal value.
|
||||
Packet mask = value_is_nan ? pnot(pcmp_eq(p, p)) : pcmp_eq(pset1<Packet>(value), p);
|
||||
Index max_idx = PacketSize - static_cast<Index>(predux_max(pand(range, mask)));
|
||||
this->res = value;
|
||||
this->row = Derived::IsRowMajor ? i : i + max_idx;
|
||||
this->col = Derived::IsRowMajor ? j + max_idx : j;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index i, Index j) {
|
||||
const Index PacketSize = packet_traits<Scalar>::size;
|
||||
Scalar value = Comparator::predux(p);
|
||||
const bool value_is_nan = (numext::isnan)(value);
|
||||
const Packet range = preverse(plset<Packet>(Scalar(1)));
|
||||
// If the value is NaN, pick the first position of a NaN, otherwise pick the first extremal value.
|
||||
Packet mask = value_is_nan ? pnot(pcmp_eq(p, p)) : pcmp_eq(pset1<Packet>(value), p);
|
||||
Index max_idx = PacketSize - static_cast<Index>(predux_max(pand(range, mask)));
|
||||
this->res = value;
|
||||
this->row = Derived::IsRowMajor ? i : i + max_idx;
|
||||
this->col = Derived::IsRowMajor ? j + max_idx : j;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived, bool is_min, int NaNPropagation>
|
||||
struct functor_traits<minmax_coeff_visitor<Derived, is_min, NaNPropagation>> {
|
||||
using Scalar = typename Derived::Scalar;
|
||||
enum { Cost = NumTraits<Scalar>::AddCost, LinearAccess = false, PacketAccess = packet_traits<Scalar>::HasCmp };
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct all_visitor {
|
||||
using result_type = bool;
|
||||
@@ -632,102 +463,19 @@ struct functor_traits<count_visitor<Scalar>> {
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Derived, bool AlwaysTrue = NumTraits<typename traits<Derived>::Scalar>::IsInteger>
|
||||
struct all_finite_impl {
|
||||
static EIGEN_DEVICE_FUNC inline bool run(const Derived& /*derived*/) { return true; }
|
||||
};
|
||||
#if !defined(__FINITE_MATH_ONLY__) || !(__FINITE_MATH_ONLY__)
|
||||
template <typename Derived>
|
||||
struct all_finite_impl<Derived, false> {
|
||||
static EIGEN_DEVICE_FUNC inline bool run(const Derived& derived) { return derived.array().isFiniteTyped().all(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \fn DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the minimum of all coefficients of *this and puts in *row and *col its location.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::minCoeff(IndexType* rowId,
|
||||
IndexType* colId) const {
|
||||
eigen_assert(this->rows() > 0 && this->cols() > 0 && "you are using an empty matrix");
|
||||
|
||||
internal::minmax_coeff_visitor<Derived, true, NaNPropagation> minVisitor;
|
||||
this->visit(minVisitor);
|
||||
*rowId = minVisitor.row;
|
||||
if (colId) *colId = minVisitor.col;
|
||||
return minVisitor.res;
|
||||
}
|
||||
|
||||
/** \returns the minimum of all coefficients of *this and puts in *index its location.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visit(),
|
||||
* DenseBase::minCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::minCoeff(IndexType* index) const {
|
||||
eigen_assert(this->rows() > 0 && this->cols() > 0 && "you are using an empty matrix");
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
|
||||
internal::minmax_coeff_visitor<Derived, true, NaNPropagation> minVisitor;
|
||||
this->visit(minVisitor);
|
||||
*index = IndexType((RowsAtCompileTime == 1) ? minVisitor.col : minVisitor.row);
|
||||
return minVisitor.res;
|
||||
}
|
||||
|
||||
/** \fn DenseBase<Derived>::maxCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the maximum of all coefficients of *this and puts in *row and *col its location.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::maxCoeff(IndexType* rowPtr,
|
||||
IndexType* colPtr) const {
|
||||
eigen_assert(this->rows() > 0 && this->cols() > 0 && "you are using an empty matrix");
|
||||
|
||||
internal::minmax_coeff_visitor<Derived, false, NaNPropagation> maxVisitor;
|
||||
this->visit(maxVisitor);
|
||||
*rowPtr = maxVisitor.row;
|
||||
if (colPtr) *colPtr = maxVisitor.col;
|
||||
return maxVisitor.res;
|
||||
}
|
||||
|
||||
/** \returns the maximum of all coefficients of *this and puts in *index its location.
|
||||
*
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(),
|
||||
* DenseBase::maxCoeff()
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar DenseBase<Derived>::maxCoeff(IndexType* index) const {
|
||||
eigen_assert(this->rows() > 0 && this->cols() > 0 && "you are using an empty matrix");
|
||||
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
internal::minmax_coeff_visitor<Derived, false, NaNPropagation> maxVisitor;
|
||||
this->visit(maxVisitor);
|
||||
*index = (RowsAtCompileTime == 1) ? maxVisitor.col : maxVisitor.row;
|
||||
return maxVisitor.res;
|
||||
}
|
||||
|
||||
/** \returns true if all coefficients are true
|
||||
*
|
||||
* Example: \include MatrixBase_all.cpp
|
||||
@@ -781,7 +529,7 @@ EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::hasNaN() const {
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::allFinite() const {
|
||||
return derived().array().isFiniteTyped().all();
|
||||
return internal::all_finite_impl<Derived>::run(derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -475,19 +475,11 @@ EIGEN_STRONG_INLINE Packet4cf pmsub(const Packet4cf& a, const Packet4cf& b, cons
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4cf pnmadd(const Packet4cf& a, const Packet4cf& b, const Packet4cf& c) {
|
||||
__m256 a_odd = _mm256_movehdup_ps(a.v);
|
||||
__m256 a_even = _mm256_moveldup_ps(a.v);
|
||||
__m256 b_swap = _mm256_permute_ps(b.v, _MM_SHUFFLE(2, 3, 0, 1));
|
||||
__m256 result = _mm256_fmaddsub_ps(a_odd, b_swap, _mm256_fmaddsub_ps(a_even, b.v, c.v));
|
||||
return Packet4cf(result);
|
||||
return pnegate(pmsub(a, b, c));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4cf pnmsub(const Packet4cf& a, const Packet4cf& b, const Packet4cf& c) {
|
||||
__m256 a_odd = _mm256_movehdup_ps(a.v);
|
||||
__m256 a_even = _mm256_moveldup_ps(a.v);
|
||||
__m256 b_swap = _mm256_permute_ps(b.v, _MM_SHUFFLE(2, 3, 0, 1));
|
||||
__m256 result = _mm256_fmaddsub_ps(a_odd, b_swap, _mm256_fmsubadd_ps(a_even, b.v, c.v));
|
||||
return Packet4cf(result);
|
||||
return pnegate(pmadd(a, b, c));
|
||||
}
|
||||
// std::complex<double>
|
||||
template <>
|
||||
@@ -508,21 +500,64 @@ EIGEN_STRONG_INLINE Packet2cd pmsub(const Packet2cd& a, const Packet2cd& b, cons
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cd pnmadd(const Packet2cd& a, const Packet2cd& b, const Packet2cd& c) {
|
||||
__m256d a_odd = _mm256_permute_pd(a.v, 0xF);
|
||||
__m256d a_even = _mm256_movedup_pd(a.v);
|
||||
__m256d b_swap = _mm256_permute_pd(b.v, 0x5);
|
||||
__m256d result = _mm256_fmaddsub_pd(a_odd, b_swap, _mm256_fmaddsub_pd(a_even, b.v, c.v));
|
||||
return Packet2cd(result);
|
||||
return pnegate(pmsub(a, b, c));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cd pnmsub(const Packet2cd& a, const Packet2cd& b, const Packet2cd& c) {
|
||||
__m256d a_odd = _mm256_permute_pd(a.v, 0xF);
|
||||
__m256d a_even = _mm256_movedup_pd(a.v);
|
||||
__m256d b_swap = _mm256_permute_pd(b.v, 0x5);
|
||||
__m256d result = _mm256_fmaddsub_pd(a_odd, b_swap, _mm256_fmsubadd_pd(a_even, b.v, c.v));
|
||||
return Packet2cd(result);
|
||||
return pnegate(pmadd(a, b, c));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*---------------- load/store segment support ----------------*/
|
||||
|
||||
/*---------------- std::complex<float> ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet2cf> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet4cf> : std::true_type {};
|
||||
|
||||
template <>
|
||||
inline Packet2cf ploaduSegment<Packet2cf>(const std::complex<float>* from, Index begin, Index count) {
|
||||
return (Packet2cf)_mm_maskload_ps(&numext::real_ref(*from), segment_mask_2x64(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<std::complex<float>, Packet2cf>(std::complex<float>* to, const Packet2cf& from, Index begin,
|
||||
Index count) {
|
||||
_mm_maskstore_ps(&numext::real_ref(*to), segment_mask_2x64(begin, count), from.v);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Packet4cf ploaduSegment<Packet4cf>(const std::complex<float>* from, Index begin, Index count) {
|
||||
return (Packet4cf)_mm256_maskload_ps(&numext::real_ref(*from), segment_mask_4x64(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<std::complex<float>, Packet4cf>(std::complex<float>* to, const Packet4cf& from, Index begin,
|
||||
Index count) {
|
||||
_mm256_maskstore_ps(&numext::real_ref(*to), segment_mask_4x64(begin, count), from.v);
|
||||
}
|
||||
|
||||
/*---------------- std::complex<double> ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet2cd> : std::true_type {};
|
||||
|
||||
template <>
|
||||
inline Packet2cd ploaduSegment<Packet2cd>(const std::complex<double>* from, Index begin, Index count) {
|
||||
return (Packet2cd)_mm256_maskload_pd(&numext::real_ref(*from), segment_mask_4x64(2 * begin, 2 * count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<std::complex<double>, Packet2cd>(std::complex<double>* to, const Packet2cd& from,
|
||||
Index begin, Index count) {
|
||||
_mm256_maskstore_pd(&numext::real_ref(*to), segment_mask_4x64(2 * begin, 2 * count), from.v);
|
||||
}
|
||||
|
||||
/*---------------- end load/store segment support ----------------*/
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -28,15 +28,13 @@ EIGEN_DOUBLE_PACKET_FUNCTION(log, Packet4d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(log2, Packet4d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(exp, Packet4d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(tanh, Packet4d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(cbrt, Packet4d)
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(sin, Packet4d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(cos, Packet4d)
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_UNUSED Packet4d patan<Packet4d>(const Packet4d& _x) {
|
||||
return generic_patan(_x);
|
||||
}
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(atan, Packet4d)
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(exp2, Packet4d)
|
||||
|
||||
// Notice that for newer processors, it is counterproductive to use Newton
|
||||
// iteration for square root. In particular, Skylake and Zen2 processors
|
||||
@@ -99,6 +97,7 @@ EIGEN_STRONG_INLINE Packet8bf pldexp(const Packet8bf& a, const Packet8bf& expone
|
||||
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, pcos)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, pexp)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, pexp2)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, pexpm1)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, plog)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, plog1p)
|
||||
@@ -108,8 +107,11 @@ BF16_PACKET_FUNCTION(Packet8f, Packet8bf, prsqrt)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, psin)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, psqrt)
|
||||
BF16_PACKET_FUNCTION(Packet8f, Packet8bf, ptanh)
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, pcos)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, pexp)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, pexp2)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, pexpm1)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, plog)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, plog1p)
|
||||
@@ -119,6 +121,7 @@ F16_PACKET_FUNCTION(Packet8f, Packet8h, prsqrt)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, psin)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, psqrt)
|
||||
F16_PACKET_FUNCTION(Packet8f, Packet8h, ptanh)
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
|
||||
@@ -118,12 +118,15 @@ struct packet_traits<float> : default_packet_traits {
|
||||
HasLog1p = 1,
|
||||
HasExpm1 = 1,
|
||||
HasExp = 1,
|
||||
HasPow = 1,
|
||||
HasNdtri = 1,
|
||||
HasBessel = 1,
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
HasCbrt = 1,
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasErf = EIGEN_FAST_MATH,
|
||||
HasErfc = EIGEN_FAST_MATH,
|
||||
HasBlend = 1
|
||||
};
|
||||
};
|
||||
@@ -144,9 +147,13 @@ struct packet_traits<double> : default_packet_traits {
|
||||
#endif
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasLog = 1,
|
||||
HasErf = 1,
|
||||
HasErfc = 1,
|
||||
HasExp = 1,
|
||||
HasPow = 1,
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
HasCbrt = 1,
|
||||
HasATan = 1,
|
||||
HasATanh = 1,
|
||||
HasBlend = 1
|
||||
@@ -649,16 +656,7 @@ template <>
|
||||
EIGEN_STRONG_INLINE uint64_t pfirst<Packet4ul>(const Packet4ul& a) {
|
||||
return _mm_extract_epi64_0(_mm256_castsi256_si128(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux<Packet4l>(const Packet4l& a) {
|
||||
__m128i r = _mm_add_epi64(_mm256_castsi256_si128(a), _mm256_extractf128_si256(a, 1));
|
||||
return _mm_extract_epi64_0(r) + _mm_extract_epi64_1(r);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE uint64_t predux<Packet4ul>(const Packet4ul& a) {
|
||||
__m128i r = _mm_add_epi64(_mm256_castsi256_si128(a), _mm256_extractf128_si256(a, 1));
|
||||
return numext::bit_cast<uint64_t>(_mm_extract_epi64_0(r) + _mm_extract_epi64_1(r));
|
||||
}
|
||||
|
||||
#define MM256_SHUFFLE_EPI64(A, B, M) _mm256_shuffle_pd(_mm256_castsi256_pd(A), _mm256_castsi256_pd(B), M)
|
||||
EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet4l, 4>& kernel) {
|
||||
__m256d T0 = MM256_SHUFFLE_EPI64(kernel.packet[0], kernel.packet[1], 15);
|
||||
@@ -1826,10 +1824,13 @@ EIGEN_STRONG_INLINE Packet8ui pabs(const Packet8ui& a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h psignbit(const Packet8h& a) {
|
||||
return _mm_cmpgt_epi16(_mm_setzero_si128(), a);
|
||||
}
|
||||
#endif // EIGEN_VECTORIZE_AVX512FP16
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf psignbit(const Packet8bf& a) {
|
||||
return _mm_cmpgt_epi16(_mm_setzero_si128(), a);
|
||||
@@ -1922,20 +1923,19 @@ EIGEN_STRONG_INLINE Packet4d pldexp<Packet4d>(const Packet4d& a, const Packet4d&
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux<Packet8f>(const Packet8f& a) {
|
||||
return predux(Packet4f(_mm_add_ps(_mm256_castps256_ps128(a), _mm256_extractf128_ps(a, 1))));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux<Packet4d>(const Packet4d& a) {
|
||||
return predux(Packet2d(_mm_add_pd(_mm256_castpd256_pd128(a), _mm256_extractf128_pd(a, 1))));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux<Packet8i>(const Packet8i& a) {
|
||||
return predux(Packet4i(_mm_add_epi32(_mm256_castsi256_si128(a), _mm256_extractf128_si256(a, 1))));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE uint32_t predux<Packet8ui>(const Packet8ui& a) {
|
||||
return predux(Packet4ui(_mm_add_epi32(_mm256_castsi256_si128(a), _mm256_extractf128_si256(a, 1))));
|
||||
EIGEN_STRONG_INLINE Packet4d pldexp_fast<Packet4d>(const Packet4d& a, const Packet4d& exponent) {
|
||||
// Clamp exponent to [-1024, 1024]
|
||||
const Packet4d min_exponent = pset1<Packet4d>(-1023.0);
|
||||
const Packet4d max_exponent = pset1<Packet4d>(1024.0);
|
||||
const Packet4i e = _mm256_cvtpd_epi32(pmin(pmax(exponent, min_exponent), max_exponent));
|
||||
const Packet4i bias = pset1<Packet4i>(1023);
|
||||
|
||||
// 2^e
|
||||
Packet4i hi = vec4i_swizzle1(padd(e, bias), 0, 2, 1, 3);
|
||||
const Packet4i lo = _mm_slli_epi64(hi, 52);
|
||||
hi = _mm_slli_epi64(_mm_srli_epi64(hi, 32), 52);
|
||||
const Packet4d c = _mm256_castsi256_pd(_mm256_insertf128_si256(_mm256_castsi128_si256(lo), hi, 1));
|
||||
return pmul(a, c); // a * 2^e
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1951,65 +1951,6 @@ EIGEN_STRONG_INLINE Packet4ui predux_half_dowto4<Packet8ui>(const Packet8ui& a)
|
||||
return _mm_add_epi32(_mm256_castsi256_si128(a), _mm256_extractf128_si256(a, 1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_mul<Packet8f>(const Packet8f& a) {
|
||||
Packet8f tmp;
|
||||
tmp = _mm256_mul_ps(a, _mm256_permute2f128_ps(a, a, 1));
|
||||
tmp = _mm256_mul_ps(tmp, _mm256_shuffle_ps(tmp, tmp, _MM_SHUFFLE(1, 0, 3, 2)));
|
||||
return pfirst(_mm256_mul_ps(tmp, _mm256_shuffle_ps(tmp, tmp, 1)));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_mul<Packet4d>(const Packet4d& a) {
|
||||
Packet4d tmp;
|
||||
tmp = _mm256_mul_pd(a, _mm256_permute2f128_pd(a, a, 1));
|
||||
return pfirst(_mm256_mul_pd(tmp, _mm256_shuffle_pd(tmp, tmp, 1)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min<Packet8f>(const Packet8f& a) {
|
||||
Packet8f tmp = _mm256_min_ps(a, _mm256_permute2f128_ps(a, a, 1));
|
||||
tmp = _mm256_min_ps(tmp, _mm256_shuffle_ps(tmp, tmp, _MM_SHUFFLE(1, 0, 3, 2)));
|
||||
return pfirst(_mm256_min_ps(tmp, _mm256_shuffle_ps(tmp, tmp, 1)));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min<Packet4d>(const Packet4d& a) {
|
||||
Packet4d tmp = _mm256_min_pd(a, _mm256_permute2f128_pd(a, a, 1));
|
||||
return pfirst(_mm256_min_pd(tmp, _mm256_shuffle_pd(tmp, tmp, 1)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max<Packet8f>(const Packet8f& a) {
|
||||
Packet8f tmp = _mm256_max_ps(a, _mm256_permute2f128_ps(a, a, 1));
|
||||
tmp = _mm256_max_ps(tmp, _mm256_shuffle_ps(tmp, tmp, _MM_SHUFFLE(1, 0, 3, 2)));
|
||||
return pfirst(_mm256_max_ps(tmp, _mm256_shuffle_ps(tmp, tmp, 1)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max<Packet4d>(const Packet4d& a) {
|
||||
Packet4d tmp = _mm256_max_pd(a, _mm256_permute2f128_pd(a, a, 1));
|
||||
return pfirst(_mm256_max_pd(tmp, _mm256_shuffle_pd(tmp, tmp, 1)));
|
||||
}
|
||||
|
||||
// not needed yet
|
||||
// template<> EIGEN_STRONG_INLINE bool predux_all(const Packet8f& x)
|
||||
// {
|
||||
// return _mm256_movemask_ps(x)==0xFF;
|
||||
// }
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8f& x) {
|
||||
return _mm256_movemask_ps(x) != 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8i& x) {
|
||||
return _mm256_movemask_ps(_mm256_castsi256_ps(x)) != 0;
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8ui& x) {
|
||||
return _mm256_movemask_ps(_mm256_castsi256_ps(x)) != 0;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet8f, 8>& kernel) {
|
||||
__m256 T0 = _mm256_unpacklo_ps(kernel.packet[0], kernel.packet[1]);
|
||||
__m256 T1 = _mm256_unpackhi_ps(kernel.packet[0], kernel.packet[1]);
|
||||
@@ -2168,7 +2109,6 @@ struct unpacket_traits<Packet8h> {
|
||||
};
|
||||
typedef Packet8h half;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pset1<Packet8h>(const Eigen::half& from) {
|
||||
@@ -2311,24 +2251,64 @@ EIGEN_STRONG_INLINE Packet8h ptrunc<Packet8h>(const Packet8h& a) {
|
||||
return float2half(ptrunc<Packet8f>(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pisinf<Packet8h>(const Packet8h& a) {
|
||||
constexpr uint16_t kInf = ((1 << 5) - 1) << 10;
|
||||
constexpr uint16_t kAbsMask = (1 << 15) - 1;
|
||||
return _mm_cmpeq_epi16(_mm_and_si128(a.m_val, _mm_set1_epi16(kAbsMask)), _mm_set1_epi16(kInf));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pisnan<Packet8h>(const Packet8h& a) {
|
||||
constexpr uint16_t kInf = ((1 << 5) - 1) << 10;
|
||||
constexpr uint16_t kAbsMask = (1 << 15) - 1;
|
||||
return _mm_cmpgt_epi16(_mm_and_si128(a.m_val, _mm_set1_epi16(kAbsMask)), _mm_set1_epi16(kInf));
|
||||
}
|
||||
|
||||
// convert the sign-magnitude representation to two's complement
|
||||
EIGEN_STRONG_INLINE __m128i pmaptosigned(const __m128i& a) {
|
||||
constexpr uint16_t kAbsMask = (1 << 15) - 1;
|
||||
// if 'a' has the sign bit set, clear the sign bit and negate the result as if it were an integer
|
||||
return _mm_sign_epi16(_mm_and_si128(a, _mm_set1_epi16(kAbsMask)), a);
|
||||
}
|
||||
|
||||
// return true if both `a` and `b` are not NaN
|
||||
EIGEN_STRONG_INLINE Packet8h pisordered(const Packet8h& a, const Packet8h& b) {
|
||||
constexpr uint16_t kInf = ((1 << 5) - 1) << 10;
|
||||
constexpr uint16_t kAbsMask = (1 << 15) - 1;
|
||||
__m128i abs_a = _mm_and_si128(a.m_val, _mm_set1_epi16(kAbsMask));
|
||||
__m128i abs_b = _mm_and_si128(b.m_val, _mm_set1_epi16(kAbsMask));
|
||||
// check if both `abs_a <= kInf` and `abs_b <= kInf` by checking if max(abs_a, abs_b) <= kInf
|
||||
// SSE has no `lesser or equal` instruction for integers, but comparing against kInf + 1 accomplishes the same goal
|
||||
return _mm_cmplt_epi16(_mm_max_epu16(abs_a, abs_b), _mm_set1_epi16(kInf + 1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcmp_eq(const Packet8h& a, const Packet8h& b) {
|
||||
return Pack16To8(pcmp_eq(half2float(a), half2float(b)));
|
||||
__m128i isOrdered = pisordered(a, b);
|
||||
__m128i isEqual = _mm_cmpeq_epi16(pmaptosigned(a.m_val), pmaptosigned(b.m_val));
|
||||
return _mm_and_si128(isOrdered, isEqual);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcmp_le(const Packet8h& a, const Packet8h& b) {
|
||||
return Pack16To8(pcmp_le(half2float(a), half2float(b)));
|
||||
__m128i isOrdered = pisordered(a, b);
|
||||
__m128i isGreater = _mm_cmpgt_epi16(pmaptosigned(a.m_val), pmaptosigned(b.m_val));
|
||||
return _mm_andnot_si128(isGreater, isOrdered);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcmp_lt(const Packet8h& a, const Packet8h& b) {
|
||||
return Pack16To8(pcmp_lt(half2float(a), half2float(b)));
|
||||
__m128i isOrdered = pisordered(a, b);
|
||||
__m128i isLess = _mm_cmplt_epi16(pmaptosigned(a.m_val), pmaptosigned(b.m_val));
|
||||
return _mm_and_si128(isOrdered, isLess);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcmp_lt_or_nan(const Packet8h& a, const Packet8h& b) {
|
||||
return Pack16To8(pcmp_lt_or_nan(half2float(a), half2float(b)));
|
||||
__m128i isUnordered = por(pisnan(a), pisnan(b));
|
||||
__m128i isLess = _mm_cmplt_epi16(pmaptosigned(a.m_val), pmaptosigned(b.m_val));
|
||||
return _mm_or_si128(isUnordered, isLess);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -2367,6 +2347,26 @@ EIGEN_STRONG_INLINE Packet8h pmul<Packet8h>(const Packet8h& a, const Packet8h& b
|
||||
return float2half(rf);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pmadd<Packet8h>(const Packet8h& a, const Packet8h& b, const Packet8h& c) {
|
||||
return float2half(pmadd(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pmsub<Packet8h>(const Packet8h& a, const Packet8h& b, const Packet8h& c) {
|
||||
return float2half(pmsub(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pnmadd<Packet8h>(const Packet8h& a, const Packet8h& b, const Packet8h& c) {
|
||||
return float2half(pnmadd(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pnmsub<Packet8h>(const Packet8h& a, const Packet8h& b, const Packet8h& c) {
|
||||
return float2half(pnmsub(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pdiv<Packet8h>(const Packet8h& a, const Packet8h& b) {
|
||||
Packet8f af = half2float(a);
|
||||
@@ -2403,36 +2403,6 @@ EIGEN_STRONG_INLINE void pscatter<Eigen::half, Packet8h>(Eigen::half* to, const
|
||||
to[stride * 7] = aux[7];
|
||||
}
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Eigen::half predux<Packet8h>(const Packet8h& a) {
|
||||
Packet8f af = half2float(a);
|
||||
float reduced = predux<Packet8f>(af);
|
||||
return Eigen::half(reduced);
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h preverse(const Packet8h& a) {
|
||||
__m128i m = _mm_setr_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
|
||||
@@ -2510,6 +2480,8 @@ EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet8h, 4>& kernel) {
|
||||
kernel.packet[3] = pload<Packet8h>(out[3]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BFloat16 implementation.
|
||||
|
||||
EIGEN_STRONG_INLINE Packet8f Bf16ToF32(const Packet8bf& a) {
|
||||
@@ -2737,6 +2709,26 @@ EIGEN_STRONG_INLINE Packet8bf pmul<Packet8bf>(const Packet8bf& a, const Packet8b
|
||||
return F32ToBf16(pmul<Packet8f>(Bf16ToF32(a), Bf16ToF32(b)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pmadd<Packet8bf>(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
return F32ToBf16(pmadd(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pmsub<Packet8bf>(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
return F32ToBf16(pmsub(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pnmadd<Packet8bf>(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
return F32ToBf16(pnmadd(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pnmsub<Packet8bf>(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
return F32ToBf16(pnmsub(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pdiv<Packet8bf>(const Packet8bf& a, const Packet8bf& b) {
|
||||
return F32ToBf16(pdiv<Packet8f>(Bf16ToF32(a), Bf16ToF32(b)));
|
||||
@@ -2769,26 +2761,6 @@ EIGEN_STRONG_INLINE void pscatter<bfloat16, Packet8bf>(bfloat16* to, const Packe
|
||||
to[stride * 7] = aux[7];
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux<Packet8bf>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux<Packet8f>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max<Packet8bf>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_max<Packet8f>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min<Packet8bf>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_min<Packet8f>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_mul<Packet8bf>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_mul<Packet8f>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf preverse(const Packet8bf& a) {
|
||||
__m128i m = _mm_setr_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
|
||||
@@ -2850,6 +2822,258 @@ EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet8bf, 4>& kernel) {
|
||||
kernel.packet[3] = _mm_unpackhi_epi32(ab_47, cd_47);
|
||||
}
|
||||
|
||||
/*---------------- load/store segment support ----------------*/
|
||||
|
||||
// returns a mask of 8-bit elements (at most 4) that are all 1's in the range [begin, begin + count) and 0 elsewhere.
|
||||
inline __m128i segment_mask_4x8(Index begin, Index count) {
|
||||
eigen_assert(begin >= 0 && begin + count <= 4);
|
||||
long long mask = 1;
|
||||
mask <<= CHAR_BIT * count;
|
||||
mask--;
|
||||
mask <<= CHAR_BIT * begin;
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
return _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&mask));
|
||||
#else
|
||||
return _mm_cvtsi64_si128(mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns a mask of 8-bit elements (at most 8) that are all 1's in the range [begin, begin + count) and 0 elsewhere.
|
||||
inline __m128i segment_mask_8x8(Index begin, Index count) {
|
||||
eigen_assert(begin >= 0 && begin + count <= 8);
|
||||
long long mask = 1;
|
||||
// avoid UB when count == 8
|
||||
mask <<= (CHAR_BIT / 2) * count;
|
||||
mask <<= (CHAR_BIT / 2) * count;
|
||||
mask--;
|
||||
mask <<= CHAR_BIT * begin;
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
return _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&mask));
|
||||
#else
|
||||
return _mm_cvtsi64_si128(mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns a mask of 32-bit elements (at most 4) that are all 1's in the range [begin, begin + count) and 0 elsewhere.
|
||||
inline __m128i segment_mask_4x32(Index begin, Index count) {
|
||||
eigen_assert(begin >= 0 && begin + count <= 4);
|
||||
return _mm_cvtepi8_epi32(segment_mask_4x8(begin, count));
|
||||
}
|
||||
|
||||
// returns a mask of 64-bit elements (at most 2) that are all 1's in the range [begin, begin + count) and 0 elsewhere.
|
||||
inline __m128i segment_mask_2x64(Index begin, Index count) {
|
||||
eigen_assert(begin >= 0 && begin + count <= 2);
|
||||
return _mm_cvtepi8_epi64(segment_mask_4x8(begin, count));
|
||||
}
|
||||
|
||||
// returns a mask of 32-bit elements (at most 8) that are all 1's in the range [begin, begin + count) and 0 elsewhere.
|
||||
inline __m256i segment_mask_8x32(Index begin, Index count) {
|
||||
__m128i mask_epi8 = segment_mask_8x8(begin, count);
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
__m256i mask_epi32 = _mm256_cvtepi8_epi32(mask_epi8);
|
||||
#else
|
||||
__m128i mask_epi32_lo = _mm_cvtepi8_epi32(mask_epi8);
|
||||
__m128i mask_epi32_hi = _mm_cvtepi8_epi32(_mm_srli_epi64(mask_epi8, 32));
|
||||
__m256i mask_epi32 = _mm256_insertf128_si256(_mm256_castsi128_si256(mask_epi32_lo), mask_epi32_hi, 1);
|
||||
#endif
|
||||
return mask_epi32;
|
||||
}
|
||||
|
||||
// returns a mask of 64-bit elements (at most 4) that are all 1's in the range [begin, begin + count) and 0 elsewhere.
|
||||
inline __m256i segment_mask_4x64(Index begin, Index count) {
|
||||
__m128i mask_epi8 = segment_mask_4x8(begin, count);
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
__m256i mask_epi64 = _mm256_cvtepi8_epi64(mask_epi8);
|
||||
#else
|
||||
__m128i mask_epi64_lo = _mm_cvtepi8_epi64(mask_epi8);
|
||||
__m128i mask_epi64_hi = _mm_cvtepi8_epi64(_mm_srli_epi64(mask_epi8, 16));
|
||||
__m256i mask_epi64 = _mm256_insertf128_si256(_mm256_castsi128_si256(mask_epi64_lo), mask_epi64_hi, 1);
|
||||
#endif
|
||||
return mask_epi64;
|
||||
}
|
||||
|
||||
/*---------------- float ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet4f> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet8f> : std::true_type {};
|
||||
|
||||
template <>
|
||||
inline Packet4f ploaduSegment<Packet4f>(const float* from, Index begin, Index count) {
|
||||
return _mm_maskload_ps(from, segment_mask_4x32(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<float, Packet4f>(float* to, const Packet4f& from, Index begin, Index count) {
|
||||
_mm_maskstore_ps(to, segment_mask_4x32(begin, count), from);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Packet8f ploaduSegment<Packet8f>(const float* from, Index begin, Index count) {
|
||||
return _mm256_maskload_ps(from, segment_mask_8x32(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<float, Packet8f>(float* to, const Packet8f& from, Index begin, Index count) {
|
||||
_mm256_maskstore_ps(to, segment_mask_8x32(begin, count), from);
|
||||
}
|
||||
|
||||
/*---------------- int32 ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet4i> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet8i> : std::true_type {};
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
|
||||
template <>
|
||||
inline Packet4i ploaduSegment<Packet4i>(const int* from, Index begin, Index count) {
|
||||
return _mm_maskload_epi32(from, segment_mask_4x32(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<int, Packet4i>(int* to, const Packet4i& from, Index begin, Index count) {
|
||||
_mm_maskstore_epi32(to, segment_mask_4x32(begin, count), from);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Packet8i ploaduSegment<Packet8i>(const int* from, Index begin, Index count) {
|
||||
return _mm256_maskload_epi32(from, segment_mask_8x32(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<int, Packet8i>(int* to, const Packet8i& from, Index begin, Index count) {
|
||||
_mm256_maskstore_epi32(to, segment_mask_8x32(begin, count), from);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <>
|
||||
inline Packet4i ploaduSegment<Packet4i>(const int* from, Index begin, Index count) {
|
||||
return _mm_castps_si128(ploaduSegment<Packet4f>(reinterpret_cast<const float*>(from), begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<int, Packet4i>(int* to, const Packet4i& from, Index begin, Index count) {
|
||||
pstoreuSegment<float, Packet4f>(reinterpret_cast<float*>(to), _mm_castsi128_ps(from), begin, count);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Packet8i ploaduSegment<Packet8i>(const int* from, Index begin, Index count) {
|
||||
return _mm256_castps_si256(ploaduSegment<Packet8f>(reinterpret_cast<const float*>(from), begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<int, Packet8i>(int* to, const Packet8i& from, Index begin, Index count) {
|
||||
pstoreuSegment<float, Packet8f>(reinterpret_cast<float*>(to), _mm256_castsi256_ps(from), begin, count);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*---------------- uint32 ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet4ui> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet8ui> : std::true_type {};
|
||||
|
||||
template <>
|
||||
inline Packet4ui ploaduSegment<Packet4ui>(const uint32_t* from, Index begin, Index count) {
|
||||
return Packet4ui(ploaduSegment<Packet4i>(reinterpret_cast<const int*>(from), begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<uint32_t, Packet4ui>(uint32_t* to, const Packet4ui& from, Index begin, Index count) {
|
||||
pstoreuSegment<int, Packet4i>(reinterpret_cast<int*>(to), Packet4i(from), begin, count);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Packet8ui ploaduSegment<Packet8ui>(const uint32_t* from, Index begin, Index count) {
|
||||
return Packet8ui(ploaduSegment<Packet8i>(reinterpret_cast<const int*>(from), begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<uint32_t, Packet8ui>(uint32_t* to, const Packet8ui& from, Index begin, Index count) {
|
||||
pstoreuSegment<int, Packet8i>(reinterpret_cast<int*>(to), Packet8i(from), begin, count);
|
||||
}
|
||||
|
||||
/*---------------- double ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet2d> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet4d> : std::true_type {};
|
||||
|
||||
template <>
|
||||
inline Packet2d ploaduSegment<Packet2d>(const double* from, Index begin, Index count) {
|
||||
return _mm_maskload_pd(from, segment_mask_2x64(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<double, Packet2d>(double* to, const Packet2d& from, Index begin, Index count) {
|
||||
_mm_maskstore_pd(to, segment_mask_2x64(begin, count), from);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Packet4d ploaduSegment<Packet4d>(const double* from, Index begin, Index count) {
|
||||
return _mm256_maskload_pd(from, segment_mask_4x64(begin, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void pstoreuSegment<double, Packet4d>(double* to, const Packet4d& from, Index begin, Index count) {
|
||||
_mm256_maskstore_pd(to, segment_mask_4x64(begin, count), from);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
|
||||
/*---------------- int64_t ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet2l> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet4l> : std::true_type {};
|
||||
|
||||
template <>
|
||||
inline Packet2l ploaduSegment<Packet2l>(const int64_t* from, Index begin, Index count) {
|
||||
return _mm_maskload_epi64(reinterpret_cast<const long long*>(from), segment_mask_2x64(begin, count));
|
||||
}
|
||||
template <>
|
||||
inline void pstoreuSegment<int64_t, Packet2l>(int64_t* to, const Packet2l& from, Index begin, Index count) {
|
||||
_mm_maskstore_epi64(reinterpret_cast<long long*>(to), segment_mask_2x64(begin, count), from);
|
||||
}
|
||||
template <>
|
||||
inline Packet4l ploaduSegment<Packet4l>(const int64_t* from, Index begin, Index count) {
|
||||
return _mm256_maskload_epi64(reinterpret_cast<const long long*>(from), segment_mask_4x64(begin, count));
|
||||
}
|
||||
template <>
|
||||
inline void pstoreuSegment<int64_t, Packet4l>(int64_t* to, const Packet4l& from, Index begin, Index count) {
|
||||
_mm256_maskstore_epi64(reinterpret_cast<long long*>(to), segment_mask_4x64(begin, count), from);
|
||||
}
|
||||
|
||||
/*---------------- uint64_t ----------------*/
|
||||
|
||||
template <>
|
||||
struct has_packet_segment<Packet4ul> : std::true_type {};
|
||||
|
||||
template <>
|
||||
inline Packet4ul ploaduSegment<Packet4ul>(const uint64_t* from, Index begin, Index count) {
|
||||
return Packet4ul(ploaduSegment<Packet4l>(reinterpret_cast<const int64_t*>(from), begin, count));
|
||||
}
|
||||
template <>
|
||||
inline void pstoreuSegment<uint64_t, Packet4ul>(uint64_t* to, const Packet4ul& from, Index begin, Index count) {
|
||||
pstoreuSegment<int64_t, Packet4l>(reinterpret_cast<int64_t*>(to), Packet4l(from), begin, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*---------------- end load/store segment support ----------------*/
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 Charlie Schlosser <cs.schlosser@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_REDUCTIONS_AVX_H
|
||||
#define EIGEN_REDUCTIONS_AVX_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "../../InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet8i -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux(const Packet8i& a) {
|
||||
Packet4i lo = _mm256_castsi256_si128(a);
|
||||
Packet4i hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux(padd(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_mul(const Packet8i& a) {
|
||||
Packet4i lo = _mm256_castsi256_si128(a);
|
||||
Packet4i hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux_mul(pmul(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_min(const Packet8i& a) {
|
||||
Packet4i lo = _mm256_castsi256_si128(a);
|
||||
Packet4i hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux_min(pmin(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_max(const Packet8i& a) {
|
||||
Packet4i lo = _mm256_castsi256_si128(a);
|
||||
Packet4i hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux_max(pmax(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8i& a) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
return _mm256_movemask_epi8(a) != 0x0;
|
||||
#else
|
||||
return _mm256_movemask_ps(_mm256_castsi256_ps(a)) != 0x0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet8ui -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE uint32_t predux(const Packet8ui& a) {
|
||||
Packet4ui lo = _mm256_castsi256_si128(a);
|
||||
Packet4ui hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux(padd(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE uint32_t predux_mul(const Packet8ui& a) {
|
||||
Packet4ui lo = _mm256_castsi256_si128(a);
|
||||
Packet4ui hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux_mul(pmul(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE uint32_t predux_min(const Packet8ui& a) {
|
||||
Packet4ui lo = _mm256_castsi256_si128(a);
|
||||
Packet4ui hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux_min(pmin(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE uint32_t predux_max(const Packet8ui& a) {
|
||||
Packet4ui lo = _mm256_castsi256_si128(a);
|
||||
Packet4ui hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux_max(pmax(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8ui& a) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
return _mm256_movemask_epi8(a) != 0x0;
|
||||
#else
|
||||
return _mm256_movemask_ps(_mm256_castsi256_ps(a)) != 0x0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet4l -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux(const Packet4l& a) {
|
||||
Packet2l lo = _mm256_castsi256_si128(a);
|
||||
Packet2l hi = _mm256_extractf128_si256(a, 1);
|
||||
return predux(padd(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet4l& a) {
|
||||
return _mm256_movemask_pd(_mm256_castsi256_pd(a)) != 0x0;
|
||||
}
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet4ul -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE uint64_t predux(const Packet4ul& a) {
|
||||
return static_cast<uint64_t>(predux(Packet4l(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet4ul& a) {
|
||||
return _mm256_movemask_pd(_mm256_castsi256_pd(a)) != 0x0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet8f -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux(padd(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_mul(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux_mul(pmul(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux_min(pmin(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min<PropagateNumbers>(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux_min<PropagateNumbers>(pmin<PropagateNumbers>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min<PropagateNaN>(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux_min<PropagateNaN>(pmin<PropagateNaN>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux_max(pmax(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max<PropagateNumbers>(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux_max<PropagateNumbers>(pmax<PropagateNumbers>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max<PropagateNaN>(const Packet8f& a) {
|
||||
Packet4f lo = _mm256_castps256_ps128(a);
|
||||
Packet4f hi = _mm256_extractf128_ps(a, 1);
|
||||
return predux_max<PropagateNaN>(pmax<PropagateNaN>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8f& a) {
|
||||
return _mm256_movemask_ps(a) != 0x0;
|
||||
}
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet4d -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux(padd(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_mul(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux_mul(pmul(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux_min(pmin(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min<PropagateNumbers>(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux_min<PropagateNumbers>(pmin<PropagateNumbers>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min<PropagateNaN>(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux_min<PropagateNaN>(pmin<PropagateNaN>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux_max(pmax(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max<PropagateNumbers>(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux_max<PropagateNumbers>(pmax<PropagateNumbers>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max<PropagateNaN>(const Packet4d& a) {
|
||||
Packet2d lo = _mm256_castpd256_pd128(a);
|
||||
Packet2d hi = _mm256_extractf128_pd(a, 1);
|
||||
return predux_max<PropagateNaN>(pmax<PropagateNaN>(lo, hi));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet4d& a) {
|
||||
return _mm256_movemask_pd(a) != 0x0;
|
||||
}
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet8h -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux(const Packet8h& a) {
|
||||
return static_cast<half>(predux(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_mul(const Packet8h& a) {
|
||||
return static_cast<half>(predux_mul(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_min(const Packet8h& a) {
|
||||
return static_cast<half>(predux_min(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_min<PropagateNumbers>(const Packet8h& a) {
|
||||
return static_cast<half>(predux_min<PropagateNumbers>(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_min<PropagateNaN>(const Packet8h& a) {
|
||||
return static_cast<half>(predux_min<PropagateNaN>(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_max(const Packet8h& a) {
|
||||
return static_cast<half>(predux_max(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_max<PropagateNumbers>(const Packet8h& a) {
|
||||
return static_cast<half>(predux_max<PropagateNumbers>(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_max<PropagateNaN>(const Packet8h& a) {
|
||||
return static_cast<half>(predux_max<PropagateNaN>(half2float(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8h& a) {
|
||||
return _mm_movemask_epi8(a) != 0;
|
||||
}
|
||||
#endif // EIGEN_VECTORIZE_AVX512FP16
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet8bf -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux<Packet8f>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_mul(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_mul<Packet8f>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_min(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min<PropagateNumbers>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_min<PropagateNumbers>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min<PropagateNaN>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_min<PropagateNaN>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_max<Packet8f>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max<PropagateNumbers>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_max<PropagateNumbers>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max<PropagateNaN>(const Packet8bf& a) {
|
||||
return static_cast<bfloat16>(predux_max<PropagateNaN>(Bf16ToF32(a)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8bf& a) {
|
||||
return _mm_movemask_epi8(a) != 0;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_REDUCTIONS_AVX_H
|
||||
@@ -279,20 +279,22 @@ EIGEN_STRONG_INLINE Packet2l preinterpret<Packet2l, Packet4l>(const Packet4l& a)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f pcast<Packet8h, Packet8f>(const Packet8h& a) {
|
||||
return half2float(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f pcast<Packet8bf, Packet8f>(const Packet8bf& a) {
|
||||
return Bf16ToF32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcast<Packet8f, Packet8h>(const Packet8f& a) {
|
||||
return float2half(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f pcast<Packet8bf, Packet8f>(const Packet8bf& a) {
|
||||
return Bf16ToF32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pcast<Packet8f, Packet8bf>(const Packet8f& a) {
|
||||
|
||||
@@ -47,16 +47,16 @@ EIGEN_STRONG_INLINE Packet16bf pldexp(const Packet16bf& a, const Packet16bf& exp
|
||||
|
||||
#if EIGEN_FAST_MATH
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet16f psqrt<Packet16f>(const Packet16f& _x) {
|
||||
return generic_sqrt_newton_step<Packet16f>::run(_x, _mm512_rsqrt14_ps(_x));
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet16f psqrt<Packet16f>(const Packet16f& x) {
|
||||
return generic_sqrt_newton_step<Packet16f>::run(x, _mm512_rsqrt14_ps(x));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet8d psqrt<Packet8d>(const Packet8d& _x) {
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet8d psqrt<Packet8d>(const Packet8d& x) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX512ER
|
||||
return generic_sqrt_newton_step<Packet8d, /*Steps=*/1>::run(_x, _mm512_rsqrt28_pd(_x));
|
||||
return generic_sqrt_newton_step<Packet8d, /*Steps=*/1>::run(x, _mm512_rsqrt28_pd(x));
|
||||
#else
|
||||
return generic_sqrt_newton_step<Packet8d, /*Steps=*/2>::run(_x, _mm512_rsqrt14_pd(_x));
|
||||
return generic_sqrt_newton_step<Packet8d, /*Steps=*/2>::run(x, _mm512_rsqrt14_pd(x));
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
@@ -80,19 +80,19 @@ EIGEN_STRONG_INLINE Packet16f prsqrt<Packet16f>(const Packet16f& x) {
|
||||
#elif EIGEN_FAST_MATH
|
||||
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet16f prsqrt<Packet16f>(const Packet16f& _x) {
|
||||
return generic_rsqrt_newton_step<Packet16f, /*Steps=*/1>::run(_x, _mm512_rsqrt14_ps(_x));
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet16f prsqrt<Packet16f>(const Packet16f& x) {
|
||||
return generic_rsqrt_newton_step<Packet16f, /*Steps=*/1>::run(x, _mm512_rsqrt14_ps(x));
|
||||
}
|
||||
#endif
|
||||
|
||||
// prsqrt for double.
|
||||
#if EIGEN_FAST_MATH
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet8d prsqrt<Packet8d>(const Packet8d& _x) {
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet8d prsqrt<Packet8d>(const Packet8d& x) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX512ER
|
||||
return generic_rsqrt_newton_step<Packet8d, /*Steps=*/1>::run(_x, _mm512_rsqrt28_pd(_x));
|
||||
return generic_rsqrt_newton_step<Packet8d, /*Steps=*/1>::run(x, _mm512_rsqrt28_pd(x));
|
||||
#else
|
||||
return generic_rsqrt_newton_step<Packet8d, /*Steps=*/2>::run(_x, _mm512_rsqrt14_pd(_x));
|
||||
return generic_rsqrt_newton_step<Packet8d, /*Steps=*/2>::run(x, _mm512_rsqrt14_pd(x));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ EIGEN_STRONG_INLINE Packet16f preciprocal<Packet16f>(const Packet16f& a) {
|
||||
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, pcos)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, pexp)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, pexp2)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, pexpm1)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, plog)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, plog1p)
|
||||
@@ -117,8 +118,11 @@ BF16_PACKET_FUNCTION(Packet16f, Packet16bf, prsqrt)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, psin)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, psqrt)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, ptanh)
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, pcos)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, pexp)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, pexp2)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, pexpm1)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, plog)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, plog1p)
|
||||
@@ -128,6 +132,7 @@ F16_PACKET_FUNCTION(Packet16f, Packet16h, prsqrt)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, psin)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, psqrt)
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, ptanh)
|
||||
#endif // EIGEN_VECTORIZE_AVX512FP16
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 The Eigen Authors.
|
||||
//
|
||||
// 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_MATH_FUNCTIONS_FP16_AVX512_H
|
||||
#define EIGEN_MATH_FUNCTIONS_FP16_AVX512_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "../../InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
EIGEN_STRONG_INLINE Packet32h combine2Packet16h(const Packet16h& a, const Packet16h& b) {
|
||||
__m512i result = _mm512_castsi256_si512(_mm256_castph_si256(a));
|
||||
result = _mm512_inserti64x4(result, _mm256_castph_si256(b), 1);
|
||||
return _mm512_castsi512_ph(result);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE void extract2Packet16h(const Packet32h& x, Packet16h& a, Packet16h& b) {
|
||||
a = _mm256_castsi256_ph(_mm512_castsi512_si256(_mm512_castph_si512(x)));
|
||||
b = _mm256_castsi256_ph(_mm512_extracti64x4_epi64(_mm512_castph_si512(x), 1));
|
||||
}
|
||||
|
||||
#define _EIGEN_GENERATE_FP16_MATH_FUNCTION(func) \
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE Packet8h func<Packet8h>(const Packet8h& a) { \
|
||||
return float2half(func(half2float(a))); \
|
||||
} \
|
||||
\
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE Packet16h func<Packet16h>(const Packet16h& a) { \
|
||||
return float2half(func(half2float(a))); \
|
||||
} \
|
||||
\
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE Packet32h func<Packet32h>(const Packet32h& a) { \
|
||||
Packet16h low; \
|
||||
Packet16h high; \
|
||||
extract2Packet16h(a, low, high); \
|
||||
return combine2Packet16h(func(low), func(high)); \
|
||||
}
|
||||
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(psin)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(pcos)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(plog)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(plog2)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(plog1p)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(pexp)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(pexpm1)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(pexp2)
|
||||
_EIGEN_GENERATE_FP16_MATH_FUNCTION(ptanh)
|
||||
#undef _EIGEN_GENERATE_FP16_MATH_FUNCTION
|
||||
|
||||
// pfrexp
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32h pfrexp<Packet32h>(const Packet32h& a, Packet32h& exponent) {
|
||||
return pfrexp_generic(a, exponent);
|
||||
}
|
||||
|
||||
// pldexp
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32h pldexp<Packet32h>(const Packet32h& a, const Packet32h& exponent) {
|
||||
return pldexp_generic(a, exponent);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_MATH_FUNCTIONS_FP16_AVX512_H
|
||||
@@ -40,6 +40,10 @@ typedef eigen_packet_wrapper<__m256i, 1> Packet16h;
|
||||
#endif
|
||||
typedef eigen_packet_wrapper<__m256i, 2> Packet16bf;
|
||||
|
||||
typedef eigen_packet_wrapper<__m512i, 6> Packet32s;
|
||||
typedef eigen_packet_wrapper<__m256i, 6> Packet16s;
|
||||
typedef eigen_packet_wrapper<__m128i, 6> Packet8s;
|
||||
|
||||
template <>
|
||||
struct is_arithmetic<__m512> {
|
||||
enum { value = true };
|
||||
@@ -124,15 +128,18 @@ struct packet_traits<float> : default_packet_traits {
|
||||
HasATanh = 1,
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
HasCbrt = 1,
|
||||
HasLog = 1,
|
||||
HasLog1p = 1,
|
||||
HasExpm1 = 1,
|
||||
HasNdtri = 1,
|
||||
HasBessel = 1,
|
||||
HasExp = 1,
|
||||
HasPow = 1,
|
||||
HasReciprocal = EIGEN_FAST_MATH,
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasErf = EIGEN_FAST_MATH,
|
||||
HasErfc = EIGEN_FAST_MATH,
|
||||
HasCmp = 1,
|
||||
HasDiv = 1
|
||||
};
|
||||
@@ -148,12 +155,16 @@ struct packet_traits<double> : default_packet_traits {
|
||||
HasBlend = 1,
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
HasCbrt = 1,
|
||||
HasSin = EIGEN_FAST_MATH,
|
||||
HasCos = EIGEN_FAST_MATH,
|
||||
HasLog = 1,
|
||||
HasExp = 1,
|
||||
HasPow = 1,
|
||||
HasATan = 1,
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasErf = EIGEN_FAST_MATH,
|
||||
HasErfc = EIGEN_FAST_MATH,
|
||||
HasATanh = 1,
|
||||
HasCmp = 1,
|
||||
HasDiv = 1
|
||||
@@ -245,6 +256,39 @@ struct unpacket_traits<Packet16h> {
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct unpacket_traits<Packet32s> {
|
||||
typedef numext::int16_t type;
|
||||
typedef Packet16s half;
|
||||
enum {
|
||||
size = 32,
|
||||
alignment = Aligned64,
|
||||
vectorizable = false,
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unpacket_traits<Packet16s> {
|
||||
typedef numext::int16_t type;
|
||||
typedef Packet8s half;
|
||||
enum {
|
||||
size = 16,
|
||||
alignment = Aligned32,
|
||||
vectorizable = false,
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unpacket_traits<Packet8s> {
|
||||
typedef numext::int16_t type;
|
||||
typedef Packet8s half;
|
||||
enum {
|
||||
size = 8,
|
||||
alignment = Aligned16,
|
||||
vectorizable = false,
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f pset1<Packet16f>(const float& from) {
|
||||
return _mm512_set1_ps(from);
|
||||
@@ -1332,10 +1376,13 @@ EIGEN_STRONG_INLINE Packet8l pabs(const Packet8l& a) {
|
||||
return _mm512_abs_epi64(a);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h psignbit(const Packet16h& a) {
|
||||
return _mm256_srai_epi16(a, 15);
|
||||
}
|
||||
#endif // EIGEN_VECTORIZE_AVX512FP16
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16bf psignbit(const Packet16bf& a) {
|
||||
return _mm256_srai_epi16(a, 15);
|
||||
@@ -1449,40 +1496,6 @@ EIGEN_STRONG_INLINE Packet8d pldexp<Packet8d>(const Packet8d& a, const Packet8d&
|
||||
OUTPUT = _mm512_inserti32x4(OUTPUT, _mm256_extractf128_si256(INPUTB, 1), 3);
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux<Packet16f>(const Packet16f& a) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
__m256 lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
__m256 lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
Packet8f x = _mm256_add_ps(lane0, lane1);
|
||||
return predux<Packet8f>(x);
|
||||
#else
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 sum = _mm_add_ps(_mm_add_ps(lane0, lane1), _mm_add_ps(lane2, lane3));
|
||||
return predux<Packet4f>(sum);
|
||||
#endif
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d sum = _mm256_add_pd(lane0, lane1);
|
||||
return predux<Packet4d>(sum);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux<Packet8l>(const Packet8l& a) {
|
||||
return _mm512_reduce_add_epi64(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux<Packet16i>(const Packet16i& a) {
|
||||
return _mm512_reduce_add_epi32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f predux_half_dowto4<Packet16f>(const Packet16f& a) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
@@ -1529,129 +1542,6 @@ EIGEN_STRONG_INLINE Packet4l predux_half_dowto4<Packet8l>(const Packet8l& a) {
|
||||
return _mm256_add_epi64(lane0, lane1);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_mul<Packet16f>(const Packet16f& a) {
|
||||
// #ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
#if 0
|
||||
Packet8f lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
Packet8f lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
Packet8f res = pmul(lane0, lane1);
|
||||
res = pmul(res, _mm256_permute2f128_ps(res, res, 1));
|
||||
res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
#else
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 res = pmul(pmul(lane0, lane1), pmul(lane2, lane3));
|
||||
res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
#endif
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_mul<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d res = pmul(lane0, lane1);
|
||||
res = pmul(res, _mm256_permute2f128_pd(res, res, 1));
|
||||
return pfirst(pmul(res, _mm256_shuffle_pd(res, res, 1)));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_mul<Packet16i>(const Packet16i& a) {
|
||||
return _mm512_reduce_mul_epi32(a);
|
||||
}
|
||||
|
||||
#if EIGEN_COMP_MSVC
|
||||
// MSVC's _mm512_reduce_mul_epi64 is borked, at least up to and including 1939.
|
||||
// alignas(64) int64_t data[] = { 1,1,-1,-1,1,-1,-1,-1 };
|
||||
// int64_t out = _mm512_reduce_mul_epi64(_mm512_load_epi64(data));
|
||||
// produces garbage: 4294967295. It seems to happen whenever the output is supposed to be negative.
|
||||
// Fall back to a manual approach:
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_mul<Packet8l>(const Packet8l& a) {
|
||||
Packet4l lane0 = _mm512_extracti64x4_epi64(a, 0);
|
||||
Packet4l lane1 = _mm512_extracti64x4_epi64(a, 1);
|
||||
Packet4l res = pmul(lane0, lane1);
|
||||
res = pmul(res, Packet4l(_mm256_permute2x128_si256(res, res, 1)));
|
||||
res = pmul(res, Packet4l(_mm256_shuffle_epi32(res, 0xE)));
|
||||
return pfirst(res);
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_mul<Packet8l>(const Packet8l& a) {
|
||||
return _mm512_reduce_mul_epi64(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min<Packet16f>(const Packet16f& a) {
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 res = _mm_min_ps(_mm_min_ps(lane0, lane1), _mm_min_ps(lane2, lane3));
|
||||
res = _mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(_mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d res = _mm256_min_pd(lane0, lane1);
|
||||
res = _mm256_min_pd(res, _mm256_permute2f128_pd(res, res, 1));
|
||||
return pfirst(_mm256_min_pd(res, _mm256_shuffle_pd(res, res, 1)));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_min<Packet16i>(const Packet16i& a) {
|
||||
return _mm512_reduce_min_epi32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_min<Packet8l>(const Packet8l& a) {
|
||||
return _mm512_reduce_min_epi64(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max<Packet16f>(const Packet16f& a) {
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 res = _mm_max_ps(_mm_max_ps(lane0, lane1), _mm_max_ps(lane2, lane3));
|
||||
res = _mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(_mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d res = _mm256_max_pd(lane0, lane1);
|
||||
res = _mm256_max_pd(res, _mm256_permute2f128_pd(res, res, 1));
|
||||
return pfirst(_mm256_max_pd(res, _mm256_shuffle_pd(res, res, 1)));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_max<Packet16i>(const Packet16i& a) {
|
||||
return _mm512_reduce_max_epi32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_max<Packet8l>(const Packet8l& a) {
|
||||
return _mm512_reduce_max_epi64(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet16f& x) {
|
||||
Packet16i xi = _mm512_castps_si512(x);
|
||||
__mmask16 tmp = _mm512_test_epi32_mask(xi, xi);
|
||||
return !_mm512_kortestz(tmp, tmp);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet16i& x) {
|
||||
__mmask16 tmp = _mm512_test_epi32_mask(x, x);
|
||||
return !_mm512_kortestz(tmp, tmp);
|
||||
}
|
||||
|
||||
#define PACK_OUTPUT(OUTPUT, INPUT, INDEX, STRIDE) \
|
||||
EIGEN_INSERT_8f_INTO_16f(OUTPUT[INDEX], INPUT[INDEX], INPUT[INDEX + STRIDE]);
|
||||
|
||||
@@ -2189,6 +2079,7 @@ EIGEN_STRONG_INLINE Packet8d pblend(const Selector<8>& ifPacket, const Packet8d&
|
||||
}
|
||||
|
||||
// Packet math for Eigen::half
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pset1<Packet16h>(const Eigen::half& from) {
|
||||
return _mm256_set1_epi16(from.x);
|
||||
@@ -2213,6 +2104,7 @@ template <>
|
||||
EIGEN_STRONG_INLINE void pstore<half>(Eigen::half* to, const Packet16h& from) {
|
||||
// (void*) -> workaround clang warning:
|
||||
// cast from 'Eigen::half *' to '__m256i *' increases required alignment from 2 to 32
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
_mm256_store_si256((__m256i*)(void*)to, from);
|
||||
}
|
||||
|
||||
@@ -2220,6 +2112,7 @@ template <>
|
||||
EIGEN_STRONG_INLINE void pstoreu<half>(Eigen::half* to, const Packet16h& from) {
|
||||
// (void*) -> workaround clang warning:
|
||||
// cast from 'Eigen::half *' to '__m256i *' increases required alignment from 2 to 32
|
||||
EIGEN_DEBUG_UNALIGNED_STORE
|
||||
_mm256_storeu_si256((__m256i*)(void*)to, from);
|
||||
}
|
||||
|
||||
@@ -2359,7 +2252,6 @@ EIGEN_STRONG_INLINE Packet16h pnegate(const Packet16h& a) {
|
||||
return _mm256_xor_si256(a, sign_mask);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h padd<Packet16h>(const Packet16h& a, const Packet16h& b) {
|
||||
Packet16f af = half2float(a);
|
||||
@@ -2393,12 +2285,24 @@ EIGEN_STRONG_INLINE Packet16h pdiv<Packet16h>(const Packet16h& a, const Packet16
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux<Packet16h>(const Packet16h& from) {
|
||||
Packet16f from_float = half2float(from);
|
||||
return half(predux(from_float));
|
||||
EIGEN_STRONG_INLINE Packet16h pmadd<Packet16h>(const Packet16h& a, const Packet16h& b, const Packet16h& c) {
|
||||
return float2half(pmadd(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
#endif
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pmsub<Packet16h>(const Packet16h& a, const Packet16h& b, const Packet16h& c) {
|
||||
return float2half(pmsub(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pnmadd<Packet16h>(const Packet16h& a, const Packet16h& b, const Packet16h& c) {
|
||||
return float2half(pnmadd(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pnmsub<Packet16h>(const Packet16h& a, const Packet16h& b, const Packet16h& c) {
|
||||
return float2half(pnmsub(half2float(a), half2float(b), half2float(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h predux_half_dowto4<Packet16h>(const Packet16h& a) {
|
||||
@@ -2407,26 +2311,6 @@ EIGEN_STRONG_INLINE Packet8h predux_half_dowto4<Packet16h>(const Packet16h& a) {
|
||||
return padd<Packet8h>(lane0, lane1);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Eigen::half predux_max<Packet16h>(const Packet16h& a) {
|
||||
Packet16f af = half2float(a);
|
||||
float reduced = predux_max<Packet16f>(af);
|
||||
return Eigen::half(reduced);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Eigen::half predux_min<Packet16h>(const Packet16h& a) {
|
||||
Packet16f af = half2float(a);
|
||||
float reduced = predux_min<Packet16f>(af);
|
||||
return Eigen::half(reduced);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_mul<Packet16h>(const Packet16h& from) {
|
||||
Packet16f from_float = half2float(from);
|
||||
return half(predux_mul(from_float));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h preverse(const Packet16h& a) {
|
||||
__m128i m = _mm_setr_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1);
|
||||
@@ -2633,6 +2517,8 @@ EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet16h, 4>& kernel) {
|
||||
kernel.packet[3] = pload<Packet16h>(out[3]);
|
||||
}
|
||||
|
||||
#endif // EIGEN_VECTORIZE_AVX512FP16
|
||||
|
||||
template <>
|
||||
struct is_arithmetic<Packet16bf> {
|
||||
enum { value = true };
|
||||
@@ -2704,11 +2590,13 @@ EIGEN_STRONG_INLINE Packet16bf ploadu<Packet16bf>(const bfloat16* from) {
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstore<bfloat16>(bfloat16* to, const Packet16bf& from) {
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
_mm256_store_si256(reinterpret_cast<__m256i*>(to), from);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstoreu<bfloat16>(bfloat16* to, const Packet16bf& from) {
|
||||
EIGEN_DEBUG_UNALIGNED_STORE
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(to), from);
|
||||
}
|
||||
|
||||
@@ -2879,7 +2767,27 @@ EIGEN_STRONG_INLINE Packet16bf psub<Packet16bf>(const Packet16bf& a, const Packe
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16bf pmul<Packet16bf>(const Packet16bf& a, const Packet16bf& b) {
|
||||
return F32ToBf16(pmul<Packet16f>(Bf16ToF32(a), Bf16ToF32(b)));
|
||||
return F32ToBf16(pmul(Bf16ToF32(a), Bf16ToF32(b)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16bf pmadd<Packet16bf>(const Packet16bf& a, const Packet16bf& b, const Packet16bf& c) {
|
||||
return F32ToBf16(pmadd(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16bf pmsub<Packet16bf>(const Packet16bf& a, const Packet16bf& b, const Packet16bf& c) {
|
||||
return F32ToBf16(pmsub(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16bf pnmadd<Packet16bf>(const Packet16bf& a, const Packet16bf& b, const Packet16bf& c) {
|
||||
return F32ToBf16(pnmadd(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16bf pnmsub<Packet16bf>(const Packet16bf& a, const Packet16bf& b, const Packet16bf& c) {
|
||||
return F32ToBf16(pnmsub(Bf16ToF32(a), Bf16ToF32(b), Bf16ToF32(c)));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -2909,26 +2817,6 @@ EIGEN_STRONG_INLINE Packet8bf predux_half_dowto4<Packet16bf>(const Packet16bf& a
|
||||
return padd<Packet8bf>(lane0, lane1);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux<Packet16bf>(const Packet16bf& p) {
|
||||
return static_cast<bfloat16>(predux<Packet16f>(Bf16ToF32(p)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_mul<Packet16bf>(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_mul<Packet16f>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min<Packet16bf>(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_min<Packet16f>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max<Packet16bf>(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_max<Packet16f>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16bf preverse(const Packet16bf& a) {
|
||||
__m256i m = _mm256_setr_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1, 14, 15, 12, 13, 10, 11, 8, 9, 6, 7,
|
||||
@@ -3085,6 +2973,172 @@ EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet16bf, 4>& kernel) {
|
||||
kernel.packet[3] = _mm256_permute2x128_si256(abcd_8b, abcd_cf, 0x31);
|
||||
}
|
||||
|
||||
// Minimal implementation of 16-bit int packets for use in pfrexp, pldexp.
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32s pset1<Packet32s>(const numext::int16_t& x) {
|
||||
return _mm512_set1_epi16(x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16s pset1<Packet16s>(const numext::int16_t& x) {
|
||||
return _mm256_set1_epi16(x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pset1<Packet8s>(const numext::int16_t& x) {
|
||||
return _mm_set1_epi16(x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstore<numext::int16_t, Packet32s>(numext::int16_t* out, const Packet32s& x) {
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
_mm512_store_epi32(out, x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstore<numext::int16_t, Packet16s>(numext::int16_t* out, const Packet16s& x) {
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
#if defined(EIGEN_VECTORIZE_AVX512F) && defined(EIGEN_VECTORIZE_AVX512VL)
|
||||
_mm256_store_epi32(out, x);
|
||||
#else
|
||||
_mm256_store_si256(reinterpret_cast<__m256i*>(out), x);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstore<numext::int16_t, Packet8s>(numext::int16_t* out, const Packet8s& x) {
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
#if defined(EIGEN_VECTORIZE_AVX512F) && defined(EIGEN_VECTORIZE_AVX512VL)
|
||||
_mm256_store_epi32(out, x);
|
||||
#else
|
||||
_mm_store_si128(reinterpret_cast<__m128i*>(out), x);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstoreu<numext::int16_t, Packet32s>(numext::int16_t* out, const Packet32s& x) {
|
||||
EIGEN_DEBUG_UNALIGNED_STORE
|
||||
_mm512_storeu_epi32(out, x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstoreu<numext::int16_t, Packet16s>(numext::int16_t* out, const Packet16s& x) {
|
||||
EIGEN_DEBUG_UNALIGNED_STORE
|
||||
_mm256_storeu_epi32(out, x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstoreu<numext::int16_t, Packet8s>(numext::int16_t* out, const Packet8s& x) {
|
||||
EIGEN_DEBUG_UNALIGNED_STORE
|
||||
_mm_storeu_epi32(out, x);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32s padd(const Packet32s& a, const Packet32s& b) {
|
||||
return _mm512_add_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16s padd(const Packet16s& a, const Packet16s& b) {
|
||||
return _mm256_add_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s padd(const Packet8s& a, const Packet8s& b) {
|
||||
return _mm_add_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32s psub(const Packet32s& a, const Packet32s& b) {
|
||||
return _mm512_sub_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16s psub(const Packet16s& a, const Packet16s& b) {
|
||||
return _mm256_sub_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s psub(const Packet8s& a, const Packet8s& b) {
|
||||
return _mm_sub_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32s pmul(const Packet32s& a, const Packet32s& b) {
|
||||
return _mm512_mullo_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16s pmul(const Packet16s& a, const Packet16s& b) {
|
||||
return _mm256_mullo_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pmul(const Packet8s& a, const Packet8s& b) {
|
||||
return _mm_mullo_epi16(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32s pnegate(const Packet32s& a) {
|
||||
return _mm512_sub_epi16(_mm512_setzero_si512(), a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16s pnegate(const Packet16s& a) {
|
||||
return _mm256_sub_epi16(_mm256_setzero_si256(), a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pnegate(const Packet8s& a) {
|
||||
return _mm_sub_epi16(_mm_setzero_si128(), a);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet32s parithmetic_shift_right(Packet32s a) {
|
||||
return _mm512_srai_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet16s parithmetic_shift_right(Packet16s a) {
|
||||
return _mm256_srai_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet8s parithmetic_shift_right(Packet8s a) {
|
||||
return _mm_srai_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet32s plogical_shift_left(Packet32s a) {
|
||||
return _mm512_slli_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet16s plogical_shift_left(Packet16s a) {
|
||||
return _mm256_slli_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet8s plogical_shift_left(Packet8s a) {
|
||||
return _mm_slli_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet32s plogical_shift_right(Packet32s a) {
|
||||
return _mm512_srli_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet16s plogical_shift_right(Packet16s a) {
|
||||
return _mm256_srli_epi16(a, N);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet8s plogical_shift_right(Packet8s a) {
|
||||
return _mm_srli_epi16(a, N);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,297 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 Charlie Schlosser <cs.schlosser@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_REDUCTIONS_AVX512_H
|
||||
#define EIGEN_REDUCTIONS_AVX512_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "../../InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet16i -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux(const Packet16i& a) {
|
||||
return _mm512_reduce_add_epi32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_mul(const Packet16i& a) {
|
||||
return _mm512_reduce_mul_epi32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_min(const Packet16i& a) {
|
||||
return _mm512_reduce_min_epi32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int predux_max(const Packet16i& a) {
|
||||
return _mm512_reduce_max_epi32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet16i& a) {
|
||||
return _mm512_reduce_or_epi32(a) != 0;
|
||||
}
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet8l -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux(const Packet8l& a) {
|
||||
return _mm512_reduce_add_epi64(a);
|
||||
}
|
||||
|
||||
#if EIGEN_COMP_MSVC
|
||||
// MSVC's _mm512_reduce_mul_epi64 is borked, at least up to and including 1939.
|
||||
// alignas(64) int64_t data[] = { 1,1,-1,-1,1,-1,-1,-1 };
|
||||
// int64_t out = _mm512_reduce_mul_epi64(_mm512_load_epi64(data));
|
||||
// produces garbage: 4294967295. It seems to happen whenever the output is supposed to be negative.
|
||||
// Fall back to a manual approach:
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_mul(const Packet8l& a) {
|
||||
Packet4l lane0 = _mm512_extracti64x4_epi64(a, 0);
|
||||
Packet4l lane1 = _mm512_extracti64x4_epi64(a, 1);
|
||||
return predux_mul(pmul(lane0, lane1));
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_mul<Packet8l>(const Packet8l& a) {
|
||||
return _mm512_reduce_mul_epi64(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_min(const Packet8l& a) {
|
||||
return _mm512_reduce_min_epi64(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int64_t predux_max(const Packet8l& a) {
|
||||
return _mm512_reduce_max_epi64(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8l& a) {
|
||||
return _mm512_reduce_or_epi64(a) != 0;
|
||||
}
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet16f -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux(const Packet16f& a) {
|
||||
return _mm512_reduce_add_ps(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_mul(const Packet16f& a) {
|
||||
return _mm512_reduce_mul_ps(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min(const Packet16f& a) {
|
||||
return _mm512_reduce_min_ps(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min<PropagateNumbers>(const Packet16f& a) {
|
||||
Packet8f lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
Packet8f lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
return predux_min<PropagateNumbers>(pmin<PropagateNumbers>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min<PropagateNaN>(const Packet16f& a) {
|
||||
Packet8f lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
Packet8f lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
return predux_min<PropagateNaN>(pmin<PropagateNaN>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max(const Packet16f& a) {
|
||||
return _mm512_reduce_max_ps(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max<PropagateNumbers>(const Packet16f& a) {
|
||||
Packet8f lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
Packet8f lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
return predux_max<PropagateNumbers>(pmax<PropagateNumbers>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max<PropagateNaN>(const Packet16f& a) {
|
||||
Packet8f lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
Packet8f lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
return predux_max<PropagateNaN>(pmax<PropagateNaN>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet16f& a) {
|
||||
return _mm512_reduce_or_epi32(_mm512_castps_si512(a)) != 0;
|
||||
}
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet8d -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux(const Packet8d& a) {
|
||||
return _mm512_reduce_add_pd(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_mul(const Packet8d& a) {
|
||||
return _mm512_reduce_mul_pd(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min(const Packet8d& a) {
|
||||
return _mm512_reduce_min_pd(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min<PropagateNumbers>(const Packet8d& a) {
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
return predux_min<PropagateNumbers>(pmin<PropagateNumbers>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min<PropagateNaN>(const Packet8d& a) {
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
return predux_min<PropagateNaN>(pmin<PropagateNaN>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max(const Packet8d& a) {
|
||||
return _mm512_reduce_max_pd(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max<PropagateNumbers>(const Packet8d& a) {
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
return predux_max<PropagateNumbers>(pmax<PropagateNumbers>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max<PropagateNaN>(const Packet8d& a) {
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
return predux_max<PropagateNaN>(pmax<PropagateNaN>(lane0, lane1));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet8d& a) {
|
||||
return _mm512_reduce_or_epi64(_mm512_castpd_si512(a)) != 0;
|
||||
}
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet16h -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux(const Packet16h& from) {
|
||||
return half(predux(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_mul(const Packet16h& from) {
|
||||
return half(predux_mul(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_min(const Packet16h& from) {
|
||||
return half(predux_min(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_min<PropagateNumbers>(const Packet16h& from) {
|
||||
return half(predux_min<PropagateNumbers>(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_min<PropagateNaN>(const Packet16h& from) {
|
||||
return half(predux_min<PropagateNaN>(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_max(const Packet16h& from) {
|
||||
return half(predux_max(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_max<PropagateNumbers>(const Packet16h& from) {
|
||||
return half(predux_max<PropagateNumbers>(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE half predux_max<PropagateNaN>(const Packet16h& from) {
|
||||
return half(predux_max<PropagateNaN>(half2float(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet16h& a) {
|
||||
return predux_any<Packet8i>(a.m_val);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- -- -- -- -- -- -- -- -- -- -- -- Packet16bf -- -- -- -- -- -- -- -- -- -- -- -- */
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux<Packet16f>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_mul(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_mul<Packet16f>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_min<Packet16f>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min<PropagateNumbers>(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_min<PropagateNumbers>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_min<PropagateNaN>(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_min<PropagateNaN>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_max(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max<PropagateNumbers>(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_max<PropagateNumbers>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bfloat16 predux_max<PropagateNaN>(const Packet16bf& from) {
|
||||
return static_cast<bfloat16>(predux_max<PropagateNaN>(Bf16ToF32(from)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE bool predux_any(const Packet16bf& a) {
|
||||
return predux_any<Packet8i>(a.m_val);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_REDUCTIONS_AVX512_H
|
||||
@@ -213,11 +213,12 @@ class trans {
|
||||
}
|
||||
|
||||
/**
|
||||
* Transposes LxunrollN row major block of matrices stored EIGEN_AVX_MAX_NUM_ACC zmm registers to
|
||||
* Transposes LxunrollN row major block of matrices stored `EIGEN_AVX_MAX_NUM_ACC` zmm registers to
|
||||
* "unrollN"xL ymm registers to be stored col-major into C.
|
||||
*
|
||||
* For 8x48, the 8x48 block (row-major) is stored in zmm as follows:
|
||||
*
|
||||
* ```
|
||||
* row0: zmm0 zmm1 zmm2
|
||||
* row1: zmm3 zmm4 zmm5
|
||||
* .
|
||||
@@ -231,10 +232,10 @@ class trans {
|
||||
* .
|
||||
* .
|
||||
* row7: zmm14 zmm15
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* In general we will have {1,2,3} groups of avx registers each of size
|
||||
* EIGEN_AVX_MAX_NUM_ROW. packetIndexOffset is used to select which "block" of
|
||||
* `EIGEN_AVX_MAX_NUM_ROW`. packetIndexOffset is used to select which "block" of
|
||||
* avx registers are being transposed.
|
||||
*/
|
||||
template <int64_t unrollN, int64_t packetIndexOffset>
|
||||
|
||||
@@ -237,16 +237,12 @@ EIGEN_STRONG_INLINE Packet4i preinterpret<Packet4i, Packet16i>(const Packet16i&
|
||||
return _mm512_castsi512_si128(a);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_VECTORIZE_AVX512FP16
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h preinterpret<Packet8h, Packet16h>(const Packet16h& a) {
|
||||
return _mm256_castsi256_si128(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf preinterpret<Packet8bf, Packet16bf>(const Packet16bf& a) {
|
||||
return _mm256_castsi256_si128(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f pcast<Packet16h, Packet16f>(const Packet16h& a) {
|
||||
return half2float(a);
|
||||
@@ -257,6 +253,13 @@ EIGEN_STRONG_INLINE Packet16h pcast<Packet16f, Packet16h>(const Packet16f& a) {
|
||||
return float2half(a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf preinterpret<Packet8bf, Packet16bf>(const Packet16bf& a) {
|
||||
return _mm256_castsi256_si128(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f pcast<Packet16bf, Packet16f>(const Packet16bf& a) {
|
||||
return Bf16ToF32(a);
|
||||
@@ -267,68 +270,6 @@ EIGEN_STRONG_INLINE Packet16bf pcast<Packet16f, Packet16bf>(const Packet16f& a)
|
||||
return F32ToBf16(a);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_AVX512FP16
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h preinterpret<Packet16h, Packet32h>(const Packet32h& a) {
|
||||
return _mm256_castpd_si256(_mm512_extractf64x4_pd(_mm512_castph_pd(a), 0));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h preinterpret<Packet8h, Packet32h>(const Packet32h& a) {
|
||||
return _mm256_castsi256_si128(preinterpret<Packet16h>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f pcast<Packet32h, Packet16f>(const Packet32h& a) {
|
||||
// Discard second-half of input.
|
||||
Packet16h low = _mm256_castpd_si256(_mm512_extractf64x4_pd(_mm512_castph_pd(a), 0));
|
||||
return _mm512_cvtxph_ps(_mm256_castsi256_ph(low));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32h pcast<Packet16f, Packet32h>(const Packet16f& a, const Packet16f& b) {
|
||||
__m512d result = _mm512_undefined_pd();
|
||||
result = _mm512_insertf64x4(
|
||||
result, _mm256_castsi256_pd(_mm512_cvtps_ph(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), 0);
|
||||
result = _mm512_insertf64x4(
|
||||
result, _mm256_castsi256_pd(_mm512_cvtps_ph(b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), 1);
|
||||
return _mm512_castpd_ph(result);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f pcast<Packet16h, Packet8f>(const Packet16h& a) {
|
||||
// Discard second-half of input.
|
||||
Packet8h low = _mm_castps_si128(_mm256_extractf32x4_ps(_mm256_castsi256_ps(a), 0));
|
||||
return _mm256_cvtxph_ps(_mm_castsi128_ph(low));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pcast<Packet8f, Packet16h>(const Packet8f& a, const Packet8f& b) {
|
||||
__m256d result = _mm256_undefined_pd();
|
||||
result = _mm256_insertf64x2(result,
|
||||
_mm_castsi128_pd(_mm256_cvtps_ph(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), 0);
|
||||
result = _mm256_insertf64x2(result,
|
||||
_mm_castsi128_pd(_mm256_cvtps_ph(b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), 1);
|
||||
return _mm256_castpd_si256(result);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pcast<Packet8h, Packet4f>(const Packet8h& a) {
|
||||
Packet8f full = _mm256_cvtxph_ps(_mm_castsi128_ph(a));
|
||||
// Discard second-half of input.
|
||||
return _mm256_extractf32x4_ps(full, 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcast<Packet4f, Packet8h>(const Packet4f& a, const Packet4f& b) {
|
||||
__m256 result = _mm256_undefined_ps();
|
||||
result = _mm256_insertf128_ps(result, a, 0);
|
||||
result = _mm256_insertf128_ps(result, b, 1);
|
||||
return _mm256_cvtps_ph(result, _MM_FROUND_TO_NEAREST_INT);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 The Eigen Authors.
|
||||
//
|
||||
// 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_TYPE_CASTING_FP16_AVX512_H
|
||||
#define EIGEN_TYPE_CASTING_FP16_AVX512_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "../../InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32s preinterpret<Packet32s, Packet32h>(const Packet32h& a) {
|
||||
return _mm512_castph_si512(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16s preinterpret<Packet16s, Packet16h>(const Packet16h& a) {
|
||||
return _mm256_castph_si256(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s preinterpret<Packet8s, Packet8h>(const Packet8h& a) {
|
||||
return _mm_castph_si128(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32h preinterpret<Packet32h, Packet32s>(const Packet32s& a) {
|
||||
return _mm512_castsi512_ph(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h preinterpret<Packet16h, Packet16s>(const Packet16s& a) {
|
||||
return _mm256_castsi256_ph(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h preinterpret<Packet8h, Packet8s>(const Packet8s& a) {
|
||||
return _mm_castsi128_ph(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f pcast<Packet16h, Packet16f>(const Packet16h& a) {
|
||||
return half2float(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f pcast<Packet8h, Packet8f>(const Packet8h& a) {
|
||||
return half2float(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pcast<Packet16f, Packet16h>(const Packet16f& a) {
|
||||
return float2half(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcast<Packet8f, Packet8h>(const Packet8f& a) {
|
||||
return float2half(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f pcast<Packet32h, Packet16f>(const Packet32h& a) {
|
||||
// Discard second-half of input.
|
||||
Packet16h low = _mm256_castpd_ph(_mm512_extractf64x4_pd(_mm512_castph_pd(a), 0));
|
||||
return _mm512_cvtxph_ps(low);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f pcast<Packet16h, Packet8f>(const Packet16h& a) {
|
||||
// Discard second-half of input.
|
||||
Packet8h low = _mm_castps_ph(_mm256_extractf32x4_ps(_mm256_castph_ps(a), 0));
|
||||
return _mm256_cvtxph_ps(low);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pcast<Packet8h, Packet4f>(const Packet8h& a) {
|
||||
Packet8f full = _mm256_cvtxph_ps(a);
|
||||
// Discard second-half of input.
|
||||
return _mm256_extractf32x4_ps(full, 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32h pcast<Packet16f, Packet32h>(const Packet16f& a, const Packet16f& b) {
|
||||
__m512 result = _mm512_castsi512_ps(_mm512_castsi256_si512(_mm256_castph_si256(_mm512_cvtxps_ph(a))));
|
||||
result = _mm512_insertf32x8(result, _mm256_castph_ps(_mm512_cvtxps_ph(b)), 1);
|
||||
return _mm512_castps_ph(result);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pcast<Packet8f, Packet16h>(const Packet8f& a, const Packet8f& b) {
|
||||
__m256 result = _mm256_castsi256_ps(_mm256_castsi128_si256(_mm_castph_si128(_mm256_cvtxps_ph(a))));
|
||||
result = _mm256_insertf32x4(result, _mm_castph_ps(_mm256_cvtxps_ph(b)), 1);
|
||||
return _mm256_castps_ph(result);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcast<Packet4f, Packet8h>(const Packet4f& a, const Packet4f& b) {
|
||||
__m256 result = _mm256_castsi256_ps(_mm256_castsi128_si256(_mm_castps_si128(a)));
|
||||
result = _mm256_insertf128_ps(result, b, 1);
|
||||
return _mm256_cvtxps_ph(result);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32s pcast<Packet32h, Packet32s>(const Packet32h& a) {
|
||||
return _mm512_cvtph_epi16(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16s pcast<Packet16h, Packet16s>(const Packet16h& a) {
|
||||
return _mm256_cvtph_epi16(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pcast<Packet8h, Packet8s>(const Packet8h& a) {
|
||||
return _mm_cvtph_epi16(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32h pcast<Packet32s, Packet32h>(const Packet32s& a) {
|
||||
return _mm512_cvtepi16_ph(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16h pcast<Packet16s, Packet16h>(const Packet16s& a) {
|
||||
return _mm256_cvtepi16_ph(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8h pcast<Packet8s, Packet8h>(const Packet8s& a) {
|
||||
return _mm_cvtepi16_ph(a);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Eigen
|
||||
|
||||
#endif // EIGEN_TYPE_CASTING_FP16_AVX512_H
|
||||
@@ -18,19 +18,28 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
static Packet4ui p4ui_CONJ_XOR =
|
||||
vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); //{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
|
||||
inline Packet4ui p4ui_CONJ_XOR() {
|
||||
return vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); //{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
|
||||
}
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
#if defined(_BIG_ENDIAN)
|
||||
static Packet2ul p2ul_CONJ_XOR1 =
|
||||
(Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO, 8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
static Packet2ul p2ul_CONJ_XOR2 =
|
||||
(Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO, 8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
inline Packet2ul p2ul_CONJ_XOR1() {
|
||||
return (Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO,
|
||||
8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
}
|
||||
inline Packet2ul p2ul_CONJ_XOR2() {
|
||||
return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
|
||||
8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
}
|
||||
#else
|
||||
static Packet2ul p2ul_CONJ_XOR1 =
|
||||
(Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO, 8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
static Packet2ul p2ul_CONJ_XOR2 =
|
||||
(Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO, 8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
inline Packet2ul p2ul_CONJ_XOR1() {
|
||||
return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
|
||||
8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
}
|
||||
inline Packet2ul p2ul_CONJ_XOR2() {
|
||||
return (Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO,
|
||||
8); //{ 0x8000000000000000, 0x0000000000000000 };
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -50,7 +59,7 @@ struct Packet2cf {
|
||||
v1 = vec_madd(v1, b.v, p4f_ZERO);
|
||||
// multiply a_im * b and get the conjugate result
|
||||
v2 = vec_madd(v2, b.v, p4f_ZERO);
|
||||
v2 = reinterpret_cast<Packet4f>(pxor(v2, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR)));
|
||||
v2 = reinterpret_cast<Packet4f>(pxor(v2, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR())));
|
||||
// permute back to a proper order
|
||||
v2 = vec_perm(v2, v2, p16uc_COMPLEX32_REV);
|
||||
|
||||
@@ -266,7 +275,7 @@ EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) {
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) {
|
||||
return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR)));
|
||||
return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR())));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -399,7 +408,7 @@ struct Packet1cd {
|
||||
// multiply a_im * b and get the conjugate result
|
||||
v2 = vec_madd(a_im, b.v, p2d_ZERO);
|
||||
v2 = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(v2), reinterpret_cast<Packet4ui>(v2), 8));
|
||||
v2 = pxor(v2, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR1));
|
||||
v2 = pxor(v2, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR1()));
|
||||
|
||||
return Packet1cd(padd<Packet2d>(v1, v2));
|
||||
}
|
||||
@@ -543,7 +552,7 @@ EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) {
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) {
|
||||
return Packet1cd(pxor(a.v, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR2)));
|
||||
return Packet1cd(pxor(a.v, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR2())));
|
||||
}
|
||||
|
||||
template <>
|
||||
|
||||
@@ -3155,7 +3155,7 @@ void gemmbfloat16(const DataMapper& res, const bfloat16* indexA, const bfloat16*
|
||||
|
||||
#undef MAX_BFLOAT16_ACC_VSX
|
||||
|
||||
#include "MatrixVectorProduct.h"
|
||||
#include "MatrixVectorProduct.inc"
|
||||
|
||||
/************************************
|
||||
* ppc64le template specializations *
|
||||
|
||||
@@ -185,7 +185,10 @@ struct packet_traits<float> : default_packet_traits {
|
||||
HasLog = 1,
|
||||
HasExp = 1,
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
HasCmp = 1,
|
||||
HasPow = 1,
|
||||
HasSqrt = 1,
|
||||
HasCbrt = 1,
|
||||
#if !EIGEN_COMP_CLANG
|
||||
HasRsqrt = 1,
|
||||
#else
|
||||
@@ -193,6 +196,7 @@ struct packet_traits<float> : default_packet_traits {
|
||||
#endif
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasErf = EIGEN_FAST_MATH,
|
||||
HasErfc = EIGEN_FAST_MATH,
|
||||
#else
|
||||
HasSqrt = 0,
|
||||
HasRsqrt = 0,
|
||||
@@ -423,55 +427,6 @@ struct unpacket_traits<Packet8bf> {
|
||||
masked_store_available = false
|
||||
};
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& s, const Packet16c& v) {
|
||||
union {
|
||||
Packet16c v;
|
||||
signed char n[16];
|
||||
} vt;
|
||||
vt.v = v;
|
||||
for (int i = 0; i < 16; i++) s << vt.n[i] << ", ";
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, const Packet16uc& v) {
|
||||
union {
|
||||
Packet16uc v;
|
||||
unsigned char n[16];
|
||||
} vt;
|
||||
vt.v = v;
|
||||
for (int i = 0; i < 16; i++) s << vt.n[i] << ", ";
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, const Packet4f& v) {
|
||||
union {
|
||||
Packet4f v;
|
||||
float n[4];
|
||||
} vt;
|
||||
vt.v = v;
|
||||
s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, const Packet4i& v) {
|
||||
union {
|
||||
Packet4i v;
|
||||
int n[4];
|
||||
} vt;
|
||||
vt.v = v;
|
||||
s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, const Packet4ui& v) {
|
||||
union {
|
||||
Packet4ui v;
|
||||
unsigned int n[4];
|
||||
} vt;
|
||||
vt.v = v;
|
||||
s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename Packet>
|
||||
EIGEN_STRONG_INLINE Packet pload_common(const __UNPACK_TYPE__(Packet) * from) {
|
||||
@@ -1513,16 +1468,13 @@ EIGEN_STRONG_INLINE Packet4f print<Packet4f>(const Packet4f& a) {
|
||||
|
||||
template <typename Packet>
|
||||
EIGEN_STRONG_INLINE Packet ploadu_common(const __UNPACK_TYPE__(Packet) * from) {
|
||||
EIGEN_DEBUG_ALIGNED_LOAD
|
||||
#if defined(EIGEN_VECTORIZE_VSX) || !defined(_BIG_ENDIAN)
|
||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||
#if defined(EIGEN_VECTORIZE_VSX)
|
||||
return vec_xl(0, const_cast<__UNPACK_TYPE__(Packet)*>(from));
|
||||
#else
|
||||
Packet16uc MSQ, LSQ;
|
||||
Packet16uc mask;
|
||||
MSQ = vec_ld(0, (unsigned char*)from); // most significant quadword
|
||||
LSQ = vec_ld(15, (unsigned char*)from); // least significant quadword
|
||||
mask = vec_lvsl(0, from); // create the permute mask
|
||||
Packet16uc MSQ = vec_ld(0, (unsigned char*)from); // most significant quadword
|
||||
Packet16uc LSQ = vec_ld(15, (unsigned char*)from); // least significant quadword
|
||||
Packet16uc mask = vec_lvsl(0, from); // create the permute mask
|
||||
// TODO: Add static_cast here
|
||||
return (Packet)vec_perm(MSQ, LSQ, mask); // align the data
|
||||
#endif
|
||||
@@ -1732,7 +1684,7 @@ EIGEN_STRONG_INLINE Packet16uc ploadquad<Packet16uc>(const unsigned char* from)
|
||||
template <typename Packet>
|
||||
EIGEN_STRONG_INLINE void pstoreu_common(__UNPACK_TYPE__(Packet) * to, const Packet& from) {
|
||||
EIGEN_DEBUG_UNALIGNED_STORE
|
||||
#if defined(EIGEN_VECTORIZE_VSX) || !defined(_BIG_ENDIAN)
|
||||
#if defined(EIGEN_VECTORIZE_VSX)
|
||||
vec_xst(from, 0, to);
|
||||
#else
|
||||
// Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
|
||||
@@ -2068,7 +2020,7 @@ EIGEN_STRONG_INLINE Packet8bf F32ToBf16(Packet4f p4f) {
|
||||
input = padd<Packet4ui>(input, rounding_bias);
|
||||
|
||||
const EIGEN_DECLARE_CONST_FAST_Packet4ui(nan, 0x7FC00000);
|
||||
#ifdef _ARCH_PWR9
|
||||
#if defined(_ARCH_PWR9) && defined(EIGEN_VECTORIZE_VSX)
|
||||
Packet4bi nan_selector = vec_test_data_class(p4f, __VEC_CLASS_FP_NAN);
|
||||
input = vec_sel(input, p4ui_nan, nan_selector);
|
||||
|
||||
@@ -2115,7 +2067,7 @@ EIGEN_STRONG_INLINE Packet8bf F32ToBf16(Packet4f p4f) {
|
||||
/**
|
||||
* Pack the high portion of two float Packets into one bfloat16 Packet
|
||||
*
|
||||
* @param lohi to expect either a low & high OR odd & even order
|
||||
* @tparam lohi to expect either a low & high OR odd & even order
|
||||
*/
|
||||
template <bool lohi>
|
||||
EIGEN_ALWAYS_INLINE Packet8bf Bf16PackHigh(Packet4f lo, Packet4f hi) {
|
||||
@@ -2162,7 +2114,7 @@ EIGEN_ALWAYS_INLINE Packet8bf Bf16PackHigh(Packet4f hi, Packet4f lo) {
|
||||
/**
|
||||
* Convert and pack two float Packets into one bfloat16 Packet
|
||||
*
|
||||
* @param lohi to expect either a low & high OR odd & even order
|
||||
* @tparam lohi to expect either a low & high OR odd & even order
|
||||
*/
|
||||
template <bool lohi = true>
|
||||
EIGEN_ALWAYS_INLINE Packet8bf F32ToBf16Two(Packet4f lo, Packet4f hi) {
|
||||
@@ -2177,7 +2129,7 @@ EIGEN_ALWAYS_INLINE Packet8bf F32ToBf16Two(Packet4f lo, Packet4f hi) {
|
||||
Packet8bi rounding_bias = vec_cmplt(lsb, p4f2);
|
||||
Packet8us input = psub<Packet8us>(p4f, reinterpret_cast<Packet8us>(rounding_bias));
|
||||
|
||||
#ifdef _ARCH_PWR9
|
||||
#if defined(_ARCH_PWR9) && defined(EIGEN_VECTORIZE_VSX)
|
||||
Packet4bi nan_selector_lo = vec_test_data_class(lo, __VEC_CLASS_FP_NAN);
|
||||
Packet4bi nan_selector_hi = vec_test_data_class(hi, __VEC_CLASS_FP_NAN);
|
||||
Packet8us nan_selector =
|
||||
@@ -2309,6 +2261,11 @@ EIGEN_STRONG_INLINE Packet8bf pexp<Packet8bf>(const Packet8bf& a) {
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(pexp_float, a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pexp2<Packet8bf>(const Packet8bf& a) {
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(generic_exp2, a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pldexp<Packet4f>(const Packet4f& a, const Packet4f& exponent) {
|
||||
return pldexp_generic(a, exponent);
|
||||
@@ -2381,6 +2338,44 @@ EIGEN_STRONG_INLINE Packet8bf pmadd(const Packet8bf& a, const Packet8bf& b, cons
|
||||
return F32ToBf16(pmadd_even, pmadd_odd);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pmsub(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
Packet4f a_even = Bf16ToF32Even(a);
|
||||
Packet4f a_odd = Bf16ToF32Odd(a);
|
||||
Packet4f b_even = Bf16ToF32Even(b);
|
||||
Packet4f b_odd = Bf16ToF32Odd(b);
|
||||
Packet4f c_even = Bf16ToF32Even(c);
|
||||
Packet4f c_odd = Bf16ToF32Odd(c);
|
||||
Packet4f pmadd_even = pmsub<Packet4f>(a_even, b_even, c_even);
|
||||
Packet4f pmadd_odd = pmsub<Packet4f>(a_odd, b_odd, c_odd);
|
||||
return F32ToBf16(pmadd_even, pmadd_odd);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pnmadd(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
Packet4f a_even = Bf16ToF32Even(a);
|
||||
Packet4f a_odd = Bf16ToF32Odd(a);
|
||||
Packet4f b_even = Bf16ToF32Even(b);
|
||||
Packet4f b_odd = Bf16ToF32Odd(b);
|
||||
Packet4f c_even = Bf16ToF32Even(c);
|
||||
Packet4f c_odd = Bf16ToF32Odd(c);
|
||||
Packet4f pmadd_even = pnmadd<Packet4f>(a_even, b_even, c_even);
|
||||
Packet4f pmadd_odd = pnmadd<Packet4f>(a_odd, b_odd, c_odd);
|
||||
return F32ToBf16(pmadd_even, pmadd_odd);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pnmsub(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
Packet4f a_even = Bf16ToF32Even(a);
|
||||
Packet4f a_odd = Bf16ToF32Odd(a);
|
||||
Packet4f b_even = Bf16ToF32Even(b);
|
||||
Packet4f b_odd = Bf16ToF32Odd(b);
|
||||
Packet4f c_even = Bf16ToF32Even(c);
|
||||
Packet4f c_odd = Bf16ToF32Odd(c);
|
||||
Packet4f pmadd_even = pnmsub<Packet4f>(a_even, b_even, c_even);
|
||||
Packet4f pmadd_odd = pnmsub<Packet4f>(a_odd, b_odd, c_odd);
|
||||
return F32ToBf16(pmadd_even, pmadd_odd);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8bf pmin<Packet8bf>(const Packet8bf& a, const Packet8bf& b) {
|
||||
BF16_TO_F32_BINARY_OP_WRAPPER(pmin<Packet4f>, a, b);
|
||||
@@ -3177,11 +3172,15 @@ struct packet_traits<double> : default_packet_traits {
|
||||
HasSin = EIGEN_FAST_MATH,
|
||||
HasCos = EIGEN_FAST_MATH,
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasErf = EIGEN_FAST_MATH,
|
||||
HasErfc = EIGEN_FAST_MATH,
|
||||
HasATanh = 1,
|
||||
HasATan = 0,
|
||||
HasLog = 0,
|
||||
HasCmp = 1,
|
||||
HasExp = 1,
|
||||
HasSqrt = 1,
|
||||
HasCbrt = 1,
|
||||
#if !EIGEN_COMP_CLANG
|
||||
HasRsqrt = 1,
|
||||
#else
|
||||
@@ -3392,9 +3391,17 @@ EIGEN_STRONG_INLINE Packet2d pcmp_eq(const Packet2d& a, const Packet2d& b) {
|
||||
return reinterpret_cast<Packet2d>(vec_cmpeq(a, b));
|
||||
}
|
||||
template <>
|
||||
#ifdef __POWER8_VECTOR__
|
||||
EIGEN_STRONG_INLINE Packet2l pcmp_eq(const Packet2l& a, const Packet2l& b) {
|
||||
return reinterpret_cast<Packet2l>(vec_cmpeq(a, b));
|
||||
}
|
||||
#else
|
||||
EIGEN_STRONG_INLINE Packet2l pcmp_eq(const Packet2l& a, const Packet2l& b) {
|
||||
Packet4i halves = reinterpret_cast<Packet4i>(vec_cmpeq(reinterpret_cast<Packet4i>(a), reinterpret_cast<Packet4i>(b)));
|
||||
Packet4i flipped = vec_perm(halves, halves, p16uc_COMPLEX32_REV);
|
||||
return reinterpret_cast<Packet2l>(pand(halves, flipped));
|
||||
}
|
||||
#endif
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pcmp_lt_or_nan(const Packet2d& a, const Packet2d& b) {
|
||||
Packet2d c = reinterpret_cast<Packet2d>(vec_cmpge(a, b));
|
||||
|
||||
@@ -129,30 +129,20 @@ EIGEN_STRONG_INLINE Packet4f preinterpret<Packet4f, Packet4i>(const Packet4i& a)
|
||||
}
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
// VSX support varies between different compilers and even different
|
||||
// versions of the same compiler. For gcc version >= 4.9.3, we can use
|
||||
// vec_cts to efficiently convert Packet2d to Packet2l. Otherwise, use
|
||||
// a slow version that works with older compilers.
|
||||
// Update: apparently vec_cts/vec_ctf intrinsics for 64-bit doubles
|
||||
// are buggy, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70963
|
||||
template <>
|
||||
inline Packet2l pcast<Packet2d, Packet2l>(const Packet2d& x) {
|
||||
#if EIGEN_GNUC_STRICT_AT_LEAST(7, 1, 0)
|
||||
return vec_cts(x, 0); // TODO: check clang version.
|
||||
#else
|
||||
double tmp[2];
|
||||
memcpy(tmp, &x, sizeof(tmp));
|
||||
Packet2l l = {static_cast<long long>(tmp[0]), static_cast<long long>(tmp[1])};
|
||||
return l;
|
||||
#endif
|
||||
EIGEN_ALIGN_MAX double dtmp[2];
|
||||
pstore(dtmp, x);
|
||||
EIGEN_ALIGN_MAX long long itmp[2] = {static_cast<long long>(dtmp[0]), static_cast<long long>(dtmp[1])};
|
||||
return vec_xl(0, itmp);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Packet2d pcast<Packet2l, Packet2d>(const Packet2l& x) {
|
||||
unsigned long long tmp[2];
|
||||
memcpy(tmp, &x, sizeof(tmp));
|
||||
Packet2d d = {static_cast<double>(tmp[0]), static_cast<double>(tmp[1])};
|
||||
return d;
|
||||
EIGEN_ALIGN_MAX long long itmp[2];
|
||||
vec_xst(x, 0, itmp);
|
||||
EIGEN_ALIGN_MAX double dtmp[2] = {static_cast<double>(itmp[0]), static_cast<double>(itmp[1])};
|
||||
return pload<Packet2d>(dtmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -613,6 +613,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 abs(const bfloat16& a) {
|
||||
return numext::bit_cast<bfloat16>(x);
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 exp(const bfloat16& a) { return bfloat16(::expf(float(a))); }
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 exp2(const bfloat16& a) { return bfloat16(::exp2f(float(a))); }
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 expm1(const bfloat16& a) { return bfloat16(numext::expm1(float(a))); }
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 log(const bfloat16& a) { return bfloat16(::logf(float(a))); }
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 log1p(const bfloat16& a) { return bfloat16(numext::log1p(float(a))); }
|
||||
@@ -672,6 +673,11 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 fmax(const bfloat16& a, const bfl
|
||||
return bfloat16(::fmaxf(f1, f2));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline bfloat16 fma(const bfloat16& a, const bfloat16& b, const bfloat16& c) {
|
||||
// Emulate FMA via float.
|
||||
return bfloat16(numext::fma(static_cast<float>(a), static_cast<float>(b), static_cast<float>(c)));
|
||||
}
|
||||
|
||||
#ifndef EIGEN_NO_IO
|
||||
EIGEN_ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, const bfloat16& v) {
|
||||
os << static_cast<float>(v);
|
||||
@@ -762,6 +768,37 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC uint16_t bit_cast<uint16_t, Eigen::bfloat1
|
||||
return Eigen::bfloat16_impl::raw_bfloat16_as_uint16(src);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 nextafter(const bfloat16& from, const bfloat16& to) {
|
||||
if (numext::isnan EIGEN_NOT_A_MACRO(from)) {
|
||||
return from;
|
||||
}
|
||||
if (numext::isnan EIGEN_NOT_A_MACRO(to)) {
|
||||
return to;
|
||||
}
|
||||
if (from == to) {
|
||||
return to;
|
||||
}
|
||||
uint16_t from_bits = numext::bit_cast<uint16_t>(from);
|
||||
bool from_sign = from_bits >> 15;
|
||||
// Whether we are adjusting toward the infinity with the same sign as from.
|
||||
bool toward_inf = (to > from) == !from_sign;
|
||||
if (toward_inf) {
|
||||
++from_bits;
|
||||
} else if ((from_bits & 0x7fff) == 0) {
|
||||
// Adjusting away from inf, but from is zero, so just toggle the sign.
|
||||
from_bits ^= 0x8000;
|
||||
} else {
|
||||
--from_bits;
|
||||
}
|
||||
return numext::bit_cast<bfloat16>(from_bits);
|
||||
}
|
||||
|
||||
// Specialize multiply-add to match packet operations and reduce conversions to/from float.
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::bfloat16 madd<Eigen::bfloat16>(const Eigen::bfloat16& x, const Eigen::bfloat16& y, const Eigen::bfloat16& z) {
|
||||
return Eigen::bfloat16(static_cast<float>(x) * static_cast<float>(y) + static_cast<float>(z));
|
||||
}
|
||||
|
||||
} // namespace numext
|
||||
} // namespace Eigen
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,26 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pfrexp_generic_get_biased_exponent(
|
||||
template <typename Packet>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pldexp_generic(const Packet& a, const Packet& exponent);
|
||||
|
||||
// Explicitly multiplies
|
||||
// a * (2^e)
|
||||
// clamping e to the range
|
||||
// [NumTraits<Scalar>::min_exponent()-2, NumTraits<Scalar>::max_exponent()]
|
||||
//
|
||||
// This is approx 7x faster than pldexp_impl, but will prematurely over/underflow
|
||||
// if 2^e doesn't fit into a normal floating-point Scalar.
|
||||
//
|
||||
// Assumes IEEE floating point format
|
||||
template <typename Packet>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Packet pldexp_fast(const Packet& a, const Packet& exponent);
|
||||
|
||||
/** \internal \returns cbrt(x) for single precision float */
|
||||
template <typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcbrt_float(const Packet& x_in);
|
||||
|
||||
/** \internal \returns cbrt(x) for double precision float */
|
||||
template <typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcbrt_double(const Packet& x_in);
|
||||
|
||||
/** \internal \returns log(x) for single precision float */
|
||||
template <typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog_float(const Packet _x);
|
||||
@@ -60,15 +80,19 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog2_double(const Pa
|
||||
|
||||
/** \internal \returns log(1 + x) */
|
||||
template <typename Packet>
|
||||
Packet generic_plog1p(const Packet& x);
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet generic_log1p(const Packet& x);
|
||||
|
||||
/** \internal \returns exp(x)-1 */
|
||||
template <typename Packet>
|
||||
Packet generic_expm1(const Packet& x);
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet generic_expm1(const Packet& x);
|
||||
|
||||
/** \internal \returns atan(x) */
|
||||
template <typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet generic_patan(const Packet& x);
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet generic_atan(const Packet& x);
|
||||
|
||||
/** \internal \returns exp2(x) */
|
||||
template <typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet generic_exp2(const Packet& x);
|
||||
|
||||
/** \internal \returns exp(x) for single precision float */
|
||||
template <typename Packet>
|
||||
@@ -159,44 +183,43 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet generic_round(const Packet& a);
|
||||
return p##METHOD##_##SCALAR(_x); \
|
||||
}
|
||||
|
||||
// Macros for instantiating these generic functions for different backends.
|
||||
#define EIGEN_GENERIC_PACKET_FUNCTION(METHOD, PACKET) \
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_UNUSED PACKET p##METHOD<PACKET>(const PACKET& _x) { \
|
||||
return generic_##METHOD(_x); \
|
||||
}
|
||||
|
||||
#define EIGEN_FLOAT_PACKET_FUNCTION(METHOD, PACKET) EIGEN_PACKET_FUNCTION(METHOD, float, PACKET)
|
||||
#define EIGEN_DOUBLE_PACKET_FUNCTION(METHOD, PACKET) EIGEN_PACKET_FUNCTION(METHOD, double, PACKET)
|
||||
|
||||
#define EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_FLOAT(PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(sin, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(cos, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(asin, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(acos, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(tanh, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(atanh, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(log, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(log2, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(exp, PACKET) \
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_UNUSED PACKET pexpm1<PACKET>(const PACKET& _x) { \
|
||||
return generic_expm1(_x); \
|
||||
} \
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_UNUSED PACKET plog1p<PACKET>(const PACKET& _x) { \
|
||||
return generic_plog1p(_x); \
|
||||
} \
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_UNUSED PACKET patan<PACKET>(const PACKET& _x) { \
|
||||
return generic_patan(_x); \
|
||||
}
|
||||
#define EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_FLOAT(PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(sin, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(cos, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(asin, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(acos, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(tanh, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(atanh, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(log, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(log2, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(exp, PACKET) \
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(cbrt, PACKET) \
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(expm1, PACKET) \
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(exp2, PACKET) \
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(log1p, PACKET) \
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(atan, PACKET)
|
||||
|
||||
#define EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_DOUBLE(PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(atanh, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(log, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(sin, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(cos, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(log2, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(exp, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(tanh, PACKET) \
|
||||
template <> \
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_UNUSED PACKET patan<PACKET>(const PACKET& _x) { \
|
||||
return generic_patan(_x); \
|
||||
}
|
||||
#define EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_DOUBLE(PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(atanh, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(log, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(sin, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(cos, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(log2, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(exp, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(tanh, PACKET) \
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(cbrt, PACKET) \
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(atan, PACKET) \
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(exp2, PACKET)
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user