Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d71c30c478 | ||
|
|
79488684e1 | ||
|
|
b66188b5df | ||
|
|
5c81034fc1 | ||
|
|
c3f9707824 | ||
|
|
4fc1cfeda5 | ||
|
|
cd7263e7f6 | ||
|
|
eb57d4bdf1 | ||
|
|
4a2c4901ce | ||
|
|
68f4e58cfa | ||
|
|
0e607fd350 | ||
|
|
13507d1efd | ||
|
|
85ffda9539 | ||
|
|
72f77ccb3e | ||
|
|
526a6328e2 | ||
|
|
7b378c2d91 | ||
|
|
129e003cdf | ||
|
|
6161ce5cde | ||
|
|
be62728876 | ||
|
|
1426855b68 | ||
|
|
b2deb94e4a | ||
|
|
c23abcf25c | ||
|
|
f23b8c0d78 | ||
|
|
d60c3a3341 | ||
|
|
57c8d7c93f | ||
|
|
ab92609cad | ||
|
|
551e95a409 | ||
|
|
2924f58188 | ||
|
|
f1922b6dac | ||
|
|
052d91349a | ||
|
|
72e38684c1 | ||
|
|
bb1dbb4df6 | ||
|
|
0a5abc042e | ||
|
|
42d9cc0b1d | ||
|
|
7312765992 | ||
|
|
88cd53774e | ||
|
|
c0378fedd8 | ||
|
|
414f0a1756 | ||
|
|
3adc78e39c | ||
|
|
e67c494cba | ||
|
|
3e7bcf54f7 | ||
|
|
9df21dc8b4 | ||
|
|
157756130a | ||
|
|
7893285e59 | ||
|
|
3ee06ec52f | ||
|
|
287c801780 | ||
|
|
42b04a08c4 | ||
|
|
b86ac5f1e7 | ||
|
|
380a9483e0 | ||
|
|
25270e35db | ||
|
|
ebf968b272 | ||
|
|
bd57b99f44 | ||
|
|
b8f894947a | ||
|
|
4be2870267 | ||
|
|
f7085a1096 | ||
|
|
63291e34bf | ||
|
|
23886fd7db | ||
|
|
7c6020e424 | ||
|
|
2e3f1d8044 | ||
|
|
fc5575264f | ||
|
|
bae907b8f6 | ||
|
|
cf207eacd5 | ||
|
|
e734787bb7 | ||
|
|
1217390db4 | ||
|
|
7176ae1623 | ||
|
|
0db5928f00 | ||
|
|
764b132a79 | ||
|
|
d0bfdc1658 | ||
|
|
75ebef26b6 | ||
|
|
208e44c979 | ||
|
|
17d57fb168 | ||
|
|
6973687c70 | ||
|
|
ac561cd038 | ||
|
|
554982beef | ||
|
|
89a71f3126 | ||
|
|
a605d6b996 | ||
|
|
dfcd6de20a | ||
|
|
1ec1b16d36 | ||
|
|
0f39c851a5 | ||
|
|
daa0b70a65 | ||
|
|
33ba98b641 | ||
|
|
e6e921f0e3 | ||
|
|
ebfdd6bdea | ||
|
|
357bb11066 | ||
|
|
9b3d104c02 | ||
|
|
af3ca50f0b | ||
|
|
26b8fabd80 | ||
|
|
385a0b38f8 | ||
|
|
a4ecfd8ead | ||
|
|
f296720d7d | ||
|
|
f04d02dbf6 | ||
|
|
6f9bffe8dd | ||
|
|
d4c24eca96 | ||
|
|
72b0759451 | ||
|
|
34d0d83278 | ||
|
|
63e8b31c94 | ||
|
|
99473f255b | ||
|
|
2ce5dc428f | ||
|
|
8f1b6198c2 | ||
|
|
dae8c6d7ad | ||
|
|
2dfdaa2abf | ||
|
|
a659b5dbb2 | ||
|
|
879854382c | ||
|
|
90dce8dfa3 | ||
|
|
b26ada1e03 | ||
|
|
f5593b4baa | ||
|
|
3eb0c8b69e | ||
|
|
26adb0e5af | ||
|
|
5547205092 | ||
|
|
771e91860b | ||
|
|
4786edba26 | ||
|
|
15e23ab849 | ||
|
|
af6e7cc66a | ||
|
|
3fbb1c1b48 | ||
|
|
28cd280726 | ||
|
|
8cc3ec8e47 | ||
|
|
d641062a05 | ||
|
|
1000cf9fbc | ||
|
|
fd2817e3d6 | ||
|
|
11dacc4802 | ||
|
|
ab6f39e1e3 | ||
|
|
6576ee4fb1 | ||
|
|
68f35d76b8 | ||
|
|
d0e2b3e58d | ||
|
|
669dc8fadf | ||
|
|
33a602eb37 | ||
|
|
a9490cd3c5 | ||
|
|
61efca2e90 | ||
|
|
a5469a6f0f | ||
|
|
6aaa45db5f | ||
|
|
ea57f9b78f | ||
|
|
f55a112cb1 | ||
|
|
a11bdf3965 | ||
|
|
b9ac284e52 | ||
|
|
3df7d7fec9 | ||
|
|
80c5b8b3c3 | ||
|
|
848db4ed2d | ||
|
|
5cb7505a44 | ||
|
|
af912a7b5c | ||
|
|
86d958e8f2 | ||
|
|
8e7bd5397f | ||
|
|
8a21df2d9c | ||
|
|
ac78f84b72 | ||
|
|
973b04f3e1 | ||
|
|
16844d7529 | ||
|
|
5cb2dfec1d | ||
|
|
c473d69d22 | ||
|
|
6469fbf93a | ||
|
|
3a4a4e9fde | ||
|
|
fab848d4f7 | ||
|
|
b158fcaa74 | ||
|
|
b6d9b6f48d | ||
|
|
b1f06aac61 | ||
|
|
f6954e4485 | ||
|
|
b30a2a527e | ||
|
|
bc1b354b32 | ||
|
|
bd0d873b16 | ||
|
|
e0fe006915 | ||
|
|
d259104c8d | ||
|
|
cd543434bf | ||
|
|
36be6747e0 | ||
|
|
d1ed3fe5c9 | ||
|
|
21e0ad056e | ||
|
|
709d704819 | ||
|
|
995714142d | ||
|
|
730a781221 | ||
|
|
77b2807322 | ||
|
|
52e545324e | ||
|
|
0cd4719f3e | ||
|
|
770ed0794e | ||
|
|
e7248b26a1 | ||
|
|
a1e1612c28 | ||
|
|
f3aaba8705 | ||
|
|
34e5f34b39 | ||
|
|
4612627355 | ||
|
|
3e71c621c9 | ||
|
|
b5d218d857 | ||
|
|
bd72e4a8c4 | ||
|
|
3af8c262ac | ||
|
|
7e3bc4177e | ||
|
|
c379a21191 | ||
|
|
6f57470bcc | ||
|
|
df53e28179 | ||
|
|
fbdaff81bd | ||
|
|
71320af66a | ||
|
|
962a596d21 | ||
|
|
0ab1f8ec03 | ||
|
|
b0fe14213e | ||
|
|
23469c3cda | ||
|
|
18824d10ea | ||
|
|
f9b2e92040 | ||
|
|
9c193db5c7 | ||
|
|
6b6ba41269 | ||
|
|
96007cae8c | ||
|
|
5d918b82a8 | ||
|
|
05c9d7ce20 | ||
|
|
943ef50a2d | ||
|
|
7ea4adb5f0 | ||
|
|
71498b32c9 | ||
|
|
ebd5c6d44b | ||
|
|
a8eb797a43 | ||
|
|
929bc0e191 | ||
|
|
f046e326d9 | ||
|
|
3335e0767c | ||
|
|
3395f4e604 | ||
|
|
f03d3e7072 | ||
|
|
b8cf1ed753 | ||
|
|
9263475740 | ||
|
|
0fdc99c65e | ||
|
|
07cc362238 | ||
|
|
4ef67cbfb2 | ||
|
|
c2b6df6e60 | ||
|
|
277d369060 | ||
|
|
7aee90b8d3 | ||
|
|
3147391d94 | ||
|
|
115591b9e3 | ||
|
|
fd100138dd | ||
|
|
1ec173b54e | ||
|
|
aef926abf6 | ||
|
|
f1032255d3 | ||
|
|
f57dec64ef | ||
|
|
926e1a8226 | ||
|
|
cd474d4cd0 | ||
|
|
0b56b62f30 | ||
|
|
44cc96e1a1 | ||
|
|
576e451b10 | ||
|
|
0d89012708 | ||
|
|
6d2506040c | ||
|
|
cb44a003de | ||
|
|
13d7658c5d | ||
|
|
338924602d | ||
|
|
93bff85a42 | ||
|
|
4e0357c6dd | ||
|
|
1e9f623f3e | ||
|
|
4240b480e0 | ||
|
|
5b83d3c4bc | ||
|
|
46ecdcd745 | ||
|
|
9a1691a14e | ||
|
|
bb33880e57 | ||
|
|
237c59a2aa | ||
|
|
3dc42eeaec | ||
|
|
7adc1545b4 | ||
|
|
c0c7b695cd | ||
|
|
c334eece44 | ||
|
|
5ccb72b2e4 | ||
|
|
9c90d5d832 | ||
|
|
5d37114fc0 | ||
|
|
930696fc53 | ||
|
|
56966fd2e6 | ||
|
|
5a3c9eddb4 | ||
|
|
69ec4907da | ||
|
|
7571704a43 | ||
|
|
84955d109f | ||
|
|
601814b575 | ||
|
|
05bab8139a | ||
|
|
eebde572d9 | ||
|
|
8190739f12 | ||
|
|
b6db013435 | ||
|
|
1f6b1c1a1f | ||
|
|
517294d6e1 | ||
|
|
94e2250b36 | ||
|
|
d82d915047 | ||
|
|
380d0e4916 | ||
|
|
e83af2cc24 | ||
|
|
413ff2b531 | ||
|
|
a235ddef39 | ||
|
|
4780d8dfb2 | ||
|
|
fd5d23fdf3 | ||
|
|
a2040ef796 | ||
|
|
c2c0f6f64b | ||
|
|
ee4e099aa2 | ||
|
|
9fc93ce31a | ||
|
|
1374f49f28 | ||
|
|
2d6eaaf687 | ||
|
|
47722a66f2 | ||
|
|
5e75331b9f | ||
|
|
b5fc69bdd8 | ||
|
|
4b683b65df | ||
|
|
1cb1ffd5b2 | ||
|
|
4b502a7215 | ||
|
|
85868564df | ||
|
|
cbb6ae6296 | ||
|
|
573570b6c9 | ||
|
|
98cf1e076f | ||
|
|
ee2a8f7139 | ||
|
|
3835046309 | ||
|
|
4fbd01cd4b | ||
|
|
a883a8797c | ||
|
|
0bd9e9bc45 | ||
|
|
77c66e368c | ||
|
|
2f908f8255 | ||
|
|
82f13830e6 | ||
|
|
d1825cbb68 | ||
|
|
d9288f078d | ||
|
|
85ebd6aff8 | ||
|
|
2947c0cc84 | ||
|
|
25424f4cf1 | ||
|
|
42acbd5700 | ||
|
|
9e0dc8f09b | ||
|
|
da19f7a910 | ||
|
|
fc2cc10842 | ||
|
|
a33855f6ee | ||
|
|
83df5df61b | ||
|
|
ac3c5aad31 | ||
|
|
63abb10000 | ||
|
|
baf601a0e3 | ||
|
|
587a691516 | ||
|
|
8830d66c02 | ||
|
|
54425a39b2 | ||
|
|
34d0be9ec1 | ||
|
|
42a8bdd4d7 | ||
|
|
28564957ac | ||
|
|
ab7fe215f9 | ||
|
|
1f4c0311cd |
@@ -0,0 +1,19 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 120
|
||||
---
|
||||
Language: Cpp
|
||||
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
|
||||
- EIGEN_ALWAYS_INLINE
|
||||
- EIGEN_DEVICE_FUNC
|
||||
- EIGEN_DONT_INLINE
|
||||
- EIGEN_DEPRECATED
|
||||
- EIGEN_UNUSED
|
||||
@@ -36,3 +36,6 @@ lapack/reference
|
||||
.settings
|
||||
Makefile
|
||||
!ci/build.gitlab-ci.yml
|
||||
!scripts/buildtests.in
|
||||
!Eigen/Core
|
||||
!Eigen/src/Core
|
||||
|
||||
+19
-8
@@ -1,23 +1,34 @@
|
||||
# This file is part of Eigen, a lightweight C++ template library
|
||||
# for linear algebra.
|
||||
#
|
||||
# Copyright (C) 2020 Arm Ltd. and Contributors
|
||||
# Copyright (C) 2023, 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/.
|
||||
|
||||
stages:
|
||||
- buildsmoketests
|
||||
- smoketests
|
||||
- checkformat
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
BUILDDIR: builddir
|
||||
EIGEN_CI_CMAKE_GENEATOR: "Ninja"
|
||||
# CMake build directory.
|
||||
EIGEN_CI_BUILDDIR: .build
|
||||
# Specify the CMake build target.
|
||||
EIGEN_CI_BUILD_TARGET: ""
|
||||
# If a test regex is specified, that will be selected.
|
||||
# Otherwise, we will try a label if specified.
|
||||
EIGEN_CI_CTEST_REGEX: ""
|
||||
EIGEN_CI_CTEST_LABEL: ""
|
||||
EIGEN_CI_CTEST_ARGS: ""
|
||||
|
||||
include:
|
||||
- "/ci/smoketests.gitlab-ci.yml"
|
||||
- "/ci/build.gitlab-ci.yml"
|
||||
- "/ci/test.gitlab-ci.yml"
|
||||
- "/ci/checkformat.gitlab-ci.yml"
|
||||
- "/ci/common.gitlab-ci.yml"
|
||||
- "/ci/build.linux.gitlab-ci.yml"
|
||||
- "/ci/build.windows.gitlab-ci.yml"
|
||||
- "/ci/test.linux.gitlab-ci.yml"
|
||||
- "/ci/test.windows.gitlab-ci.yml"
|
||||
- "/ci/deploy.gitlab-ci.yml"
|
||||
|
||||
+680
-559
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ extern "C" {
|
||||
* This module provides an interface to the Cholmod library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||
* It provides the two following main factorization classes:
|
||||
* - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization.
|
||||
* - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial).
|
||||
* - class CholmodDecomposition: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial).
|
||||
*
|
||||
* For the sake of completeness, this module also propose the two following classes:
|
||||
* - class CholmodSimplicialLLT
|
||||
|
||||
+4
-3
@@ -83,8 +83,8 @@
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#ifndef EIGEN_NO_IO
|
||||
#include <sstream>
|
||||
#include <iosfwd>
|
||||
#endif
|
||||
#include <cstring>
|
||||
@@ -109,7 +109,8 @@
|
||||
#endif
|
||||
|
||||
// required for __cpuid, needs to be included after cmath
|
||||
#if EIGEN_COMP_MSVC && EIGEN_ARCH_i386_OR_x86_64 && !EIGEN_OS_WINCE
|
||||
// also required for _BitScanReverse on Windows on ARM
|
||||
#if EIGEN_COMP_MSVC && (EIGEN_ARCH_i386_OR_x86_64 || EIGEN_ARCH_ARM64) && !EIGEN_OS_WINCE
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
@@ -346,7 +347,7 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/CoreIterators.h"
|
||||
#include "src/Core/ConditionEstimator.h"
|
||||
|
||||
#if defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX)
|
||||
#if defined(EIGEN_VECTORIZE_VSX)
|
||||
#include "src/Core/arch/AltiVec/MatrixProduct.h"
|
||||
#elif defined EIGEN_VECTORIZE_NEON
|
||||
#include "src/Core/arch/NEON/GeneralBlockPanelKernel.h"
|
||||
|
||||
@@ -38,9 +38,7 @@
|
||||
#include "src/LU/Determinant.h"
|
||||
#include "src/LU/InverseImpl.h"
|
||||
|
||||
// Use the SSE optimized version whenever possible. At the moment the
|
||||
// SSE version doesn't compile when AVX is enabled
|
||||
#if (defined EIGEN_VECTORIZE_SSE && !defined EIGEN_VECTORIZE_AVX) || defined EIGEN_VECTORIZE_NEON
|
||||
#if defined EIGEN_VECTORIZE_SSE || defined EIGEN_VECTORIZE_NEON
|
||||
#include "src/LU/arch/InverseSize4.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
#include "src/SparseLU/SparseLU_gemm_kernel.h"
|
||||
|
||||
#include "src/SparseLU/SparseLU_Structs.h"
|
||||
#include "src/SparseLU/SparseLU_SupernodalMatrix.h"
|
||||
#include "src/SparseLU/SparseLUImpl.h"
|
||||
|
||||
@@ -172,7 +172,8 @@ seqN(FirstType first, SizeType size) {
|
||||
return ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type>(first,size);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
|
||||
/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and with positive (or negative) increment \a incr
|
||||
*
|
||||
@@ -183,24 +184,6 @@ seqN(FirstType first, SizeType size) {
|
||||
*
|
||||
* \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType)
|
||||
*/
|
||||
template<typename FirstType,typename LastType, typename IncrType>
|
||||
auto seq(FirstType f, LastType l, IncrType incr);
|
||||
|
||||
/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and unit increment
|
||||
*
|
||||
* It is essentially an alias to:
|
||||
* \code
|
||||
* seqN(f,l-f+1);
|
||||
* \endcode
|
||||
*
|
||||
* \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType)
|
||||
*/
|
||||
template<typename FirstType,typename LastType>
|
||||
auto seq(FirstType f, LastType l);
|
||||
|
||||
#else // EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
template<typename FirstType,typename LastType>
|
||||
auto seq(FirstType f, LastType l) -> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
( typename internal::cleanup_index_type<LastType>::type(l)
|
||||
@@ -211,6 +194,15 @@ auto seq(FirstType f, LastType l) -> decltype(seqN(typename internal::cleanup_in
|
||||
-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>()));
|
||||
}
|
||||
|
||||
/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and unit increment
|
||||
*
|
||||
* It is essentially an alias to:
|
||||
* \code
|
||||
* seqN(f,l-f+1);
|
||||
* \endcode
|
||||
*
|
||||
* \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType)
|
||||
*/
|
||||
template<typename FirstType,typename LastType, typename IncrType>
|
||||
auto seq(FirstType f, LastType l, IncrType incr)
|
||||
-> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
@@ -317,26 +309,12 @@ seq(const symbolic::BaseExpr<FirstTypeDerived> &f, const symbolic::BaseExpr<Last
|
||||
}
|
||||
#endif // EIGEN_HAS_CXX11
|
||||
|
||||
#endif // EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
|
||||
#if EIGEN_HAS_CXX11 || defined(EIGEN_PARSED_BY_DOXYGEN)
|
||||
/** \cpp11
|
||||
* \returns a symbolic ArithmeticSequence representing the last \a size elements with increment \a incr.
|
||||
*
|
||||
* It is a shortcut for: \code seqN(last-(size-fix<1>)*incr, size, incr) \endcode
|
||||
*
|
||||
* \sa lastN(SizeType), seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */
|
||||
template<typename SizeType,typename IncrType>
|
||||
auto lastN(SizeType size, IncrType incr)
|
||||
-> decltype(seqN(Eigen::last-(size-fix<1>())*incr, size, incr))
|
||||
{
|
||||
return seqN(Eigen::last-(size-fix<1>())*incr, size, incr);
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
/** \cpp11
|
||||
* \returns a symbolic ArithmeticSequence representing the last \a size elements with a unit increment.
|
||||
*
|
||||
* \anchor indexing_lastN
|
||||
*
|
||||
* It is a shortcut for: \code seq(last+fix<1>-size, last) \endcode
|
||||
*
|
||||
* \sa lastN(SizeType,IncrType, seqN(FirstType,SizeType), seq(FirstType,LastType) */
|
||||
@@ -346,6 +324,21 @@ auto lastN(SizeType size)
|
||||
{
|
||||
return seqN(Eigen::last+fix<1>()-size, size);
|
||||
}
|
||||
|
||||
/** \cpp11
|
||||
* \returns a symbolic ArithmeticSequence representing the last \a size elements with increment \a incr.
|
||||
*
|
||||
* \anchor indexing_lastN_with_incr
|
||||
*
|
||||
* It is a shortcut for: \code seqN(last-(size-fix<1>)*incr, size, incr) \endcode
|
||||
*
|
||||
* \sa lastN(SizeType), seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */
|
||||
template<typename SizeType,typename IncrType>
|
||||
auto lastN(SizeType size, IncrType incr)
|
||||
-> decltype(seqN(Eigen::last-(size-fix<1>())*incr, size, incr))
|
||||
{
|
||||
return seqN(Eigen::last-(size-fix<1>())*incr, size, incr);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -163,7 +163,15 @@ class Array
|
||||
#endif
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
/** \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. \cpp11
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* This constructor is for 1D array or vectors with more than 4 coefficients.
|
||||
* There exists C++98 analogue constructors for fixed-size array/vector having 1, 2, 3, or 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
|
||||
|
||||
@@ -591,7 +591,7 @@ struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, InnerUnrolling>
|
||||
|
||||
enum { innerSize = DstXprType::InnerSizeAtCompileTime,
|
||||
packetSize =unpacket_traits<PacketType>::size,
|
||||
vectorizableSize = (innerSize/packetSize)*packetSize,
|
||||
vectorizableSize = (int(innerSize) / int(packetSize)) * int(packetSize),
|
||||
size = DstXprType::SizeAtCompileTime };
|
||||
|
||||
for(Index outer = 0; outer < kernel.outerSize(); ++outer)
|
||||
@@ -785,6 +785,16 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType
|
||||
dense_assignment_loop<Kernel>::run(kernel);
|
||||
}
|
||||
|
||||
// Specialization for filling the destination with a constant value.
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<typename DstXprType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<typename DstXprType::Scalar>, DstXprType>& src, const internal::assign_op<typename DstXprType::Scalar,typename DstXprType::Scalar>& func)
|
||||
{
|
||||
resize_if_allowed(dst, src, func);
|
||||
std::fill_n(dst.data(), dst.size(), src.functor()());
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename DstXprType, typename SrcXprType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src)
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
||||
* \warning the internal storage must be column major. */
|
||||
inline Block<CoefficientsType,Dynamic,1> col(Index i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((Options&RowMajor)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
|
||||
EIGEN_STATIC_ASSERT((int(Options) & int(RowMajor)) == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
|
||||
Index start = 0;
|
||||
Index len = coeffs().rows();
|
||||
if (i<=supers())
|
||||
@@ -90,7 +90,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
||||
|
||||
template<int Index> struct DiagonalIntReturnType {
|
||||
enum {
|
||||
ReturnOpposite = (Options&SelfAdjoint) && (((Index)>0 && Supers==0) || ((Index)<0 && Subs==0)),
|
||||
ReturnOpposite = (int(Options) & int(SelfAdjoint)) && (((Index) > 0 && Supers == 0) || ((Index) < 0 && Subs == 0)),
|
||||
Conjugate = ReturnOpposite && NumTraits<Scalar>::IsComplex,
|
||||
ActualIndex = ReturnOpposite ? -Index : Index,
|
||||
DiagonalSize = (RowsAtCompileTime==Dynamic || ColsAtCompileTime==Dynamic)
|
||||
@@ -192,7 +192,7 @@ struct traits<BandMatrix<_Scalar,_Rows,_Cols,_Supers,_Subs,_Options> >
|
||||
Options = _Options,
|
||||
DataRowsAtCompileTime = ((Supers!=Dynamic) && (Subs!=Dynamic)) ? 1 + Supers + Subs : Dynamic
|
||||
};
|
||||
typedef Matrix<Scalar,DataRowsAtCompileTime,ColsAtCompileTime,Options&RowMajor?RowMajor:ColMajor> CoefficientsType;
|
||||
typedef Matrix<Scalar, DataRowsAtCompileTime, ColsAtCompileTime, int(Options) & int(RowMajor) ? RowMajor : ColMajor> CoefficientsType;
|
||||
};
|
||||
|
||||
template<typename _Scalar, int Rows, int Cols, int Supers, int Subs, int Options>
|
||||
|
||||
+23
-8
@@ -260,19 +260,19 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(Index rowId, Index colId) const
|
||||
EIGEN_DEVICE_FUNC inline PacketScalar packet(Index rowId, Index colId) const
|
||||
{
|
||||
return m_xpr.template packet<Unaligned>(rowId + m_startRow.value(), colId + m_startCol.value());
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
|
||||
EIGEN_DEVICE_FUNC inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
|
||||
{
|
||||
m_xpr.template writePacket<Unaligned>(rowId + m_startRow.value(), colId + m_startCol.value(), val);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(Index index) const
|
||||
EIGEN_DEVICE_FUNC inline PacketScalar packet(Index index) const
|
||||
{
|
||||
return m_xpr.template packet<Unaligned>
|
||||
(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
|
||||
@@ -280,7 +280,7 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index index, const PacketScalar& val)
|
||||
EIGEN_DEVICE_FUNC inline void writePacket(Index index, const PacketScalar& val)
|
||||
{
|
||||
m_xpr.template writePacket<Unaligned>
|
||||
(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
|
||||
@@ -334,6 +334,17 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
enum {
|
||||
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0
|
||||
};
|
||||
|
||||
/** \internal Returns base+offset (unless base is null, in which case returns null).
|
||||
* 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)
|
||||
{
|
||||
return base != NULL ? base+offset : NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef MapBase<BlockType> Base;
|
||||
@@ -344,8 +355,9 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
BlockImpl_dense(XprType& xpr, Index i)
|
||||
: Base(xpr.data() + i * ( ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor))
|
||||
|| ((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && ( XprTypeIsRowMajor)) ? xpr.innerStride() : xpr.outerStride()),
|
||||
: Base((BlockRows == 0 || BlockCols == 0) ? NULL : add_to_nullable_pointer(xpr.data(),
|
||||
i * ( ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor))
|
||||
|| ((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && ( XprTypeIsRowMajor)) ? xpr.innerStride() : xpr.outerStride())),
|
||||
BlockRows==1 ? 1 : xpr.rows(),
|
||||
BlockCols==1 ? 1 : xpr.cols()),
|
||||
m_xpr(xpr),
|
||||
@@ -359,7 +371,8 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
|
||||
: Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol)),
|
||||
: Base((BlockRows == 0 || BlockCols == 0) ? NULL : add_to_nullable_pointer(xpr.data(),
|
||||
xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol))),
|
||||
m_xpr(xpr), m_startRow(startRow), m_startCol(startCol)
|
||||
{
|
||||
init();
|
||||
@@ -371,7 +384,9 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
BlockImpl_dense(XprType& xpr,
|
||||
Index startRow, Index startCol,
|
||||
Index blockRows, Index blockCols)
|
||||
: Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol), blockRows, blockCols),
|
||||
: Base((blockRows == 0 || blockCols == 0) ? NULL : add_to_nullable_pointer(xpr.data(),
|
||||
xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol)),
|
||||
blockRows, blockCols),
|
||||
m_xpr(xpr), m_startRow(startRow), m_startCol(startCol)
|
||||
{
|
||||
init();
|
||||
|
||||
@@ -14,54 +14,56 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Derived, int UnrollCount, int Rows>
|
||||
template<typename Derived, int UnrollCount, int InnerSize>
|
||||
struct all_unroller
|
||||
{
|
||||
enum {
|
||||
col = (UnrollCount-1) / Rows,
|
||||
row = (UnrollCount-1) % Rows
|
||||
IsRowMajor = (int(Derived::Flags) & int(RowMajor)),
|
||||
i = (UnrollCount-1) / InnerSize,
|
||||
j = (UnrollCount-1) % InnerSize
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &mat)
|
||||
{
|
||||
return all_unroller<Derived, UnrollCount-1, Rows>::run(mat) && mat.coeff(row, col);
|
||||
return all_unroller<Derived, UnrollCount-1, InnerSize>::run(mat) && mat.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct all_unroller<Derived, 0, Rows>
|
||||
template<typename Derived, int InnerSize>
|
||||
struct all_unroller<Derived, 0, InnerSize>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &/*mat*/) { return true; }
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct all_unroller<Derived, Dynamic, Rows>
|
||||
template<typename Derived, int InnerSize>
|
||||
struct all_unroller<Derived, Dynamic, InnerSize>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &) { return false; }
|
||||
};
|
||||
|
||||
template<typename Derived, int UnrollCount, int Rows>
|
||||
template<typename Derived, int UnrollCount, int InnerSize>
|
||||
struct any_unroller
|
||||
{
|
||||
enum {
|
||||
col = (UnrollCount-1) / Rows,
|
||||
row = (UnrollCount-1) % Rows
|
||||
IsRowMajor = (int(Derived::Flags) & int(RowMajor)),
|
||||
i = (UnrollCount-1) / InnerSize,
|
||||
j = (UnrollCount-1) % InnerSize
|
||||
};
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &mat)
|
||||
{
|
||||
return any_unroller<Derived, UnrollCount-1, Rows>::run(mat) || mat.coeff(row, col);
|
||||
return any_unroller<Derived, UnrollCount-1, InnerSize>::run(mat) || mat.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct any_unroller<Derived, 0, Rows>
|
||||
template<typename Derived, int InnerSize>
|
||||
struct any_unroller<Derived, 0, InnerSize>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived & /*mat*/) { return false; }
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct any_unroller<Derived, Dynamic, Rows>
|
||||
template<typename Derived, int InnerSize>
|
||||
struct any_unroller<Derived, Dynamic, InnerSize>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &) { return false; }
|
||||
};
|
||||
@@ -81,16 +83,16 @@ EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::all() const
|
||||
typedef internal::evaluator<Derived> Evaluator;
|
||||
enum {
|
||||
unroll = SizeAtCompileTime != Dynamic
|
||||
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
|
||||
&& SizeAtCompileTime * (int(Evaluator::CoeffReadCost) + int(NumTraits<Scalar>::AddCost)) <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
Evaluator evaluator(derived());
|
||||
if(unroll)
|
||||
return internal::all_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, internal::traits<Derived>::RowsAtCompileTime>::run(evaluator);
|
||||
return internal::all_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, InnerSizeAtCompileTime>::run(evaluator);
|
||||
else
|
||||
{
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
for(Index i = 0; i < rows(); ++i)
|
||||
if (!evaluator.coeff(i, j)) return false;
|
||||
for(Index i = 0; i < derived().outerSize(); ++i)
|
||||
for(Index j = 0; j < derived().innerSize(); ++j)
|
||||
if (!evaluator.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -105,16 +107,16 @@ EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::any() const
|
||||
typedef internal::evaluator<Derived> Evaluator;
|
||||
enum {
|
||||
unroll = SizeAtCompileTime != Dynamic
|
||||
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
|
||||
&& SizeAtCompileTime * (int(Evaluator::CoeffReadCost) + int(NumTraits<Scalar>::AddCost)) <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
Evaluator evaluator(derived());
|
||||
if(unroll)
|
||||
return internal::any_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, internal::traits<Derived>::RowsAtCompileTime>::run(evaluator);
|
||||
return internal::any_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, InnerSizeAtCompileTime>::run(evaluator);
|
||||
else
|
||||
{
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
for(Index i = 0; i < rows(); ++i)
|
||||
if (evaluator.coeff(i, j)) return true;
|
||||
for(Index i = 0; i < derived().outerSize(); ++i)
|
||||
for(Index j = 0; j < derived().innerSize(); ++j)
|
||||
if (evaluator.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -156,7 +158,7 @@ inline bool DenseBase<Derived>::allFinite() const
|
||||
return !((derived()-derived()).hasNaN());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ALLANDANY_H
|
||||
|
||||
@@ -561,7 +561,7 @@ struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
|
||||
typedef CwiseUnaryOp<UnaryOp, ArgType> XprType;
|
||||
|
||||
enum {
|
||||
CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
|
||||
CoeffReadCost = int(evaluator<ArgType>::CoeffReadCost) + int(functor_traits<UnaryOp>::Cost),
|
||||
|
||||
Flags = evaluator<ArgType>::Flags
|
||||
& (HereditaryBits | LinearAccessBit | (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
|
||||
@@ -606,13 +606,13 @@ struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
|
||||
protected:
|
||||
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
class Data : private UnaryOp
|
||||
struct Data
|
||||
{
|
||||
public:
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : UnaryOp(xpr.functor()), argImpl(xpr.nestedExpression()) {}
|
||||
Data(const XprType& xpr) : op(xpr.functor()), argImpl(xpr.nestedExpression()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const UnaryOp& func() const { return static_cast<const UnaryOp&>(*this); }
|
||||
const UnaryOp& func() const { return op; }
|
||||
UnaryOp op;
|
||||
evaluator<ArgType> argImpl;
|
||||
};
|
||||
|
||||
@@ -639,7 +639,7 @@ struct ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3>, IndexBased
|
||||
typedef CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> XprType;
|
||||
|
||||
enum {
|
||||
CoeffReadCost = evaluator<Arg1>::CoeffReadCost + evaluator<Arg2>::CoeffReadCost + evaluator<Arg3>::CoeffReadCost + functor_traits<TernaryOp>::Cost,
|
||||
CoeffReadCost = int(evaluator<Arg1>::CoeffReadCost) + int(evaluator<Arg2>::CoeffReadCost) + int(evaluator<Arg3>::CoeffReadCost) + int(functor_traits<TernaryOp>::Cost),
|
||||
|
||||
Arg1Flags = evaluator<Arg1>::Flags,
|
||||
Arg2Flags = evaluator<Arg2>::Flags,
|
||||
@@ -700,12 +700,13 @@ struct ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3>, IndexBased
|
||||
|
||||
protected:
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
struct Data : private TernaryOp
|
||||
struct Data
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : TernaryOp(xpr.functor()), arg1Impl(xpr.arg1()), arg2Impl(xpr.arg2()), arg3Impl(xpr.arg3()) {}
|
||||
Data(const XprType& xpr) : op(xpr.functor()), arg1Impl(xpr.arg1()), arg2Impl(xpr.arg2()), arg3Impl(xpr.arg3()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const TernaryOp& func() const { return static_cast<const TernaryOp&>(*this); }
|
||||
const TernaryOp& func() const { return op; }
|
||||
TernaryOp op;
|
||||
evaluator<Arg1> arg1Impl;
|
||||
evaluator<Arg2> arg2Impl;
|
||||
evaluator<Arg3> arg3Impl;
|
||||
@@ -735,7 +736,7 @@ struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBase
|
||||
typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
|
||||
|
||||
enum {
|
||||
CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
|
||||
CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
|
||||
|
||||
LhsFlags = evaluator<Lhs>::Flags,
|
||||
RhsFlags = evaluator<Rhs>::Flags,
|
||||
@@ -793,12 +794,13 @@ struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBase
|
||||
protected:
|
||||
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
struct Data : private BinaryOp
|
||||
struct Data
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : BinaryOp(xpr.functor()), lhsImpl(xpr.lhs()), rhsImpl(xpr.rhs()) {}
|
||||
Data(const XprType& xpr) : op(xpr.functor()), lhsImpl(xpr.lhs()), rhsImpl(xpr.rhs()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const BinaryOp& func() const { return static_cast<const BinaryOp&>(*this); }
|
||||
const BinaryOp& func() const { return op; }
|
||||
BinaryOp op;
|
||||
evaluator<Lhs> lhsImpl;
|
||||
evaluator<Rhs> rhsImpl;
|
||||
};
|
||||
@@ -815,7 +817,7 @@ struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, IndexBased>
|
||||
typedef CwiseUnaryView<UnaryOp, ArgType> XprType;
|
||||
|
||||
enum {
|
||||
CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
|
||||
CoeffReadCost = int(evaluator<ArgType>::CoeffReadCost) + int(functor_traits<UnaryOp>::Cost),
|
||||
|
||||
Flags = (evaluator<ArgType>::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit)),
|
||||
|
||||
@@ -858,12 +860,13 @@ struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, IndexBased>
|
||||
protected:
|
||||
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
struct Data : private UnaryOp
|
||||
struct Data
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : UnaryOp(xpr.functor()), argImpl(xpr.nestedExpression()) {}
|
||||
Data(const XprType& xpr) : op(xpr.functor()), argImpl(xpr.nestedExpression()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const UnaryOp& func() const { return static_cast<const UnaryOp&>(*this); }
|
||||
const UnaryOp& func() const { return op; }
|
||||
UnaryOp op;
|
||||
evaluator<ArgType> argImpl;
|
||||
};
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ class CwiseBinaryOp :
|
||||
|
||||
#if EIGEN_COMP_MSVC && EIGEN_HAS_CXX11
|
||||
//Required for Visual Studio or the Copy constructor will probably not get inlined!
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
EIGEN_STRONG_INLINE
|
||||
CwiseBinaryOp(const CwiseBinaryOp<BinaryOp,LhsType,RhsType>&) = default;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -292,7 +292,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>
|
||||
|
||||
@@ -324,9 +324,9 @@ template<typename Derived> class DenseBase
|
||||
typedef Transpose<Derived> TransposeReturnType;
|
||||
EIGEN_DEVICE_FUNC
|
||||
TransposeReturnType transpose();
|
||||
typedef typename internal::add_const<Transpose<const Derived> >::type ConstTransposeReturnType;
|
||||
typedef Transpose<const Derived> ConstTransposeReturnType;
|
||||
EIGEN_DEVICE_FUNC
|
||||
ConstTransposeReturnType transpose() const;
|
||||
const ConstTransposeReturnType transpose() const;
|
||||
EIGEN_DEVICE_FUNC
|
||||
void transposeInPlace();
|
||||
|
||||
|
||||
@@ -163,6 +163,30 @@ struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
|
||||
EIGEN_DEVICE_FUNC plain_array(constructor_without_unaligned_array_assert) {}
|
||||
};
|
||||
|
||||
struct plain_array_helper {
|
||||
template<typename T, int Size, int MatrixOrArrayOptions, int Alignment>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
static void copy(const plain_array<T, Size, MatrixOrArrayOptions, Alignment>& src, const Eigen::Index size,
|
||||
plain_array<T, Size, MatrixOrArrayOptions, Alignment>& dst) {
|
||||
smart_copy(src.array, src.array + size, dst.array);
|
||||
}
|
||||
|
||||
template<typename T, int Size, int MatrixOrArrayOptions, int Alignment>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
static void swap(plain_array<T, Size, MatrixOrArrayOptions, Alignment>& a, const Eigen::Index a_size,
|
||||
plain_array<T, Size, MatrixOrArrayOptions, Alignment>& b, const Eigen::Index b_size) {
|
||||
if (a_size < b_size) {
|
||||
std::swap_ranges(b.array, b.array + a_size, a.array);
|
||||
smart_move(b.array + a_size, b.array + b_size, a.array + a_size);
|
||||
} else if (a_size > b_size) {
|
||||
std::swap_ranges(a.array, a.array + b_size, b.array);
|
||||
smart_move(a.array + b_size, a.array + a_size, b.array + b_size);
|
||||
} else {
|
||||
std::swap_ranges(a.array, a.array + a_size, b.array);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \internal
|
||||
@@ -190,17 +214,26 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()) {}
|
||||
#if !EIGEN_HAS_CXX11 || defined(EIGEN_DENSE_STORAGE_CTOR_PLUGIN)
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage(const DenseStorage& other) : m_data(other.m_data) {
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size)
|
||||
}
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage&) = default;
|
||||
#endif
|
||||
#if !EIGEN_HAS_CXX11
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other) m_data = other.m_data;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage&) = default;
|
||||
#endif
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
#if !EIGEN_HAS_CXX11
|
||||
EIGEN_DEVICE_FUNC DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
: m_data(std::move(other.m_data))
|
||||
{
|
||||
@@ -211,6 +244,10 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
||||
m_data = std::move(other.m_data);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC DenseStorage(DenseStorage&&) = default;
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(DenseStorage&&) = default;
|
||||
#endif
|
||||
#endif
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) {
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
@@ -268,21 +305,25 @@ template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic
|
||||
EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0), m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(other.m_rows), m_cols(other.m_cols)
|
||||
{
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * m_cols, m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
m_rows = other.m_rows;
|
||||
m_cols = other.m_cols;
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * m_cols, m_data);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index, Index rows, Index cols) : m_rows(rows), m_cols(cols) {}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other)
|
||||
{
|
||||
numext::swap(m_data,other.m_data);
|
||||
internal::plain_array_helper::swap(m_data, m_rows * m_cols, other.m_data, other.m_rows * other.m_cols);
|
||||
numext::swap(m_rows,other.m_rows);
|
||||
numext::swap(m_cols,other.m_cols);
|
||||
}
|
||||
@@ -303,21 +344,26 @@ template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Si
|
||||
EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0) {}
|
||||
EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(other.m_rows)
|
||||
{
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * _Cols, m_data);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
m_rows = other.m_rows;
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * _Cols, m_data);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index, Index rows, Index) : m_rows(rows) {}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other)
|
||||
{
|
||||
numext::swap(m_data,other.m_data);
|
||||
numext::swap(m_rows,other.m_rows);
|
||||
{
|
||||
internal::plain_array_helper::swap(m_data, m_rows * _Cols, other.m_data, other.m_rows * _Cols);
|
||||
numext::swap(m_rows, other.m_rows);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const EIGEN_NOEXCEPT {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols(void) const EIGEN_NOEXCEPT {return _Cols;}
|
||||
@@ -336,20 +382,24 @@ template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Si
|
||||
EIGEN_DEVICE_FUNC DenseStorage() : m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_cols(other.m_cols) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(other.m_cols)
|
||||
{
|
||||
internal::plain_array_helper::copy(other.m_data, _Rows * m_cols, m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
m_cols = other.m_cols;
|
||||
internal::plain_array_helper::copy(other.m_data, _Rows * m_cols, m_data);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index, Index, Index cols) : m_cols(cols) {}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) {
|
||||
numext::swap(m_data,other.m_data);
|
||||
numext::swap(m_cols,other.m_cols);
|
||||
internal::plain_array_helper::swap(m_data, _Rows * m_cols, other.m_data, _Rows * other.m_cols);
|
||||
numext::swap(m_cols, other.m_cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows(void) const EIGEN_NOEXCEPT {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const EIGEN_NOEXCEPT {return m_cols;}
|
||||
|
||||
@@ -191,7 +191,8 @@ MatrixBase<Derived>::diagonal()
|
||||
|
||||
/** This is the const version of diagonal(). */
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::ConstDiagonalReturnType
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
const typename MatrixBase<Derived>::ConstDiagonalReturnType
|
||||
MatrixBase<Derived>::diagonal() const
|
||||
{
|
||||
return ConstDiagonalReturnType(derived());
|
||||
@@ -209,18 +210,18 @@ MatrixBase<Derived>::diagonal() const
|
||||
*
|
||||
* \sa MatrixBase::diagonal(), class Diagonal */
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::DiagonalDynamicIndexReturnType
|
||||
EIGEN_DEVICE_FUNC inline Diagonal<Derived, DynamicIndex>
|
||||
MatrixBase<Derived>::diagonal(Index index)
|
||||
{
|
||||
return DiagonalDynamicIndexReturnType(derived(), index);
|
||||
return Diagonal<Derived, DynamicIndex>(derived(), index);
|
||||
}
|
||||
|
||||
/** This is the const version of diagonal(Index). */
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::ConstDiagonalDynamicIndexReturnType
|
||||
EIGEN_DEVICE_FUNC inline const Diagonal<const Derived, DynamicIndex>
|
||||
MatrixBase<Derived>::diagonal(Index index) const
|
||||
{
|
||||
return ConstDiagonalDynamicIndexReturnType(derived(), index);
|
||||
return Diagonal<const Derived, DynamicIndex>(derived(), index);
|
||||
}
|
||||
|
||||
/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
|
||||
@@ -237,20 +238,20 @@ MatrixBase<Derived>::diagonal(Index index) const
|
||||
template<typename Derived>
|
||||
template<int Index_>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Index_>::Type
|
||||
inline Diagonal<Derived, Index_>
|
||||
MatrixBase<Derived>::diagonal()
|
||||
{
|
||||
return typename DiagonalIndexReturnType<Index_>::Type(derived());
|
||||
return Diagonal<Derived, Index_>(derived());
|
||||
}
|
||||
|
||||
/** This is the const version of diagonal<int>(). */
|
||||
template<typename Derived>
|
||||
template<int Index_>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Index_>::Type
|
||||
inline const Diagonal<const Derived, Index_>
|
||||
MatrixBase<Derived>::diagonal() const
|
||||
{
|
||||
return typename ConstDiagonalIndexReturnType<Index_>::Type(derived());
|
||||
return Diagonal<const Derived, Index_>(derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -18,14 +18,9 @@ namespace internal {
|
||||
// with mismatched types, the compiler emits errors about failing to instantiate cwiseProduct BEFORE
|
||||
// looking at the static assertions. Thus this is a trick to get better compile errors.
|
||||
template<typename T, typename U,
|
||||
// the NeedToTranspose condition here is taken straight from Assign.h
|
||||
bool NeedToTranspose = T::IsVectorAtCompileTime
|
||||
&& U::IsVectorAtCompileTime
|
||||
&& ((int(T::RowsAtCompileTime) == 1 && int(U::ColsAtCompileTime) == 1)
|
||||
| // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
|
||||
// revert to || as soon as not needed anymore.
|
||||
(int(T::ColsAtCompileTime) == 1 && int(U::RowsAtCompileTime) == 1))
|
||||
>
|
||||
bool NeedToTranspose = T::IsVectorAtCompileTime && U::IsVectorAtCompileTime &&
|
||||
((int(T::RowsAtCompileTime) == 1 && int(U::ColsAtCompileTime) == 1) ||
|
||||
(int(T::ColsAtCompileTime) == 1 && int(U::RowsAtCompileTime) == 1))>
|
||||
struct dot_nocheck
|
||||
{
|
||||
typedef scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> conj_prod;
|
||||
@@ -86,7 +81,7 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||
|
||||
//---------- implementation of L2 norm and related functions ----------
|
||||
|
||||
/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm.
|
||||
/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the squared Frobenius norm.
|
||||
* In both cases, it consists in the sum of the square of all the matrix entries.
|
||||
* For vectors, this is also equals to the dot product of \c *this with itself.
|
||||
*
|
||||
|
||||
@@ -129,6 +129,22 @@ template<typename T> struct packet_traits : default_packet_traits
|
||||
|
||||
template<typename T> struct packet_traits<const T> : packet_traits<T> { };
|
||||
|
||||
template<typename T> struct unpacket_traits
|
||||
{
|
||||
typedef T type;
|
||||
typedef T half;
|
||||
enum
|
||||
{
|
||||
size = 1,
|
||||
alignment = 1,
|
||||
vectorizable = false,
|
||||
masked_load_available=false,
|
||||
masked_store_available=false
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T> struct unpacket_traits<const T> : unpacket_traits<T> { };
|
||||
|
||||
template <typename Src, typename Tgt> struct type_casting_traits {
|
||||
enum {
|
||||
VectorizedCast = 0,
|
||||
@@ -144,7 +160,7 @@ struct eigen_packet_wrapper
|
||||
{
|
||||
EIGEN_ALWAYS_INLINE operator T&() { return m_val; }
|
||||
EIGEN_ALWAYS_INLINE operator const T&() const { return m_val; }
|
||||
EIGEN_ALWAYS_INLINE eigen_packet_wrapper() {}
|
||||
EIGEN_ALWAYS_INLINE eigen_packet_wrapper() {};
|
||||
EIGEN_ALWAYS_INLINE eigen_packet_wrapper(const T &v) : m_val(v) {}
|
||||
EIGEN_ALWAYS_INLINE eigen_packet_wrapper& operator=(const T &v) {
|
||||
m_val = v;
|
||||
@@ -154,6 +170,18 @@ struct eigen_packet_wrapper
|
||||
T m_val;
|
||||
};
|
||||
|
||||
|
||||
/** \internal A convenience utility for determining if the type is a scalar.
|
||||
* This is used to enable some generic packet implementations.
|
||||
*/
|
||||
template<typename Packet>
|
||||
struct is_scalar {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
enum {
|
||||
value = internal::is_same<Packet, Scalar>::value
|
||||
};
|
||||
};
|
||||
|
||||
/** \internal \returns static_cast<TgtType>(a) (coeff-wise) */
|
||||
template <typename SrcPacket, typename TgtPacket>
|
||||
EIGEN_DEVICE_FUNC inline TgtPacket
|
||||
@@ -215,13 +243,59 @@ pmul(const bool& a, const bool& b) { return a && b; }
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pdiv(const Packet& a, const Packet& b) { return a/b; }
|
||||
|
||||
/** \internal \returns one bits */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
ptrue(const Packet& /*a*/) { Packet b; memset((void*)&b, 0xff, sizeof(b)); return b;}
|
||||
// In the generic 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*/){
|
||||
Packet b;
|
||||
memset(static_cast<void*>(&b), 0xff, sizeof(Packet));
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns zero bits */
|
||||
// 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,
|
||||
typename internal::enable_if<is_scalar<T>::value && NumTraits<T>::RequireInitialization>::type > {
|
||||
static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/){
|
||||
return T(1);
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns one bits. */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pzero(const Packet& /*a*/) { Packet b; memset((void*)&b, 0, sizeof(b)); return b;}
|
||||
ptrue(const Packet& a) {
|
||||
return ptrue_impl<Packet>::run(a);
|
||||
}
|
||||
|
||||
// In the general case, memset to zero.
|
||||
template<typename Packet, typename EnableIf = void>
|
||||
struct pzero_impl {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) {
|
||||
Packet b;
|
||||
memset(static_cast<void*>(&b), 0x00, sizeof(Packet));
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
// For scalars, explicitly set to Scalar(0), since the underlying representation
|
||||
// for zero may not consist of all-zero bits.
|
||||
template<typename T>
|
||||
struct pzero_impl<T,
|
||||
typename internal::enable_if<is_scalar<T>::value>::type> {
|
||||
static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/) {
|
||||
return T(0);
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns packet of zeros */
|
||||
template<typename Packet> 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
|
||||
@@ -238,33 +312,6 @@ 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<> EIGEN_DEVICE_FUNC inline float pzero<float>(const float& a) {
|
||||
EIGEN_UNUSED_VARIABLE(a)
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline double pzero<double>(const double& a) {
|
||||
EIGEN_UNUSED_VARIABLE(a)
|
||||
return 0.;
|
||||
}
|
||||
|
||||
template <typename RealScalar>
|
||||
EIGEN_DEVICE_FUNC inline std::complex<RealScalar> ptrue(const std::complex<RealScalar>& /*a*/) {
|
||||
RealScalar b = ptrue(RealScalar(0));
|
||||
return std::complex<RealScalar>(b, b);
|
||||
}
|
||||
|
||||
template <typename Packet, typename Op>
|
||||
EIGEN_DEVICE_FUNC inline Packet bitwise_helper(const Packet& a, const Packet& b, Op op) {
|
||||
const unsigned char* a_ptr = reinterpret_cast<const unsigned char*>(&a);
|
||||
const unsigned char* b_ptr = reinterpret_cast<const unsigned char*>(&b);
|
||||
Packet c;
|
||||
unsigned char* c_ptr = reinterpret_cast<unsigned char*>(&c);
|
||||
for (size_t i = 0; i < sizeof(Packet); ++i) {
|
||||
*c_ptr++ = op(*a_ptr++, *b_ptr++);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct bit_and {
|
||||
@@ -287,42 +334,123 @@ struct bit_xor {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct bit_not {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a) const {
|
||||
return ~a;
|
||||
}
|
||||
};
|
||||
|
||||
// Use operators &, |, ^, ~.
|
||||
template<typename T>
|
||||
struct operator_bitwise_helper {
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) { return bit_and<T>()(a, b); }
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) { return bit_or<T>()(a, b); }
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) { return bit_xor<T>()(a, b); }
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) { return bit_not<T>()(a); }
|
||||
};
|
||||
|
||||
// Apply binary operations byte-by-byte
|
||||
template<typename T>
|
||||
struct bytewise_bitwise_helper {
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) {
|
||||
return binary(a, b, bit_and<unsigned char>());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) {
|
||||
return binary(a, b, bit_or<unsigned char>());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) {
|
||||
return binary(a, b, bit_xor<unsigned char>());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) {
|
||||
return unary(a,bit_not<unsigned char>());
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Op>
|
||||
EIGEN_DEVICE_FUNC static inline T unary(const T& a, Op op) {
|
||||
const unsigned char* a_ptr = reinterpret_cast<const unsigned char*>(&a);
|
||||
T c;
|
||||
unsigned char* c_ptr = reinterpret_cast<unsigned char*>(&c);
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
*c_ptr++ = op(*a_ptr++);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename Op>
|
||||
EIGEN_DEVICE_FUNC static inline T binary(const T& a, const T& b, Op op) {
|
||||
const unsigned char* a_ptr = reinterpret_cast<const unsigned char*>(&a);
|
||||
const unsigned char* b_ptr = reinterpret_cast<const unsigned char*>(&b);
|
||||
T c;
|
||||
unsigned char* c_ptr = reinterpret_cast<unsigned char*>(&c);
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
*c_ptr++ = op(*a_ptr++, *b_ptr++);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
// In the general case, use byte-by-byte manipulation.
|
||||
template<typename T, typename EnableIf = void>
|
||||
struct bitwise_helper : public bytewise_bitwise_helper<T> {};
|
||||
|
||||
// For integers or non-trivial scalars, use binary operators.
|
||||
template<typename T>
|
||||
struct bitwise_helper<T,
|
||||
typename internal::enable_if<
|
||||
is_scalar<T>::value && (NumTraits<T>::IsInteger || NumTraits<T>::RequireInitialization)>::type
|
||||
> : public operator_bitwise_helper<T> {};
|
||||
|
||||
/** \internal \returns the bitwise and of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pand(const Packet& a, const Packet& b) {
|
||||
return bitwise_helper(a, b, bit_and<unsigned char>());
|
||||
return bitwise_helper<Packet>::bitwise_and(a, b);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise or of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
por(const Packet& a, const Packet& b) {
|
||||
return bitwise_helper(a ,b, bit_or<unsigned char>());
|
||||
return bitwise_helper<Packet>::bitwise_or(a, b);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise xor of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pxor(const Packet& a, const Packet& b) {
|
||||
return bitwise_helper(a ,b, bit_xor<unsigned char>());
|
||||
return bitwise_helper<Packet>::bitwise_xor(a, b);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise not of \a a */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pnot(const Packet& a) {
|
||||
return bitwise_helper<Packet>::bitwise_not(a);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise and of \a a and not \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pandnot(const Packet& a, const Packet& b) { return pand(a, pxor(ptrue(b), b)); }
|
||||
pandnot(const Packet& a, const Packet& b) { return pand(a, pnot(b)); }
|
||||
|
||||
// In the general case, use bitwise select.
|
||||
template<typename Packet, typename EnableIf = void>
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
// For scalars, use ternary select.
|
||||
template<typename Packet>
|
||||
struct pselect_impl<Packet,
|
||||
typename internal::enable_if<is_scalar<Packet>::value>::type > {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns \a or \b for each field in packet according to \mask */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pselect(const Packet& mask, const Packet& a, const Packet& b) {
|
||||
return por(pand(a,mask),pandnot(b,mask));
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline float pselect<float>(
|
||||
const float& cond, const float& a, const float&b) {
|
||||
return numext::equal_strict(cond,0.f) ? b : a;
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline double pselect<double>(
|
||||
const double& cond, const double& a, const double& b) {
|
||||
return numext::equal_strict(cond,0.) ? b : a;
|
||||
return pselect_impl<Packet>::run(mask, a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline bool pselect<bool>(
|
||||
@@ -679,7 +807,7 @@ Packet plog10(const Packet& a) { EIGEN_USING_STD(log10); return log10(a); }
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet plog2(const Packet& a) {
|
||||
typedef typename internal::unpacket_traits<Packet>::type Scalar;
|
||||
return pmul(pset1<Packet>(Scalar(EIGEN_LOG2E)), plog(a));
|
||||
return pmul(pset1<Packet>(Scalar(EIGEN_LOG2E)), plog(a));
|
||||
}
|
||||
|
||||
/** \internal \returns the square-root of \a a (coeff-wise) */
|
||||
@@ -753,7 +881,7 @@ predux(const Packet& a)
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_mul(
|
||||
const Packet& a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmul<Scalar>)));
|
||||
}
|
||||
|
||||
@@ -761,14 +889,14 @@ EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_mul(
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(
|
||||
const Packet &a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<PropagateFast, 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;
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<NaNPropagation, Scalar>)));
|
||||
}
|
||||
|
||||
@@ -776,14 +904,14 @@ EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(
|
||||
const Packet &a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<PropagateFast, Scalar>)));
|
||||
}
|
||||
|
||||
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;
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<NaNPropagation, Scalar>)));
|
||||
}
|
||||
|
||||
|
||||
@@ -122,10 +122,10 @@ public:
|
||||
{}
|
||||
|
||||
/** \returns number of rows */
|
||||
Index rows() const { return internal::size(m_rowIndices); }
|
||||
Index rows() const { return internal::index_list_size(m_rowIndices); }
|
||||
|
||||
/** \returns number of columns */
|
||||
Index cols() const { return internal::size(m_colIndices); }
|
||||
Index cols() const { return internal::index_list_size(m_colIndices); }
|
||||
|
||||
/** \returns the nested expression */
|
||||
const typename internal::remove_all<XprType>::type&
|
||||
@@ -189,12 +189,16 @@ struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows()
|
||||
&& m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
|
||||
return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows()
|
||||
&& m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
|
||||
return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
@@ -204,6 +208,8 @@ struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
|
||||
EIGEN_STATIC_ASSERT_LVALUE(XprType)
|
||||
Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
|
||||
Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
|
||||
eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows()
|
||||
&& m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
|
||||
return m_argImpl.coeffRef( m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
@@ -212,6 +218,8 @@ struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
|
||||
{
|
||||
Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
|
||||
Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
|
||||
eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows()
|
||||
&& m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
|
||||
return m_argImpl.coeffRef( m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
@@ -220,6 +228,8 @@ struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
|
||||
{
|
||||
Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
|
||||
Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
|
||||
eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows()
|
||||
&& m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols());
|
||||
return m_argImpl.coeff( m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ private:
|
||||
* \brief A matrix or vector expression mapping an existing array of data.
|
||||
*
|
||||
* \tparam PlainObjectType the equivalent matrix type of the mapped data
|
||||
* \tparam MapOptions specifies the pointer alignment in bytes. It can be: \c #Aligned128, , \c #Aligned64, \c #Aligned32, \c #Aligned16, \c #Aligned8 or \c #Unaligned.
|
||||
* \tparam MapOptions specifies the pointer alignment in bytes. It can be: \c #Aligned128, \c #Aligned64, \c #Aligned32, \c #Aligned16, \c #Aligned8 or \c #Unaligned.
|
||||
* The default is \c #Unaligned.
|
||||
* \tparam StrideType optionally specifies strides. By default, Map assumes the memory layout
|
||||
* of an ordinary, contiguous array. This can be overridden by specifying strides.
|
||||
|
||||
+217
-34
@@ -2,6 +2,7 @@
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// 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
|
||||
@@ -260,19 +261,8 @@ struct conj_default_impl<Scalar,true>
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar> struct conj_impl : conj_default_impl<Scalar> {};
|
||||
|
||||
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
template<typename T>
|
||||
struct conj_impl<std::complex<T> >
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline std::complex<T> run(const std::complex<T>& x)
|
||||
{
|
||||
return std::complex<T>(x.real(), -x.imag());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
|
||||
struct conj_impl : conj_default_impl<Scalar, IsComplex> {};
|
||||
|
||||
template<typename Scalar>
|
||||
struct conj_retval
|
||||
@@ -582,7 +572,9 @@ struct rint_retval
|
||||
* Implementation of arg *
|
||||
****************************************************************************/
|
||||
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
// Visual Studio 2017 has a bug where arg(float) returns 0 for negative inputs.
|
||||
// This seems to be fixed in VS 2019.
|
||||
#if EIGEN_HAS_CXX11_MATH && (!EIGEN_COMP_MSVC || EIGEN_COMP_MSVC >= 1920)
|
||||
// std::arg is only defined for types of std::complex, or integer types or float/double/long double
|
||||
template<typename Scalar,
|
||||
bool HasStdImpl = NumTraits<Scalar>::IsComplex || is_integral<Scalar>::value
|
||||
@@ -592,16 +584,13 @@ struct arg_default_impl;
|
||||
|
||||
template<typename Scalar>
|
||||
struct arg_default_impl<Scalar, true> {
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline Scalar run(const Scalar& x)
|
||||
static inline RealScalar run(const Scalar& x)
|
||||
{
|
||||
#if defined(EIGEN_HIP_DEVICE_COMPILE)
|
||||
// HIP does not seem to have a native device side implementation for the math routine "arg"
|
||||
// There is no official ::arg on device in CUDA/HIP, so we always need to use std::arg.
|
||||
using std::arg;
|
||||
#else
|
||||
EIGEN_USING_STD(arg);
|
||||
#endif
|
||||
return static_cast<Scalar>(arg(x));
|
||||
return static_cast<RealScalar>(arg(x));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -612,7 +601,7 @@ struct arg_default_impl<Scalar, false> {
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline RealScalar run(const Scalar& x)
|
||||
{
|
||||
return (x < Scalar(0)) ? Scalar(EIGEN_PI) : Scalar(0);
|
||||
return (x < Scalar(0)) ? RealScalar(EIGEN_PI) : RealScalar(0);
|
||||
}
|
||||
};
|
||||
#else
|
||||
@@ -623,7 +612,7 @@ struct arg_default_impl
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline RealScalar run(const Scalar& x)
|
||||
{
|
||||
return (x < Scalar(0)) ? Scalar(EIGEN_PI) : Scalar(0);
|
||||
return (x < RealScalar(0)) ? RealScalar(EIGEN_PI) : RealScalar(0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -697,6 +686,30 @@ struct expm1_retval
|
||||
typedef Scalar type;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Implementation of log *
|
||||
****************************************************************************/
|
||||
|
||||
// Complex log defined in MathFunctionsImpl.h.
|
||||
template<typename T> EIGEN_DEVICE_FUNC std::complex<T> complex_log(const std::complex<T>& z);
|
||||
|
||||
template<typename Scalar>
|
||||
struct log_impl {
|
||||
EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
|
||||
{
|
||||
EIGEN_USING_STD(log);
|
||||
return static_cast<Scalar>(log(x));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
struct log_impl<std::complex<Scalar> > {
|
||||
EIGEN_DEVICE_FUNC static inline std::complex<Scalar> run(const std::complex<Scalar>& z)
|
||||
{
|
||||
return complex_log(z);
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Implementation of log1p *
|
||||
****************************************************************************/
|
||||
@@ -710,7 +723,7 @@ namespace std_fallback {
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
EIGEN_USING_STD(log);
|
||||
Scalar x1p = RealScalar(1) + x;
|
||||
Scalar log_1p = log(x1p);
|
||||
Scalar log_1p = log_impl<Scalar>::run(x1p);
|
||||
const bool is_small = numext::equal_strict(x1p, Scalar(1));
|
||||
const bool is_inf = numext::equal_strict(x1p, log_1p);
|
||||
return (is_small || is_inf) ? x : x * (log_1p / (x1p - RealScalar(1)));
|
||||
@@ -864,13 +877,159 @@ struct meta_floor_log2<n, lower, upper, meta_floor_log2_bogus>
|
||||
// no value, error at compile time
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
struct random_default_impl<Scalar, false, true>
|
||||
{
|
||||
static inline Scalar run(const Scalar& x, const Scalar& y)
|
||||
{
|
||||
if (y <= x)
|
||||
return x;
|
||||
template <typename BitsType, typename EnableIf = void>
|
||||
struct count_bits_impl {
|
||||
static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(
|
||||
is_integral<BitsType>::value && !NumTraits<BitsType>::IsSigned,
|
||||
THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
int n = CHAR_BIT * sizeof(BitsType);
|
||||
int shift = n / 2;
|
||||
while (bits > 0 && shift > 0) {
|
||||
BitsType y = bits >> shift;
|
||||
if (y > 0) {
|
||||
n -= shift;
|
||||
bits = y;
|
||||
}
|
||||
shift /= 2;
|
||||
}
|
||||
if (shift == 0) {
|
||||
--n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(
|
||||
is_integral<BitsType>::value && !NumTraits<BitsType>::IsSigned,
|
||||
THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
int n = CHAR_BIT * sizeof(BitsType);
|
||||
int shift = n / 2;
|
||||
while (bits > 0 && shift > 0) {
|
||||
BitsType y = bits << shift;
|
||||
if (y > 0) {
|
||||
n -= shift;
|
||||
bits = y;
|
||||
}
|
||||
shift /= 2;
|
||||
}
|
||||
if (shift == 0) {
|
||||
--n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
// Count leading zeros.
|
||||
template <typename BitsType>
|
||||
EIGEN_DEVICE_FUNC inline int clz(BitsType bits) {
|
||||
return count_bits_impl<BitsType>::clz(bits);
|
||||
}
|
||||
|
||||
// Count trailing zeros.
|
||||
template <typename BitsType>
|
||||
EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) {
|
||||
return count_bits_impl<BitsType>::ctz(bits);
|
||||
}
|
||||
|
||||
#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
|
||||
|
||||
template <typename BitsType>
|
||||
struct count_bits_impl<BitsType, typename enable_if<sizeof(BitsType) <= sizeof(unsigned int)>::type> {
|
||||
static const int kNumBits = static_cast<int>(sizeof(BitsType) * CHAR_BIT);
|
||||
static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
static const int kLeadingBitsOffset = (sizeof(unsigned int) - sizeof(BitsType)) * CHAR_BIT;
|
||||
return bits == 0 ? kNumBits : __builtin_clz(static_cast<unsigned int>(bits)) - kLeadingBitsOffset;
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
return bits == 0 ? kNumBits : __builtin_ctz(static_cast<unsigned int>(bits));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BitsType>
|
||||
struct count_bits_impl<
|
||||
BitsType, typename enable_if<sizeof(unsigned int) < sizeof(BitsType) && sizeof(BitsType) <= sizeof(unsigned long)>::type> {
|
||||
static const int kNumBits = static_cast<int>(sizeof(BitsType) * CHAR_BIT);
|
||||
static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
static const int kLeadingBitsOffset = (sizeof(unsigned long) - sizeof(BitsType)) * CHAR_BIT;
|
||||
return bits == 0 ? kNumBits : __builtin_clzl(static_cast<unsigned long>(bits)) - kLeadingBitsOffset;
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
return bits == 0 ? kNumBits : __builtin_ctzl(static_cast<unsigned long>(bits));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BitsType>
|
||||
struct count_bits_impl<BitsType, typename enable_if<sizeof(unsigned long) < sizeof(BitsType) &&
|
||||
sizeof(BitsType) <= sizeof(unsigned long long)>::type> {
|
||||
static const int kNumBits = static_cast<int>(sizeof(BitsType) * CHAR_BIT);
|
||||
static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
static const int kLeadingBitsOffset = (sizeof(unsigned long long) - sizeof(BitsType)) * CHAR_BIT;
|
||||
return bits == 0 ? kNumBits : __builtin_clzll(static_cast<unsigned long long>(bits)) - kLeadingBitsOffset;
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
return bits == 0 ? kNumBits : __builtin_ctzll(static_cast<unsigned long long>(bits));
|
||||
}
|
||||
};
|
||||
|
||||
#elif EIGEN_COMP_MSVC
|
||||
|
||||
template <typename BitsType>
|
||||
struct count_bits_impl<BitsType, typename enable_if<sizeof(BitsType) <= sizeof(unsigned long)>::type> {
|
||||
static const int kNumBits = static_cast<int>(sizeof(BitsType) * CHAR_BIT);
|
||||
static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
unsigned long out;
|
||||
_BitScanReverse(&out, static_cast<unsigned long>(bits));
|
||||
return bits == 0 ? kNumBits : (kNumBits - 1) - static_cast<int>(out);
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
unsigned long out;
|
||||
_BitScanForward(&out, static_cast<unsigned long>(bits));
|
||||
return bits == 0 ? kNumBits : static_cast<int>(out);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
template <typename BitsType>
|
||||
struct count_bits_impl<
|
||||
BitsType, typename enable_if<sizeof(unsigned long) < sizeof(BitsType) && sizeof(BitsType) <= sizeof(__int64)>::type> {
|
||||
static const int kNumBits = static_cast<int>(sizeof(BitsType) * CHAR_BIT);
|
||||
static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
unsigned long out;
|
||||
_BitScanReverse64(&out, static_cast<unsigned __int64>(bits));
|
||||
return bits == 0 ? kNumBits : (kNumBits - 1) - static_cast<int>(out);
|
||||
}
|
||||
|
||||
static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) {
|
||||
EIGEN_STATIC_ASSERT(is_integral<BitsType>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
unsigned long out;
|
||||
_BitScanForward64(&out, static_cast<unsigned __int64>(bits));
|
||||
return bits == 0 ? kNumBits : static_cast<int>(out);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _WIN64
|
||||
|
||||
#endif // EIGEN_COMP_GNUC || EIGEN_COMP_CLANG
|
||||
|
||||
template <typename Scalar>
|
||||
struct random_default_impl<Scalar, false, true> {
|
||||
static inline Scalar run(const Scalar& x, const Scalar& y) {
|
||||
if (y <= x) return x;
|
||||
// ScalarU is the unsigned counterpart of Scalar, possibly Scalar itself.
|
||||
typedef typename make_unsigned<Scalar>::type ScalarU;
|
||||
// ScalarX is the widest of ScalarU and unsigned int.
|
||||
@@ -1015,11 +1174,15 @@ template<typename T> EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x)
|
||||
}
|
||||
|
||||
//MSVC defines a _isnan builtin function, but for double only
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
EIGEN_DEVICE_FUNC inline bool isnan_impl(const long double& x) { return _isnan(x)!=0; }
|
||||
#endif
|
||||
EIGEN_DEVICE_FUNC inline bool isnan_impl(const double& x) { return _isnan(x)!=0; }
|
||||
EIGEN_DEVICE_FUNC inline bool isnan_impl(const float& x) { return _isnan(x)!=0; }
|
||||
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
EIGEN_DEVICE_FUNC inline bool isinf_impl(const long double& x) { return isinf_msvc_helper(x); }
|
||||
#endif
|
||||
EIGEN_DEVICE_FUNC inline bool isinf_impl(const double& x) { return isinf_msvc_helper(x); }
|
||||
EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_msvc_helper(x); }
|
||||
|
||||
@@ -1033,12 +1196,16 @@ EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_ms
|
||||
#define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((noinline,optimize("no-finite-math-only")))
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const long double& x) { return __builtin_isnan(x); }
|
||||
#endif
|
||||
template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const double& x) { return __builtin_isnan(x); }
|
||||
template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const float& x) { return __builtin_isnan(x); }
|
||||
template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const double& x) { return __builtin_isinf(x); }
|
||||
template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const float& x) { return __builtin_isinf(x); }
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const long double& x) { return __builtin_isinf(x); }
|
||||
#endif
|
||||
|
||||
#undef EIGEN_TMP_NOOPT_ATTRIB
|
||||
|
||||
@@ -1095,6 +1262,8 @@ EIGEN_ALWAYS_INLINE double mini(const double& x, const double& y)
|
||||
{
|
||||
return fmin(x, y);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_ALWAYS_INLINE long double mini(const long double& x, const long double& y)
|
||||
@@ -1106,6 +1275,7 @@ EIGEN_ALWAYS_INLINE long double mini(const long double& x, const long double& y)
|
||||
return fminl(x, y);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -1125,6 +1295,7 @@ EIGEN_ALWAYS_INLINE double maxi(const double& x, const double& y)
|
||||
{
|
||||
return fmax(x, y);
|
||||
}
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_ALWAYS_INLINE long double maxi(const long double& x, const long double& y)
|
||||
@@ -1137,6 +1308,7 @@ EIGEN_ALWAYS_INLINE long double maxi(const long double& x, const long double& y)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SYCL_DEVICE_ONLY)
|
||||
|
||||
@@ -1293,8 +1465,8 @@ EIGEN_ALWAYS_INLINE double absdiff(const double& x, const double& y)
|
||||
return fabs(x - y);
|
||||
}
|
||||
|
||||
#if !defined(EIGEN_GPUCC)
|
||||
// HIP and CUDA do not support long double.
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_ALWAYS_INLINE long double absdiff(const long double& x, const long double& y) {
|
||||
@@ -1470,8 +1642,7 @@ T rsqrt(const T& x)
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
T log(const T &x) {
|
||||
EIGEN_USING_STD(log);
|
||||
return static_cast<T>(log(x));
|
||||
return internal::log_impl<T>::run(x);
|
||||
}
|
||||
|
||||
#if defined(SYCL_DEVICE_ONLY)
|
||||
@@ -2022,6 +2193,18 @@ struct rsqrt_impl {
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
template<typename T>
|
||||
struct conj_impl<std::complex<T>, true>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline std::complex<T> run(const std::complex<T>& x)
|
||||
{
|
||||
return std::complex<T>(numext::real(x), -numext::imag(x));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -184,6 +184,15 @@ EIGEN_DEVICE_FUNC std::complex<T> complex_rsqrt(const std::complex<T>& z) {
|
||||
: std::complex<T>(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) {
|
||||
// Computes complex log.
|
||||
T a = numext::abs(z);
|
||||
EIGEN_USING_STD(atan2);
|
||||
T b = atan2(z.imag(), z.real());
|
||||
return std::complex<T>(numext::log(a), b);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
+16
-3
@@ -225,8 +225,6 @@ class Matrix
|
||||
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)
|
||||
@@ -284,7 +282,15 @@ class Matrix
|
||||
#endif
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
/** \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. \cpp11
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* This constructor is for 1D array or vectors with more than 4 coefficients.
|
||||
* There exists C++98 analogue constructors for fixed-size array/vector having 1, 2, 3, or 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
|
||||
@@ -297,6 +303,8 @@ class Matrix
|
||||
: Base(a0, a1, a2, a3, args...) {}
|
||||
|
||||
/** \brief Constructs a Matrix and initializes it from the coefficients given as initializer-lists grouped by row. \cpp11
|
||||
*
|
||||
* \anchor matrix_constructor_initializer_list
|
||||
*
|
||||
* In the general case, the constructor takes a list of rows, each row being represented as a list of coefficients:
|
||||
*
|
||||
@@ -480,16 +488,21 @@ class Matrix
|
||||
|
||||
#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \noop */ \
|
||||
typedef Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix; \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \noop */ \
|
||||
typedef Matrix<Type, Size, 1> Vector##SizeSuffix##TypeSuffix; \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \noop */ \
|
||||
typedef Matrix<Type, 1, Size> RowVector##SizeSuffix##TypeSuffix;
|
||||
|
||||
#define EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \noop */ \
|
||||
typedef Matrix<Type, Size, Dynamic> Matrix##Size##X##TypeSuffix; \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \noop */ \
|
||||
typedef Matrix<Type, Dynamic, Size> Matrix##X##Size##TypeSuffix;
|
||||
|
||||
#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
|
||||
|
||||
@@ -206,28 +206,22 @@ template<typename Derived> class MatrixBase
|
||||
EIGEN_DEVICE_FUNC
|
||||
DiagonalReturnType diagonal();
|
||||
|
||||
typedef typename internal::add_const<Diagonal<const Derived> >::type ConstDiagonalReturnType;
|
||||
typedef Diagonal<const Derived> ConstDiagonalReturnType;
|
||||
EIGEN_DEVICE_FUNC
|
||||
ConstDiagonalReturnType diagonal() const;
|
||||
|
||||
template<int Index> struct DiagonalIndexReturnType { typedef Diagonal<Derived,Index> Type; };
|
||||
template<int Index> struct ConstDiagonalIndexReturnType { typedef const Diagonal<const Derived,Index> Type; };
|
||||
const ConstDiagonalReturnType diagonal() const;
|
||||
|
||||
template<int Index>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename DiagonalIndexReturnType<Index>::Type diagonal();
|
||||
Diagonal<Derived, Index> diagonal();
|
||||
|
||||
template<int Index>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const;
|
||||
|
||||
typedef Diagonal<Derived,DynamicIndex> DiagonalDynamicIndexReturnType;
|
||||
typedef typename internal::add_const<Diagonal<const Derived,DynamicIndex> >::type ConstDiagonalDynamicIndexReturnType;
|
||||
const Diagonal<const Derived, Index> diagonal() const;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
DiagonalDynamicIndexReturnType diagonal(Index index);
|
||||
Diagonal<Derived, DynamicIndex> diagonal(Index index);
|
||||
EIGEN_DEVICE_FUNC
|
||||
ConstDiagonalDynamicIndexReturnType diagonal(Index index) const;
|
||||
const Diagonal<const Derived, DynamicIndex> diagonal(Index index) const;
|
||||
|
||||
template<unsigned int Mode> struct TriangularViewReturnType { typedef TriangularView<Derived, Mode> Type; };
|
||||
template<unsigned int Mode> struct ConstTriangularViewReturnType { typedef const TriangularView<const Derived, Mode> Type; };
|
||||
|
||||
+41
-25
@@ -98,6 +98,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
|
||||
}
|
||||
} // namespace numext
|
||||
|
||||
// clang-format off
|
||||
/** \class NumTraits
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
@@ -109,45 +110,47 @@ 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
|
||||
* \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.
|
||||
* \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 \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
|
||||
* \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 \a IsComplex. It is equal to 1 if \a T is a \c std::complex
|
||||
* \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 \a IsInteger. It is equal to \c 1 if \a T is an integer type such as \c int,
|
||||
* \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 ReadCost, AddCost and MulCost representing a rough estimate of the number of CPU cycles needed
|
||||
* \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 \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
|
||||
* \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 \a Real instead of a \a T.
|
||||
* \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a default
|
||||
* \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
|
||||
* \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
|
||||
* \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 min_exponent() and max_exponent() functions returning the highest and lowest possible values, respectively,
|
||||
* \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>.
|
||||
* \li infinity() function returning a representation of positive infinity, if available.
|
||||
* \li quiet_NaN function returning a non-signaling "not-a-number", if available.
|
||||
* <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.
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
template<typename T> struct GenericNumTraits
|
||||
{
|
||||
@@ -245,12 +248,25 @@ template<> struct NumTraits<double> : GenericNumTraits<double>
|
||||
static inline 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_CONSTEXPR
|
||||
static inline long double dummy_precision() { return 1e-15l; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline 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()
|
||||
{
|
||||
// 2^(-(__LDBL_MANT_DIG__)+1)
|
||||
return static_cast<long double>(2.4651903288156618919116517665087e-32l);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename _Real> struct NumTraits<std::complex<_Real> >
|
||||
: GenericNumTraits<std::complex<_Real> >
|
||||
@@ -289,9 +305,9 @@ struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
|
||||
IsInteger = NumTraits<Scalar>::IsInteger,
|
||||
IsSigned = NumTraits<Scalar>::IsSigned,
|
||||
RequireInitialization = 1,
|
||||
ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::ReadCost,
|
||||
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
|
||||
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
|
||||
ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::ReadCost),
|
||||
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::AddCost),
|
||||
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::MulCost)
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
|
||||
@@ -54,12 +54,17 @@ struct packetwise_redux_traits
|
||||
/* Value to be returned when size==0 , by default let's return 0 */
|
||||
template<typename PacketType,typename Func>
|
||||
EIGEN_DEVICE_FUNC
|
||||
PacketType packetwise_redux_empty_value(const Func& ) { return pset1<PacketType>(0); }
|
||||
PacketType packetwise_redux_empty_value(const Func& ) {
|
||||
const typename unpacket_traits<PacketType>::type zero(0);
|
||||
return pset1<PacketType>(zero);
|
||||
}
|
||||
|
||||
/* For products the default is 1 */
|
||||
template<typename PacketType,typename Scalar>
|
||||
EIGEN_DEVICE_FUNC
|
||||
PacketType packetwise_redux_empty_value(const scalar_product_op<Scalar,Scalar>& ) { return pset1<PacketType>(1); }
|
||||
PacketType packetwise_redux_empty_value(const scalar_product_op<Scalar,Scalar>& ) {
|
||||
return pset1<PacketType>(Scalar(1));
|
||||
}
|
||||
|
||||
/* Perform the actual reduction */
|
||||
template<typename Func, typename Evaluator,
|
||||
@@ -145,7 +150,7 @@ struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
enum {
|
||||
CoeffReadCost = TraversalSize==Dynamic ? HugeCost
|
||||
: TraversalSize==0 ? 1
|
||||
: TraversalSize * evaluator<ArgType>::CoeffReadCost + int(CostOpType::value),
|
||||
: int(TraversalSize) * int(evaluator<ArgType>::CoeffReadCost) + int(CostOpType::value),
|
||||
|
||||
_ArgFlags = evaluator<ArgType>::Flags,
|
||||
|
||||
|
||||
@@ -1019,7 +1019,7 @@ struct conservative_resize_like_impl
|
||||
else
|
||||
{
|
||||
// The storage order does not allow us to use reallocation.
|
||||
typename Derived::PlainObject tmp(rows,cols);
|
||||
Derived tmp(rows,cols);
|
||||
const Index common_rows = numext::mini(rows, _this.rows());
|
||||
const Index common_cols = numext::mini(cols, _this.cols());
|
||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||
@@ -1054,7 +1054,7 @@ struct conservative_resize_like_impl
|
||||
else
|
||||
{
|
||||
// The storage order does not allow us to use reallocation.
|
||||
typename Derived::PlainObject tmp(other);
|
||||
Derived tmp(other);
|
||||
const Index common_rows = numext::mini(tmp.rows(), _this.rows());
|
||||
const Index common_cols = numext::mini(tmp.cols(), _this.cols());
|
||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||
|
||||
@@ -831,7 +831,7 @@ struct diagonal_product_evaluator_base
|
||||
typedef typename ScalarBinaryOpTraits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType Scalar;
|
||||
public:
|
||||
enum {
|
||||
CoeffReadCost = NumTraits<Scalar>::MulCost + evaluator<MatrixType>::CoeffReadCost + evaluator<DiagonalType>::CoeffReadCost,
|
||||
CoeffReadCost = int(NumTraits<Scalar>::MulCost) + int(evaluator<MatrixType>::CoeffReadCost) + int(evaluator<DiagonalType>::CoeffReadCost),
|
||||
|
||||
MatrixFlags = evaluator<MatrixType>::Flags,
|
||||
DiagFlags = evaluator<DiagonalType>::Flags,
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
public:
|
||||
enum {
|
||||
Cost = Evaluator::SizeAtCompileTime == Dynamic ? HugeCost
|
||||
: Evaluator::SizeAtCompileTime * Evaluator::CoeffReadCost + (Evaluator::SizeAtCompileTime-1) * functor_traits<Func>::Cost,
|
||||
: int(Evaluator::SizeAtCompileTime) * int(Evaluator::CoeffReadCost) + (Evaluator::SizeAtCompileTime-1) * functor_traits<Func>::Cost,
|
||||
UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize))
|
||||
};
|
||||
|
||||
@@ -331,7 +331,7 @@ struct redux_impl<Func, Evaluator, LinearVectorizedTraversal, CompleteUnrolling>
|
||||
enum {
|
||||
PacketSize = redux_traits<Func, Evaluator>::PacketSize,
|
||||
Size = Evaluator::SizeAtCompileTime,
|
||||
VectorizedSize = (Size / PacketSize) * PacketSize
|
||||
VectorizedSize = (int(Size) / int(PacketSize)) * int(PacketSize)
|
||||
};
|
||||
|
||||
template<typename XprType>
|
||||
|
||||
@@ -312,8 +312,8 @@ template<typename PlainObjectType, int Options, typename StrideType> class Ref
|
||||
inline Ref(DenseBase<Derived>& expr)
|
||||
#endif
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
|
||||
EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
||||
EIGEN_STATIC_ASSERT((static_cast<bool>(internal::is_lvalue<Derived>::value)), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
|
||||
EIGEN_STATIC_ASSERT((static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime)), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
||||
EIGEN_STATIC_ASSERT(!Derived::IsPlainObjectBase,THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
|
||||
// Construction must pass since we will not create temporary storage in the non-const case.
|
||||
const bool success = Base::construct(expr.const_cast_derived());
|
||||
|
||||
@@ -250,7 +250,7 @@ class ReshapedImpl_dense<XprType, Rows, Cols, Order, true>
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const
|
||||
{
|
||||
return ((Flags&RowMajorBit)==RowMajorBit) ? this->cols() : this->rows();
|
||||
return (((Flags&RowMajorBit)==RowMajorBit) ? this->cols() : this->rows()) * m_xpr.innerStride();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -66,7 +66,7 @@ template<typename _MatrixType, unsigned int UpLo> class SelfAdjointView
|
||||
enum {
|
||||
Mode = internal::traits<SelfAdjointView>::Mode,
|
||||
Flags = internal::traits<SelfAdjointView>::Flags,
|
||||
TransposeMode = ((Mode & Upper) ? Lower : 0) | ((Mode & Lower) ? Upper : 0)
|
||||
TransposeMode = ((int(Mode) & int(Upper)) ? Lower : 0) | ((int(Mode) & int(Lower)) ? Upper : 0)
|
||||
};
|
||||
typedef typename MatrixType::PlainObject PlainObject;
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ EIGEN_DEVICE_FUNC void TriangularViewImpl<MatrixType,Mode,Dense>::solveInPlace(c
|
||||
{
|
||||
OtherDerived& other = _other.const_cast_derived();
|
||||
eigen_assert( derived().cols() == derived().rows() && ((Side==OnTheLeft && derived().cols() == other.rows()) || (Side==OnTheRight && derived().cols() == other.cols())) );
|
||||
eigen_assert((!(Mode & ZeroDiag)) && bool(Mode & (Upper|Lower)));
|
||||
eigen_assert((!(int(Mode) & int(ZeroDiag))) && bool(int(Mode) & (int(Upper) | int(Lower))));
|
||||
// If solving for a 0x0 matrix, nothing to do, simply return.
|
||||
if (derived().cols() == 0)
|
||||
return;
|
||||
|
||||
@@ -110,7 +110,7 @@ class SolverBase : public EigenBase<Derived>
|
||||
}
|
||||
|
||||
/** \internal the return type of transpose() */
|
||||
typedef typename internal::add_const<Transpose<const Derived> >::type ConstTransposeReturnType;
|
||||
typedef Transpose<const Derived> ConstTransposeReturnType;
|
||||
/** \returns an expression of the transposed of the factored matrix.
|
||||
*
|
||||
* A typical usage is to solve for the transposed problem A^T x = b:
|
||||
@@ -118,16 +118,16 @@ class SolverBase : public EigenBase<Derived>
|
||||
*
|
||||
* \sa adjoint(), solve()
|
||||
*/
|
||||
inline ConstTransposeReturnType transpose() const
|
||||
inline const ConstTransposeReturnType transpose() const
|
||||
{
|
||||
return ConstTransposeReturnType(derived());
|
||||
}
|
||||
|
||||
/** \internal the return type of adjoint() */
|
||||
typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
|
||||
CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, ConstTransposeReturnType>,
|
||||
ConstTransposeReturnType
|
||||
>::type AdjointReturnType;
|
||||
CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const ConstTransposeReturnType>,
|
||||
const ConstTransposeReturnType
|
||||
>::type AdjointReturnType;
|
||||
/** \returns an expression of the adjoint of the factored matrix
|
||||
*
|
||||
* A typical usage is to solve for the adjoint problem A' x = b:
|
||||
@@ -137,7 +137,7 @@ class SolverBase : public EigenBase<Derived>
|
||||
*
|
||||
* \sa transpose(), solve()
|
||||
*/
|
||||
inline AdjointReturnType adjoint() const
|
||||
inline const AdjointReturnType adjoint() const
|
||||
{
|
||||
return AdjointReturnType(derived().transpose());
|
||||
}
|
||||
|
||||
@@ -38,10 +38,14 @@ namespace Eigen {
|
||||
* \include Map_general_stride.cpp
|
||||
* Output: \verbinclude Map_general_stride.out
|
||||
*
|
||||
* Both strides can be negative, however, a negative stride of -1 cannot be specified at compiletime
|
||||
* Both strides can be negative. However, a negative stride of -1 cannot be specified at compile time
|
||||
* because of the ambiguity with Dynamic which is defined to -1 (historically, negative strides were
|
||||
* not allowed).
|
||||
*
|
||||
* Note that for compile-time vectors (ColsAtCompileTime==1 or RowsAtCompile==1),
|
||||
* the inner stride is the pointer increment between two consecutive elements,
|
||||
* regardless of storage layout.
|
||||
*
|
||||
* \sa class InnerStride, class OuterStride, \ref TopicStorageOrders
|
||||
*/
|
||||
template<int _OuterStrideAtCompileTime, int _InnerStrideAtCompileTime>
|
||||
|
||||
@@ -178,7 +178,7 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
|
||||
* \sa transposeInPlace(), adjoint() */
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Transpose<Derived>
|
||||
typename DenseBase<Derived>::TransposeReturnType
|
||||
DenseBase<Derived>::transpose()
|
||||
{
|
||||
return TransposeReturnType(derived());
|
||||
@@ -191,7 +191,7 @@ DenseBase<Derived>::transpose()
|
||||
* \sa transposeInPlace(), adjoint() */
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
typename DenseBase<Derived>::ConstTransposeReturnType
|
||||
const typename DenseBase<Derived>::ConstTransposeReturnType
|
||||
DenseBase<Derived>::transpose() const
|
||||
{
|
||||
return ConstTransposeReturnType(derived());
|
||||
|
||||
@@ -53,7 +53,7 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived>
|
||||
typedef Derived const& Nested;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline TriangularBase() { eigen_assert(!((Mode&UnitDiag) && (Mode&ZeroDiag))); }
|
||||
inline TriangularBase() { eigen_assert(!((int(Mode) & int(UnitDiag)) && (int(Mode) & int(ZeroDiag)))); }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const EIGEN_NOEXCEPT { return derived().rows(); }
|
||||
@@ -100,12 +100,10 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived>
|
||||
return coeffRef(row,col);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
template<typename DenseDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -442,7 +440,6 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_Mat
|
||||
EIGEN_DEVICE_FUNC
|
||||
TriangularViewType& operator=(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
EIGEN_DEVICE_FUNC
|
||||
TriangularViewType& operator=(const TriangularViewImpl& other)
|
||||
{ return *this = other.derived().nestedExpression(); }
|
||||
@@ -456,7 +453,6 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_Mat
|
||||
/** \deprecated */
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC
|
||||
void lazyAssign(const MatrixBase<OtherDerived>& other);
|
||||
#endif
|
||||
|
||||
/** Efficient triangular matrix times vector/matrix product */
|
||||
template<typename OtherDerived>
|
||||
@@ -524,11 +520,7 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_Mat
|
||||
/** Swaps the coefficients of the common triangular parts of two matrices */
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
void swap(TriangularBase<OtherDerived> &other)
|
||||
#else
|
||||
void swap(TriangularBase<OtherDerived> const & other)
|
||||
#endif
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_LVALUE(OtherDerived);
|
||||
call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op<Scalar>());
|
||||
@@ -552,9 +544,10 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_Mat
|
||||
this->solveInPlace(dst);
|
||||
}
|
||||
|
||||
template<typename ProductType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha, bool beta);
|
||||
template <typename ProductType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha,
|
||||
bool beta);
|
||||
|
||||
protected:
|
||||
EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl)
|
||||
EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl)
|
||||
@@ -819,7 +812,7 @@ void call_triangular_assignment_loop(DstXprType& dst, const SrcXprType& src, con
|
||||
enum {
|
||||
unroll = DstXprType::SizeAtCompileTime != Dynamic
|
||||
&& SrcEvaluatorType::CoeffReadCost < HugeCost
|
||||
&& DstXprType::SizeAtCompileTime * (DstEvaluatorType::CoeffReadCost+SrcEvaluatorType::CoeffReadCost) / 2 <= EIGEN_UNROLLING_LIMIT
|
||||
&& DstXprType::SizeAtCompileTime * (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
|
||||
triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, SetOpposite>::run(kernel);
|
||||
@@ -853,7 +846,7 @@ struct Assignment<DstXprType, SrcXprType, Functor, Triangular2Dense>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
|
||||
{
|
||||
call_triangular_assignment_loop<SrcXprType::Mode, (SrcXprType::Mode&SelfAdjoint)==0>(dst, src, func);
|
||||
call_triangular_assignment_loop<SrcXprType::Mode, (int(SrcXprType::Mode) & int(SelfAdjoint)) == 0>(dst, src, func);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -951,7 +944,7 @@ template<typename DenseDerived>
|
||||
EIGEN_DEVICE_FUNC void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const
|
||||
{
|
||||
other.derived().resize(this->rows(), this->cols());
|
||||
internal::call_triangular_assignment_loop<Derived::Mode,(Derived::Mode&SelfAdjoint)==0 /* SetOpposite */>(other.derived(), derived().nestedExpression());
|
||||
internal::call_triangular_assignment_loop<Derived::Mode, (int(Derived::Mode) & int(SelfAdjoint)) == 0 /* SetOpposite */>(other.derived(), derived().nestedExpression());
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -124,7 +124,7 @@ void DenseBase<Derived>::visit(Visitor& visitor) const
|
||||
|
||||
enum {
|
||||
unroll = SizeAtCompileTime != Dynamic
|
||||
&& SizeAtCompileTime * ThisEvaluator::CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost <= EIGEN_UNROLLING_LIMIT
|
||||
&& SizeAtCompileTime * int(ThisEvaluator::CoeffReadCost) + (SizeAtCompileTime-1) * int(internal::functor_traits<Visitor>::Cost) <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
return internal::visitor_impl<Visitor, ThisEvaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(thisEval, visitor);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,9 @@ template<> EIGEN_STRONG_INLINE Packet4cf ploadu<Packet4cf>(const std::complex<fl
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cf pset1<Packet4cf>(const std::complex<float>& from)
|
||||
{
|
||||
return Packet4cf(_mm256_castpd_ps(_mm256_broadcast_sd((const double*)(const void*)&from)));
|
||||
const float re = std::real(from);
|
||||
const float im = std::imag(from);
|
||||
return Packet4cf(_mm256_set_ps(im, re, im, re, im, re, im, re));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cf ploaddup<Packet4cf>(const std::complex<float>* from)
|
||||
@@ -167,48 +169,12 @@ template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet4cf>(const P
|
||||
Packet2cf(_mm256_extractf128_ps(a.v, 1))));
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet4cf, Packet4cf, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet4cf& y, const Packet4cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& a, const Packet4cf& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet4cf, Packet4cf, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet4cf& y, const Packet4cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& a, const Packet4cf& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet4cf, Packet4cf, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet4cf& y, const Packet4cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& a, const Packet4cf& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet4cf,Packet8f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cf pdiv<Packet4cf>(const Packet4cf& a, const Packet4cf& b)
|
||||
{
|
||||
Packet4cf num = pmul(a, pconj(b));
|
||||
__m256 tmp = _mm256_mul_ps(b.v, b.v);
|
||||
__m256 tmp2 = _mm256_shuffle_ps(tmp,tmp,0xB1);
|
||||
__m256 denom = _mm256_add_ps(tmp, tmp2);
|
||||
return Packet4cf(_mm256_div_ps(num.v, denom));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cf pcplxflip<Packet4cf>(const Packet4cf& x)
|
||||
@@ -350,47 +316,11 @@ template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet2cd>(const
|
||||
Packet1cd(_mm256_extractf128_pd(a.v,1))));
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet2cd, Packet2cd, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet2cd& y, const Packet2cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& a, const Packet2cd& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cd, Packet2cd, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet2cd& y, const Packet2cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& a, const Packet2cd& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cd, Packet2cd, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet2cd& y, const Packet2cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& a, const Packet2cd& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cd,Packet4d)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cd pdiv<Packet2cd>(const Packet2cd& a, const Packet2cd& b)
|
||||
{
|
||||
Packet2cd num = pmul(a, pconj(b));
|
||||
__m256d tmp = _mm256_mul_pd(b.v, b.v);
|
||||
__m256d denom = _mm256_hadd_pd(tmp, tmp);
|
||||
return Packet2cd(_mm256_div_pd(num.v, denom));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cd pcplxflip<Packet2cd>(const Packet2cd& x)
|
||||
|
||||
@@ -285,11 +285,13 @@ template<> EIGEN_STRONG_INLINE Packet8i psub<Packet8i>(const Packet8i& a, const
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8f pnegate(const Packet8f& a)
|
||||
{
|
||||
return _mm256_sub_ps(_mm256_set1_ps(0.0),a);
|
||||
const Packet8f mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
|
||||
return _mm256_xor_ps(a, mask);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4d pnegate(const Packet4d& a)
|
||||
{
|
||||
return _mm256_sub_pd(_mm256_set1_pd(0.0),a);
|
||||
const Packet4d mask = _mm256_castsi256_pd(_mm256_set1_epi64x(0x8000000000000000ULL));
|
||||
return _mm256_xor_pd(a, mask);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8f pconj(const Packet8f& a) { return a; }
|
||||
@@ -628,11 +630,23 @@ template<> EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const Packet4d&
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet8i& from) { EIGEN_DEBUG_UNALIGNED_STORE _mm256_storeu_si256(reinterpret_cast<__m256i*>(to), from); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet8f& from, uint8_t umask) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX512
|
||||
__mmask16 mask = static_cast<__mmask16>(umask & 0x00FF);
|
||||
EIGEN_DEBUG_UNALIGNED_STORE _mm512_mask_storeu_ps(to, mask, _mm512_castps256_ps512(from));
|
||||
#else
|
||||
Packet8i mask = _mm256_set1_epi8(static_cast<char>(umask));
|
||||
const Packet8i bit_mask = _mm256_set_epi32(0xffffff7f, 0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7, 0xfffffffb, 0xfffffffd, 0xfffffffe);
|
||||
const Packet8i bit_mask = _mm256_set_epi32(0x7f7f7f7f, 0xbfbfbfbf, 0xdfdfdfdf, 0xefefefef, 0xf7f7f7f7, 0xfbfbfbfb, 0xfdfdfdfd, 0xfefefefe);
|
||||
mask = por<Packet8i>(mask, bit_mask);
|
||||
mask = pcmp_eq<Packet8i>(mask, _mm256_set1_epi32(0xffffffff));
|
||||
EIGEN_DEBUG_UNALIGNED_STORE return _mm256_maskstore_ps(to, mask, from);
|
||||
#if EIGEN_COMP_MSVC
|
||||
// MSVC sometimes seems to use a bogus mask with maskstore.
|
||||
const __m256i ifrom = _mm256_castps_si256(from);
|
||||
EIGEN_DEBUG_UNALIGNED_STORE _mm_maskmoveu_si128(_mm256_extractf128_si256(ifrom, 0), _mm256_extractf128_si256(mask, 0), reinterpret_cast<char*>(to));
|
||||
EIGEN_DEBUG_UNALIGNED_STORE _mm_maskmoveu_si128(_mm256_extractf128_si256(ifrom, 1), _mm256_extractf128_si256(mask, 1), reinterpret_cast<char*>(to + 4));
|
||||
#else
|
||||
EIGEN_DEBUG_UNALIGNED_STORE _mm256_maskstore_ps(to, mask, from);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: leverage _mm256_i32gather_ps and _mm256_i32gather_pd if AVX2 instructions are available
|
||||
@@ -1006,7 +1020,7 @@ EIGEN_STRONG_INLINE Packet8f half2float(const Packet8h& a) {
|
||||
|
||||
EIGEN_STRONG_INLINE Packet8h float2half(const Packet8f& a) {
|
||||
#ifdef EIGEN_HAS_FP16_C
|
||||
return _mm256_cvtps_ph(a, _MM_FROUND_TO_NEAREST_INT|_MM_FROUND_NO_EXC);
|
||||
return _mm256_cvtps_ph(a, _MM_FROUND_TO_NEAREST_INT);
|
||||
#else
|
||||
EIGEN_ALIGN32 float aux[8];
|
||||
pstore(aux, a);
|
||||
@@ -1274,12 +1288,7 @@ EIGEN_STRONG_INLINE Packet8f Bf16ToF32(const Packet8bf& a) {
|
||||
EIGEN_STRONG_INLINE Packet8bf F32ToBf16(const Packet8f& a) {
|
||||
Packet8bf r;
|
||||
|
||||
// Flush input denormals value to zero with hardware capability.
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
__m256 flush = _mm256_and_ps(a, a);
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_OFF);
|
||||
|
||||
__m256i input = _mm256_castps_si256(flush);
|
||||
__m256i input = _mm256_castps_si256(a);
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_AVX2
|
||||
// uint32_t lsb = (input >> 16);
|
||||
@@ -1293,7 +1302,7 @@ EIGEN_STRONG_INLINE Packet8bf F32ToBf16(const Packet8f& a) {
|
||||
// input = input >> 16;
|
||||
t = _mm256_srli_epi32(t, 16);
|
||||
// Check NaN before converting back to bf16
|
||||
__m256 mask = _mm256_cmp_ps(flush, flush, _CMP_ORD_Q);
|
||||
__m256 mask = _mm256_cmp_ps(a, a, _CMP_ORD_Q);
|
||||
__m256i nan = _mm256_set1_epi32(0x7fc0);
|
||||
t = _mm256_blendv_epi8(nan, t, _mm256_castps_si256(mask));
|
||||
// output = numext::bit_cast<uint16_t>(input);
|
||||
@@ -1316,7 +1325,7 @@ EIGEN_STRONG_INLINE Packet8bf F32ToBf16(const Packet8f& a) {
|
||||
lo = _mm_srli_epi32(lo, 16);
|
||||
hi = _mm_srli_epi32(hi, 16);
|
||||
// Check NaN before converting back to bf16
|
||||
__m256 mask = _mm256_cmp_ps(flush, flush, _CMP_ORD_Q);
|
||||
__m256 mask = _mm256_cmp_ps(a, a, _CMP_ORD_Q);
|
||||
__m128i nan = _mm_set1_epi32(0x7fc0);
|
||||
lo = _mm_blendv_epi8(nan, lo, _mm_castps_si128(_mm256_castps256_ps128(mask)));
|
||||
hi = _mm_blendv_epi8(nan, hi, _mm_castps_si128(_mm256_extractf128_ps(mask, 1)));
|
||||
|
||||
@@ -37,7 +37,7 @@ template<> struct packet_traits<std::complex<float> > : default_packet_traits
|
||||
HasMul = 1,
|
||||
HasDiv = 1,
|
||||
HasNegate = 1,
|
||||
HasSqrt = 1,
|
||||
HasSqrt = EIGEN_HAS_AVX512_MATH,
|
||||
HasAbs = 0,
|
||||
HasAbs2 = 0,
|
||||
HasMin = 0,
|
||||
@@ -97,7 +97,9 @@ template<> EIGEN_STRONG_INLINE Packet8cf ploadu<Packet8cf>(const std::complex<fl
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8cf pset1<Packet8cf>(const std::complex<float>& from)
|
||||
{
|
||||
return Packet8cf(_mm512_castpd_ps(pload1<Packet8d>((const double*)(const void*)&from)));
|
||||
const float re = std::real(from);
|
||||
const float im = std::imag(from);
|
||||
return Packet8cf(_mm512_set_ps(im, re, im, re, im, re, im, re, im, re, im, re, im, re, im, re));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8cf ploaddup<Packet8cf>(const std::complex<float>* from)
|
||||
@@ -153,48 +155,11 @@ EIGEN_STRONG_INLINE Packet4cf predux_half_dowto4<Packet8cf>(const Packet8cf& a)
|
||||
return Packet4cf(res);
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet8cf, Packet8cf, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet8cf pmadd(const Packet8cf& x, const Packet8cf& y, const Packet8cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet8cf pmul(const Packet8cf& a, const Packet8cf& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet8cf, Packet8cf, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet8cf pmadd(const Packet8cf& x, const Packet8cf& y, const Packet8cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet8cf pmul(const Packet8cf& a, const Packet8cf& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet8cf, Packet8cf, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet8cf pmadd(const Packet8cf& x, const Packet8cf& y, const Packet8cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet8cf pmul(const Packet8cf& a, const Packet8cf& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet8cf,Packet16f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8cf pdiv<Packet8cf>(const Packet8cf& a, const Packet8cf& b)
|
||||
{
|
||||
Packet8cf num = pmul(a, pconj(b));
|
||||
__m512 tmp = _mm512_mul_ps(b.v, b.v);
|
||||
__m512 tmp2 = _mm512_shuffle_ps(tmp,tmp,0xB1);
|
||||
__m512 denom = _mm512_add_ps(tmp, tmp2);
|
||||
return Packet8cf(_mm512_div_ps(num.v, denom));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8cf pcplxflip<Packet8cf>(const Packet8cf& x)
|
||||
@@ -225,7 +190,7 @@ template<> struct packet_traits<std::complex<double> > : default_packet_traits
|
||||
HasMul = 1,
|
||||
HasDiv = 1,
|
||||
HasNegate = 1,
|
||||
HasSqrt = 1,
|
||||
HasSqrt = EIGEN_HAS_AVX512_MATH,
|
||||
HasAbs = 0,
|
||||
HasAbs2 = 0,
|
||||
HasMin = 0,
|
||||
@@ -286,11 +251,7 @@ template<> EIGEN_STRONG_INLINE Packet4cd ploadu<Packet4cd>(const std::complex<do
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cd pset1<Packet4cd>(const std::complex<double>& from)
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
return Packet4cd(_mm512_broadcast_f64x2(pset1<Packet1cd>(from).v));
|
||||
#else
|
||||
return Packet4cd(_mm512_castps_pd(_mm512_broadcast_f32x4( _mm_castpd_ps(pset1<Packet1cd>(from).v))));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cd ploaddup<Packet4cd>(const std::complex<double>* from) {
|
||||
@@ -342,47 +303,11 @@ template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet4cd>(const
|
||||
Packet2cd(_mm512_extractf64x4_pd(a.v,1))));
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet4cd, Packet4cd, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet4cd pmadd(const Packet4cd& x, const Packet4cd& y, const Packet4cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet4cd pmul(const Packet4cd& a, const Packet4cd& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet4cd, Packet4cd, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet4cd pmadd(const Packet4cd& x, const Packet4cd& y, const Packet4cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet4cd pmul(const Packet4cd& a, const Packet4cd& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet4cd, Packet4cd, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet4cd pmadd(const Packet4cd& x, const Packet4cd& y, const Packet4cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet4cd pmul(const Packet4cd& a, const Packet4cd& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet4cd,Packet8d)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cd pdiv<Packet4cd>(const Packet4cd& a, const Packet4cd& b)
|
||||
{
|
||||
Packet4cd num = pmul(a, pconj(b));
|
||||
__m512d tmp = _mm512_mul_pd(b.v, b.v);
|
||||
__m512d denom = padd(_mm512_permute_pd(tmp,0x55), tmp);
|
||||
return Packet4cd(_mm512_div_pd(num.v, denom));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cd pcplxflip<Packet4cd>(const Packet4cd& x)
|
||||
@@ -441,6 +366,8 @@ ptranspose(PacketBlock<Packet4cd,4>& kernel) {
|
||||
kernel.packet[0] = Packet4cd(_mm512_shuffle_f64x2(T0, T2, (shuffle_mask<0,2,0,2>::mask))); // [a0 b0 c0 d0]
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_AVX512_MATH
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4cd psqrt<Packet4cd>(const Packet4cd& a) {
|
||||
return psqrt_complex<Packet4cd>(a);
|
||||
}
|
||||
@@ -449,6 +376,8 @@ template<> EIGEN_STRONG_INLINE Packet8cf psqrt<Packet8cf>(const Packet8cf& a) {
|
||||
return psqrt_complex<Packet8cf>(a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Disable the code for older versions of gcc that don't support many of the required avx512 instrinsics.
|
||||
#if EIGEN_GNUC_AT_LEAST(5, 3) || EIGEN_COMP_CLANG || EIGEN_COMP_MSVC >= 1923
|
||||
#if EIGEN_HAS_AVX512_MATH
|
||||
|
||||
#define _EIGEN_DECLARE_CONST_Packet16f(NAME, X) \
|
||||
const Packet16f p16f_##NAME = pset1<Packet16f>(X)
|
||||
@@ -119,74 +118,11 @@ pexp<Packet16f>(const Packet16f& _x) {
|
||||
return pmax(pmul(y, _mm512_castsi512_ps(emm0)), _x);
|
||||
}
|
||||
|
||||
/*template <>
|
||||
template <>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8d
|
||||
pexp<Packet8d>(const Packet8d& _x) {
|
||||
Packet8d x = _x;
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(1, 1.0);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(2, 2.0);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(exp_hi, 709.437);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(exp_lo, -709.436139303);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_LOG2EF, 1.4426950408889634073599);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_p0, 1.26177193074810590878e-4);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_p1, 3.02994407707441961300e-2);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_p2, 9.99999999999999999910e-1);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q0, 3.00198505138664455042e-6);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q1, 2.52448340349684104192e-3);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q2, 2.27265548208155028766e-1);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_q3, 2.00000000000000000009e0);
|
||||
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_C1, 0.693145751953125);
|
||||
_EIGEN_DECLARE_CONST_Packet8d(cephes_exp_C2, 1.42860682030941723212e-6);
|
||||
|
||||
// clamp x
|
||||
x = pmax(pmin(x, p8d_exp_hi), p8d_exp_lo);
|
||||
|
||||
// Express exp(x) as exp(g + n*log(2)).
|
||||
const Packet8d n =
|
||||
_mm512_mul_round_pd(p8d_cephes_LOG2EF, x, _MM_FROUND_TO_NEAREST_INT);
|
||||
|
||||
// Get the remainder modulo log(2), i.e. the "g" described above. Subtract
|
||||
// n*log(2) out in two steps, i.e. n*C1 + n*C2, C1+C2=log2 to get the last
|
||||
// digits right.
|
||||
const Packet8d nC1 = pmul(n, p8d_cephes_exp_C1);
|
||||
const Packet8d nC2 = pmul(n, p8d_cephes_exp_C2);
|
||||
x = psub(x, nC1);
|
||||
x = psub(x, nC2);
|
||||
|
||||
const Packet8d x2 = pmul(x, x);
|
||||
|
||||
// Evaluate the numerator polynomial of the rational interpolant.
|
||||
Packet8d px = p8d_cephes_exp_p0;
|
||||
px = pmadd(px, x2, p8d_cephes_exp_p1);
|
||||
px = pmadd(px, x2, p8d_cephes_exp_p2);
|
||||
px = pmul(px, x);
|
||||
|
||||
// Evaluate the denominator polynomial of the rational interpolant.
|
||||
Packet8d qx = p8d_cephes_exp_q0;
|
||||
qx = pmadd(qx, x2, p8d_cephes_exp_q1);
|
||||
qx = pmadd(qx, x2, p8d_cephes_exp_q2);
|
||||
qx = pmadd(qx, x2, p8d_cephes_exp_q3);
|
||||
|
||||
// I don't really get this bit, copied from the SSE2 routines, so...
|
||||
// TODO(gonnet): Figure out what is going on here, perhaps find a better
|
||||
// rational interpolant?
|
||||
x = _mm512_div_pd(px, psub(qx, px));
|
||||
x = pmadd(p8d_2, x, p8d_1);
|
||||
|
||||
// Build e=2^n.
|
||||
const Packet8d e = _mm512_castsi512_pd(_mm512_slli_epi64(
|
||||
_mm512_add_epi64(_mm512_cvtpd_epi64(n), _mm512_set1_epi64(1023)), 52));
|
||||
|
||||
// Construct the result 2^n * exp(g) = e * x. The max is used to catch
|
||||
// non-finite values in the input.
|
||||
return pmax(pmul(x, e), _x);
|
||||
}*/
|
||||
return pexp_double(_x);
|
||||
}
|
||||
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, pexp)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, pexp)
|
||||
@@ -389,7 +325,7 @@ Packet16f pexpm1<Packet16f>(const Packet16f& _x) {
|
||||
F16_PACKET_FUNCTION(Packet16f, Packet16h, pexpm1)
|
||||
BF16_PACKET_FUNCTION(Packet16f, Packet16bf, pexpm1)
|
||||
|
||||
#endif
|
||||
#endif // EIGEN_HAS_AVX512_MATH
|
||||
|
||||
|
||||
template <>
|
||||
|
||||
@@ -28,6 +28,13 @@ namespace internal {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Disable the code for older versions of gcc that don't support many of the required avx512 math instrinsics.
|
||||
#if EIGEN_GNUC_AT_LEAST(5, 3) || EIGEN_COMP_CLANG || EIGEN_COMP_MSVC >= 1923 || EIGEN_COMP_ICC >= 1900
|
||||
#define EIGEN_HAS_AVX512_MATH 1
|
||||
#else
|
||||
#define EIGEN_HAS_AVX512_MATH 0
|
||||
#endif
|
||||
|
||||
typedef __m512 Packet16f;
|
||||
typedef __m512i Packet16i;
|
||||
typedef __m512d Packet8d;
|
||||
@@ -72,12 +79,14 @@ struct packet_traits<half> : default_packet_traits {
|
||||
HasMax = 1,
|
||||
HasConj = 1,
|
||||
HasSetLinear = 0,
|
||||
HasLog = 1,
|
||||
HasLog1p = 1,
|
||||
HasExpm1 = 1,
|
||||
HasExp = 1,
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
HasLog = EIGEN_HAS_AVX512_MATH,
|
||||
HasLog1p = EIGEN_HAS_AVX512_MATH,
|
||||
HasExp = EIGEN_HAS_AVX512_MATH,
|
||||
HasExpm1 = EIGEN_HAS_AVX512_MATH,
|
||||
HasSqrt = EIGEN_HAS_AVX512_MATH,
|
||||
HasRsqrt = EIGEN_HAS_AVX512_MATH,
|
||||
HasBessel = EIGEN_HAS_AVX512_MATH,
|
||||
HasNdtri = EIGEN_HAS_AVX512_MATH,
|
||||
HasSin = EIGEN_FAST_MATH,
|
||||
HasCos = EIGEN_FAST_MATH,
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
@@ -86,9 +95,7 @@ struct packet_traits<half> : default_packet_traits {
|
||||
HasRound = 1,
|
||||
HasFloor = 1,
|
||||
HasCeil = 1,
|
||||
HasRint = 1,
|
||||
HasBessel = 1,
|
||||
HasNdtri = 1
|
||||
HasRint = 1
|
||||
};
|
||||
};
|
||||
|
||||
@@ -109,7 +116,7 @@ template<> struct packet_traits<float> : default_packet_traits
|
||||
HasBlend = 0,
|
||||
HasSin = EIGEN_FAST_MATH,
|
||||
HasCos = EIGEN_FAST_MATH,
|
||||
#if EIGEN_GNUC_AT_LEAST(5, 3) || (!EIGEN_COMP_GNUC_STRICT)
|
||||
#if EIGEN_HAS_AVX512_MATH
|
||||
HasLog = 1,
|
||||
HasLog1p = 1,
|
||||
HasExpm1 = 1,
|
||||
@@ -138,8 +145,9 @@ template<> struct packet_traits<double> : default_packet_traits
|
||||
AlignedOnScalar = 1,
|
||||
size = 8,
|
||||
HasHalfPacket = 1,
|
||||
#if EIGEN_GNUC_AT_LEAST(5, 3) || (!EIGEN_COMP_GNUC_STRICT)
|
||||
#if EIGEN_HAS_AVX512_MATH
|
||||
HasLog = 1,
|
||||
HasExp = 1,
|
||||
HasSqrt = EIGEN_FAST_MATH,
|
||||
HasRsqrt = EIGEN_FAST_MATH,
|
||||
#endif
|
||||
@@ -288,11 +296,20 @@ EIGEN_STRONG_INLINE Packet16i psub<Packet16i>(const Packet16i& a,
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f pnegate(const Packet16f& a) {
|
||||
return _mm512_sub_ps(_mm512_set1_ps(0.0), a);
|
||||
// NOTE: MSVC seems to struggle with _mm512_set1_epi32, leading to random results.
|
||||
// The intel docs give it a relatively high latency as well, so we're probably
|
||||
// better off with using _mm512_set_epi32 directly anyways.
|
||||
const __m512i mask = _mm512_set_epi32(0x80000000,0x80000000,0x80000000,0x80000000,
|
||||
0x80000000,0x80000000,0x80000000,0x80000000,
|
||||
0x80000000,0x80000000,0x80000000,0x80000000,
|
||||
0x80000000,0x80000000,0x80000000,0x80000000);
|
||||
return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a), mask));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8d pnegate(const Packet8d& a) {
|
||||
return _mm512_sub_pd(_mm512_set1_pd(0.0), a);
|
||||
const __m512i mask = _mm512_set_epi64(0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL,
|
||||
0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL, 0x8000000000000000ULL);
|
||||
return _mm512_castsi512_pd(_mm512_xor_epi64(_mm512_castpd_si512(a), mask));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -486,7 +503,7 @@ template<> EIGEN_STRONG_INLINE Packet16f pcmp_lt(const Packet16f& a, const Packe
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16f pcmp_lt_or_nan(const Packet16f& a, const Packet16f& b) {
|
||||
__mmask16 mask = _mm512_cmp_ps_mask(a, b, _CMP_NGT_UQ);
|
||||
__mmask16 mask = _mm512_cmp_ps_mask(a, b, _CMP_NGE_UQ);
|
||||
return _mm512_castsi512_ps(
|
||||
_mm512_mask_set1_epi32(_mm512_set1_epi32(0), mask, 0xffffffffu));
|
||||
}
|
||||
@@ -517,7 +534,7 @@ EIGEN_STRONG_INLINE Packet8d pcmp_lt(const Packet8d& a, const Packet8d& b) {
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8d pcmp_lt_or_nan(const Packet8d& a, const Packet8d& b) {
|
||||
__mmask8 mask = _mm512_cmp_pd_mask(a, b, _CMP_NGT_UQ);
|
||||
__mmask8 mask = _mm512_cmp_pd_mask(a, b, _CMP_NGE_UQ);
|
||||
return _mm512_castsi512_pd(
|
||||
_mm512_mask_set1_epi64(_mm512_set1_epi64(0), mask, 0xffffffffffffffffu));
|
||||
}
|
||||
@@ -685,7 +702,7 @@ EIGEN_STRONG_INLINE Packet8d pload<Packet8d>(const double* from) {
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16i pload<Packet16i>(const int* from) {
|
||||
EIGEN_DEBUG_ALIGNED_LOAD return _mm512_load_si512(
|
||||
reinterpret_cast<const __m512i*>(from));
|
||||
reinterpret_cast<const __m512i*>(from));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -929,7 +946,8 @@ template<> EIGEN_STRONG_INLINE Packet8d pldexp<Packet8d>(const Packet8d& a, cons
|
||||
Packet8i b = parithmetic_shift_right<2>(e); // floor(e/4)
|
||||
|
||||
// 2^b
|
||||
Packet8i hi = _mm256_shuffle_epi32(padd(b, bias), _MM_SHUFFLE(3, 1, 2, 0));
|
||||
const Packet8i permute_idx = _mm256_setr_epi32(0, 4, 1, 5, 2, 6, 3, 7);
|
||||
Packet8i hi = _mm256_permutevar8x32_epi32(padd(b, bias), permute_idx);
|
||||
Packet8i lo = _mm256_slli_epi64(hi, 52);
|
||||
hi = _mm256_slli_epi64(_mm256_srli_epi64(hi, 32), 52);
|
||||
Packet8d c = _mm512_castsi512_pd(_mm512_inserti64x4(_mm512_castsi256_si512(lo), hi, 1));
|
||||
@@ -937,7 +955,7 @@ template<> EIGEN_STRONG_INLINE Packet8d pldexp<Packet8d>(const Packet8d& a, cons
|
||||
|
||||
// 2^(e - 3b)
|
||||
b = psub(psub(psub(e, b), b), b); // e - 3b
|
||||
hi = _mm256_shuffle_epi32(padd(b, bias), _MM_SHUFFLE(3, 1, 2, 0));
|
||||
hi = _mm256_permutevar8x32_epi32(padd(b, bias), permute_idx);
|
||||
lo = _mm256_slli_epi64(hi, 52);
|
||||
hi = _mm256_slli_epi64(_mm256_srli_epi64(hi, 32), 52);
|
||||
c = _mm512_castsi512_pd(_mm512_inserti64x4(_mm512_castsi256_si512(lo), hi, 1));
|
||||
@@ -1424,60 +1442,11 @@ ploadquad(const Eigen::half* from) {
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet16f half2float(const Packet16h& a) {
|
||||
#ifdef EIGEN_HAS_FP16_C
|
||||
return _mm512_cvtph_ps(a);
|
||||
#else
|
||||
EIGEN_ALIGN64 half aux[16];
|
||||
pstore(aux, a);
|
||||
float f0(aux[0]);
|
||||
float f1(aux[1]);
|
||||
float f2(aux[2]);
|
||||
float f3(aux[3]);
|
||||
float f4(aux[4]);
|
||||
float f5(aux[5]);
|
||||
float f6(aux[6]);
|
||||
float f7(aux[7]);
|
||||
float f8(aux[8]);
|
||||
float f9(aux[9]);
|
||||
float fa(aux[10]);
|
||||
float fb(aux[11]);
|
||||
float fc(aux[12]);
|
||||
float fd(aux[13]);
|
||||
float fe(aux[14]);
|
||||
float ff(aux[15]);
|
||||
|
||||
return _mm512_set_ps(
|
||||
ff, fe, fd, fc, fb, fa, f9, f8, f7, f6, f5, f4, f3, f2, f1, f0);
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet16h float2half(const Packet16f& a) {
|
||||
#ifdef EIGEN_HAS_FP16_C
|
||||
return _mm512_cvtps_ph(a, _MM_FROUND_TO_NEAREST_INT|_MM_FROUND_NO_EXC);
|
||||
#else
|
||||
EIGEN_ALIGN64 float aux[16];
|
||||
pstore(aux, a);
|
||||
half h0(aux[0]);
|
||||
half h1(aux[1]);
|
||||
half h2(aux[2]);
|
||||
half h3(aux[3]);
|
||||
half h4(aux[4]);
|
||||
half h5(aux[5]);
|
||||
half h6(aux[6]);
|
||||
half h7(aux[7]);
|
||||
half h8(aux[8]);
|
||||
half h9(aux[9]);
|
||||
half ha(aux[10]);
|
||||
half hb(aux[11]);
|
||||
half hc(aux[12]);
|
||||
half hd(aux[13]);
|
||||
half he(aux[14]);
|
||||
half hf(aux[15]);
|
||||
|
||||
return _mm256_set_epi16(
|
||||
hf.x, he.x, hd.x, hc.x, hb.x, ha.x, h9.x, h8.x,
|
||||
h7.x, h6.x, h5.x, h4.x, h3.x, h2.x, h1.x, h0.x);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet16h ptrue(const Packet16h& a) {
|
||||
@@ -1850,7 +1819,7 @@ struct packet_traits<bfloat16> : default_packet_traits {
|
||||
HasInsert = 1,
|
||||
HasSin = EIGEN_FAST_MATH,
|
||||
HasCos = EIGEN_FAST_MATH,
|
||||
#if EIGEN_GNUC_AT_LEAST(5, 3) || (!EIGEN_COMP_GNUC_STRICT)
|
||||
#if EIGEN_HAS_AVX512_MATH
|
||||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
HasLog = 1, // Currently fails test with bad accuracy.
|
||||
HasLog1p = 1,
|
||||
@@ -1943,23 +1912,15 @@ EIGEN_STRONG_INLINE Packet16f Bf16ToF32(const Packet16bf& a) {
|
||||
EIGEN_STRONG_INLINE Packet16bf F32ToBf16(const Packet16f& a) {
|
||||
Packet16bf r;
|
||||
|
||||
// Flush input denormals value to zero with hardware capability.
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
#if defined(EIGEN_VECTORIZE_AVX512DQ)
|
||||
__m512 flush = _mm512_and_ps(a, a);
|
||||
#else
|
||||
__m512 flush = _mm512_max_ps(a, a);
|
||||
#endif // EIGEN_VECTORIZE_AVX512DQ
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_OFF);
|
||||
|
||||
#if defined(EIGEN_VECTORIZE_AVX512BF16) && EIGEN_GNUC_AT_LEAST(10, 1)
|
||||
// Since GCC 10.1 supports avx512bf16 and C style explicit cast
|
||||
// (C++ static_cast is not supported yet), do converion via intrinsic
|
||||
// and register path for performance.
|
||||
r = (__m256i)(_mm512_cvtneps_pbh(flush));
|
||||
r = (__m256i)(_mm512_cvtneps_pbh(a));
|
||||
|
||||
#else
|
||||
__m512i t;
|
||||
__m512i input = _mm512_castps_si512(flush);
|
||||
__m512i input = _mm512_castps_si512(a);
|
||||
__m512i nan = _mm512_set1_epi32(0x7fc0);
|
||||
|
||||
// uint32_t lsb = (input >> 16) & 1;
|
||||
@@ -1972,9 +1933,9 @@ EIGEN_STRONG_INLINE Packet16bf F32ToBf16(const Packet16f& a) {
|
||||
t = _mm512_srli_epi32(t, 16);
|
||||
|
||||
// Check NaN before converting back to bf16
|
||||
__mmask16 mask = _mm512_cmp_ps_mask(flush, flush, _CMP_ORD_Q);
|
||||
t = _mm512_mask_blend_epi32(mask, nan, t);
|
||||
__mmask16 mask = _mm512_cmp_ps_mask(a, a, _CMP_ORD_Q);
|
||||
|
||||
t = _mm512_mask_blend_epi32(mask, nan, t);
|
||||
// output.value = static_cast<uint16_t>(input);
|
||||
r = _mm512_cvtepi32_epi16(t);
|
||||
#endif // EIGEN_VECTORIZE_AVX512BF16
|
||||
|
||||
@@ -15,8 +15,10 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
static Packet4ui p4ui_CONJ_XOR = vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO);//{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
|
||||
#ifdef __VSX__
|
||||
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 };
|
||||
@@ -44,7 +46,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);
|
||||
|
||||
@@ -74,7 +76,7 @@ struct Packet2cf
|
||||
return Packet2cf(*this) -= b;
|
||||
}
|
||||
EIGEN_STRONG_INLINE Packet2cf operator-(void) const {
|
||||
return Packet2cf(vec_neg(v));
|
||||
return Packet2cf(-v);
|
||||
}
|
||||
|
||||
Packet4f v;
|
||||
@@ -100,7 +102,8 @@ template<> struct packet_traits<std::complex<float> > : default_packet_traits
|
||||
HasAbs2 = 0,
|
||||
HasMin = 0,
|
||||
HasMax = 0,
|
||||
#ifdef __VSX__
|
||||
HasSqrt = 1,
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
HasBlend = 1,
|
||||
#endif
|
||||
HasSetLinear = 0
|
||||
@@ -127,20 +130,20 @@ template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<
|
||||
template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { pstore((float*)to, from.v); }
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { pstoreu((float*)to, from.v); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pload2(const std::complex<float>* from0, const std::complex<float>* from1)
|
||||
EIGEN_STRONG_INLINE Packet2cf pload2(const std::complex<float>& from0, const std::complex<float>& from1)
|
||||
{
|
||||
Packet4f res0, res1;
|
||||
#ifdef __VSX__
|
||||
__asm__ ("lxsdx %x0,%y1" : "=wa" (res0) : "Z" (*from0));
|
||||
__asm__ ("lxsdx %x0,%y1" : "=wa" (res1) : "Z" (*from1));
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
__asm__ ("lxsdx %x0,%y1" : "=wa" (res0) : "Z" (from0));
|
||||
__asm__ ("lxsdx %x0,%y1" : "=wa" (res1) : "Z" (from1));
|
||||
#ifdef _BIG_ENDIAN
|
||||
__asm__ ("xxpermdi %x0, %x1, %x2, 0" : "=wa" (res0) : "wa" (res0), "wa" (res1));
|
||||
#else
|
||||
__asm__ ("xxpermdi %x0, %x2, %x1, 0" : "=wa" (res0) : "wa" (res0), "wa" (res1));
|
||||
#endif
|
||||
#else
|
||||
*reinterpret_cast<std::complex<float> *>(&res0) = *from0;
|
||||
*reinterpret_cast<std::complex<float> *>(&res1) = *from1;
|
||||
*reinterpret_cast<std::complex<float> *>(&res0) = from0;
|
||||
*reinterpret_cast<std::complex<float> *>(&res1) = from1;
|
||||
res0 = vec_perm(res0, res1, p16uc_TRANSPOSE64_HI);
|
||||
#endif
|
||||
return Packet2cf(res0);
|
||||
@@ -164,7 +167,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(a.v + b.v); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(a.v - b.v); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { return Packet2cf(pnegate(a.v)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) { return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR))); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) { return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR()))); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pand <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(pand<Packet4f>(a.v, b.v)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf por <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(por<Packet4f>(a.v, b.v)); }
|
||||
@@ -206,47 +209,11 @@ template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const P
|
||||
return pfirst<Packet2cf>(prod);
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
// TODO optimize it for AltiVec
|
||||
Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a, b);
|
||||
Packet4f s = pmul<Packet4f>(b.v, b.v);
|
||||
return Packet2cf(pdiv(res.v, padd<Packet4f>(s, vec_perm(s, s, p16uc_COMPLEX32_REV))));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x)
|
||||
@@ -266,21 +233,21 @@ template<> EIGEN_STRONG_INLINE Packet2cf pcmp_eq(const Packet2cf& a, const Packe
|
||||
return Packet2cf(vec_and(eq, vec_perm(eq, eq, p16uc_COMPLEX32_REV)));
|
||||
}
|
||||
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, const Packet2cf& thenPacket, const Packet2cf& elsePacket) {
|
||||
Packet2cf result;
|
||||
result.v = reinterpret_cast<Packet4f>(pblend<Packet2d>(ifPacket, reinterpret_cast<Packet2d>(thenPacket.v), reinterpret_cast<Packet2d>(elsePacket.v)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf psqrt<Packet2cf>(const Packet2cf& a)
|
||||
{
|
||||
return psqrt_complex<Packet2cf>(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------- double ----------
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
struct Packet1cd
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd() {}
|
||||
@@ -327,7 +294,7 @@ struct Packet1cd
|
||||
return Packet1cd(*this) -= b;
|
||||
}
|
||||
EIGEN_STRONG_INLINE Packet1cd operator-(void) const {
|
||||
return Packet1cd(vec_neg(v));
|
||||
return Packet1cd(-v);
|
||||
}
|
||||
|
||||
Packet2d v;
|
||||
@@ -353,6 +320,7 @@ template<> struct packet_traits<std::complex<double> > : default_packet_traits
|
||||
HasAbs2 = 0,
|
||||
HasMin = 0,
|
||||
HasMax = 0,
|
||||
HasSqrt = 1,
|
||||
HasSetLinear = 0
|
||||
};
|
||||
};
|
||||
@@ -404,47 +372,11 @@ template<> EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Pack
|
||||
|
||||
template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) { return pfirst(a); }
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
|
||||
{
|
||||
// TODO optimize it for AltiVec
|
||||
Packet1cd res = conj_helper<Packet1cd,Packet1cd,false,true>().pmul(a,b);
|
||||
Packet2d s = pmul<Packet2d>(b.v, b.v);
|
||||
return Packet1cd(pdiv(res.v, padd<Packet2d>(s, vec_perm(s, s, p16uc_REVERSE64))));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pcplxflip/*<Packet1cd>*/(const Packet1cd& x)
|
||||
@@ -475,7 +407,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd psqrt<Packet1cd>(const Packet1cd& a)
|
||||
return psqrt_complex<Packet1cd>(a);
|
||||
}
|
||||
|
||||
#endif // __VSX__
|
||||
#endif // EIGEN_VECTORIZE_VSX
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -40,16 +40,14 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
|
||||
return pcos_float(_x);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
#ifndef EIGEN_COMP_CLANG
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
Packet4f prsqrt<Packet4f>(const Packet4f& x)
|
||||
{
|
||||
return vec_rsqrt(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __VSX__
|
||||
#ifndef EIGEN_COMP_CLANG
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
Packet2d prsqrt<Packet2d>(const Packet2d& x)
|
||||
{
|
||||
@@ -57,7 +55,7 @@ Packet2d prsqrt<Packet2d>(const Packet2d& x)
|
||||
}
|
||||
#endif
|
||||
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet4f psqrt<Packet4f>(const Packet4f& x)
|
||||
{
|
||||
return vec_sqrt(x);
|
||||
@@ -69,12 +67,43 @@ Packet2d psqrt<Packet2d>(const Packet2d& x)
|
||||
return vec_sqrt(x);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||
#if !EIGEN_COMP_CLANG
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet4f prsqrt<Packet4f>(const Packet4f& x)
|
||||
{
|
||||
return pset1<Packet4f>(1.0f) / psqrt<Packet4f>(x);
|
||||
// vec_rsqrt returns different results from the generic version
|
||||
// return vec_rsqrt(x);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet2d prsqrt<Packet2d>(const Packet2d& x)
|
||||
{
|
||||
return pset1<Packet2d>(1.0) / psqrt<Packet2d>(x);
|
||||
// vec_rsqrt returns different results from the generic version
|
||||
// return vec_rsqrt(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet2d pexp<Packet2d>(const Packet2d& _x)
|
||||
{
|
||||
return pexp_double(_x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf psqrt<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(vec_sqrt, a);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf prsqrt<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(prsqrt<Packet4f>, a);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf pexp<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(pexp_float, a);
|
||||
}
|
||||
|
||||
#endif // EIGEN_VECTORIZE_VSX
|
||||
|
||||
// Hyperbolic Tangent function.
|
||||
template <>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,22 +9,8 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Scalar, typename Packet, typename DataMapper, typename Index, const Index accRows>
|
||||
EIGEN_STRONG_INLINE void gemm_extra_col(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index row,
|
||||
Index col,
|
||||
Index remaining_rows,
|
||||
Index remaining_cols,
|
||||
const Packet& pAlpha);
|
||||
|
||||
template<typename Scalar, typename Packet, typename DataMapper, typename Index, const Index accRows, const Index accCols>
|
||||
EIGEN_STRONG_INLINE void gemm_extra_row(
|
||||
EIGEN_ALWAYS_INLINE void gemm_extra_row(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
@@ -39,41 +25,28 @@ EIGEN_STRONG_INLINE void gemm_extra_row(
|
||||
const Packet& pAlpha,
|
||||
const Packet& pMask);
|
||||
|
||||
template<typename Scalar, typename Packet, typename DataMapper, typename Index, const Index accCols>
|
||||
EIGEN_STRONG_INLINE void gemm_unrolled_col(
|
||||
template<typename Scalar, typename Packet, typename DataMapper, typename Index, const Index accCols, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
EIGEN_STRONG_INLINE void gemm_extra_cols(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index& row,
|
||||
Index rows,
|
||||
Index col,
|
||||
Index remaining_cols,
|
||||
const Packet& pAlpha);
|
||||
|
||||
template<typename Packet>
|
||||
EIGEN_STRONG_INLINE Packet bmask(const int remaining_rows);
|
||||
|
||||
template<typename Scalar, typename Packet, typename Packetc, typename DataMapper, typename Index, const Index accRows, const Index accCols, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
EIGEN_STRONG_INLINE void gemm_complex_extra_col(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
const Scalar* blockA,
|
||||
const Scalar* blockB,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index strideB,
|
||||
Index row,
|
||||
Index offsetB,
|
||||
Index col,
|
||||
Index rows,
|
||||
Index cols,
|
||||
Index remaining_rows,
|
||||
Index remaining_cols,
|
||||
const Packet& pAlphaReal,
|
||||
const Packet& pAlphaImag);
|
||||
const Packet& pAlpha,
|
||||
const Packet& pMask);
|
||||
|
||||
template<typename Packet>
|
||||
EIGEN_ALWAYS_INLINE Packet bmask(const int remaining_rows);
|
||||
|
||||
template<typename Scalar, typename Packet, typename Packetc, typename DataMapper, typename Index, const Index accRows, const Index accCols, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
EIGEN_STRONG_INLINE void gemm_complex_extra_row(
|
||||
EIGEN_ALWAYS_INLINE void gemm_complex_extra_row(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
@@ -91,130 +64,95 @@ EIGEN_STRONG_INLINE void gemm_complex_extra_row(
|
||||
const Packet& pMask);
|
||||
|
||||
template<typename Scalar, typename Packet, typename Packetc, typename DataMapper, typename Index, const Index accCols, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
EIGEN_STRONG_INLINE void gemm_complex_unrolled_col(
|
||||
EIGEN_STRONG_INLINE void gemm_complex_extra_cols(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
const Scalar* blockA,
|
||||
const Scalar* blockB,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index strideB,
|
||||
Index& row,
|
||||
Index rows,
|
||||
Index offsetB,
|
||||
Index col,
|
||||
Index remaining_cols,
|
||||
Index rows,
|
||||
Index cols,
|
||||
Index remaining_rows,
|
||||
const Packet& pAlphaReal,
|
||||
const Packet& pAlphaImag);
|
||||
const Packet& pAlphaImag,
|
||||
const Packet& pMask);
|
||||
|
||||
template<typename Scalar, typename Packet>
|
||||
EIGEN_STRONG_INLINE Packet ploadLhs(const Scalar* lhs);
|
||||
EIGEN_ALWAYS_INLINE Packet ploadLhs(const Scalar* lhs);
|
||||
|
||||
template<typename DataMapper, typename Packet, typename Index, const Index accCols, int N, int StorageOrder>
|
||||
EIGEN_STRONG_INLINE void bload(PacketBlock<Packet,4>& acc, const DataMapper& res, Index row, Index col);
|
||||
|
||||
template<typename DataMapper, typename Packet, typename Index, const Index accCols, int N, int StorageOrder>
|
||||
EIGEN_STRONG_INLINE void bload(PacketBlock<Packet,8>& acc, const DataMapper& res, Index row, Index col);
|
||||
|
||||
template<typename Packet>
|
||||
EIGEN_STRONG_INLINE void bscale(PacketBlock<Packet,4>& acc, PacketBlock<Packet,4>& accZ, const Packet& pAlpha);
|
||||
template<typename DataMapper, typename Packet, typename Index, const Index accCols, int StorageOrder, bool Complex, int N>
|
||||
EIGEN_ALWAYS_INLINE void bload(PacketBlock<Packet,N>& acc, const DataMapper& res, Index row, Index col);
|
||||
|
||||
template<typename Packet, int N>
|
||||
EIGEN_STRONG_INLINE void bscalec(PacketBlock<Packet,N>& aReal, PacketBlock<Packet,N>& aImag, const Packet& bReal, const Packet& bImag, PacketBlock<Packet,N>& cReal, PacketBlock<Packet,N>& cImag);
|
||||
|
||||
const static Packet16uc p16uc_SETCOMPLEX32_FIRST = { 0, 1, 2, 3,
|
||||
16, 17, 18, 19,
|
||||
4, 5, 6, 7,
|
||||
20, 21, 22, 23};
|
||||
|
||||
const static Packet16uc p16uc_SETCOMPLEX32_SECOND = { 8, 9, 10, 11,
|
||||
24, 25, 26, 27,
|
||||
12, 13, 14, 15,
|
||||
28, 29, 30, 31};
|
||||
//[a,b],[ai,bi] = [a,ai] - This is equivalent to p16uc_GETREAL64
|
||||
const static Packet16uc p16uc_SETCOMPLEX64_FIRST = { 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
16, 17, 18, 19, 20, 21, 22, 23};
|
||||
|
||||
//[a,b],[ai,bi] = [b,bi] - This is equivalent to p16uc_GETIMAG64
|
||||
const static Packet16uc p16uc_SETCOMPLEX64_SECOND = { 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
24, 25, 26, 27, 28, 29, 30, 31};
|
||||
EIGEN_ALWAYS_INLINE void bscale(PacketBlock<Packet,N>& acc, PacketBlock<Packet,N>& accZ, const Packet& pAlpha);
|
||||
|
||||
template<typename Packet, int N>
|
||||
EIGEN_ALWAYS_INLINE void bscalec(PacketBlock<Packet,N>& aReal, PacketBlock<Packet,N>& aImag, const Packet& bReal, const Packet& bImag, PacketBlock<Packet,N>& cReal, PacketBlock<Packet,N>& cImag);
|
||||
|
||||
// Grab two decouples real/imaginary PacketBlocks and return two coupled (real/imaginary pairs) PacketBlocks.
|
||||
template<typename Packet, typename Packetc>
|
||||
EIGEN_STRONG_INLINE void bcouple_common(PacketBlock<Packet,4>& taccReal, PacketBlock<Packet,4>& taccImag, PacketBlock<Packetc, 4>& acc1, PacketBlock<Packetc, 4>& acc2)
|
||||
template<typename Packet, typename Packetc, int N>
|
||||
EIGEN_ALWAYS_INLINE void bcouple_common(PacketBlock<Packet,N>& taccReal, PacketBlock<Packet,N>& taccImag, PacketBlock<Packetc, N>& acc1, PacketBlock<Packetc, N>& acc2)
|
||||
{
|
||||
acc1.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX32_FIRST);
|
||||
acc1.packet[1].v = vec_perm(taccReal.packet[1], taccImag.packet[1], p16uc_SETCOMPLEX32_FIRST);
|
||||
acc1.packet[2].v = vec_perm(taccReal.packet[2], taccImag.packet[2], p16uc_SETCOMPLEX32_FIRST);
|
||||
acc1.packet[3].v = vec_perm(taccReal.packet[3], taccImag.packet[3], p16uc_SETCOMPLEX32_FIRST);
|
||||
acc1.packet[0].v = vec_mergeh(taccReal.packet[0], taccImag.packet[0]);
|
||||
if (N > 1) {
|
||||
acc1.packet[1].v = vec_mergeh(taccReal.packet[1], taccImag.packet[1]);
|
||||
}
|
||||
if (N > 2) {
|
||||
acc1.packet[2].v = vec_mergeh(taccReal.packet[2], taccImag.packet[2]);
|
||||
}
|
||||
if (N > 3) {
|
||||
acc1.packet[3].v = vec_mergeh(taccReal.packet[3], taccImag.packet[3]);
|
||||
}
|
||||
|
||||
acc2.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX32_SECOND);
|
||||
acc2.packet[1].v = vec_perm(taccReal.packet[1], taccImag.packet[1], p16uc_SETCOMPLEX32_SECOND);
|
||||
acc2.packet[2].v = vec_perm(taccReal.packet[2], taccImag.packet[2], p16uc_SETCOMPLEX32_SECOND);
|
||||
acc2.packet[3].v = vec_perm(taccReal.packet[3], taccImag.packet[3], p16uc_SETCOMPLEX32_SECOND);
|
||||
acc2.packet[0].v = vec_mergel(taccReal.packet[0], taccImag.packet[0]);
|
||||
if (N > 1) {
|
||||
acc2.packet[1].v = vec_mergel(taccReal.packet[1], taccImag.packet[1]);
|
||||
}
|
||||
if (N > 2) {
|
||||
acc2.packet[2].v = vec_mergel(taccReal.packet[2], taccImag.packet[2]);
|
||||
}
|
||||
if (N > 3) {
|
||||
acc2.packet[3].v = vec_mergel(taccReal.packet[3], taccImag.packet[3]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Packet, typename Packetc>
|
||||
EIGEN_STRONG_INLINE void bcouple(PacketBlock<Packet,4>& taccReal, PacketBlock<Packet,4>& taccImag, PacketBlock<Packetc,8>& tRes, PacketBlock<Packetc, 4>& acc1, PacketBlock<Packetc, 4>& acc2)
|
||||
template<typename Packet, typename Packetc, int N>
|
||||
EIGEN_ALWAYS_INLINE void bcouple(PacketBlock<Packet,N>& taccReal, PacketBlock<Packet,N>& taccImag, PacketBlock<Packetc,N*2>& tRes, PacketBlock<Packetc, N>& acc1, PacketBlock<Packetc, N>& acc2)
|
||||
{
|
||||
bcouple_common<Packet, Packetc>(taccReal, taccImag, acc1, acc2);
|
||||
bcouple_common<Packet, Packetc, N>(taccReal, taccImag, acc1, acc2);
|
||||
|
||||
acc1.packet[0] = padd<Packetc>(tRes.packet[0], acc1.packet[0]);
|
||||
acc1.packet[1] = padd<Packetc>(tRes.packet[1], acc1.packet[1]);
|
||||
acc1.packet[2] = padd<Packetc>(tRes.packet[2], acc1.packet[2]);
|
||||
acc1.packet[3] = padd<Packetc>(tRes.packet[3], acc1.packet[3]);
|
||||
if (N > 1) {
|
||||
acc1.packet[1] = padd<Packetc>(tRes.packet[1], acc1.packet[1]);
|
||||
}
|
||||
if (N > 2) {
|
||||
acc1.packet[2] = padd<Packetc>(tRes.packet[2], acc1.packet[2]);
|
||||
}
|
||||
if (N > 3) {
|
||||
acc1.packet[3] = padd<Packetc>(tRes.packet[3], acc1.packet[3]);
|
||||
}
|
||||
|
||||
acc2.packet[0] = padd<Packetc>(tRes.packet[4], acc2.packet[0]);
|
||||
acc2.packet[1] = padd<Packetc>(tRes.packet[5], acc2.packet[1]);
|
||||
acc2.packet[2] = padd<Packetc>(tRes.packet[6], acc2.packet[2]);
|
||||
acc2.packet[3] = padd<Packetc>(tRes.packet[7], acc2.packet[3]);
|
||||
}
|
||||
|
||||
template<typename Packet, typename Packetc>
|
||||
EIGEN_STRONG_INLINE void bcouple_common(PacketBlock<Packet,1>& taccReal, PacketBlock<Packet,1>& taccImag, PacketBlock<Packetc, 1>& acc1, PacketBlock<Packetc, 1>& acc2)
|
||||
{
|
||||
acc1.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX32_FIRST);
|
||||
|
||||
acc2.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX32_SECOND);
|
||||
}
|
||||
|
||||
template<typename Packet, typename Packetc>
|
||||
EIGEN_STRONG_INLINE void bcouple(PacketBlock<Packet,1>& taccReal, PacketBlock<Packet,1>& taccImag, PacketBlock<Packetc,2>& tRes, PacketBlock<Packetc, 1>& acc1, PacketBlock<Packetc, 1>& acc2)
|
||||
{
|
||||
bcouple_common<Packet, Packetc>(taccReal, taccImag, acc1, acc2);
|
||||
|
||||
acc1.packet[0] = padd<Packetc>(tRes.packet[0], acc1.packet[0]);
|
||||
|
||||
acc2.packet[0] = padd<Packetc>(tRes.packet[1], acc2.packet[0]);
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE void bcouple_common<Packet2d, Packet1cd>(PacketBlock<Packet2d,4>& taccReal, PacketBlock<Packet2d,4>& taccImag, PacketBlock<Packet1cd, 4>& acc1, PacketBlock<Packet1cd, 4>& acc2)
|
||||
{
|
||||
acc1.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX64_FIRST);
|
||||
acc1.packet[1].v = vec_perm(taccReal.packet[1], taccImag.packet[1], p16uc_SETCOMPLEX64_FIRST);
|
||||
acc1.packet[2].v = vec_perm(taccReal.packet[2], taccImag.packet[2], p16uc_SETCOMPLEX64_FIRST);
|
||||
acc1.packet[3].v = vec_perm(taccReal.packet[3], taccImag.packet[3], p16uc_SETCOMPLEX64_FIRST);
|
||||
|
||||
acc2.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX64_SECOND);
|
||||
acc2.packet[1].v = vec_perm(taccReal.packet[1], taccImag.packet[1], p16uc_SETCOMPLEX64_SECOND);
|
||||
acc2.packet[2].v = vec_perm(taccReal.packet[2], taccImag.packet[2], p16uc_SETCOMPLEX64_SECOND);
|
||||
acc2.packet[3].v = vec_perm(taccReal.packet[3], taccImag.packet[3], p16uc_SETCOMPLEX64_SECOND);
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE void bcouple_common<Packet2d, Packet1cd>(PacketBlock<Packet2d,1>& taccReal, PacketBlock<Packet2d,1>& taccImag, PacketBlock<Packet1cd, 1>& acc1, PacketBlock<Packet1cd, 1>& acc2)
|
||||
{
|
||||
acc1.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX64_FIRST);
|
||||
|
||||
acc2.packet[0].v = vec_perm(taccReal.packet[0], taccImag.packet[0], p16uc_SETCOMPLEX64_SECOND);
|
||||
acc2.packet[0] = padd<Packetc>(tRes.packet[0+N], acc2.packet[0]);
|
||||
if (N > 1) {
|
||||
acc2.packet[1] = padd<Packetc>(tRes.packet[1+N], acc2.packet[1]);
|
||||
}
|
||||
if (N > 2) {
|
||||
acc2.packet[2] = padd<Packetc>(tRes.packet[2+N], acc2.packet[2]);
|
||||
}
|
||||
if (N > 3) {
|
||||
acc2.packet[3] = padd<Packetc>(tRes.packet[3+N], acc2.packet[3]);
|
||||
}
|
||||
}
|
||||
|
||||
// This is necessary because ploadRhs for double returns a pair of vectors when MMA is enabled.
|
||||
template<typename Scalar, typename Packet>
|
||||
EIGEN_STRONG_INLINE Packet ploadRhs(const Scalar* rhs)
|
||||
EIGEN_ALWAYS_INLINE Packet ploadRhs(const Scalar* rhs)
|
||||
{
|
||||
return *reinterpret_cast<Packet *>(const_cast<Scalar *>(rhs));
|
||||
return ploadu<Packet>(rhs);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
@@ -11,7 +11,11 @@
|
||||
#ifndef EIGEN_MATRIX_PRODUCT_MMA_ALTIVEC_H
|
||||
#define EIGEN_MATRIX_PRODUCT_MMA_ALTIVEC_H
|
||||
|
||||
#pragma GCC target("cpu=power10")
|
||||
// If using dynamic dispatch, set the CPU target.
|
||||
#if defined(EIGEN_ALTIVEC_MMA_DYNAMIC_DISPATCH)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target("cpu=power10,htm")
|
||||
#endif
|
||||
|
||||
#ifdef __has_builtin
|
||||
#if !__has_builtin(__builtin_vsx_assemble_pair)
|
||||
@@ -24,48 +28,48 @@ namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
template<typename Scalar, typename Packet>
|
||||
EIGEN_STRONG_INLINE void bsetzeroMMA(__vector_quad* acc)
|
||||
EIGEN_ALWAYS_INLINE void bsetzeroMMA(__vector_quad* acc)
|
||||
{
|
||||
__builtin_mma_xxsetaccz(acc);
|
||||
}
|
||||
|
||||
template<typename DataMapper, typename Index, typename Packet, const Index accCols>
|
||||
EIGEN_STRONG_INLINE void storeAccumulator(Index i, Index j, const DataMapper& data, const Packet& alpha, __vector_quad* acc)
|
||||
EIGEN_ALWAYS_INLINE void storeAccumulator(Index i, const DataMapper& data, const Packet& alpha, __vector_quad* acc)
|
||||
{
|
||||
PacketBlock<Packet, 4> result;
|
||||
__builtin_mma_disassemble_acc(&result.packet, acc);
|
||||
|
||||
PacketBlock<Packet, 4> tRes;
|
||||
bload<DataMapper, Packet, Index, accCols, 0, ColMajor>(tRes, data, i, j);
|
||||
bload<DataMapper, Packet, Index, accCols, ColMajor, false, 4>(tRes, data, i, 0);
|
||||
|
||||
bscale<Packet>(tRes, result, alpha);
|
||||
bscale<Packet, 4>(tRes, result, alpha);
|
||||
|
||||
data.template storePacketBlock<Packet, 4>(i, j, tRes);
|
||||
data.template storePacketBlock<Packet, 4>(i, 0, tRes);
|
||||
}
|
||||
|
||||
template<typename DataMapper, typename Index, typename Packet, typename Packetc, const Index accColsC, int N>
|
||||
EIGEN_STRONG_INLINE void storeComplexAccumulator(Index i, Index j, const DataMapper& data, const Packet& alphaReal, const Packet& alphaImag, __vector_quad* accReal, __vector_quad* accImag)
|
||||
template<typename DataMapper, typename Index, typename Packet, typename Packetc, const Index accColsC>
|
||||
EIGEN_ALWAYS_INLINE void storeComplexAccumulator(Index i, const DataMapper& data, const Packet& alphaReal, const Packet& alphaImag, __vector_quad* accReal, __vector_quad* accImag)
|
||||
{
|
||||
PacketBlock<Packet, 4> resultReal, resultImag;
|
||||
__builtin_mma_disassemble_acc(&resultReal.packet, accReal);
|
||||
__builtin_mma_disassemble_acc(&resultImag.packet, accImag);
|
||||
|
||||
PacketBlock<Packetc, 8> tRes;
|
||||
bload<DataMapper, Packetc, Index, accColsC, N, ColMajor>(tRes, data, i, j);
|
||||
bload<DataMapper, Packetc, Index, accColsC, ColMajor, true, 4>(tRes, data, i, 0);
|
||||
|
||||
PacketBlock<Packet,4> taccReal, taccImag;
|
||||
bscalec<Packet,4>(resultReal, resultImag, alphaReal, alphaImag, taccReal, taccImag);
|
||||
|
||||
PacketBlock<Packetc, 4> acc1, acc2;
|
||||
bcouple<Packet, Packetc>(taccReal, taccImag, tRes, acc1, acc2);
|
||||
bcouple<Packet, Packetc, 4>(taccReal, taccImag, tRes, acc1, acc2);
|
||||
|
||||
data.template storePacketBlock<Packetc, 4>(i + N*accColsC, j, acc1);
|
||||
data.template storePacketBlock<Packetc, 4>(i + (N+1)*accColsC, j, acc2);
|
||||
data.template storePacketBlock<Packetc, 4>(i, 0, acc1);
|
||||
data.template storePacketBlock<Packetc, 4>(i + accColsC, 0, acc2);
|
||||
}
|
||||
|
||||
// Defaults to float32, since Eigen still supports C++03 we can't use default template arguments
|
||||
template<typename LhsPacket, typename RhsPacket, bool NegativeAccumulate>
|
||||
EIGEN_STRONG_INLINE void pgerMMA(__vector_quad* acc, const RhsPacket& a, const LhsPacket& b)
|
||||
EIGEN_ALWAYS_INLINE void pgerMMA(__vector_quad* acc, const RhsPacket& a, const LhsPacket& b)
|
||||
{
|
||||
if(NegativeAccumulate)
|
||||
{
|
||||
@@ -76,7 +80,7 @@ EIGEN_STRONG_INLINE void pgerMMA(__vector_quad* acc, const RhsPacket& a, const L
|
||||
}
|
||||
|
||||
template<typename LhsPacket, typename RhsPacket, bool NegativeAccumulate>
|
||||
EIGEN_STRONG_INLINE void pgerMMA(__vector_quad* acc, const PacketBlock<Packet2d,2>& a, const Packet2d& b)
|
||||
EIGEN_ALWAYS_INLINE void pgerMMA(__vector_quad* acc, const PacketBlock<Packet2d,2>& a, const Packet2d& b)
|
||||
{
|
||||
__vector_pair* a0 = (__vector_pair *)(&a.packet[0]);
|
||||
if(NegativeAccumulate)
|
||||
@@ -88,7 +92,7 @@ EIGEN_STRONG_INLINE void pgerMMA(__vector_quad* acc, const PacketBlock<Packet2d,
|
||||
}
|
||||
|
||||
template<typename LhsPacket, typename RhsPacket, bool NegativeAccumulate>
|
||||
EIGEN_STRONG_INLINE void pgerMMA(__vector_quad* acc, const __vector_pair& a, const Packet2d& b)
|
||||
EIGEN_ALWAYS_INLINE void pgerMMA(__vector_quad* acc, const __vector_pair& a, const Packet2d& b)
|
||||
{
|
||||
if(NegativeAccumulate)
|
||||
{
|
||||
@@ -99,15 +103,13 @@ EIGEN_STRONG_INLINE void pgerMMA(__vector_quad* acc, const __vector_pair& a, con
|
||||
}
|
||||
|
||||
template<typename LhsPacket, typename RhsPacket, bool NegativeAccumulate>
|
||||
EIGEN_STRONG_INLINE void pgerMMA(__vector_quad* acc, const __vector_pair& a, const Packet4f& b)
|
||||
EIGEN_ALWAYS_INLINE void pgerMMA(__vector_quad*, const __vector_pair&, const Packet4f&)
|
||||
{
|
||||
EIGEN_UNUSED_VARIABLE(acc); // Just for compilation
|
||||
EIGEN_UNUSED_VARIABLE(a);
|
||||
EIGEN_UNUSED_VARIABLE(b);
|
||||
// Just for compilation
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Packet, typename RhsPacket, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
EIGEN_STRONG_INLINE void pgercMMA(__vector_quad* accReal, __vector_quad* accImag, const Packet& lhsV, const Packet& lhsVi, const RhsPacket& rhsV, const RhsPacket& rhsVi)
|
||||
EIGEN_ALWAYS_INLINE void pgercMMA(__vector_quad* accReal, __vector_quad* accImag, const Packet& lhsV, const Packet& lhsVi, const RhsPacket& rhsV, const RhsPacket& rhsVi)
|
||||
{
|
||||
pgerMMA<Packet, RhsPacket, false>(accReal, rhsV, lhsV);
|
||||
if(LhsIsReal) {
|
||||
@@ -125,20 +127,20 @@ EIGEN_STRONG_INLINE void pgercMMA(__vector_quad* accReal, __vector_quad* accImag
|
||||
|
||||
// This is necessary because ploadRhs for double returns a pair of vectors when MMA is enabled.
|
||||
template<typename Scalar, typename Packet>
|
||||
EIGEN_STRONG_INLINE void ploadRhsMMA(const Scalar* rhs, Packet& rhsV)
|
||||
EIGEN_ALWAYS_INLINE void ploadRhsMMA(const Scalar* rhs, Packet& rhsV)
|
||||
{
|
||||
rhsV = ploadRhs<Scalar, Packet>((const Scalar*)(rhs));
|
||||
rhsV = ploadRhs<Scalar, Packet>(rhs);
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE void ploadRhsMMA<double, PacketBlock<Packet2d, 2> >(const double* rhs, PacketBlock<Packet2d, 2>& rhsV)
|
||||
EIGEN_ALWAYS_INLINE void ploadRhsMMA<double, PacketBlock<Packet2d, 2> >(const double* rhs, PacketBlock<Packet2d, 2>& rhsV)
|
||||
{
|
||||
rhsV.packet[0] = ploadRhs<double, Packet2d>((const double *)((Packet2d *)rhs ));
|
||||
rhsV.packet[1] = ploadRhs<double, Packet2d>((const double *)(((Packet2d *)rhs) + 1));
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE void ploadRhsMMA<double, __vector_pair>(const double* rhs, __vector_pair& rhsV)
|
||||
EIGEN_ALWAYS_INLINE void ploadRhsMMA<double, __vector_pair>(const double* rhs, __vector_pair& rhsV)
|
||||
{
|
||||
#if EIGEN_COMP_LLVM
|
||||
__builtin_vsx_assemble_pair(&rhsV,
|
||||
@@ -150,11 +152,9 @@ EIGEN_STRONG_INLINE void ploadRhsMMA<double, __vector_pair>(const double* rhs, _
|
||||
}
|
||||
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE void ploadRhsMMA(const float* rhs, __vector_pair& rhsV)
|
||||
EIGEN_ALWAYS_INLINE void ploadRhsMMA(const float*, __vector_pair&)
|
||||
{
|
||||
// Just for compilation
|
||||
EIGEN_UNUSED_VARIABLE(rhs);
|
||||
EIGEN_UNUSED_VARIABLE(rhsV);
|
||||
}
|
||||
|
||||
// PEEL_MMA loop factor.
|
||||
@@ -188,12 +188,11 @@ EIGEN_STRONG_INLINE void ploadRhsMMA(const float* rhs, __vector_pair& rhsV)
|
||||
}
|
||||
|
||||
#define MICRO_MMA_UNROLL_TYPE_PEEL(func, func2, type) \
|
||||
type rhsV0, rhsV1, rhsV2, rhsV3, rhsV4, rhsV5, rhsV6, rhsV7, rhsV8, rhsV9; \
|
||||
type rhsV0, rhsV1, rhsV2, rhsV3, rhsV4, rhsV5, rhsV6, rhsV7; \
|
||||
MICRO_MMA_TYPE_PEEL(func,func2,type,0); MICRO_MMA_TYPE_PEEL(func,func2,type,1); \
|
||||
MICRO_MMA_TYPE_PEEL(func,func2,type,2); MICRO_MMA_TYPE_PEEL(func,func2,type,3); \
|
||||
MICRO_MMA_TYPE_PEEL(func,func2,type,4); MICRO_MMA_TYPE_PEEL(func,func2,type,5); \
|
||||
MICRO_MMA_TYPE_PEEL(func,func2,type,6); MICRO_MMA_TYPE_PEEL(func,func2,type,7); \
|
||||
MICRO_MMA_TYPE_PEEL(func,func2,type,8); MICRO_MMA_TYPE_PEEL(func,func2,type,9);
|
||||
MICRO_MMA_TYPE_PEEL(func,func2,type,6); MICRO_MMA_TYPE_PEEL(func,func2,type,7);
|
||||
|
||||
#define MICRO_MMA_UNROLL_TYPE_ONE(func, func2, type) \
|
||||
type rhsV0; \
|
||||
@@ -226,7 +225,7 @@ EIGEN_STRONG_INLINE void ploadRhsMMA(const float* rhs, __vector_pair& rhsV)
|
||||
|
||||
#define MICRO_MMA_SRC_PTR_ONE(iter) \
|
||||
if (unroll_factor > iter) { \
|
||||
lhs_ptr##iter = lhs_base + ( (row/accCols) + iter )*strideA*accCols + accCols*offsetA; \
|
||||
lhs_ptr##iter = lhs_base + ( (row/accCols) + iter )*strideA*accCols; \
|
||||
} else { \
|
||||
EIGEN_UNUSED_VARIABLE(lhs_ptr##iter); \
|
||||
}
|
||||
@@ -242,26 +241,23 @@ EIGEN_STRONG_INLINE void ploadRhsMMA(const float* rhs, __vector_pair& rhsV)
|
||||
|
||||
#define MICRO_MMA_STORE_ONE(iter) \
|
||||
if (unroll_factor > iter) { \
|
||||
storeAccumulator<DataMapper, Index, Packet, accCols>(row + iter*accCols, col, res, pAlpha, &accZero##iter); \
|
||||
storeAccumulator<DataMapper, Index, Packet, accCols>(row + iter*accCols, res, pAlpha, &accZero##iter); \
|
||||
}
|
||||
|
||||
#define MICRO_MMA_STORE MICRO_MMA_UNROLL(MICRO_MMA_STORE_ONE)
|
||||
|
||||
template<int unroll_factor, typename Scalar, typename Packet, typename RhsPacket, typename DataMapper, typename Index, const Index accRows, const Index accCols>
|
||||
EIGEN_STRONG_INLINE void gemm_unrolled_MMA_iteration(
|
||||
EIGEN_ALWAYS_INLINE void gemm_unrolled_MMA_iteration(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index& row,
|
||||
Index col,
|
||||
const Packet& pAlpha)
|
||||
{
|
||||
asm("#gemm_MMA begin");
|
||||
const Scalar* rhs_ptr = rhs_base;
|
||||
const Scalar* lhs_ptr0, * lhs_ptr1, * lhs_ptr2, * lhs_ptr3, * lhs_ptr4, * lhs_ptr5, * lhs_ptr6, * lhs_ptr7;
|
||||
const Scalar* lhs_ptr0 = NULL, * lhs_ptr1 = NULL, * lhs_ptr2 = NULL, * lhs_ptr3 = NULL, * lhs_ptr4 = NULL, * lhs_ptr5 = NULL, * lhs_ptr6 = NULL, * lhs_ptr7 = NULL;
|
||||
__vector_quad accZero0, accZero1, accZero2, accZero3, accZero4, accZero5, accZero6, accZero7;
|
||||
|
||||
MICRO_MMA_SRC_PTR
|
||||
@@ -281,14 +277,86 @@ asm("#gemm_MMA begin");
|
||||
MICRO_MMA_STORE
|
||||
|
||||
row += unroll_factor*accCols;
|
||||
asm("#gemm_MMA end");
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Packet, typename RhsPacket, typename DataMapper, typename Index, const Index accRows, const Index accCols>
|
||||
EIGEN_ALWAYS_INLINE void gemmMMA_cols(
|
||||
const DataMapper& res,
|
||||
const Scalar* blockA,
|
||||
const Scalar* blockB,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index strideB,
|
||||
Index offsetB,
|
||||
Index col,
|
||||
Index rows,
|
||||
Index cols,
|
||||
Index remaining_rows,
|
||||
const Packet& pAlpha,
|
||||
const Packet& pMask)
|
||||
{
|
||||
const DataMapper res3 = res.getSubMapper(0, col);
|
||||
|
||||
const Scalar* rhs_base = blockB + col*strideB + accRows*offsetB;
|
||||
const Scalar* lhs_base = blockA + accCols*offsetA;
|
||||
Index row = 0;
|
||||
|
||||
#define MAX_MMA_UNROLL 7
|
||||
while(row + MAX_MMA_UNROLL*accCols <= rows) {
|
||||
gemm_unrolled_MMA_iteration<MAX_MMA_UNROLL, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
}
|
||||
switch( (rows-row)/accCols ) {
|
||||
#if MAX_MMA_UNROLL > 7
|
||||
case 7:
|
||||
gemm_unrolled_MMA_iteration<7, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 6
|
||||
case 6:
|
||||
gemm_unrolled_MMA_iteration<6, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 5
|
||||
case 5:
|
||||
gemm_unrolled_MMA_iteration<5, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 4
|
||||
case 4:
|
||||
gemm_unrolled_MMA_iteration<4, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 3
|
||||
case 3:
|
||||
gemm_unrolled_MMA_iteration<3, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 2
|
||||
case 2:
|
||||
gemm_unrolled_MMA_iteration<2, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 1
|
||||
case 1:
|
||||
gemm_unrolled_MMA_iteration<1, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res3, lhs_base, rhs_base, depth, strideA, row, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef MAX_MMA_UNROLL
|
||||
|
||||
if(remaining_rows > 0)
|
||||
{
|
||||
gemm_extra_row<Scalar, Packet, DataMapper, Index, accRows, accCols>(res3, blockA, rhs_base, depth, strideA, offsetA, row, col, rows, cols, remaining_rows, pAlpha, pMask);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Index, typename Packet, typename RhsPacket, typename DataMapper, const Index accRows, const Index accCols>
|
||||
void gemmMMA(const DataMapper& res, const Scalar* blockA, const Scalar* blockB, Index rows, Index depth, Index cols, Scalar alpha, Index strideA, Index strideB, Index offsetA, Index offsetB)
|
||||
{
|
||||
const Index remaining_rows = rows % accCols;
|
||||
const Index remaining_cols = cols % accRows;
|
||||
|
||||
if( strideA == -1 ) strideA = depth;
|
||||
if( strideB == -1 ) strideB = depth;
|
||||
@@ -299,79 +367,10 @@ void gemmMMA(const DataMapper& res, const Scalar* blockA, const Scalar* blockB,
|
||||
Index col = 0;
|
||||
for(; col + accRows <= cols; col += accRows)
|
||||
{
|
||||
const Scalar* rhs_base = blockB + col*strideB + accRows*offsetB;
|
||||
const Scalar* lhs_base = blockA;
|
||||
|
||||
Index row = 0;
|
||||
#define MAX_MMA_UNROLL 7
|
||||
while(row + MAX_MMA_UNROLL*accCols <= rows) {
|
||||
gemm_unrolled_MMA_iteration<MAX_MMA_UNROLL, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
}
|
||||
switch( (rows-row)/accCols ) {
|
||||
#if MAX_MMA_UNROLL > 7
|
||||
case 7:
|
||||
gemm_unrolled_MMA_iteration<7, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 6
|
||||
case 6:
|
||||
gemm_unrolled_MMA_iteration<6, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 5
|
||||
case 5:
|
||||
gemm_unrolled_MMA_iteration<5, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 4
|
||||
case 4:
|
||||
gemm_unrolled_MMA_iteration<4, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 3
|
||||
case 3:
|
||||
gemm_unrolled_MMA_iteration<3, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 2
|
||||
case 2:
|
||||
gemm_unrolled_MMA_iteration<2, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_MMA_UNROLL > 1
|
||||
case 1:
|
||||
gemm_unrolled_MMA_iteration<1, Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, pAlpha);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef MAX_MMA_UNROLL
|
||||
|
||||
if(remaining_rows > 0)
|
||||
{
|
||||
gemm_extra_row<Scalar, Packet, DataMapper, Index, accRows, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, rows, cols, remaining_rows, pAlpha, pMask);
|
||||
}
|
||||
gemmMMA_cols<Scalar, Packet, RhsPacket, DataMapper, Index, accRows, accCols>(res, blockA, blockB, depth, strideA, offsetA, strideB, offsetB, col, rows, cols, remaining_rows, pAlpha, pMask);
|
||||
}
|
||||
|
||||
if(remaining_cols > 0)
|
||||
{
|
||||
const Scalar* rhs_base = blockB + col*strideB + remaining_cols*offsetB;
|
||||
const Scalar* lhs_base = blockA;
|
||||
|
||||
for(; col < cols; col++)
|
||||
{
|
||||
Index row = 0;
|
||||
|
||||
gemm_unrolled_col<Scalar, Packet, DataMapper, Index, accCols>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, rows, col, remaining_cols, pAlpha);
|
||||
|
||||
if (remaining_rows > 0)
|
||||
{
|
||||
gemm_extra_col<Scalar, Packet, DataMapper, Index, accRows>(res, lhs_base, rhs_base, depth, strideA, offsetA, row, col, remaining_rows, remaining_cols, pAlpha);
|
||||
}
|
||||
rhs_base++;
|
||||
}
|
||||
}
|
||||
gemm_extra_cols<Scalar, Packet, DataMapper, Index, accCols>(res, blockA, blockB, depth, strideA, offsetA, strideB, offsetB, col, rows, cols, remaining_rows, pAlpha, pMask);
|
||||
}
|
||||
|
||||
#define accColsC (accCols / 2)
|
||||
@@ -379,21 +378,20 @@ void gemmMMA(const DataMapper& res, const Scalar* blockA, const Scalar* blockB,
|
||||
#define advanceCols ((RhsIsReal) ? 1 : 2)
|
||||
|
||||
// PEEL_COMPLEX_MMA loop factor.
|
||||
#define PEEL_COMPLEX_MMA 7
|
||||
#define PEEL_COMPLEX_MMA 3
|
||||
|
||||
#define MICRO_COMPLEX_MMA_UNROLL(func) \
|
||||
func(0) func(1) func(2) func(3) func(4)
|
||||
func(0) func(1) func(2) func(3)
|
||||
|
||||
#define MICRO_COMPLEX_MMA_LOAD_ONE(iter) \
|
||||
if (unroll_factor > iter) { \
|
||||
lhsV##iter = ploadLhs<Scalar, Packet>(lhs_ptr_real##iter); \
|
||||
lhs_ptr_real##iter += accCols; \
|
||||
if(!LhsIsReal) { \
|
||||
lhsVi##iter = ploadLhs<Scalar, Packet>(lhs_ptr_imag##iter); \
|
||||
lhs_ptr_imag##iter += accCols; \
|
||||
lhsVi##iter = ploadLhs<Scalar, Packet>(lhs_ptr_real##iter + imag_delta); \
|
||||
} else { \
|
||||
EIGEN_UNUSED_VARIABLE(lhsVi##iter); \
|
||||
} \
|
||||
lhs_ptr_real##iter += accCols; \
|
||||
} else { \
|
||||
EIGEN_UNUSED_VARIABLE(lhsV##iter); \
|
||||
EIGEN_UNUSED_VARIABLE(lhsVi##iter); \
|
||||
@@ -406,8 +404,8 @@ void gemmMMA(const DataMapper& res, const Scalar* blockA, const Scalar* blockB,
|
||||
|
||||
#define MICRO_COMPLEX_MMA_TYPE_PEEL(func, func2, type, peel) \
|
||||
if (PEEL_COMPLEX_MMA > peel) { \
|
||||
Packet lhsV0, lhsV1, lhsV2, lhsV3, lhsV4; \
|
||||
Packet lhsVi0, lhsVi1, lhsVi2, lhsVi3, lhsVi4; \
|
||||
Packet lhsV0, lhsV1, lhsV2, lhsV3; \
|
||||
Packet lhsVi0, lhsVi1, lhsVi2, lhsVi3; \
|
||||
ploadRhsMMA<Scalar, type>(rhs_ptr_real + (accRows * peel), rhsV##peel); \
|
||||
if(!RhsIsReal) { \
|
||||
ploadRhsMMA<Scalar, type>(rhs_ptr_imag + (accRows * peel), rhsVi##peel); \
|
||||
@@ -415,20 +413,17 @@ void gemmMMA(const DataMapper& res, const Scalar* blockA, const Scalar* blockB,
|
||||
EIGEN_UNUSED_VARIABLE(rhsVi##peel); \
|
||||
} \
|
||||
MICRO_COMPLEX_MMA_UNROLL(func2); \
|
||||
func(0,type,peel) func(1,type,peel) func(2,type,peel) func(3,type,peel) func(4,type,peel) \
|
||||
func(0,type,peel) func(1,type,peel) func(2,type,peel) func(3,type,peel) \
|
||||
} else { \
|
||||
EIGEN_UNUSED_VARIABLE(rhsV##peel); \
|
||||
EIGEN_UNUSED_VARIABLE(rhsVi##peel); \
|
||||
}
|
||||
|
||||
#define MICRO_COMPLEX_MMA_UNROLL_TYPE_PEEL(func, func2, type) \
|
||||
type rhsV0, rhsV1, rhsV2, rhsV3, rhsV4, rhsV5, rhsV6, rhsV7, rhsV8, rhsV9; \
|
||||
type rhsVi0, rhsVi1, rhsVi2, rhsVi3, rhsVi4, rhsVi5, rhsVi6, rhsVi7, rhsVi8, rhsVi9; \
|
||||
type rhsV0, rhsV1, rhsV2, rhsV3; \
|
||||
type rhsVi0, rhsVi1, rhsVi2, rhsVi3; \
|
||||
MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,0); MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,1); \
|
||||
MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,2); MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,3); \
|
||||
MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,4); MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,5); \
|
||||
MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,6); MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,7); \
|
||||
MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,8); MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,9);
|
||||
MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,2); MICRO_COMPLEX_MMA_TYPE_PEEL(func,func2,type,3);
|
||||
|
||||
#define MICRO_COMPLEX_MMA_UNROLL_TYPE_ONE(func, func2, type) \
|
||||
type rhsV0, rhsVi0; \
|
||||
@@ -465,15 +460,9 @@ void gemmMMA(const DataMapper& res, const Scalar* blockA, const Scalar* blockB,
|
||||
|
||||
#define MICRO_COMPLEX_MMA_SRC_PTR_ONE(iter) \
|
||||
if (unroll_factor > iter) { \
|
||||
lhs_ptr_real##iter = lhs_base + ( ((advanceRows*row)/accCols) + iter*advanceRows )*strideA*accCols + accCols*offsetA; \
|
||||
if(!LhsIsReal) { \
|
||||
lhs_ptr_imag##iter = lhs_ptr_real##iter + accCols*strideA; \
|
||||
} else { \
|
||||
EIGEN_UNUSED_VARIABLE(lhs_ptr_imag##iter); \
|
||||
} \
|
||||
lhs_ptr_real##iter = lhs_base + ( ((advanceRows*row)/accCols) + iter*advanceRows )*strideA*accCols; \
|
||||
} else { \
|
||||
EIGEN_UNUSED_VARIABLE(lhs_ptr_real##iter); \
|
||||
EIGEN_UNUSED_VARIABLE(lhs_ptr_imag##iter); \
|
||||
}
|
||||
|
||||
#define MICRO_COMPLEX_MMA_SRC_PTR MICRO_COMPLEX_MMA_UNROLL(MICRO_COMPLEX_MMA_SRC_PTR_ONE)
|
||||
@@ -481,46 +470,40 @@ void gemmMMA(const DataMapper& res, const Scalar* blockA, const Scalar* blockB,
|
||||
#define MICRO_COMPLEX_MMA_PREFETCH_ONE(iter) \
|
||||
if (unroll_factor > iter) { \
|
||||
EIGEN_POWER_PREFETCH(lhs_ptr_real##iter); \
|
||||
if(!LhsIsReal) { \
|
||||
EIGEN_POWER_PREFETCH(lhs_ptr_imag##iter); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MICRO_COMPLEX_MMA_PREFETCH MICRO_COMPLEX_MMA_UNROLL(MICRO_COMPLEX_MMA_PREFETCH_ONE)
|
||||
|
||||
#define MICRO_COMPLEX_MMA_STORE_ONE(iter) \
|
||||
if (unroll_factor > iter) { \
|
||||
storeComplexAccumulator<DataMapper, Index, Packet, Packetc, accColsC, 0>(row + iter*accCols, col, res, pAlphaReal, pAlphaImag, &accReal##iter, &accImag##iter); \
|
||||
storeComplexAccumulator<DataMapper, Index, Packet, Packetc, accColsC>(row + iter*accCols, res, pAlphaReal, pAlphaImag, &accReal##iter, &accImag##iter); \
|
||||
}
|
||||
|
||||
#define MICRO_COMPLEX_MMA_STORE MICRO_COMPLEX_MMA_UNROLL(MICRO_COMPLEX_MMA_STORE_ONE)
|
||||
|
||||
template<int unroll_factor, typename Scalar, typename Packet, typename Packetc, typename RhsPacket, typename DataMapper, typename Index, const Index accRows, const Index accCols, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
EIGEN_STRONG_INLINE void gemm_complex_unrolled_MMA_iteration(
|
||||
EIGEN_ALWAYS_INLINE void gemm_complex_unrolled_MMA_iteration(
|
||||
const DataMapper& res,
|
||||
const Scalar* lhs_base,
|
||||
const Scalar* rhs_base,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index strideB,
|
||||
Index& row,
|
||||
Index col,
|
||||
const Packet& pAlphaReal,
|
||||
const Packet& pAlphaImag)
|
||||
{
|
||||
asm("#gemm_complex_MMA begin");
|
||||
const Scalar* rhs_ptr_real = rhs_base;
|
||||
const Scalar* rhs_ptr_imag;
|
||||
const Scalar* rhs_ptr_imag = NULL;
|
||||
const Index imag_delta = accCols*strideA;
|
||||
if(!RhsIsReal) {
|
||||
rhs_ptr_imag = rhs_base + accRows*strideB;
|
||||
} else {
|
||||
EIGEN_UNUSED_VARIABLE(rhs_ptr_imag);
|
||||
}
|
||||
const Scalar* lhs_ptr_real0, * lhs_ptr_imag0, * lhs_ptr_real1, * lhs_ptr_imag1;
|
||||
const Scalar* lhs_ptr_real2, * lhs_ptr_imag2, * lhs_ptr_real3, * lhs_ptr_imag3;
|
||||
const Scalar* lhs_ptr_real4, * lhs_ptr_imag4;
|
||||
__vector_quad accReal0, accImag0, accReal1, accImag1, accReal2, accImag2, accReal3, accImag3, accReal4, accImag4;
|
||||
const Scalar* lhs_ptr_real0 = NULL, * lhs_ptr_real1 = NULL;
|
||||
const Scalar* lhs_ptr_real2 = NULL, * lhs_ptr_real3 = NULL;
|
||||
__vector_quad accReal0, accImag0, accReal1, accImag1, accReal2, accImag2, accReal3, accImag3;
|
||||
|
||||
MICRO_COMPLEX_MMA_SRC_PTR
|
||||
MICRO_COMPLEX_MMA_DST_PTR
|
||||
@@ -542,14 +525,72 @@ asm("#gemm_complex_MMA begin");
|
||||
MICRO_COMPLEX_MMA_STORE
|
||||
|
||||
row += unroll_factor*accCols;
|
||||
asm("#gemm_complex_MMA end");
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Packet, typename Packetc, typename RhsPacket, typename DataMapper, typename Index, const Index accRows, const Index accCols, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
EIGEN_ALWAYS_INLINE void gemmMMA_complex_cols(
|
||||
const DataMapper& res,
|
||||
const Scalar* blockA,
|
||||
const Scalar* blockB,
|
||||
Index depth,
|
||||
Index strideA,
|
||||
Index offsetA,
|
||||
Index strideB,
|
||||
Index offsetB,
|
||||
Index col,
|
||||
Index rows,
|
||||
Index cols,
|
||||
Index remaining_rows,
|
||||
const Packet& pAlphaReal,
|
||||
const Packet& pAlphaImag,
|
||||
const Packet& pMask)
|
||||
{
|
||||
const DataMapper res3 = res.getSubMapper(0, col);
|
||||
|
||||
const Scalar* rhs_base = blockB + advanceCols*col*strideB + accRows*offsetB;
|
||||
const Scalar* lhs_base = blockA + accCols*offsetA;
|
||||
Index row = 0;
|
||||
|
||||
#define MAX_COMPLEX_MMA_UNROLL 4
|
||||
while(row + MAX_COMPLEX_MMA_UNROLL*accCols <= rows) {
|
||||
gemm_complex_unrolled_MMA_iteration<MAX_COMPLEX_MMA_UNROLL, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res3, lhs_base, rhs_base, depth, strideA, strideB, row, pAlphaReal, pAlphaImag);
|
||||
}
|
||||
switch( (rows-row)/accCols ) {
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 4
|
||||
case 4:
|
||||
gemm_complex_unrolled_MMA_iteration<4, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res3, lhs_base, rhs_base, depth, strideA, strideB, row, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 3
|
||||
case 3:
|
||||
gemm_complex_unrolled_MMA_iteration<3, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res3, lhs_base, rhs_base, depth, strideA, strideB, row, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 2
|
||||
case 2:
|
||||
gemm_complex_unrolled_MMA_iteration<2, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res3, lhs_base, rhs_base, depth, strideA, strideB, row, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 1
|
||||
case 1:
|
||||
gemm_complex_unrolled_MMA_iteration<1, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res3, lhs_base, rhs_base, depth, strideA, strideB, row, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef MAX_COMPLEX_MMA_UNROLL
|
||||
|
||||
if(remaining_rows > 0)
|
||||
{
|
||||
gemm_complex_extra_row<Scalar, Packet, Packetc, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res3, blockA, rhs_base, depth, strideA, offsetA, strideB, row, col, rows, cols, remaining_rows, pAlphaReal, pAlphaImag, pMask);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename LhsScalar, typename RhsScalar, typename Scalarc, typename Scalar, typename Index, typename Packet, typename Packetc, typename RhsPacket, typename DataMapper, const Index accRows, const Index accCols, bool ConjugateLhs, bool ConjugateRhs, bool LhsIsReal, bool RhsIsReal>
|
||||
void gemm_complexMMA(const DataMapper& res, const LhsScalar* blockAc, const RhsScalar* blockBc, Index rows, Index depth, Index cols, Scalarc alpha, Index strideA, Index strideB, Index offsetA, Index offsetB)
|
||||
{
|
||||
const Index remaining_rows = rows % accCols;
|
||||
const Index remaining_cols = cols % accRows;
|
||||
|
||||
if( strideA == -1 ) strideA = depth;
|
||||
if( strideB == -1 ) strideB = depth;
|
||||
@@ -564,74 +605,23 @@ void gemm_complexMMA(const DataMapper& res, const LhsScalar* blockAc, const RhsS
|
||||
Index col = 0;
|
||||
for(; col + accRows <= cols; col += accRows)
|
||||
{
|
||||
const Scalar* rhs_base = blockB + advanceCols*col*strideB + accRows*offsetB;
|
||||
const Scalar* lhs_base = blockA;
|
||||
Index row = 0;
|
||||
|
||||
#define MAX_COMPLEX_MMA_UNROLL 4
|
||||
while(row + MAX_COMPLEX_MMA_UNROLL*accCols <= rows) {
|
||||
gemm_complex_unrolled_MMA_iteration<MAX_COMPLEX_MMA_UNROLL, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, col, pAlphaReal, pAlphaImag);
|
||||
}
|
||||
switch( (rows-row)/accCols ) {
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 4
|
||||
case 4:
|
||||
gemm_complex_unrolled_MMA_iteration<4, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, col, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 3
|
||||
case 3:
|
||||
gemm_complex_unrolled_MMA_iteration<3, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, col, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 2
|
||||
case 2:
|
||||
gemm_complex_unrolled_MMA_iteration<2, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, col, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
#if MAX_COMPLEX_MMA_UNROLL > 1
|
||||
case 1:
|
||||
gemm_complex_unrolled_MMA_iteration<1, Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, col, pAlphaReal, pAlphaImag);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef MAX_COMPLEX_MMA_UNROLL
|
||||
|
||||
if(remaining_rows > 0)
|
||||
{
|
||||
gemm_complex_extra_row<Scalar, Packet, Packetc, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, col, rows, cols, remaining_rows, pAlphaReal, pAlphaImag, pMask);
|
||||
}
|
||||
gemmMMA_complex_cols<Scalar, Packet, Packetc, RhsPacket, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, blockA, blockB, depth, strideA, offsetA, strideB, offsetB, col, rows, cols, remaining_rows, pAlphaReal, pAlphaImag, pMask);
|
||||
}
|
||||
|
||||
if(remaining_cols > 0)
|
||||
{
|
||||
const Scalar* rhs_base = blockB + advanceCols*col*strideB + remaining_cols*offsetB;
|
||||
const Scalar* lhs_base = blockA;
|
||||
|
||||
for(; col < cols; col++)
|
||||
{
|
||||
Index row = 0;
|
||||
|
||||
gemm_complex_unrolled_col<Scalar, Packet, Packetc, DataMapper, Index, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, rows, col, remaining_cols, pAlphaReal, pAlphaImag);
|
||||
|
||||
if (remaining_rows > 0)
|
||||
{
|
||||
gemm_complex_extra_col<Scalar, Packet, Packetc, DataMapper, Index, accRows, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, lhs_base, rhs_base, depth, strideA, offsetA, strideB, row, col, remaining_rows, remaining_cols, pAlphaReal, pAlphaImag);
|
||||
}
|
||||
rhs_base++;
|
||||
}
|
||||
}
|
||||
gemm_complex_extra_cols<Scalar, Packet, Packetc, DataMapper, Index, accCols, ConjugateLhs, ConjugateRhs, LhsIsReal, RhsIsReal>(res, blockA, blockB, depth, strideA, offsetA, strideB, offsetB, col, rows, cols, remaining_rows, pAlphaReal, pAlphaImag, pMask);
|
||||
}
|
||||
|
||||
#undef accColsC
|
||||
#undef advanceRows
|
||||
#undef advanceCols
|
||||
|
||||
#pragma GCC reset_options
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#if defined(EIGEN_ALTIVEC_MMA_DYNAMIC_DISPATCH)
|
||||
#pragma GCC pop_options
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_MATRIX_PRODUCT_MMA_ALTIVEC_H
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,10 +22,6 @@ namespace internal {
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#endif
|
||||
|
||||
// NOTE Altivec has 32 registers, but Eigen only accepts a value of 8 or 16
|
||||
#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
|
||||
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 32
|
||||
@@ -88,7 +84,7 @@ static _EIGEN_DECLARE_CONST_FAST_Packet4ui(PREV0DOT5, 0x3EFFFFFFu);
|
||||
static _EIGEN_DECLARE_CONST_FAST_Packet8us(ONE,1); //{ 1, 1, 1, 1, 1, 1, 1, 1}
|
||||
static _EIGEN_DECLARE_CONST_FAST_Packet16uc(ONE,1);
|
||||
static Packet4f p4f_MZERO = (Packet4f) vec_sl((Packet4ui)p4i_MINUS1, (Packet4ui)p4i_MINUS1); //{ 0x80000000, 0x80000000, 0x80000000, 0x80000000}
|
||||
#ifndef __VSX__
|
||||
#ifndef EIGEN_VECTORIZE_VSX
|
||||
static Packet4f p4f_ONE = vec_ctf(p4i_ONE, 0); //{ 1.0, 1.0, 1.0, 1.0}
|
||||
#endif
|
||||
|
||||
@@ -118,7 +114,7 @@ static Packet16uc p16uc_QUADRUPLICATE16_HI = { 0,1,0,1,0,1,0,1, 2,3,2,3,2,3,2,3
|
||||
// Define global static constants:
|
||||
#ifdef _BIG_ENDIAN
|
||||
static Packet16uc p16uc_FORWARD = vec_lvsl(0, (float*)0);
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
static Packet16uc p16uc_REVERSE64 = { 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 };
|
||||
#endif
|
||||
static Packet16uc p16uc_PSET32_WODD = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 };
|
||||
@@ -172,13 +168,16 @@ struct packet_traits<float> : default_packet_traits {
|
||||
HasCos = EIGEN_FAST_MATH,
|
||||
HasLog = 1,
|
||||
HasExp = 1,
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
HasSqrt = 1,
|
||||
#if !EIGEN_COMP_CLANG
|
||||
HasRsqrt = 1,
|
||||
#else
|
||||
HasRsqrt = 0,
|
||||
#endif
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasErf = EIGEN_FAST_MATH,
|
||||
HasRint = 1,
|
||||
#else
|
||||
HasSqrt = 0,
|
||||
HasRsqrt = 0,
|
||||
@@ -188,7 +187,6 @@ struct packet_traits<float> : default_packet_traits {
|
||||
HasRound = 1,
|
||||
HasFloor = 1,
|
||||
HasCeil = 1,
|
||||
HasRint = 1,
|
||||
HasNegate = 1,
|
||||
HasBlend = 1
|
||||
};
|
||||
@@ -214,23 +212,24 @@ struct packet_traits<bfloat16> : default_packet_traits {
|
||||
HasCos = EIGEN_FAST_MATH,
|
||||
HasLog = 1,
|
||||
HasExp = 1,
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
HasSqrt = 1,
|
||||
#if !EIGEN_COMP_CLANG
|
||||
HasRsqrt = 1,
|
||||
#else
|
||||
HasRsqrt = 0,
|
||||
#endif
|
||||
HasRint = 1,
|
||||
#else
|
||||
HasSqrt = 0,
|
||||
HasRsqrt = 0,
|
||||
HasTanh = EIGEN_FAST_MATH,
|
||||
HasErf = EIGEN_FAST_MATH,
|
||||
HasRint = 0,
|
||||
#endif
|
||||
HasTanh = 0,
|
||||
HasErf = 0,
|
||||
HasRound = 1,
|
||||
HasFloor = 1,
|
||||
HasCeil = 1,
|
||||
HasRint = 1,
|
||||
HasNegate = 1,
|
||||
HasBlend = 1
|
||||
};
|
||||
@@ -436,8 +435,8 @@ EIGEN_STRONG_INLINE Packet pload_common(const __UNPACK_TYPE__(Packet)* from)
|
||||
// ignoring these warnings for now.
|
||||
EIGEN_UNUSED_VARIABLE(from);
|
||||
EIGEN_DEBUG_ALIGNED_LOAD
|
||||
#ifdef __VSX__
|
||||
return vec_xl(0, from);
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
return vec_xl(0, const_cast<__UNPACK_TYPE__(Packet)*>(from));
|
||||
#else
|
||||
return vec_ld(0, from);
|
||||
#endif
|
||||
@@ -485,7 +484,7 @@ EIGEN_STRONG_INLINE void pstore_common(__UNPACK_TYPE__(Packet)* to, const Packet
|
||||
// ignoring these warnings for now.
|
||||
EIGEN_UNUSED_VARIABLE(to);
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
vec_xst(from, 0, to);
|
||||
#else
|
||||
vec_st(from, 0, to);
|
||||
@@ -790,8 +789,22 @@ template<> EIGEN_STRONG_INLINE Packet8us psub<Packet8us> (const Packet8us& a,
|
||||
template<> EIGEN_STRONG_INLINE Packet16c psub<Packet16c> (const Packet16c& a, const Packet16c& b) { return a - b; }
|
||||
template<> EIGEN_STRONG_INLINE Packet16uc psub<Packet16uc>(const Packet16uc& a, const Packet16uc& b) { return a - b; }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return p4f_ZERO - a; }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return p4i_ZERO - a; }
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a)
|
||||
{
|
||||
#ifdef __POWER8_VECTOR__
|
||||
return vec_neg(a);
|
||||
#else
|
||||
return vec_xor(a, p4f_MZERO);
|
||||
#endif
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a)
|
||||
{
|
||||
#ifdef __POWER8_VECTOR__
|
||||
return vec_neg(a);
|
||||
#else
|
||||
return p4i_ZERO - a;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
|
||||
@@ -806,7 +819,7 @@ template<> EIGEN_STRONG_INLINE Packet16uc pmul<Packet16uc>(const Packet16uc& a,
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pdiv<Packet4f>(const Packet4f& a, const Packet4f& b)
|
||||
{
|
||||
#ifndef __VSX__ // VSX actually provides a div instruction
|
||||
#ifndef EIGEN_VECTORIZE_VSX // VSX actually provides a div instruction
|
||||
Packet4f t, y_0, y_1;
|
||||
|
||||
// Altivec does not offer a divide instruction, we have to do a reciprocal approximation
|
||||
@@ -835,7 +848,7 @@ template<> EIGEN_STRONG_INLINE Packet8us pmadd(const Packet8us& a, const Packet8
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b)
|
||||
{
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
// NOTE: about 10% slower than vec_min, but consistent with std::min and SSE regarding NaN
|
||||
Packet4f ret;
|
||||
__asm__ ("xvcmpgesp %x0,%x1,%x2\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b));
|
||||
@@ -853,7 +866,7 @@ template<> EIGEN_STRONG_INLINE Packet16uc pmin<Packet16uc>(const Packet16uc& a,
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b)
|
||||
{
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
// NOTE: about 10% slower than vec_max, but consistent with std::max and SSE regarding NaN
|
||||
Packet4f ret;
|
||||
__asm__ ("xvcmpgtsp %x0,%x2,%x1\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b));
|
||||
@@ -869,19 +882,41 @@ template<> EIGEN_STRONG_INLINE Packet16c pmax<Packet16c>(const Packet16c& a, con
|
||||
template<> EIGEN_STRONG_INLINE Packet16uc pmax<Packet16uc>(const Packet16uc& a, const Packet16uc& b) { return vec_max(a, b); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pcmp_le(const Packet4f& a, const Packet4f& b) { return reinterpret_cast<Packet4f>(vec_cmple(a,b)); }
|
||||
// To fix bug with vec_cmplt on older versions
|
||||
#if defined(__POWER8_VECTOR__) || EIGEN_COMP_LLVM
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pcmp_lt(const Packet4f& a, const Packet4f& b) { return reinterpret_cast<Packet4f>(vec_cmplt(a,b)); }
|
||||
#endif
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pcmp_eq(const Packet4f& a, const Packet4f& b) { return reinterpret_cast<Packet4f>(vec_cmpeq(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet16c pcmp_eq(const Packet16c& a, const Packet16c& b) { return reinterpret_cast<Packet16c>(vec_cmpeq(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet16uc pcmp_eq(const Packet16uc& a, const Packet16uc& b) { return reinterpret_cast<Packet16uc>(vec_cmpeq(a,b)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8s pcmp_eq(const Packet8s& a, const Packet8s& b) { return reinterpret_cast<Packet8s>(vec_cmpeq(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet8us pcmp_eq(const Packet8us& a, const Packet8us& b) { return reinterpret_cast<Packet8us>(vec_cmpeq(a,b)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pcmp_lt_or_nan(const Packet4f& a, const Packet4f& b) {
|
||||
Packet4f c = reinterpret_cast<Packet4f>(vec_cmpge(a,b));
|
||||
return vec_nor(c,c);
|
||||
}
|
||||
|
||||
#ifdef __VSX__
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pcmp_le(const Packet4i& a, const Packet4i& b) { return reinterpret_cast<Packet4i>(vec_cmple(a,b)); }
|
||||
#endif
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pcmp_lt(const Packet4i& a, const Packet4i& b) { return reinterpret_cast<Packet4i>(vec_cmplt(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pcmp_eq(const Packet4i& a, const Packet4i& b) { return reinterpret_cast<Packet4i>(vec_cmpeq(a,b)); }
|
||||
#ifdef __VSX__
|
||||
template<> EIGEN_STRONG_INLINE Packet8s pcmp_le(const Packet8s& a, const Packet8s& b) { return reinterpret_cast<Packet8s>(vec_cmple(a,b)); }
|
||||
#endif
|
||||
template<> EIGEN_STRONG_INLINE Packet8s pcmp_lt(const Packet8s& a, const Packet8s& b) { return reinterpret_cast<Packet8s>(vec_cmplt(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet8s pcmp_eq(const Packet8s& a, const Packet8s& b) { return reinterpret_cast<Packet8s>(vec_cmpeq(a,b)); }
|
||||
#ifdef __VSX__
|
||||
template<> EIGEN_STRONG_INLINE Packet8us pcmp_le(const Packet8us& a, const Packet8us& b) { return reinterpret_cast<Packet8us>(vec_cmple(a,b)); }
|
||||
#endif
|
||||
template<> EIGEN_STRONG_INLINE Packet8us pcmp_lt(const Packet8us& a, const Packet8us& b) { return reinterpret_cast<Packet8us>(vec_cmplt(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet8us pcmp_eq(const Packet8us& a, const Packet8us& b) { return reinterpret_cast<Packet8us>(vec_cmpeq(a,b)); }
|
||||
#ifdef __VSX__
|
||||
template<> EIGEN_STRONG_INLINE Packet16c pcmp_le(const Packet16c& a, const Packet16c& b) { return reinterpret_cast<Packet16c>(vec_cmple(a,b)); }
|
||||
#endif
|
||||
template<> EIGEN_STRONG_INLINE Packet16c pcmp_lt(const Packet16c& a, const Packet16c& b) { return reinterpret_cast<Packet16c>(vec_cmplt(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet16c pcmp_eq(const Packet16c& a, const Packet16c& b) { return reinterpret_cast<Packet16c>(vec_cmpeq(a,b)); }
|
||||
#ifdef __VSX__
|
||||
template<> EIGEN_STRONG_INLINE Packet16uc pcmp_le(const Packet16uc& a, const Packet16uc& b) { return reinterpret_cast<Packet16uc>(vec_cmple(a,b)); }
|
||||
#endif
|
||||
template<> EIGEN_STRONG_INLINE Packet16uc pcmp_lt(const Packet16uc& a, const Packet16uc& b) { return reinterpret_cast<Packet16uc>(vec_cmplt(a,b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet16uc pcmp_eq(const Packet16uc& a, const Packet16uc& b) { return reinterpret_cast<Packet16uc>(vec_cmpeq(a,b)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_and(a, b); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pand<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_and(a, b); }
|
||||
@@ -906,8 +941,8 @@ template<> EIGEN_STRONG_INLINE Packet8bf pxor<Packet8bf>(const Packet8bf& a, con
|
||||
return pxor<Packet8us>(a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_and(a, vec_nor(b, b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_and(a, vec_nor(b, b)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_andc(a, b); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_andc(a, b); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pselect(const Packet4f& mask, const Packet4f& a, const Packet4f& b) {
|
||||
return vec_sel(b, a, reinterpret_cast<Packet4ui>(mask));
|
||||
@@ -918,7 +953,7 @@ template<> EIGEN_STRONG_INLINE Packet4f pround<Packet4f>(const Packet4f& a)
|
||||
Packet4f t = vec_add(reinterpret_cast<Packet4f>(vec_or(vec_and(reinterpret_cast<Packet4ui>(a), p4ui_SIGN), p4ui_PREV0DOT5)), a);
|
||||
Packet4f res;
|
||||
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
__asm__("xvrspiz %x0, %x1\n\t"
|
||||
: "=&wa" (res)
|
||||
: "wa" (t));
|
||||
@@ -932,6 +967,7 @@ template<> EIGEN_STRONG_INLINE Packet4f pround<Packet4f>(const Packet4f& a)
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pceil<Packet4f>(const Packet4f& a) { return vec_ceil(a); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pfloor<Packet4f>(const Packet4f& a) { return vec_floor(a); }
|
||||
#ifdef __VSX__
|
||||
template<> EIGEN_STRONG_INLINE Packet4f print<Packet4f>(const Packet4f& a)
|
||||
{
|
||||
Packet4f res;
|
||||
@@ -942,21 +978,19 @@ template<> EIGEN_STRONG_INLINE Packet4f print<Packet4f>(const Packet4f& a)
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Packet> EIGEN_STRONG_INLINE Packet ploadu_common(const __UNPACK_TYPE__(Packet)* from)
|
||||
{
|
||||
EIGEN_DEBUG_ALIGNED_LOAD
|
||||
#ifdef _BIG_ENDIAN
|
||||
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
|
||||
//TODO: Add static_cast here
|
||||
return (Packet) vec_perm(MSQ, LSQ, mask); // align the data
|
||||
#else
|
||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||
return vec_xl(0, from);
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
return vec_xl(0, const_cast<__UNPACK_TYPE__(Packet)*>(from));
|
||||
#else
|
||||
Packet16uc 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
|
||||
//TODO: Add static_cast here
|
||||
return (Packet) vec_perm(MSQ, LSQ, mask); // align the data
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1061,7 +1095,9 @@ template<> EIGEN_STRONG_INLINE Packet16uc ploaddup<Packet16uc>(const unsigned ch
|
||||
template<typename Packet> EIGEN_STRONG_INLINE void pstoreu_common(__UNPACK_TYPE__(Packet)* to, const Packet& from)
|
||||
{
|
||||
EIGEN_DEBUG_UNALIGNED_STORE
|
||||
#ifdef _BIG_ENDIAN
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
vec_xst(from, 0, to);
|
||||
#else
|
||||
// Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
|
||||
// Warning: not thread safe!
|
||||
Packet16uc MSQ, LSQ, edges;
|
||||
@@ -1076,8 +1112,6 @@ template<typename Packet> EIGEN_STRONG_INLINE void pstoreu_common(__UNPACK_TYPE_
|
||||
LSQ = vec_perm((Packet16uc)from,edges,align); // misalign the data (LSQ)
|
||||
vec_st( LSQ, 15, (unsigned char *)to ); // Store the LSQ part first
|
||||
vec_st( MSQ, 0, (unsigned char *)to ); // Store the MSQ part second
|
||||
#else
|
||||
vec_xst(from, 0, to);
|
||||
#endif
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from)
|
||||
@@ -1264,15 +1298,15 @@ EIGEN_STRONG_INLINE Packet8bf F32ToBf16(Packet4f p4f){
|
||||
Packet4bi is_max_exp = vec_cmpeq(exp, p4ui_max_exp);
|
||||
Packet4bi is_zero_exp = vec_cmpeq(exp, reinterpret_cast<Packet4ui>(p4i_ZERO));
|
||||
|
||||
Packet4bi is_mant_not_zero = vec_cmpne(mantissa, reinterpret_cast<Packet4ui>(p4i_ZERO));
|
||||
Packet4ui nan_selector = pand<Packet4ui>(
|
||||
Packet4bi is_mant_zero = vec_cmpeq(mantissa, reinterpret_cast<Packet4ui>(p4i_ZERO));
|
||||
Packet4ui nan_selector = pandnot<Packet4ui>(
|
||||
reinterpret_cast<Packet4ui>(is_max_exp),
|
||||
reinterpret_cast<Packet4ui>(is_mant_not_zero)
|
||||
reinterpret_cast<Packet4ui>(is_mant_zero)
|
||||
);
|
||||
|
||||
Packet4ui subnormal_selector = pand<Packet4ui>(
|
||||
Packet4ui subnormal_selector = pandnot<Packet4ui>(
|
||||
reinterpret_cast<Packet4ui>(is_zero_exp),
|
||||
reinterpret_cast<Packet4ui>(is_mant_not_zero)
|
||||
reinterpret_cast<Packet4ui>(is_mant_zero)
|
||||
);
|
||||
|
||||
const _EIGEN_DECLARE_CONST_FAST_Packet4ui(nan, 0x7FC00000);
|
||||
@@ -1336,16 +1370,6 @@ template<> EIGEN_STRONG_INLINE Packet8bf psub<Packet8bf>(const Packet8bf& a, con
|
||||
BF16_TO_F32_BINARY_OP_WRAPPER(psub<Packet4f>, a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf psqrt<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(vec_sqrt, a);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf prsqrt<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(prsqrt<Packet4f>, a);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf pexp<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(pexp_float, a);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pldexp<Packet4f>(const Packet4f& a, const Packet4f& exponent) {
|
||||
return pldexp_generic(a,exponent);
|
||||
}
|
||||
@@ -1385,9 +1409,11 @@ template<> EIGEN_STRONG_INLINE Packet8bf pceil<Packet8bf> (const Packet8bf& a){
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf pround<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(pround<Packet4f>, a);
|
||||
}
|
||||
#ifdef __VSX__
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf print<Packet8bf> (const Packet8bf& a){
|
||||
BF16_TO_F32_UNARY_OP_WRAPPER(print<Packet4f>, a);
|
||||
}
|
||||
#endif
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf pmadd(const Packet8bf& a, const Packet8bf& b, const Packet8bf& c) {
|
||||
Packet4f a_even = Bf16ToF32Even(a);
|
||||
Packet4f a_odd = Bf16ToF32Odd(a);
|
||||
@@ -1411,6 +1437,9 @@ template<> EIGEN_STRONG_INLINE Packet8bf pmax<Packet8bf>(const Packet8bf& a, con
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf pcmp_lt(const Packet8bf& a, const Packet8bf& b) {
|
||||
BF16_TO_F32_BINARY_OP_WRAPPER_BOOL(pcmp_lt<Packet4f>, a, b);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf pcmp_lt_or_nan(const Packet8bf& a, const Packet8bf& b) {
|
||||
BF16_TO_F32_BINARY_OP_WRAPPER_BOOL(pcmp_lt_or_nan<Packet4f>, a, b);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet8bf pcmp_le(const Packet8bf& a, const Packet8bf& b) {
|
||||
BF16_TO_F32_BINARY_OP_WRAPPER_BOOL(pcmp_le<Packet4f>, a, b);
|
||||
}
|
||||
@@ -2244,7 +2273,7 @@ template<> EIGEN_STRONG_INLINE Packet4f preinterpret<Packet4f,Packet4i>(const Pa
|
||||
|
||||
|
||||
//---------- double ----------
|
||||
#ifdef __VSX__
|
||||
#ifdef EIGEN_VECTORIZE_VSX
|
||||
typedef __vector double Packet2d;
|
||||
typedef __vector unsigned long long Packet2ul;
|
||||
typedef __vector long long Packet2l;
|
||||
@@ -2260,7 +2289,8 @@ static Packet2ul p2ul_SIGN = { 0x8000000000000000ull, 0x8000000000000000ull };
|
||||
static Packet2ul p2ul_PREV0DOT5 = { 0x3FDFFFFFFFFFFFFFull, 0x3FDFFFFFFFFFFFFFull };
|
||||
static Packet2d p2d_ONE = { 1.0, 1.0 };
|
||||
static Packet2d p2d_ZERO = reinterpret_cast<Packet2d>(p4f_ZERO);
|
||||
static Packet2d p2d_MZERO = { -0.0, -0.0 };
|
||||
static Packet2d p2d_MZERO = { numext::bit_cast<double>(0x8000000000000000ull),
|
||||
numext::bit_cast<double>(0x8000000000000000ull) };
|
||||
|
||||
#ifdef _BIG_ENDIAN
|
||||
static Packet2d p2d_COUNTDOWN = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4f>(p2d_ZERO), reinterpret_cast<Packet4f>(p2d_ONE), 8));
|
||||
@@ -2295,7 +2325,11 @@ template<> struct packet_traits<double> : default_packet_traits
|
||||
HasLog = 0,
|
||||
HasExp = 1,
|
||||
HasSqrt = 1,
|
||||
#if !EIGEN_COMP_CLANG
|
||||
HasRsqrt = 1,
|
||||
#else
|
||||
HasRsqrt = 0,
|
||||
#endif
|
||||
HasRound = 1,
|
||||
HasFloor = 1,
|
||||
HasCeil = 1,
|
||||
@@ -2384,7 +2418,14 @@ template<> EIGEN_STRONG_INLINE Packet2d padd<Packet2d>(const Packet2d& a, const
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2d psub<Packet2d>(const Packet2d& a, const Packet2d& b) { return a - b; }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2d pnegate(const Packet2d& a) { return p2d_ZERO - a; }
|
||||
template<> EIGEN_STRONG_INLINE Packet2d pnegate(const Packet2d& a)
|
||||
{
|
||||
#ifdef __POWER8_VECTOR__
|
||||
return vec_neg(a);
|
||||
#else
|
||||
return vec_xor(a, p2d_MZERO);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2d pconj(const Packet2d& a) { return a; }
|
||||
|
||||
@@ -2453,7 +2494,7 @@ template<> EIGEN_STRONG_INLINE Packet2d print<Packet2d>(const Packet2d& a)
|
||||
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from)
|
||||
{
|
||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||
return vec_xl(0, from);
|
||||
return vec_xl(0, const_cast<double*>(from));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2d ploaddup<Packet2d>(const double* from)
|
||||
@@ -2694,7 +2735,7 @@ template<> EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, cons
|
||||
}
|
||||
|
||||
|
||||
#endif // __VSX__
|
||||
#endif // EIGEN_VECTORIZE_VSX
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -11,13 +11,24 @@
|
||||
#ifndef EIGEN_COMPLEX_CUDA_H
|
||||
#define EIGEN_COMPLEX_CUDA_H
|
||||
|
||||
// clang-format off
|
||||
// Many std::complex methods such as operator+, operator-, operator* and
|
||||
// operator/ are not constexpr. Due to this, GCC and older versions of clang do
|
||||
// not treat them as device functions and thus Eigen functors making use of
|
||||
// these operators fail to compile. Here, we manually specialize these
|
||||
// operators and functors for complex types when building for CUDA to enable
|
||||
// their use on-device.
|
||||
//
|
||||
// NOTES:
|
||||
// - Compound assignment operators +=,-=,*=,/=(Scalar) will not work on device,
|
||||
// since they are already specialized in the standard. Using them will result
|
||||
// in silent kernel failures.
|
||||
// - Compiling with MSVC and using +=,-=,*=,/=(std::complex<Scalar>) will lead
|
||||
// to duplicate definition errors, since these are already specialized in
|
||||
// Visual Studio's <complex> header (contrary to the standard). This is
|
||||
// preferable to removing such definitions, which will lead to silent kernel
|
||||
// failures.
|
||||
// - Compiling with ICC requires defining _USE_COMPLEX_SPECIALIZATION_ prior
|
||||
// to the first inclusion of <complex>.
|
||||
|
||||
#if defined(EIGEN_CUDACC) && defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
|
||||
@@ -67,27 +78,26 @@ std::complex<T> complex_divide_fast(const std::complex<T>& a, const std::complex
|
||||
const T a_imag = numext::imag(a);
|
||||
const T b_real = numext::real(b);
|
||||
const T b_imag = numext::imag(b);
|
||||
const T norm = T(1) / (b_real * b_real + b_imag * b_imag);
|
||||
return std::complex<T>((a_real * b_real + a_imag * b_imag) * norm,
|
||||
(a_imag * b_real - a_real * b_imag) * norm);
|
||||
const T norm = (b_real * b_real + b_imag * b_imag);
|
||||
return std::complex<T>((a_real * b_real + a_imag * b_imag) / norm,
|
||||
(a_imag * b_real - a_real * b_imag) / norm);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
std::complex<T> complex_divide_stable(const std::complex<T>& a, const std::complex<T>& b) {
|
||||
const T a_real = numext::real(a);
|
||||
const T a_imag = numext::imag(a);
|
||||
const T b_real = numext::real(b);
|
||||
const T b_imag = numext::imag(b);
|
||||
// Guard against over/under-flow.
|
||||
const T scale = T(1) / (numext::abs(b_real) + numext::abs(b_imag));
|
||||
const T a_real_scaled = numext::real(a) * scale;
|
||||
const T a_imag_scaled = numext::imag(a) * scale;
|
||||
const T b_real_scaled = b_real * scale;
|
||||
const T b_imag_scaled = b_imag * scale;
|
||||
|
||||
const T b_norm2_scaled = b_real_scaled * b_real_scaled + b_imag_scaled * b_imag_scaled;
|
||||
return std::complex<T>(
|
||||
(a_real_scaled * b_real_scaled + a_imag_scaled * b_imag_scaled) / b_norm2_scaled,
|
||||
(a_imag_scaled * b_real_scaled - a_real_scaled * b_imag_scaled) / b_norm2_scaled);
|
||||
// Smith's complex division (https://arxiv.org/pdf/1210.4539.pdf),
|
||||
// guards against over/under-flow.
|
||||
const bool scale_imag = numext::abs(b_imag) <= numext::abs(b_real);
|
||||
const T rscale = scale_imag ? T(1) : b_real / b_imag;
|
||||
const T iscale = scale_imag ? b_imag / b_real : T(1);
|
||||
const T denominator = b_real * rscale + b_imag * iscale;
|
||||
return std::complex<T>((a_real * rscale + a_imag * iscale) / denominator,
|
||||
(a_imag * rscale - a_real * iscale) / denominator);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -250,17 +250,8 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __bfloat16_raw truncate_to_bfloat16(const
|
||||
if (Eigen::numext::isnan EIGEN_NOT_A_MACRO(v)) {
|
||||
output.value = std::signbit(v) ? 0xFFC0: 0x7FC0;
|
||||
return output;
|
||||
} else if (std::fabs(v) < std::numeric_limits<float>::min EIGEN_NOT_A_MACRO()) {
|
||||
// Flush denormal to +/- 0.
|
||||
output.value = std::signbit(v) ? 0x8000 : 0;
|
||||
return output;
|
||||
}
|
||||
const uint16_t* p = reinterpret_cast<const uint16_t*>(&v);
|
||||
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
output.value = p[0];
|
||||
#else
|
||||
output.value = p[1];
|
||||
#endif
|
||||
output.value = static_cast<numext::uint16_t>(numext::bit_cast<numext::uint32_t>(v) >> 16);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -288,9 +279,6 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __bfloat16_raw float_to_bfloat16_rtne<fals
|
||||
// qNaN magic: All exponent bits set + most significant bit of fraction
|
||||
// set.
|
||||
output.value = std::signbit(ff) ? 0xFFC0: 0x7FC0;
|
||||
} else if (std::fabs(ff) < std::numeric_limits<float>::min EIGEN_NOT_A_MACRO()) {
|
||||
// Flush denormal to +/- 0.0
|
||||
output.value = std::signbit(ff) ? 0x8000 : 0;
|
||||
} else {
|
||||
// Fast rounding algorithm that rounds a half value to nearest even. This
|
||||
// reduces expected error when we convert a large number of floats. Here
|
||||
@@ -469,14 +457,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __bfloat16_raw float_to_bfloat16_rtne<true
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float bfloat16_to_float(__bfloat16_raw h) {
|
||||
float result = 0;
|
||||
unsigned short* q = reinterpret_cast<unsigned short*>(&result);
|
||||
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
q[0] = h.value;
|
||||
#else
|
||||
q[1] = h.value;
|
||||
#endif
|
||||
return result;
|
||||
return numext::bit_cast<float>(static_cast<numext::uint32_t>(h.value) << 16);
|
||||
}
|
||||
// --- standard functions ---
|
||||
|
||||
|
||||
@@ -11,19 +11,107 @@
|
||||
#ifndef EIGEN_ARCH_CONJ_HELPER_H
|
||||
#define EIGEN_ARCH_CONJ_HELPER_H
|
||||
|
||||
#define EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PACKET_CPLX, PACKET_REAL) \
|
||||
template<> struct conj_helper<PACKET_REAL, PACKET_CPLX, false,false> { \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_REAL& x, const PACKET_CPLX& y, const PACKET_CPLX& c) const \
|
||||
{ return padd(c, pmul(x,y)); } \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_REAL& x, const PACKET_CPLX& y) const \
|
||||
{ return PACKET_CPLX(Eigen::internal::pmul<PACKET_REAL>(x, y.v)); } \
|
||||
}; \
|
||||
\
|
||||
template<> struct conj_helper<PACKET_CPLX, PACKET_REAL, false,false> { \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_CPLX& x, const PACKET_REAL& y, const PACKET_CPLX& c) const \
|
||||
{ return padd(c, pmul(x,y)); } \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_CPLX& x, const PACKET_REAL& y) const \
|
||||
{ return PACKET_CPLX(Eigen::internal::pmul<PACKET_REAL>(x.v, y)); } \
|
||||
#define EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PACKET_CPLX, PACKET_REAL) \
|
||||
template <> \
|
||||
struct conj_helper<PACKET_REAL, PACKET_CPLX, false, false> { \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_REAL& x, \
|
||||
const PACKET_CPLX& y, \
|
||||
const PACKET_CPLX& c) const { \
|
||||
return padd(c, this->pmul(x, y)); \
|
||||
} \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_REAL& x, \
|
||||
const PACKET_CPLX& y) const { \
|
||||
return PACKET_CPLX(Eigen::internal::pmul<PACKET_REAL>(x, y.v)); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <> \
|
||||
struct conj_helper<PACKET_CPLX, PACKET_REAL, false, false> { \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_CPLX& x, \
|
||||
const PACKET_REAL& y, \
|
||||
const PACKET_CPLX& c) const { \
|
||||
return padd(c, this->pmul(x, y)); \
|
||||
} \
|
||||
EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_CPLX& x, \
|
||||
const PACKET_REAL& y) const { \
|
||||
return PACKET_CPLX(Eigen::internal::pmul<PACKET_REAL>(x.v, y)); \
|
||||
} \
|
||||
};
|
||||
|
||||
#endif // EIGEN_ARCH_CONJ_HELPER_H
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
template<bool Conjugate> struct conj_if;
|
||||
|
||||
template<> struct conj_if<true> {
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const { return numext::conj(x); }
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T pconj(const T& x) const { return internal::pconj(x); }
|
||||
};
|
||||
|
||||
template<> struct conj_if<false> {
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& operator()(const T& x) const { return x; }
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& pconj(const T& x) const { return x; }
|
||||
};
|
||||
|
||||
// Generic Implementation, assume scalars since the packet-version is
|
||||
// specialized below.
|
||||
template<typename LhsType, typename RhsType, bool ConjLhs, bool ConjRhs>
|
||||
struct conj_helper {
|
||||
typedef typename ScalarBinaryOpTraits<LhsType, RhsType>::ReturnType ResultType;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType
|
||||
pmadd(const LhsType& x, const RhsType& y, const ResultType& c) const
|
||||
{ return this->pmul(x, y) + c; }
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType
|
||||
pmul(const LhsType& x, const RhsType& y) const
|
||||
{ return conj_if<ConjLhs>()(x) * conj_if<ConjRhs>()(y); }
|
||||
};
|
||||
|
||||
template<typename LhsScalar, typename RhsScalar>
|
||||
struct conj_helper<LhsScalar, RhsScalar, true, true> {
|
||||
typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar>::ReturnType ResultType;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType
|
||||
pmadd(const LhsScalar& x, const RhsScalar& y, const ResultType& c) const
|
||||
{ return this->pmul(x, y) + c; }
|
||||
|
||||
// We save a conjuation by using the identity conj(a)*conj(b) = conj(a*b).
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType
|
||||
pmul(const LhsScalar& x, const RhsScalar& y) const
|
||||
{ return numext::conj(x * y); }
|
||||
};
|
||||
|
||||
// Implementation with equal type, use packet operations.
|
||||
template<typename Packet, bool ConjLhs, bool ConjRhs>
|
||||
struct conj_helper<Packet, Packet, ConjLhs, ConjRhs>
|
||||
{
|
||||
typedef Packet ResultType;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmadd(const Packet& x, const Packet& y, const Packet& c) const
|
||||
{ return Eigen::internal::pmadd(conj_if<ConjLhs>().pconj(x), conj_if<ConjRhs>().pconj(y), c); }
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmul(const Packet& x, const Packet& y) const
|
||||
{ return Eigen::internal::pmul(conj_if<ConjLhs>().pconj(x), conj_if<ConjRhs>().pconj(y)); }
|
||||
};
|
||||
|
||||
template<typename Packet>
|
||||
struct conj_helper<Packet, Packet, true, true>
|
||||
{
|
||||
typedef Packet ResultType;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmadd(const Packet& x, const Packet& y, const Packet& c) const
|
||||
{ return Eigen::internal::pmadd(pconj(x), pconj(y), c); }
|
||||
// We save a conjuation by using the identity conj(a)*conj(b) = conj(a*b).
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmul(const Packet& x, const Packet& y) const
|
||||
{ return pconj(Eigen::internal::pmul(x, y)); }
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace Eigen
|
||||
|
||||
#endif // EIGEN_ARCH_CONJ_HELPER_H
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
template<typename Packet, int N> EIGEN_DEVICE_FUNC inline Packet
|
||||
pset(const typename unpacket_traits<Packet>::type (&a)[N] /* a */) {
|
||||
EIGEN_STATIC_ASSERT(unpacket_traits<Packet>::size == N, THE_ARRAY_SIZE_SHOULD_EQUAL_WITH_PACKET_SIZE);
|
||||
return pload<Packet>(a);
|
||||
}
|
||||
|
||||
// Creates a Scalar integer type with same bit-width.
|
||||
template<typename T> struct make_integer;
|
||||
template<> struct make_integer<float> { typedef numext::int32_t type; };
|
||||
@@ -648,10 +642,10 @@ Packet psincos_float(const Packet& _x)
|
||||
PacketI y_int = preinterpret<PacketI>(y_round); // last 23 digits represent integer (if abs(x)<2^24)
|
||||
y = psub(y_round, cst_rounding_magic); // nearest integer to x*4/pi
|
||||
|
||||
// Reduce x by y octants to get: -Pi/4 <= x <= +Pi/4
|
||||
// Subtract y * Pi/2 to reduce x to the interval -Pi/4 <= x <= +Pi/4
|
||||
// using "Extended precision modular arithmetic"
|
||||
#if defined(EIGEN_HAS_SINGLE_INSTRUCTION_MADD)
|
||||
// This version requires true FMA for high accuracy
|
||||
#if defined(EIGEN_VECTORIZE_FMA)
|
||||
// This version requires true FMA for high accuracy.
|
||||
// It provides a max error of 1ULP up to (with absolute_error < 5.9605e-08):
|
||||
const float huge_th = ComputeSine ? 117435.992f : 71476.0625f;
|
||||
x = pmadd(y, pset1<Packet>(-1.57079601287841796875f), x);
|
||||
@@ -763,6 +757,26 @@ Packet pcos_float(const Packet& x)
|
||||
return psincos_float<false>(x);
|
||||
}
|
||||
|
||||
template<typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
EIGEN_UNUSED Packet pdiv_complex(const Packet& x, const Packet& y) {
|
||||
typedef typename unpacket_traits<Packet>::as_real RealPacket;
|
||||
// In the following we annotate the code for the case where the inputs
|
||||
// are a pair length-2 SIMD vectors representing a single pair of complex
|
||||
// numbers x = a + i*b, y = c + i*d.
|
||||
const RealPacket y_abs = pabs(y.v); // |c|, |d|
|
||||
const RealPacket y_abs_flip = pcplxflip(Packet(y_abs)).v; // |d|, |c|
|
||||
const RealPacket y_max = pmax(y_abs, y_abs_flip); // max(|c|, |d|), max(|c|, |d|)
|
||||
const RealPacket y_scaled = pdiv(y.v, y_max); // c / max(|c|, |d|), d / max(|c|, |d|)
|
||||
// Compute scaled denominator.
|
||||
const RealPacket y_scaled_sq = pmul(y_scaled, y_scaled); // c'**2, d'**2
|
||||
const RealPacket denom = padd(y_scaled_sq, pcplxflip(Packet(y_scaled_sq)).v);
|
||||
Packet result_scaled = pmul(x, pconj(Packet(y_scaled))); // a * c' + b * d', -a * d + b * c
|
||||
// Divide elementwise by denom.
|
||||
result_scaled = Packet(pdiv(result_scaled.v, denom));
|
||||
// Rescale result
|
||||
return Packet(pdiv(result_scaled.v, y_max));
|
||||
}
|
||||
|
||||
template<typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
@@ -808,9 +822,8 @@ Packet psqrt_complex(const Packet& a) {
|
||||
// l0 = (min0 == 0 ? max0 : max0 * sqrt(1 + (min0/max0)**2)),
|
||||
// where max0 = max(|x0|, |y0|), min0 = min(|x0|, |y0|), and similarly for l1.
|
||||
|
||||
Packet a_flip = pcplxflip(a);
|
||||
RealPacket a_abs = pabs(a.v); // [|x0|, |y0|, |x1|, |y1|]
|
||||
RealPacket a_abs_flip = pabs(a_flip.v); // [|y0|, |x0|, |y1|, |x1|]
|
||||
RealPacket a_abs_flip = pcplxflip(Packet(a_abs)).v; // [|y0|, |x0|, |y1|, |x1|]
|
||||
RealPacket a_max = pmax(a_abs, a_abs_flip);
|
||||
RealPacket a_min = pmin(a_abs, a_abs_flip);
|
||||
RealPacket a_min_zero_mask = pcmp_eq(a_min, pzero(a_min));
|
||||
@@ -839,7 +852,8 @@ Packet psqrt_complex(const Packet& a) {
|
||||
|
||||
// Step 4. Compute solution for inputs with negative real part:
|
||||
// [|eta0|, sign(y0)*rho0, |eta1|, sign(y1)*rho1]
|
||||
const RealPacket cst_imag_sign_mask = pset1<Packet>(Scalar(RealScalar(0.0), RealScalar(-0.0))).v;
|
||||
const RealScalar neg_zero = RealScalar(numext::bit_cast<float>(0x80000000u));
|
||||
const RealPacket cst_imag_sign_mask = pset1<Packet>(Scalar(RealScalar(0.0), neg_zero)).v;
|
||||
RealPacket imag_signs = pand(a.v, cst_imag_sign_mask);
|
||||
Packet negative_real_result;
|
||||
// Notice that rho is positive, so taking it's absolute value is a noop.
|
||||
@@ -901,7 +915,7 @@ void fast_twosum(const Packet& x, const Packet& y, Packet& s_hi, Packet& s_lo) {
|
||||
s_lo = psub(y, t);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||
#ifdef EIGEN_VECTORIZE_FMA
|
||||
// This function implements the extended precision product of
|
||||
// a pair of floating point numbers. Given {x, y}, it computes the pair
|
||||
// {p_hi, p_lo} such that x * y = p_hi + p_lo holds exactly and
|
||||
@@ -952,7 +966,7 @@ void twoprod(const Packet& x, const Packet& y,
|
||||
p_lo = pmadd(x_lo, y_lo, p_lo);
|
||||
}
|
||||
|
||||
#endif // EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||
#endif // EIGEN_VECTORIZE_FMA
|
||||
|
||||
|
||||
// This function implements Dekker's algorithm for the addition
|
||||
@@ -1449,39 +1463,40 @@ EIGEN_STRONG_INLINE Packet generic_pow_impl(const Packet& x, const Packet& y) {
|
||||
}
|
||||
|
||||
// Generic implementation of pow(x,y).
|
||||
template<typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
EIGEN_UNUSED
|
||||
Packet generic_pow(const Packet& x, const Packet& y) {
|
||||
template <typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet generic_pow(const Packet& x, const Packet& y) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
|
||||
const Packet cst_pos_inf = pset1<Packet>(NumTraits<Scalar>::infinity());
|
||||
const Packet cst_neg_inf = pset1<Packet>(-NumTraits<Scalar>::infinity());
|
||||
const Packet cst_zero = pset1<Packet>(Scalar(0));
|
||||
const Packet cst_one = pset1<Packet>(Scalar(1));
|
||||
const Packet cst_nan = pset1<Packet>(NumTraits<Scalar>::quiet_NaN());
|
||||
|
||||
const Packet abs_x = pabs(x);
|
||||
// Predicates for sign and magnitude of x.
|
||||
const Packet x_is_zero = pcmp_eq(x, cst_zero);
|
||||
const Packet x_is_neg = pcmp_lt(x, cst_zero);
|
||||
const Packet abs_x_is_zero = pcmp_eq(abs_x, cst_zero);
|
||||
const Packet x_has_signbit = pcmp_eq(por(pand(x, cst_neg_inf), cst_pos_inf), cst_neg_inf);
|
||||
const Packet x_is_neg = pandnot(x_has_signbit, abs_x_is_zero);
|
||||
const Packet x_is_neg_zero = pand(x_has_signbit, abs_x_is_zero);
|
||||
const Packet abs_x_is_inf = pcmp_eq(abs_x, cst_pos_inf);
|
||||
const Packet abs_x_is_one = pcmp_eq(abs_x, cst_one);
|
||||
const Packet abs_x_is_one = pcmp_eq(abs_x, cst_one);
|
||||
const Packet abs_x_is_gt_one = pcmp_lt(cst_one, abs_x);
|
||||
const Packet abs_x_is_lt_one = pcmp_lt(abs_x, cst_one);
|
||||
const Packet x_is_one = pandnot(abs_x_is_one, x_is_neg);
|
||||
const Packet x_is_neg_one = pand(abs_x_is_one, x_is_neg);
|
||||
const Packet x_is_one = pandnot(abs_x_is_one, x_is_neg);
|
||||
const Packet x_is_neg_one = pand(abs_x_is_one, x_is_neg);
|
||||
const Packet x_is_nan = pandnot(ptrue(x), pcmp_eq(x, x));
|
||||
|
||||
// Predicates for sign and magnitude of y.
|
||||
const Packet abs_y = pabs(y);
|
||||
const Packet y_is_one = pcmp_eq(y, cst_one);
|
||||
const Packet y_is_zero = pcmp_eq(y, cst_zero);
|
||||
const Packet abs_y_is_zero = pcmp_eq(abs_y, cst_zero);
|
||||
const Packet y_is_neg = pcmp_lt(y, cst_zero);
|
||||
const Packet y_is_pos = pandnot(ptrue(y), por(y_is_zero, y_is_neg));
|
||||
const Packet y_is_pos = pandnot(ptrue(y), por(abs_y_is_zero, y_is_neg));
|
||||
const Packet y_is_nan = pandnot(ptrue(y), pcmp_eq(y, y));
|
||||
const Packet abs_y_is_inf = pcmp_eq(pabs(y), cst_pos_inf);
|
||||
const Packet abs_y_is_inf = pcmp_eq(abs_y, cst_pos_inf);
|
||||
EIGEN_CONSTEXPR Scalar huge_exponent =
|
||||
(NumTraits<Scalar>::max_exponent() * Scalar(EIGEN_LN2)) /
|
||||
NumTraits<Scalar>::epsilon();
|
||||
(NumTraits<Scalar>::max_exponent() * Scalar(EIGEN_LN2)) / NumTraits<Scalar>::epsilon();
|
||||
const Packet abs_y_is_huge = pcmp_le(pset1<Packet>(huge_exponent), pabs(y));
|
||||
|
||||
// Predicates for whether y is integer and/or even.
|
||||
@@ -1490,39 +1505,31 @@ Packet generic_pow(const Packet& x, const Packet& y) {
|
||||
const Packet y_is_even = pcmp_eq(pround(y_div_2), y_div_2);
|
||||
|
||||
// Predicates encoding special cases for the value of pow(x,y)
|
||||
const Packet invalid_negative_x = pandnot(pandnot(pandnot(x_is_neg, abs_x_is_inf),
|
||||
y_is_int),
|
||||
abs_y_is_inf);
|
||||
const Packet pow_is_one = por(por(x_is_one, y_is_zero),
|
||||
pand(x_is_neg_one,
|
||||
por(abs_y_is_inf, pandnot(y_is_even, invalid_negative_x))));
|
||||
const Packet invalid_negative_x = pandnot(pandnot(pandnot(x_is_neg, abs_x_is_inf), y_is_int), abs_y_is_inf);
|
||||
const Packet pow_is_nan = por(invalid_negative_x, por(x_is_nan, y_is_nan));
|
||||
const Packet pow_is_zero = por(por(por(pand(x_is_zero, y_is_pos),
|
||||
pand(abs_x_is_inf, y_is_neg)),
|
||||
pand(pand(abs_x_is_lt_one, abs_y_is_huge),
|
||||
y_is_pos)),
|
||||
pand(pand(abs_x_is_gt_one, abs_y_is_huge),
|
||||
y_is_neg));
|
||||
const Packet pow_is_inf = por(por(por(pand(x_is_zero, y_is_neg),
|
||||
pand(abs_x_is_inf, y_is_pos)),
|
||||
pand(pand(abs_x_is_lt_one, abs_y_is_huge),
|
||||
y_is_neg)),
|
||||
pand(pand(abs_x_is_gt_one, abs_y_is_huge),
|
||||
y_is_pos));
|
||||
const Packet pow_is_one =
|
||||
por(por(x_is_one, abs_y_is_zero), pand(x_is_neg_one, por(abs_y_is_inf, pandnot(y_is_even, invalid_negative_x))));
|
||||
const Packet pow_is_zero = por(por(por(pand(abs_x_is_zero, y_is_pos), pand(abs_x_is_inf, y_is_neg)),
|
||||
pand(pand(abs_x_is_lt_one, abs_y_is_huge), y_is_pos)),
|
||||
pand(pand(abs_x_is_gt_one, abs_y_is_huge), y_is_neg));
|
||||
const Packet pow_is_inf = por(por(por(pand(abs_x_is_zero, y_is_neg), pand(abs_x_is_inf, y_is_pos)),
|
||||
pand(pand(abs_x_is_lt_one, abs_y_is_huge), y_is_neg)),
|
||||
pand(pand(abs_x_is_gt_one, abs_y_is_huge), y_is_pos));
|
||||
const Packet inf_val =
|
||||
pselect(pandnot(pand(por(pand(abs_x_is_inf, x_is_neg), pand(x_is_neg_zero, y_is_neg)), y_is_int), y_is_even),
|
||||
cst_neg_inf, cst_pos_inf);
|
||||
|
||||
// General computation of pow(x,y) for positive x or negative x and integer y.
|
||||
const Packet negate_pow_abs = pandnot(x_is_neg, y_is_even);
|
||||
const Packet pow_abs = generic_pow_impl(abs_x, y);
|
||||
return pselect(y_is_one, x,
|
||||
pselect(pow_is_one, cst_one,
|
||||
pselect(pow_is_nan, cst_nan,
|
||||
pselect(pow_is_inf, cst_pos_inf,
|
||||
pselect(pow_is_zero, cst_zero,
|
||||
pselect(negate_pow_abs, pnegate(pow_abs), pow_abs))))));
|
||||
return pselect(
|
||||
y_is_one, x,
|
||||
pselect(pow_is_one, cst_one,
|
||||
pselect(pow_is_nan, cst_nan,
|
||||
pselect(pow_is_inf, inf_val,
|
||||
pselect(pow_is_zero, cst_zero, pselect(negate_pow_abs, pnegate(pow_abs), pow_abs))))));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* polevl (modified for Eigen)
|
||||
*
|
||||
* Evaluate polynomial
|
||||
|
||||
@@ -17,10 +17,6 @@ namespace internal {
|
||||
// implemented in GenericPacketMathFunctions.h
|
||||
// This is needed to workaround a circular dependency.
|
||||
|
||||
/** \internal \returns a packet with constant coefficients \a a, e.g.: (a[N-1],...,a[0]) */
|
||||
template<typename Packet, int N> EIGEN_DEVICE_FUNC inline Packet
|
||||
pset(const typename unpacket_traits<Packet>::type (&a)[N] /* a */);
|
||||
|
||||
/***************************************************************************
|
||||
* Some generic implementations to be used by implementors
|
||||
***************************************************************************/
|
||||
@@ -105,6 +101,12 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
EIGEN_UNUSED
|
||||
Packet psqrt_complex(const Packet& a);
|
||||
|
||||
/** \internal \returns x / y for complex types */
|
||||
template<typename Packet>
|
||||
EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
EIGEN_UNUSED
|
||||
Packet pdiv_complex(const Packet& x, const Packet& y);
|
||||
|
||||
template <typename Packet, int N> struct ppolevl;
|
||||
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
#ifndef EIGEN_HALF_H
|
||||
#define EIGEN_HALF_H
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#if defined(EIGEN_HAS_GPU_FP16) || defined(EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC)
|
||||
// When compiling with GPU support, the "__half_raw" base class as well as
|
||||
// some other routines are defined in the GPU compiler header files
|
||||
@@ -334,7 +332,7 @@ EIGEN_STRONG_INLINE __device__ bool operator >= (const half& a, const half& b) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC)
|
||||
#if defined(EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC) && !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half operator + (const half& a, const half& b) {
|
||||
return half(vaddh_f16(a.x, b.x));
|
||||
}
|
||||
@@ -534,7 +532,12 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw float_to_half_rtne(float ff) {
|
||||
|
||||
#elif defined(EIGEN_HAS_FP16_C)
|
||||
__half_raw h;
|
||||
h.x = _cvtss_sh(ff, 0);
|
||||
#if EIGEN_COMP_MSVC
|
||||
// MSVC does not have scalar instructions.
|
||||
h.x =_mm_extract_epi16(_mm_cvtps_ph(_mm_set_ss(ff), 0), 0);
|
||||
#else
|
||||
h.x = _cvtss_sh(ff, 0);
|
||||
#endif
|
||||
return h;
|
||||
|
||||
#elif defined(EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC)
|
||||
@@ -595,7 +598,12 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half_raw h) {
|
||||
(defined(EIGEN_HAS_HIP_FP16) && defined(EIGEN_HIP_DEVICE_COMPILE))
|
||||
return __half2float(h);
|
||||
#elif defined(EIGEN_HAS_FP16_C)
|
||||
return _cvtsh_ss(h.x);
|
||||
#if EIGEN_COMP_MSVC
|
||||
// MSVC does not have scalar instructions.
|
||||
return _mm_cvtss_f32(_mm_cvtph_ps(_mm_set1_epi16(h.x)));
|
||||
#else
|
||||
return _cvtsh_ss(h.x);
|
||||
#endif
|
||||
#elif defined(EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC)
|
||||
return static_cast<float>(h.x);
|
||||
#else
|
||||
|
||||
@@ -121,7 +121,6 @@ template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pset1<double2>(const do
|
||||
// invoked by NVCC’ (e.g. on MacOS). The former needs to see both host and device implementation
|
||||
// of the functions, while the latter can only deal with one of them.
|
||||
#if defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG && !EIGEN_COMP_NVCC)
|
||||
namespace {
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_and(const float& a,
|
||||
const float& b) {
|
||||
@@ -180,8 +179,6 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double lt_mask(const double& a,
|
||||
return __longlong_as_double(a < b ? 0xffffffffffffffffull : 0ull);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pand<float4>(const float4& a,
|
||||
const float4& b) {
|
||||
@@ -493,9 +490,10 @@ ptranspose(PacketBlock<double2,2>& kernel) {
|
||||
|
||||
#endif // defined(EIGEN_GPUCC) && defined(EIGEN_USE_GPU)
|
||||
|
||||
// Packet4h2 must be defined in the macro without EIGEN_CUDA_ARCH, meaning
|
||||
// its corresponding packet_traits<Eigen::half> must be visible on host.
|
||||
#if defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)
|
||||
// Half-packet functions are not available on the host for CUDA 9.0-9.2, only
|
||||
// on device. There is no benefit to using them on the host anyways, since they are
|
||||
// emulated.
|
||||
#if (defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)) && defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
|
||||
typedef ulonglong2 Packet4h2;
|
||||
template<> struct unpacket_traits<Packet4h2> { typedef Eigen::half type; enum {size=8, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false}; typedef Packet4h2 half; };
|
||||
@@ -526,42 +524,9 @@ template<> struct packet_traits<Eigen::half> : default_packet_traits
|
||||
};
|
||||
};
|
||||
|
||||
namespace {
|
||||
// This is equivalent to make_half2, which is undocumented and doesn't seem to always exist.
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 combine_half(const __half& a, const __half& b) {
|
||||
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
return __halves2half2(a, b);
|
||||
#else
|
||||
// Round-about way since __halves2half2 is a __device__ function.
|
||||
return __floats2half2_rn(__half2float(a), __half2float(b));
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE __half get_half2_low(const half2& a) {
|
||||
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
return __low2half(a);
|
||||
#else
|
||||
return __float2half(__low2float(a));
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE __half get_half2_high(const half2& a) {
|
||||
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
return __high2half(a);
|
||||
#else
|
||||
return __float2half(__high2float(a));
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pset1<half2>(const Eigen::half& from) {
|
||||
#if defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
return __half2half2(from);
|
||||
#else
|
||||
const float f = __half2float(from);
|
||||
return __floats2half2_rn(f, f);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -576,8 +541,6 @@ pset1<Packet4h2>(const Eigen::half& from) {
|
||||
return r;
|
||||
}
|
||||
|
||||
// We now need this visible on both host and device.
|
||||
// #if defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG && !EIGEN_COMP_NVCC)
|
||||
namespace {
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pload(const Eigen::half* from) {
|
||||
@@ -585,11 +548,11 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pload(const Eigen::half* from) {
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploadu(const Eigen::half* from) {
|
||||
return combine_half(from[0], from[1]);
|
||||
return __halves2half2(from[0], from[1]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploaddup(const Eigen::half* from) {
|
||||
return combine_half(from[0], from[0]);
|
||||
return __halves2half2(from[0], from[0]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore(Eigen::half* to,
|
||||
@@ -599,8 +562,8 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore(Eigen::half* to,
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu(Eigen::half* to,
|
||||
const half2& from) {
|
||||
to[0] = get_half2_low(from);
|
||||
to[1] = get_half2_high(from);
|
||||
to[0] = __low2half(from);
|
||||
to[1] = __high2half(from);
|
||||
}
|
||||
|
||||
|
||||
@@ -610,7 +573,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_aligned(
|
||||
// Input is guaranteed to be properly aligned.
|
||||
return __ldg(reinterpret_cast<const half2*>(from));
|
||||
#else
|
||||
return combine_half(*(from+0), *(from+1));
|
||||
return __halves2half2(*(from+0), *(from+1));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -619,31 +582,31 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_unaligned(
|
||||
#if defined(EIGEN_GPU_HAS_LDG)
|
||||
return __halves2half2(__ldg(from+0), __ldg(from+1));
|
||||
#else
|
||||
return combine_half(*(from+0), *(from+1));
|
||||
return __halves2half2(*(from+0), *(from+1));
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pgather(const Eigen::half* from,
|
||||
Index stride) {
|
||||
return combine_half(from[0*stride], from[1*stride]);
|
||||
return __halves2half2(from[0*stride], from[1*stride]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter(
|
||||
Eigen::half* to, const half2& from, Index stride) {
|
||||
to[stride*0] = get_half2_low(from);
|
||||
to[stride*1] = get_half2_high(from);
|
||||
to[stride*0] = __low2half(from);
|
||||
to[stride*1] = __high2half(from);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst(const half2& a) {
|
||||
return get_half2_low(a);
|
||||
return __low2half(a);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pabs(const half2& a) {
|
||||
half a1 = get_half2_low(a);
|
||||
half a2 = get_half2_high(a);
|
||||
half a1 = __low2half(a);
|
||||
half a2 = __high2half(a);
|
||||
half result1 = half_impl::raw_uint16_to_half(a1.x & 0x7FFF);
|
||||
half result2 = half_impl::raw_uint16_to_half(a2.x & 0x7FFF);
|
||||
return combine_half(result1, result2);
|
||||
return __halves2half2(result1, result2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ptrue(const half2& /*a*/) {
|
||||
@@ -658,12 +621,12 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pzero(const half2& /*a*/) {
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
|
||||
ptranspose(PacketBlock<half2,2>& kernel) {
|
||||
__half a1 = get_half2_low(kernel.packet[0]);
|
||||
__half a2 = get_half2_high(kernel.packet[0]);
|
||||
__half b1 = get_half2_low(kernel.packet[1]);
|
||||
__half b2 = get_half2_high(kernel.packet[1]);
|
||||
kernel.packet[0] = combine_half(a1, b1);
|
||||
kernel.packet[1] = combine_half(a2, b2);
|
||||
__half a1 = __low2half(kernel.packet[0]);
|
||||
__half a2 = __high2half(kernel.packet[0]);
|
||||
__half b1 = __low2half(kernel.packet[1]);
|
||||
__half b2 = __high2half(kernel.packet[1]);
|
||||
kernel.packet[0] = __halves2half2(a1, b1);
|
||||
kernel.packet[1] = __halves2half2(a2, b2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset(const Eigen::half& a) {
|
||||
@@ -671,88 +634,88 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset(const Eigen::half& a) {
|
||||
return __halves2half2(a, __hadd(a, __float2half(1.0f)));
|
||||
#else
|
||||
float f = __half2float(a) + 1.0f;
|
||||
return combine_half(a, __float2half(f));
|
||||
return __halves2half2(a, __float2half(f));
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pselect(const half2& mask,
|
||||
const half2& a,
|
||||
const half2& b) {
|
||||
half mask_low = get_half2_low(mask);
|
||||
half mask_high = get_half2_high(mask);
|
||||
half result_low = mask_low == half(0) ? get_half2_low(b) : get_half2_low(a);
|
||||
half result_high = mask_high == half(0) ? get_half2_high(b) : get_half2_high(a);
|
||||
return combine_half(result_low, result_high);
|
||||
half mask_low = __low2half(mask);
|
||||
half mask_high = __high2half(mask);
|
||||
half result_low = mask_low == half(0) ? __low2half(b) : __low2half(a);
|
||||
half result_high = mask_high == half(0) ? __high2half(b) : __high2half(a);
|
||||
return __halves2half2(result_low, result_high);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_eq(const half2& a,
|
||||
const half2& b) {
|
||||
half true_half = half_impl::raw_uint16_to_half(0xffffu);
|
||||
half false_half = half_impl::raw_uint16_to_half(0x0000u);
|
||||
half a1 = get_half2_low(a);
|
||||
half a2 = get_half2_high(a);
|
||||
half b1 = get_half2_low(b);
|
||||
half b2 = get_half2_high(b);
|
||||
half a1 = __low2half(a);
|
||||
half a2 = __high2half(a);
|
||||
half b1 = __low2half(b);
|
||||
half b2 = __high2half(b);
|
||||
half eq1 = __half2float(a1) == __half2float(b1) ? true_half : false_half;
|
||||
half eq2 = __half2float(a2) == __half2float(b2) ? true_half : false_half;
|
||||
return combine_half(eq1, eq2);
|
||||
return __halves2half2(eq1, eq2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_lt(const half2& a,
|
||||
const half2& b) {
|
||||
half true_half = half_impl::raw_uint16_to_half(0xffffu);
|
||||
half false_half = half_impl::raw_uint16_to_half(0x0000u);
|
||||
half a1 = get_half2_low(a);
|
||||
half a2 = get_half2_high(a);
|
||||
half b1 = get_half2_low(b);
|
||||
half b2 = get_half2_high(b);
|
||||
half a1 = __low2half(a);
|
||||
half a2 = __high2half(a);
|
||||
half b1 = __low2half(b);
|
||||
half b2 = __high2half(b);
|
||||
half eq1 = __half2float(a1) < __half2float(b1) ? true_half : false_half;
|
||||
half eq2 = __half2float(a2) < __half2float(b2) ? true_half : false_half;
|
||||
return combine_half(eq1, eq2);
|
||||
return __halves2half2(eq1, eq2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pand(const half2& a,
|
||||
const half2& b) {
|
||||
half a1 = get_half2_low(a);
|
||||
half a2 = get_half2_high(a);
|
||||
half b1 = get_half2_low(b);
|
||||
half b2 = get_half2_high(b);
|
||||
half a1 = __low2half(a);
|
||||
half a2 = __high2half(a);
|
||||
half b1 = __low2half(b);
|
||||
half b2 = __high2half(b);
|
||||
half result1 = half_impl::raw_uint16_to_half(a1.x & b1.x);
|
||||
half result2 = half_impl::raw_uint16_to_half(a2.x & b2.x);
|
||||
return combine_half(result1, result2);
|
||||
return __halves2half2(result1, result2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 por(const half2& a,
|
||||
const half2& b) {
|
||||
half a1 = get_half2_low(a);
|
||||
half a2 = get_half2_high(a);
|
||||
half b1 = get_half2_low(b);
|
||||
half b2 = get_half2_high(b);
|
||||
half a1 = __low2half(a);
|
||||
half a2 = __high2half(a);
|
||||
half b1 = __low2half(b);
|
||||
half b2 = __high2half(b);
|
||||
half result1 = half_impl::raw_uint16_to_half(a1.x | b1.x);
|
||||
half result2 = half_impl::raw_uint16_to_half(a2.x | b2.x);
|
||||
return combine_half(result1, result2);
|
||||
return __halves2half2(result1, result2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pxor(const half2& a,
|
||||
const half2& b) {
|
||||
half a1 = get_half2_low(a);
|
||||
half a2 = get_half2_high(a);
|
||||
half b1 = get_half2_low(b);
|
||||
half b2 = get_half2_high(b);
|
||||
half a1 = __low2half(a);
|
||||
half a2 = __high2half(a);
|
||||
half b1 = __low2half(b);
|
||||
half b2 = __high2half(b);
|
||||
half result1 = half_impl::raw_uint16_to_half(a1.x ^ b1.x);
|
||||
half result2 = half_impl::raw_uint16_to_half(a2.x ^ b2.x);
|
||||
return combine_half(result1, result2);
|
||||
return __halves2half2(result1, result2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pandnot(const half2& a,
|
||||
const half2& b) {
|
||||
half a1 = get_half2_low(a);
|
||||
half a2 = get_half2_high(a);
|
||||
half b1 = get_half2_low(b);
|
||||
half b2 = get_half2_high(b);
|
||||
half a1 = __low2half(a);
|
||||
half a2 = __high2half(a);
|
||||
half b1 = __low2half(b);
|
||||
half b2 = __high2half(b);
|
||||
half result1 = half_impl::raw_uint16_to_half(a1.x & ~b1.x);
|
||||
half result2 = half_impl::raw_uint16_to_half(a2.x & ~b2.x);
|
||||
return combine_half(result1, result2);
|
||||
return __halves2half2(result1, result2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd(const half2& a,
|
||||
@@ -851,9 +814,9 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin(const half2& a,
|
||||
float a2 = __high2float(a);
|
||||
float b1 = __low2float(b);
|
||||
float b2 = __high2float(b);
|
||||
__half r1 = a1 < b1 ? get_half2_low(a) : get_half2_low(b);
|
||||
__half r2 = a2 < b2 ? get_half2_high(a) : get_half2_high(b);
|
||||
return combine_half(r1, r2);
|
||||
__half r1 = a1 < b1 ? __low2half(a) : __low2half(b);
|
||||
__half r2 = a2 < b2 ? __high2half(a) : __high2half(b);
|
||||
return __halves2half2(r1, r2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax(const half2& a,
|
||||
@@ -862,9 +825,9 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax(const half2& a,
|
||||
float a2 = __high2float(a);
|
||||
float b1 = __low2float(b);
|
||||
float b2 = __high2float(b);
|
||||
__half r1 = a1 > b1 ? get_half2_low(a) : get_half2_low(b);
|
||||
__half r2 = a2 > b2 ? get_half2_high(a) : get_half2_high(b);
|
||||
return combine_half(r1, r2);
|
||||
__half r1 = a1 > b1 ? __low2half(a) : __low2half(b);
|
||||
__half r2 = a2 > b2 ? __high2half(a) : __high2half(b);
|
||||
return __halves2half2(r1, r2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux(const half2& a) {
|
||||
@@ -885,7 +848,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max(const half2& a) {
|
||||
#else
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
return a1 > a2 ? get_half2_low(a) : get_half2_high(a);
|
||||
return a1 > a2 ? __low2half(a) : __high2half(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -897,7 +860,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min(const half2& a) {
|
||||
#else
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
return a1 < a2 ? get_half2_low(a) : get_half2_high(a);
|
||||
return a1 < a2 ? __low2half(a) : __high2half(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1068,10 +1031,10 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
|
||||
pgather<Eigen::half, Packet4h2>(const Eigen::half* from, Index stride) {
|
||||
Packet4h2 r;
|
||||
half2* p_alias = reinterpret_cast<half2*>(&r);
|
||||
p_alias[0] = combine_half(from[0 * stride], from[1 * stride]);
|
||||
p_alias[1] = combine_half(from[2 * stride], from[3 * stride]);
|
||||
p_alias[2] = combine_half(from[4 * stride], from[5 * stride]);
|
||||
p_alias[3] = combine_half(from[6 * stride], from[7 * stride]);
|
||||
p_alias[0] = __halves2half2(from[0 * stride], from[1 * stride]);
|
||||
p_alias[1] = __halves2half2(from[2 * stride], from[3 * stride]);
|
||||
p_alias[2] = __halves2half2(from[4 * stride], from[5 * stride]);
|
||||
p_alias[3] = __halves2half2(from[6 * stride], from[7 * stride]);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1152,12 +1115,12 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_half2(
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
|
||||
ptranspose_half(half2& f0, half2& f1) {
|
||||
__half a1 = get_half2_low(f0);
|
||||
__half a2 = get_half2_high(f0);
|
||||
__half b1 = get_half2_low(f1);
|
||||
__half b2 = get_half2_high(f1);
|
||||
f0 = combine_half(a1, b1);
|
||||
f1 = combine_half(a2, b2);
|
||||
__half a1 = __low2half(f0);
|
||||
__half a2 = __high2half(f0);
|
||||
__half b1 = __low2half(f1);
|
||||
__half b2 = __high2half(f1);
|
||||
f0 = __halves2half2(a1, b1);
|
||||
f1 = __halves2half2(a2, b2);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
|
||||
@@ -1254,10 +1217,10 @@ plset<Packet4h2>(const Eigen::half& a) {
|
||||
float f = __half2float(a);
|
||||
Packet4h2 r;
|
||||
half2* p_alias = reinterpret_cast<half2*>(&r);
|
||||
p_alias[0] = combine_half(a, __float2half(f + 1.0f));
|
||||
p_alias[1] = combine_half(__float2half(f + 2.0f), __float2half(f + 3.0f));
|
||||
p_alias[2] = combine_half(__float2half(f + 4.0f), __float2half(f + 5.0f));
|
||||
p_alias[3] = combine_half(__float2half(f + 6.0f), __float2half(f + 7.0f));
|
||||
p_alias[0] = __halves2half2(a, __float2half(f + 1.0f));
|
||||
p_alias[1] = __halves2half2(__float2half(f + 2.0f), __float2half(f + 3.0f));
|
||||
p_alias[2] = __halves2half2(__float2half(f + 4.0f), __float2half(f + 5.0f));
|
||||
p_alias[3] = __halves2half2(__float2half(f + 6.0f), __float2half(f + 7.0f));
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
@@ -1477,9 +1440,9 @@ template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max<Packet4h2>(
|
||||
const Packet4h2& a) {
|
||||
const half2* a_alias = reinterpret_cast<const half2*>(&a);
|
||||
half2 m0 = combine_half(predux_max(a_alias[0]),
|
||||
half2 m0 = __halves2half2(predux_max(a_alias[0]),
|
||||
predux_max(a_alias[1]));
|
||||
half2 m1 = combine_half(predux_max(a_alias[2]),
|
||||
half2 m1 = __halves2half2(predux_max(a_alias[2]),
|
||||
predux_max(a_alias[3]));
|
||||
__half first = predux_max(m0);
|
||||
__half second = predux_max(m1);
|
||||
@@ -1496,9 +1459,9 @@ template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min<Packet4h2>(
|
||||
const Packet4h2& a) {
|
||||
const half2* a_alias = reinterpret_cast<const half2*>(&a);
|
||||
half2 m0 = combine_half(predux_min(a_alias[0]),
|
||||
half2 m0 = __halves2half2(predux_min(a_alias[0]),
|
||||
predux_min(a_alias[1]));
|
||||
half2 m1 = combine_half(predux_min(a_alias[2]),
|
||||
half2 m1 = __halves2half2(predux_min(a_alias[2]),
|
||||
predux_min(a_alias[3]));
|
||||
__half first = predux_min(m0);
|
||||
__half second = predux_min(m1);
|
||||
@@ -1652,9 +1615,9 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin<half2>(const half2& a,
|
||||
float a2 = __high2float(a);
|
||||
float b1 = __low2float(b);
|
||||
float b2 = __high2float(b);
|
||||
__half r1 = a1 < b1 ? get_half2_low(a) : get_half2_low(b);
|
||||
__half r2 = a2 < b2 ? get_half2_high(a) : get_half2_high(b);
|
||||
return combine_half(r1, r2);
|
||||
__half r1 = a1 < b1 ? __low2half(a) : __low2half(b);
|
||||
__half r2 = a2 < b2 ? __high2half(a) : __high2half(b);
|
||||
return __halves2half2(r1, r2);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -1664,14 +1627,12 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax<half2>(const half2& a,
|
||||
float a2 = __high2float(a);
|
||||
float b1 = __low2float(b);
|
||||
float b2 = __high2float(b);
|
||||
__half r1 = a1 > b1 ? get_half2_low(a) : get_half2_low(b);
|
||||
__half r2 = a2 > b2 ? get_half2_high(a) : get_half2_high(b);
|
||||
return combine_half(r1, r2);
|
||||
__half r1 = a1 > b1 ? __low2half(a) : __low2half(b);
|
||||
__half r2 = a2 > b2 ? __high2half(a) : __high2half(b);
|
||||
return __halves2half2(r1, r2);
|
||||
}
|
||||
|
||||
// #endif // defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG && !EIGEN_COMP_NVCC)
|
||||
|
||||
#endif // defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)
|
||||
#endif // (defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)) && defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
|
||||
#undef EIGEN_GPU_HAS_LDG
|
||||
#undef EIGEN_CUDA_HAS_FP16_ARITHMETIC
|
||||
|
||||
@@ -15,8 +15,7 @@ namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
#if (defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 300) || \
|
||||
(defined(EIGEN_HAS_HIP_FP16) && defined(EIGEN_HIP_DEVICE_COMPILE))
|
||||
|
||||
(defined(EIGEN_HAS_HIP_FP16) && defined(EIGEN_HIP_DEVICE_COMPILE))
|
||||
|
||||
template <>
|
||||
struct type_casting_traits<Eigen::half, float> {
|
||||
|
||||
@@ -75,15 +75,12 @@ struct Packet2cf {
|
||||
EIGEN_STRONG_INLINE Packet2cf operator-(const Packet2cf& b) const {
|
||||
return Packet2cf(*this) -= b;
|
||||
}
|
||||
EIGEN_STRONG_INLINE Packet2cf& operator/=(const Packet2cf& b) {
|
||||
*this *= b.conjugate();
|
||||
Packet4f s = pmul<Packet4f>(b.v, b.v);
|
||||
s = padd(s, (Packet4f)__builtin_msa_shf_w((v4i32)s, EIGEN_MSA_SHF_I8(1, 0, 3, 2)));
|
||||
v = pdiv(v, s);
|
||||
return *this;
|
||||
}
|
||||
EIGEN_STRONG_INLINE Packet2cf operator/(const Packet2cf& b) const {
|
||||
return Packet2cf(*this) /= b;
|
||||
return pdiv_complex(Packet2cf(*this), b);
|
||||
}
|
||||
EIGEN_STRONG_INLINE Packet2cf& operator/=(const Packet2cf& b) {
|
||||
*this = Packet2cf(*this) / b;
|
||||
return *this;
|
||||
}
|
||||
EIGEN_STRONG_INLINE Packet2cf operator-(void) const {
|
||||
return Packet2cf(pnegate(v));
|
||||
@@ -305,42 +302,6 @@ EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a
|
||||
(a.v[0] * a.v[3]) + (a.v[1] * a.v[2]));
|
||||
}
|
||||
|
||||
template <>
|
||||
struct conj_helper<Packet2cf, Packet2cf, false, true> {
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y,
|
||||
const Packet2cf& c) const {
|
||||
return padd(pmul(x, y), c);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const {
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct conj_helper<Packet2cf, Packet2cf, true, false> {
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y,
|
||||
const Packet2cf& c) const {
|
||||
return padd(pmul(x, y), c);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const {
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct conj_helper<Packet2cf, Packet2cf, true, true> {
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y,
|
||||
const Packet2cf& c) const {
|
||||
return padd(pmul(x, y), c);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const {
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf, Packet4f)
|
||||
|
||||
template <>
|
||||
@@ -644,42 +605,6 @@ EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd&
|
||||
return pfirst(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct conj_helper<Packet1cd, Packet1cd, false, true> {
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y,
|
||||
const Packet1cd& c) const {
|
||||
return padd(pmul(x, y), c);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const {
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct conj_helper<Packet1cd, Packet1cd, true, false> {
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y,
|
||||
const Packet1cd& c) const {
|
||||
return padd(pmul(x, y), c);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const {
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct conj_helper<Packet1cd, Packet1cd, true, true> {
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y,
|
||||
const Packet1cd& c) const {
|
||||
return padd(pmul(x, y), c);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const {
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd, Packet2d)
|
||||
|
||||
template <>
|
||||
|
||||
@@ -28,10 +28,6 @@ namespace internal {
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
|
||||
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 32
|
||||
#endif
|
||||
|
||||
@@ -124,24 +124,17 @@ template<> EIGEN_STRONG_INLINE Packet1cf psub<Packet1cf>(const Packet1cf& a, con
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{ return Packet2cf(psub<Packet4f>(a.v, b.v)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pxor<Packet2cf>(const Packet2cf& a, const Packet2cf& b);
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf paddsub<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
Packet4f mask = {-0.0f, -0.0f, 0.0f, 0.0f};
|
||||
return Packet2cf(padd(a.v, pxor(mask, b.v)));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cf pnegate(const Packet1cf& a) { return Packet1cf(pnegate<Packet2f>(a.v)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { return Packet2cf(pnegate<Packet4f>(a.v)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cf pconj(const Packet1cf& a)
|
||||
{
|
||||
const Packet2ui b = vreinterpret_u32_f32(a.v);
|
||||
const Packet2ui b = Packet2ui(vreinterpret_u32_f32(a.v));
|
||||
return Packet1cf(vreinterpret_f32_u32(veor_u32(b, p2ui_CONJ_XOR())));
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a)
|
||||
{
|
||||
const Packet4ui b = vreinterpretq_u32_f32(a.v);
|
||||
const Packet4ui b = Packet4ui(vreinterpretq_u32_f32(a.v));
|
||||
return Packet2cf(vreinterpretq_f32_u32(veorq_u32(b, p4ui_CONJ_XOR())));
|
||||
}
|
||||
|
||||
@@ -349,86 +342,16 @@ template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const P
|
||||
return s;
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet1cf,Packet1cf,false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cf pmadd(const Packet1cf& x, const Packet1cf& y, const Packet1cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cf pmul(const Packet1cf& a, const Packet1cf& b) const
|
||||
{ return internal::pmul(a, pconj(b)); }
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cf,Packet1cf,true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cf pmadd(const Packet1cf& x, const Packet1cf& y, const Packet1cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cf pmul(const Packet1cf& a, const Packet1cf& b) const
|
||||
{ return internal::pmul(pconj(a), b); }
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cf,Packet1cf,true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cf pmadd(const Packet1cf& x, const Packet1cf& y, const Packet1cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cf pmul(const Packet1cf& a, const Packet1cf& b) const
|
||||
{ return pconj(internal::pmul(a,b)); }
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf,Packet2cf,false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{ return internal::pmul(a, pconj(b)); }
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf,Packet2cf,true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{ return internal::pmul(pconj(a), b); }
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf,Packet2cf,true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{ return pconj(internal::pmul(a,b)); }
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cf,Packet2f)
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cf pdiv<Packet1cf>(const Packet1cf& a, const Packet1cf& b)
|
||||
{
|
||||
// TODO optimize it for NEON
|
||||
Packet1cf res = conj_helper<Packet1cf, Packet1cf, false, true>().pmul(a,b);
|
||||
Packet2f s, rev_s;
|
||||
|
||||
// this computes the norm
|
||||
s = vmul_f32(b.v, b.v);
|
||||
rev_s = vrev64_f32(s);
|
||||
|
||||
return Packet1cf(pdiv<Packet2f>(res.v, vadd_f32(s, rev_s)));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
// TODO optimize it for NEON
|
||||
Packet2cf res = conj_helper<Packet2cf, Packet2cf, false, true>().pmul(a,b);
|
||||
Packet4f s, rev_s;
|
||||
|
||||
// this computes the norm
|
||||
s = vmulq_f32(b.v, b.v);
|
||||
rev_s = vrev64q_f32(s);
|
||||
|
||||
return Packet2cf(pdiv<Packet4f>(res.v, vaddq_f32(s, rev_s)));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet1cf, 1>& /*kernel*/) {}
|
||||
@@ -450,13 +373,10 @@ template<> EIGEN_STRONG_INLINE Packet2cf psqrt<Packet2cf>(const Packet2cf& a) {
|
||||
//---------- double ----------
|
||||
#if EIGEN_ARCH_ARM64 && !EIGEN_APPLE_DOUBLE_NEON_BUG
|
||||
|
||||
// See bug 1325, clang fails to call vld1q_u64.
|
||||
#if EIGEN_COMP_CLANG || EIGEN_COMP_CASTXML
|
||||
static uint64x2_t p2ul_CONJ_XOR = {0x0, 0x8000000000000000};
|
||||
#else
|
||||
const uint64_t p2ul_conj_XOR_DATA[] = { 0x0, 0x8000000000000000 };
|
||||
static uint64x2_t p2ul_CONJ_XOR = vld1q_u64( p2ul_conj_XOR_DATA );
|
||||
#endif
|
||||
inline uint64x2_t p2ul_CONJ_XOR() {
|
||||
static const uint64_t p2ul_conj_XOR_DATA[] = {0x0, 0x8000000000000000};
|
||||
return vld1q_u64(p2ul_conj_XOR_DATA);
|
||||
}
|
||||
|
||||
struct Packet1cd
|
||||
{
|
||||
@@ -526,7 +446,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a)
|
||||
{ return Packet1cd(pnegate<Packet2d>(a.v)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a)
|
||||
{ return Packet1cd(vreinterpretq_f64_u64(veorq_u64(vreinterpretq_u64_f64(a.v), p2ul_CONJ_XOR))); }
|
||||
{ return Packet1cd(vreinterpretq_f64_u64(veorq_u64(vreinterpretq_u64_f64(a.v), p2ul_CONJ_XOR()))); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pmul<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
|
||||
{
|
||||
@@ -541,7 +461,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd pmul<Packet1cd>(const Packet1cd& a, con
|
||||
// Multiply the imag a with b
|
||||
v2 = vmulq_f64(v2, b.v);
|
||||
// Conjugate v2
|
||||
v2 = vreinterpretq_f64_u64(veorq_u64(vreinterpretq_u64_f64(v2), p2ul_CONJ_XOR));
|
||||
v2 = vreinterpretq_f64_u64(veorq_u64(vreinterpretq_u64_f64(v2), p2ul_CONJ_XOR()));
|
||||
// Swap real/imag elements in v2.
|
||||
v2 = preverse<Packet2d>(v2);
|
||||
// Add and return the result
|
||||
@@ -610,43 +530,11 @@ template<> EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Pack
|
||||
|
||||
template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) { return pfirst(a); }
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{ return internal::pmul(a, pconj(b)); }
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{ return internal::pmul(pconj(a), b); }
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{ return pconj(internal::pmul(a,b)); }
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
|
||||
{
|
||||
// TODO optimize it for NEON
|
||||
Packet1cd res = conj_helper<Packet1cd,Packet1cd,false,true>().pmul(a,b);
|
||||
Packet2d s = pmul<Packet2d>(b.v, b.v);
|
||||
Packet2d rev_s = preverse<Packet2d>(s);
|
||||
|
||||
return Packet1cd(pdiv(res.v, padd<Packet2d>(s,rev_s)));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pcplxflip/*<Packet1cd>*/(const Packet1cd& x)
|
||||
|
||||
@@ -24,7 +24,7 @@ struct gebp_traits <float,float,false,false,Architecture::NEON,GEBPPacketFull>
|
||||
|
||||
template <typename LaneIdType>
|
||||
EIGEN_STRONG_INLINE void madd(const Packet4f& a, const Packet4f& b,
|
||||
Packet4f& c, Packet4f& tmp,
|
||||
Packet4f& c, Packet4f&,
|
||||
const LaneIdType&) const {
|
||||
acc(a, b, c);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,113 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
//==============================================================================
|
||||
// preinterpret
|
||||
//==============================================================================
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2f preinterpret<Packet2f, Packet2i>(const Packet2i& a) {
|
||||
return Packet2f(vreinterpret_f32_s32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2f preinterpret<Packet2f, Packet2ui>(const Packet2ui& a) {
|
||||
return Packet2f(vreinterpret_f32_u32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f preinterpret<Packet4f, Packet4i>(const Packet4i& a) {
|
||||
return Packet4f(vreinterpretq_f32_s32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f preinterpret<Packet4f, Packet4ui>(const Packet4ui& a) {
|
||||
return Packet4f(vreinterpretq_f32_u32(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4c preinterpret<Packet4c, Packet4uc>(const Packet4uc& a) {
|
||||
return static_cast<Packet4c>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8c preinterpret<Packet8c, Packet8uc>(const Packet8uc& a) {
|
||||
return Packet8c(vreinterpret_s8_u8(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16c preinterpret<Packet16c, Packet16uc>(const Packet16uc& a) {
|
||||
return Packet16c(vreinterpretq_s8_u8(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4uc preinterpret<Packet4uc, Packet4c>(const Packet4c& a) {
|
||||
return static_cast<Packet4uc>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8uc preinterpret<Packet8uc, Packet8c>(const Packet8c& a) {
|
||||
return Packet8uc(vreinterpret_u8_s8(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16uc preinterpret<Packet16uc, Packet16c>(const Packet16c& a) {
|
||||
return Packet16uc(vreinterpretq_u8_s8(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4s preinterpret<Packet4s, Packet4us>(const Packet4us& a) {
|
||||
return Packet4s(vreinterpret_s16_u16(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s preinterpret<Packet8s, Packet8us>(const Packet8us& a) {
|
||||
return Packet8s(vreinterpretq_s16_u16(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4us preinterpret<Packet4us, Packet4s>(const Packet4s& a) {
|
||||
return Packet4us(vreinterpret_u16_s16(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8us preinterpret<Packet8us, Packet8s>(const Packet8s& a) {
|
||||
return Packet8us(vreinterpretq_u16_s16(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2i preinterpret<Packet2i, Packet2f>(const Packet2f& a) {
|
||||
return Packet2i(vreinterpret_s32_f32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2i preinterpret<Packet2i, Packet2ui>(const Packet2ui& a) {
|
||||
return Packet2i(vreinterpret_s32_u32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i preinterpret<Packet4i, Packet4f>(const Packet4f& a) {
|
||||
return Packet4i(vreinterpretq_s32_f32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i preinterpret<Packet4i, Packet4ui>(const Packet4ui& a) {
|
||||
return Packet4i(vreinterpretq_s32_u32(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ui preinterpret<Packet2ui, Packet2f>(const Packet2f& a) {
|
||||
return Packet2ui(vreinterpret_u32_f32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ui preinterpret<Packet2ui, Packet2i>(const Packet2i& a) {
|
||||
return Packet2ui(vreinterpret_u32_s32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui preinterpret<Packet4ui, Packet4f>(const Packet4f& a) {
|
||||
return Packet4ui(vreinterpretq_u32_f32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui preinterpret<Packet4ui, Packet4i>(const Packet4i& a) {
|
||||
return Packet4ui(vreinterpretq_u32_s32(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l preinterpret<Packet2l, Packet2ul>(const Packet2ul& a) {
|
||||
return Packet2l(vreinterpretq_s64_u64(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul preinterpret<Packet2ul, Packet2l>(const Packet2l& a) {
|
||||
return Packet2ul(vreinterpretq_u64_s64(a));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// pcast, SrcType = float
|
||||
//==============================================================================
|
||||
@@ -188,7 +295,7 @@ struct type_casting_traits<numext::int8_t, numext::uint64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul pcast<Packet16c, Packet2ul>(const Packet16c& a) {
|
||||
return vreinterpretq_u64_s64(pcast<Packet16c, Packet2l>(a));
|
||||
return preinterpret<Packet2ul>(pcast<Packet16c, Packet2l>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -212,11 +319,11 @@ struct type_casting_traits<numext::int8_t, numext::uint32_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui pcast<Packet16c, Packet4ui>(const Packet16c& a) {
|
||||
return vreinterpretq_u32_s32(pcast<Packet16c, Packet4i>(a));
|
||||
return preinterpret<Packet4ui>(pcast<Packet16c, Packet4i>(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ui pcast<Packet8c, Packet2ui>(const Packet8c& a) {
|
||||
return vreinterpret_u32_s32(pcast<Packet8c, Packet2i>(a));
|
||||
return preinterpret<Packet2ui>(pcast<Packet8c, Packet2i>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -240,11 +347,11 @@ struct type_casting_traits<numext::int8_t, numext::uint16_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8us pcast<Packet16c, Packet8us>(const Packet16c& a) {
|
||||
return vreinterpretq_u16_s16(pcast<Packet16c, Packet8s>(a));
|
||||
return preinterpret<Packet8us>(pcast<Packet16c, Packet8s>(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4us pcast<Packet8c, Packet4us>(const Packet8c& a) {
|
||||
return vreinterpret_u16_s16(pcast<Packet8c, Packet4s>(a));
|
||||
return preinterpret<Packet4us>(pcast<Packet8c, Packet4s>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -270,11 +377,11 @@ struct type_casting_traits<numext::int8_t, numext::uint8_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16uc pcast<Packet16c, Packet16uc>(const Packet16c& a) {
|
||||
return vreinterpretq_u8_s8(a);
|
||||
return preinterpret<Packet16uc>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8uc pcast<Packet8c, Packet8uc>(const Packet8c& a) {
|
||||
return vreinterpret_u8_s8(a);
|
||||
return preinterpret<Packet8uc>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4uc pcast<Packet4c, Packet4uc>(const Packet4c& a) {
|
||||
@@ -315,7 +422,7 @@ struct type_casting_traits<numext::uint8_t, numext::int64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l pcast<Packet16uc, Packet2l>(const Packet16uc& a) {
|
||||
return vreinterpretq_s64_u64(pcast<Packet16uc, Packet2ul>(a));
|
||||
return preinterpret<Packet2l>(pcast<Packet16uc, Packet2ul>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -339,11 +446,11 @@ struct type_casting_traits<numext::uint8_t, numext::int32_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i pcast<Packet16uc, Packet4i>(const Packet16uc& a) {
|
||||
return vreinterpretq_s32_u32(pcast<Packet16uc, Packet4ui>(a));
|
||||
return preinterpret<Packet4i>(pcast<Packet16uc, Packet4ui>(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2i pcast<Packet8uc, Packet2i>(const Packet8uc& a) {
|
||||
return vreinterpret_s32_u32(pcast<Packet8uc, Packet2ui>(a));
|
||||
return preinterpret<Packet2i>(pcast<Packet8uc, Packet2ui>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -367,11 +474,11 @@ struct type_casting_traits<numext::uint8_t, numext::int16_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pcast<Packet16uc, Packet8s>(const Packet16uc& a) {
|
||||
return vreinterpretq_s16_u16(pcast<Packet16uc, Packet8us>(a));
|
||||
return preinterpret<Packet8s>(pcast<Packet16uc, Packet8us>(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4s pcast<Packet8uc, Packet4s>(const Packet8uc& a) {
|
||||
return vreinterpret_s16_u16(pcast<Packet8uc, Packet4us>(a));
|
||||
return preinterpret<Packet4s>(pcast<Packet8uc, Packet4us>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -397,11 +504,11 @@ struct type_casting_traits<numext::uint8_t, numext::int8_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16c pcast<Packet16uc, Packet16c>(const Packet16uc& a) {
|
||||
return vreinterpretq_s8_u8(a);
|
||||
return preinterpret<Packet16c>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8c pcast<Packet8uc, Packet8c>(const Packet8uc& a) {
|
||||
return vreinterpret_s8_u8(a);
|
||||
return preinterpret<Packet8c>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4c pcast<Packet4uc, Packet4c>(const Packet4uc& a) {
|
||||
@@ -442,7 +549,7 @@ struct type_casting_traits<numext::int16_t, numext::uint64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul pcast<Packet8s, Packet2ul>(const Packet8s& a) {
|
||||
return vreinterpretq_u64_s64(pcast<Packet8s, Packet2l>(a));
|
||||
return preinterpret<Packet2ul>(pcast<Packet8s, Packet2l>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -466,11 +573,11 @@ struct type_casting_traits<numext::int16_t, numext::uint32_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui pcast<Packet8s, Packet4ui>(const Packet8s& a) {
|
||||
return vreinterpretq_u32_s32(pcast<Packet8s, Packet4i>(a));
|
||||
return preinterpret<Packet4ui>(pcast<Packet8s, Packet4i>(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ui pcast<Packet4s, Packet2ui>(const Packet4s& a) {
|
||||
return vreinterpret_u32_s32(pcast<Packet4s, Packet2i>(a));
|
||||
return preinterpret<Packet2ui>(pcast<Packet4s, Packet2i>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -492,11 +599,11 @@ struct type_casting_traits<numext::int16_t, numext::uint16_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8us pcast<Packet8s, Packet8us>(const Packet8s& a) {
|
||||
return vreinterpretq_u16_s16(a);
|
||||
return preinterpret<Packet8us>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4us pcast<Packet4s, Packet4us>(const Packet4s& a) {
|
||||
return vreinterpret_u16_s16(a);
|
||||
return preinterpret<Packet4us>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -559,7 +666,7 @@ struct type_casting_traits<numext::uint16_t, numext::int64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l pcast<Packet8us, Packet2l>(const Packet8us& a) {
|
||||
return vreinterpretq_s64_u64(pcast<Packet8us, Packet2ul>(a));
|
||||
return preinterpret<Packet2l>(pcast<Packet8us, Packet2ul>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -583,11 +690,11 @@ struct type_casting_traits<numext::uint16_t, numext::int32_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i pcast<Packet8us, Packet4i>(const Packet8us& a) {
|
||||
return vreinterpretq_s32_u32(pcast<Packet8us, Packet4ui>(a));
|
||||
return preinterpret<Packet4i>(pcast<Packet8us, Packet4ui>(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2i pcast<Packet4us, Packet2i>(const Packet4us& a) {
|
||||
return vreinterpret_s32_u32(pcast<Packet4us, Packet2ui>(a));
|
||||
return preinterpret<Packet2i>(pcast<Packet4us, Packet2ui>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -609,11 +716,11 @@ struct type_casting_traits<numext::uint16_t, numext::int16_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pcast<Packet8us, Packet8s>(const Packet8us& a) {
|
||||
return vreinterpretq_s16_u16(a);
|
||||
return preinterpret<Packet8s>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4s pcast<Packet4us, Packet4s>(const Packet4us& a) {
|
||||
return vreinterpret_s16_u16(a);
|
||||
return preinterpret<Packet4s>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -635,11 +742,11 @@ struct type_casting_traits<numext::uint16_t, numext::int8_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16c pcast<Packet8us, Packet16c>(const Packet8us& a, const Packet8us& b) {
|
||||
return vreinterpretq_s8_u8(pcast<Packet8us, Packet16uc>(a, b));
|
||||
return preinterpret<Packet16c>(pcast<Packet8us, Packet16uc>(a, b));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8c pcast<Packet4us, Packet8c>(const Packet4us& a, const Packet4us& b) {
|
||||
return vreinterpret_s8_u8(pcast<Packet4us, Packet8uc>(a, b));
|
||||
return preinterpret<Packet8c>(pcast<Packet4us, Packet8uc>(a, b));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -674,7 +781,7 @@ struct type_casting_traits<numext::int32_t, numext::uint64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul pcast<Packet4i, Packet2ul>(const Packet4i& a) {
|
||||
return vreinterpretq_u64_s64(pcast<Packet4i, Packet2l>(a));
|
||||
return preinterpret<Packet2ul>(pcast<Packet4i, Packet2l>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -696,11 +803,11 @@ struct type_casting_traits<numext::int32_t, numext::uint32_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui pcast<Packet4i, Packet4ui>(const Packet4i& a) {
|
||||
return vreinterpretq_u32_s32(a);
|
||||
return preinterpret<Packet4ui>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ui pcast<Packet2i, Packet2ui>(const Packet2i& a) {
|
||||
return vreinterpret_u32_s32(a);
|
||||
return preinterpret<Packet2ui>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -799,7 +906,7 @@ struct type_casting_traits<numext::uint32_t, numext::int64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l pcast<Packet4ui, Packet2l>(const Packet4ui& a) {
|
||||
return vreinterpretq_s64_u64(pcast<Packet4ui, Packet2ul>(a));
|
||||
return preinterpret<Packet2l>(pcast<Packet4ui, Packet2ul>(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -821,11 +928,11 @@ struct type_casting_traits<numext::uint32_t, numext::int32_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i pcast<Packet4ui, Packet4i>(const Packet4ui& a) {
|
||||
return vreinterpretq_s32_u32(a);
|
||||
return preinterpret<Packet4i>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2i pcast<Packet2ui, Packet2i>(const Packet2ui& a) {
|
||||
return vreinterpret_s32_u32(a);
|
||||
return preinterpret<Packet2i>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -847,11 +954,11 @@ struct type_casting_traits<numext::uint32_t, numext::int16_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pcast<Packet4ui, Packet8s>(const Packet4ui& a, const Packet4ui& b) {
|
||||
return vreinterpretq_s16_u16(pcast<Packet4ui, Packet8us>(a, b));
|
||||
return preinterpret<Packet8s>(pcast<Packet4ui, Packet8us>(a, b));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4s pcast<Packet2ui, Packet4s>(const Packet2ui& a, const Packet2ui& b) {
|
||||
return vreinterpret_s16_u16(pcast<Packet2ui, Packet4us>(a, b));
|
||||
return preinterpret<Packet4s>(pcast<Packet2ui, Packet4us>(a, b));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -880,12 +987,12 @@ struct type_casting_traits<numext::uint32_t, numext::int8_t> {
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16c pcast<Packet4ui, Packet16c>(const Packet4ui& a, const Packet4ui& b, const Packet4ui& c,
|
||||
const Packet4ui& d) {
|
||||
return vreinterpretq_s8_u8(pcast<Packet4ui, Packet16uc>(a, b, c, d));
|
||||
return preinterpret<Packet16c>(pcast<Packet4ui, Packet16uc>(a, b, c, d));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8c pcast<Packet2ui, Packet8c>(const Packet2ui& a, const Packet2ui& b, const Packet2ui& c,
|
||||
const Packet2ui& d) {
|
||||
return vreinterpret_s8_u8(pcast<Packet2ui, Packet8uc>(a, b, c, d));
|
||||
return preinterpret<Packet8c>(pcast<Packet2ui, Packet8uc>(a, b, c, d));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@@ -915,7 +1022,7 @@ struct type_casting_traits<numext::int64_t, numext::uint64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul pcast<Packet2l, Packet2ul>(const Packet2l& a) {
|
||||
return vreinterpretq_u64_s64(a);
|
||||
return preinterpret<Packet2ul>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1013,7 +1120,7 @@ struct type_casting_traits<numext::uint64_t, numext::int64_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l pcast<Packet2ul, Packet2l>(const Packet2ul& a) {
|
||||
return vreinterpretq_s64_u64(a);
|
||||
return preinterpret<Packet2l>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1031,7 +1138,7 @@ struct type_casting_traits<numext::uint64_t, numext::int32_t> {
|
||||
};
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i pcast<Packet2ul, Packet4i>(const Packet2ul& a, const Packet2ul& b) {
|
||||
return vreinterpretq_s32_u32(pcast<Packet2ul, Packet4ui>(a, b));
|
||||
return preinterpret<Packet4i>(pcast<Packet2ul, Packet4ui>(a, b));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1053,7 +1160,7 @@ struct type_casting_traits<numext::uint64_t, numext::int16_t> {
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s pcast<Packet2ul, Packet8s>(const Packet2ul& a, const Packet2ul& b, const Packet2ul& c,
|
||||
const Packet2ul& d) {
|
||||
return vreinterpretq_s16_u16(pcast<Packet2ul, Packet8us>(a, b, c, d));
|
||||
return preinterpret<Packet8s>(pcast<Packet2ul, Packet8us>(a, b, c, d));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1077,114 +1184,7 @@ template <>
|
||||
EIGEN_STRONG_INLINE Packet16c pcast<Packet2ul, Packet16c>(const Packet2ul& a, const Packet2ul& b, const Packet2ul& c,
|
||||
const Packet2ul& d, const Packet2ul& e, const Packet2ul& f,
|
||||
const Packet2ul& g, const Packet2ul& h) {
|
||||
return vreinterpretq_s8_u8(pcast<Packet2ul, Packet16uc>(a, b, c, d, e, f, g, h));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// preinterpret
|
||||
//==============================================================================
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2f preinterpret<Packet2f, Packet2i>(const Packet2i& a) {
|
||||
return vreinterpret_f32_s32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2f preinterpret<Packet2f, Packet2ui>(const Packet2ui& a) {
|
||||
return vreinterpret_f32_u32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f preinterpret<Packet4f, Packet4i>(const Packet4i& a) {
|
||||
return vreinterpretq_f32_s32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f preinterpret<Packet4f, Packet4ui>(const Packet4ui& a) {
|
||||
return vreinterpretq_f32_u32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4c preinterpret<Packet4c, Packet4uc>(const Packet4uc& a) {
|
||||
return static_cast<Packet4c>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8c preinterpret<Packet8c, Packet8uc>(const Packet8uc& a) {
|
||||
return vreinterpret_s8_u8(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16c preinterpret<Packet16c, Packet16uc>(const Packet16uc& a) {
|
||||
return vreinterpretq_s8_u8(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4uc preinterpret<Packet4uc, Packet4c>(const Packet4c& a) {
|
||||
return static_cast<Packet4uc>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8uc preinterpret<Packet8uc, Packet8c>(const Packet8c& a) {
|
||||
return vreinterpret_u8_s8(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16uc preinterpret<Packet16uc, Packet16c>(const Packet16c& a) {
|
||||
return vreinterpretq_u8_s8(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4s preinterpret<Packet4s, Packet4us>(const Packet4us& a) {
|
||||
return vreinterpret_s16_u16(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8s preinterpret<Packet8s, Packet8us>(const Packet8us& a) {
|
||||
return vreinterpretq_s16_u16(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4us preinterpret<Packet4us, Packet4s>(const Packet4s& a) {
|
||||
return vreinterpret_u16_s16(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8us preinterpret<Packet8us, Packet8s>(const Packet8s& a) {
|
||||
return vreinterpretq_u16_s16(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2i preinterpret<Packet2i, Packet2f>(const Packet2f& a) {
|
||||
return vreinterpret_s32_f32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2i preinterpret<Packet2i, Packet2ui>(const Packet2ui& a) {
|
||||
return vreinterpret_s32_u32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i preinterpret<Packet4i, Packet4f>(const Packet4f& a) {
|
||||
return vreinterpretq_s32_f32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i preinterpret<Packet4i, Packet4ui>(const Packet4ui& a) {
|
||||
return vreinterpretq_s32_u32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ui preinterpret<Packet2ui, Packet2f>(const Packet2f& a) {
|
||||
return vreinterpret_u32_f32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ui preinterpret<Packet2ui, Packet2i>(const Packet2i& a) {
|
||||
return vreinterpret_u32_s32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui preinterpret<Packet4ui, Packet4f>(const Packet4f& a) {
|
||||
return vreinterpretq_u32_f32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui preinterpret<Packet4ui, Packet4i>(const Packet4i& a) {
|
||||
return vreinterpretq_u32_s32(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l preinterpret<Packet2l, Packet2ul>(const Packet2ul& a) {
|
||||
return vreinterpretq_s64_u64(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul preinterpret<Packet2ul, Packet2l>(const Packet2l& a) {
|
||||
return vreinterpretq_u64_s64(a);
|
||||
return preinterpret<Packet16c>(pcast<Packet2ul, Packet16uc>(a, b, c, d, e, f, g, h));
|
||||
}
|
||||
|
||||
#if EIGEN_ARCH_ARM64
|
||||
@@ -1193,6 +1193,31 @@ EIGEN_STRONG_INLINE Packet2ul preinterpret<Packet2ul, Packet2l>(const Packet2l&
|
||||
// pcast/preinterpret, Double
|
||||
//==============================================================================
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d preinterpret<Packet2d, Packet2l>(const Packet2l& a) {
|
||||
return Packet2d(vreinterpretq_f64_s64(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d preinterpret<Packet2d, Packet2ul>(const Packet2ul& a) {
|
||||
return Packet2d(vreinterpretq_f64_u64(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l preinterpret<Packet2l, Packet2d>(const Packet2d& a) {
|
||||
return Packet2l(vreinterpretq_s64_f64(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul preinterpret<Packet2ul, Packet2d>(const Packet2d& a) {
|
||||
return Packet2ul(vreinterpretq_u64_f64(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d preinterpret<Packet2d, Packet4i>(const Packet4i& a) {
|
||||
return Packet2d(vreinterpretq_f64_s32(a));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i preinterpret<Packet4i, Packet2d>(const Packet2d& a) {
|
||||
return Packet4i(vreinterpretq_s32_f64(a));
|
||||
}
|
||||
|
||||
template <>
|
||||
struct type_casting_traits<double, double> {
|
||||
enum { VectorizedCast = 1, SrcCoeffRatio = 1, TgtCoeffRatio = 1 };
|
||||
@@ -1314,7 +1339,9 @@ struct type_casting_traits<numext::int8_t, double> {
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pcast<Packet16c, Packet2d>(const Packet16c& a) {
|
||||
// Discard all but first two values.
|
||||
return vcvt_f64_f32(pcast<Packet8c, Packet2f>(vget_low_s8(a)));
|
||||
// MSVC defines most intrinsics as macros, so we need to do this in two lines for portability.
|
||||
Packet2f tmp = pcast<Packet8c, Packet2f>(vget_low_s8(a));
|
||||
return vcvt_f64_f32(tmp);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1324,7 +1351,8 @@ struct type_casting_traits<numext::uint8_t, double> {
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pcast<Packet16uc, Packet2d>(const Packet16uc& a) {
|
||||
// Discard all but first two values.
|
||||
return vcvt_f64_f32(pcast<Packet8uc, Packet2f>(vget_low_u8(a)));
|
||||
Packet2f tmp = pcast<Packet8uc, Packet2f>(vget_low_u8(a));
|
||||
return vcvt_f64_f32(tmp);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1334,7 +1362,8 @@ struct type_casting_traits<numext::int16_t, double> {
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pcast<Packet8s, Packet2d>(const Packet8s& a) {
|
||||
// Discard all but first two values.
|
||||
return vcvt_f64_f32(pcast<Packet4s, Packet2f>(vget_low_s16(a)));
|
||||
Packet2f tmp = pcast<Packet4s, Packet2f>(vget_low_s16(a));
|
||||
return vcvt_f64_f32(tmp);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1344,7 +1373,8 @@ struct type_casting_traits<numext::uint16_t, double> {
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pcast<Packet8us, Packet2d>(const Packet8us& a) {
|
||||
// Discard all but first two values.
|
||||
return vcvt_f64_f32(pcast<Packet4us, Packet2f>(vget_low_u16(a)));
|
||||
Packet2f tmp = pcast<Packet4us, Packet2f>(vget_low_u16(a));
|
||||
return vcvt_f64_f32(tmp);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1385,31 +1415,6 @@ EIGEN_STRONG_INLINE Packet2d pcast<Packet2ul, Packet2d>(const Packet2ul& a) {
|
||||
return vcvtq_f64_u64(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d preinterpret<Packet2d, Packet2l>(const Packet2l& a) {
|
||||
return vreinterpretq_f64_s64(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d preinterpret<Packet2d, Packet2ul>(const Packet2ul& a) {
|
||||
return vreinterpretq_f64_u64(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2l preinterpret<Packet2l, Packet2d>(const Packet2d& a) {
|
||||
return vreinterpretq_s64_f64(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2ul preinterpret<Packet2ul, Packet2d>(const Packet2d& a) {
|
||||
return vreinterpretq_u64_f64(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d preinterpret<Packet2d, Packet4i>(const Packet4i& a) {
|
||||
return vreinterpretq_f64_s32(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i preinterpret<Packet4i, Packet2d>(const Packet2d& a) {
|
||||
return vreinterpretq_s32_f64(a);
|
||||
}
|
||||
|
||||
#endif // EIGEN_ARCH_ARM64
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
@@ -19,7 +19,7 @@ struct Packet2cf
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf() {}
|
||||
EIGEN_STRONG_INLINE explicit Packet2cf(const __m128& a) : v(a) {}
|
||||
__m128 v;
|
||||
Packet4f v;
|
||||
};
|
||||
|
||||
// Use the packet_traits defined in AVX/PacketMath.h instead if we're going
|
||||
@@ -66,12 +66,6 @@ template<> struct unpacket_traits<Packet2cf> {
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_add_ps(a.v,b.v)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_sub_ps(a.v,b.v)); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pxor<Packet2cf>(const Packet2cf& a, const Packet2cf& b);
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf paddsub<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
const Packet4f mask = _mm_castsi128_ps(_mm_setr_epi32(0x80000000,0x80000000,0x0,0x0));
|
||||
return Packet2cf(padd(a.v, pxor(mask, b.v)));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a)
|
||||
{
|
||||
@@ -112,14 +106,9 @@ template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<fl
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
|
||||
{
|
||||
Packet2cf res;
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
res.v = _mm_castpd_ps(_mm_loaddup_pd(reinterpret_cast<double const*>(&from)));
|
||||
#else
|
||||
res.v = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<double const*>(&from)));
|
||||
res.v = _mm_movelh_ps(res.v, res.v);
|
||||
#endif
|
||||
return res;
|
||||
const float re = std::real(from);
|
||||
const float im = std::imag(from);
|
||||
return Packet2cf(_mm_set_ps(im, re, im, re));
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { return pset1<Packet2cf>(*from); }
|
||||
@@ -171,82 +160,24 @@ template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const P
|
||||
return pfirst(pmul(a, Packet2cf(_mm_movehl_ps(a.v,a.v))));
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
return internal::pmul(a, pconj(b));
|
||||
#else
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000));
|
||||
return Packet2cf(_mm_add_ps(_mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v), mask),
|
||||
_mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
|
||||
vec4f_swizzle1(b.v, 1, 0, 3, 2))));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
return internal::pmul(pconj(a), b);
|
||||
#else
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000));
|
||||
return Packet2cf(_mm_add_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v),
|
||||
_mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
|
||||
vec4f_swizzle1(b.v, 1, 0, 3, 2)), mask)));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
return pconj(internal::pmul(a, b));
|
||||
#else
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000));
|
||||
return Packet2cf(_mm_sub_ps(_mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v), mask),
|
||||
_mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
|
||||
vec4f_swizzle1(b.v, 1, 0, 3, 2))));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
// TODO optimize it for SSE3 and 4
|
||||
Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a,b);
|
||||
__m128 s = _mm_mul_ps(b.v,b.v);
|
||||
return Packet2cf(_mm_div_ps(res.v,_mm_add_ps(s,_mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(s), 0xb1)))));
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pcplxflip/* <Packet2cf> */(const Packet2cf& x)
|
||||
{
|
||||
return Packet2cf(vec4f_swizzle1(x.v, 1, 0, 3, 2));
|
||||
}
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
//---------- double ----------
|
||||
struct Packet1cd
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd() {}
|
||||
EIGEN_STRONG_INLINE explicit Packet1cd(const __m128d& a) : v(a) {}
|
||||
__m128d v;
|
||||
Packet2d v;
|
||||
};
|
||||
|
||||
// Use the packet_traits defined in AVX/PacketMath.h instead if we're going
|
||||
@@ -354,68 +285,11 @@ template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const
|
||||
return pfirst(a);
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
return internal::pmul(a, pconj(b));
|
||||
#else
|
||||
const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
|
||||
return Packet1cd(_mm_add_pd(_mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v), mask),
|
||||
_mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
|
||||
vec2d_swizzle1(b.v, 1, 0))));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
return internal::pmul(pconj(a), b);
|
||||
#else
|
||||
const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
|
||||
return Packet1cd(_mm_add_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v),
|
||||
_mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
|
||||
vec2d_swizzle1(b.v, 1, 0)), mask)));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
return pconj(internal::pmul(a, b));
|
||||
#else
|
||||
const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
|
||||
return Packet1cd(_mm_sub_pd(_mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v), mask),
|
||||
_mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
|
||||
vec2d_swizzle1(b.v, 1, 0))));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
|
||||
{
|
||||
// TODO optimize it for SSE3 and 4
|
||||
Packet1cd res = conj_helper<Packet1cd,Packet1cd,false,true>().pmul(a,b);
|
||||
__m128d s = _mm_mul_pd(b.v,b.v);
|
||||
return Packet1cd(_mm_div_pd(res.v, _mm_add_pd(s,_mm_shuffle_pd(s, s, 0x1))));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pcplxflip/* <Packet1cd> */(const Packet1cd& x)
|
||||
|
||||
@@ -444,7 +444,7 @@ template<> EIGEN_STRONG_INLINE Packet16b pcmp_eq(const Packet16b& a, const Packe
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pcmp_le(const Packet4i& a, const Packet4i& b) { return por(pcmp_lt(a,b), pcmp_eq(a,b)); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b) {
|
||||
#if EIGEN_COMP_GNUC && EIGEN_COMP_GNUC < 63
|
||||
#if EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC < 63
|
||||
// There appears to be a bug in GCC, by which the optimizer may
|
||||
// flip the argument order in calls to _mm_min_ps, so we have to
|
||||
// resort to inline ASM here. This is supposed to be fixed in gcc6.3,
|
||||
@@ -463,7 +463,7 @@ template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const
|
||||
#endif
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet2d pmin<Packet2d>(const Packet2d& a, const Packet2d& b) {
|
||||
#if EIGEN_COMP_GNUC && EIGEN_COMP_GNUC < 63
|
||||
#if EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC < 63
|
||||
// There appears to be a bug in GCC, by which the optimizer may
|
||||
// flip the argument order in calls to _mm_min_pd, so we have to
|
||||
// resort to inline ASM here. This is supposed to be fixed in gcc6.3,
|
||||
@@ -494,7 +494,7 @@ template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const
|
||||
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b) {
|
||||
#if EIGEN_COMP_GNUC && EIGEN_COMP_GNUC < 63
|
||||
#if EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC < 63
|
||||
// There appears to be a bug in GCC, by which the optimizer may
|
||||
// flip the argument order in calls to _mm_max_ps, so we have to
|
||||
// resort to inline ASM here. This is supposed to be fixed in gcc6.3,
|
||||
@@ -513,7 +513,7 @@ template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const
|
||||
#endif
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet2d pmax<Packet2d>(const Packet2d& a, const Packet2d& b) {
|
||||
#if EIGEN_COMP_GNUC && EIGEN_COMP_GNUC < 63
|
||||
#if EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC < 63
|
||||
// There appears to be a bug in GCC, by which the optimizer may
|
||||
// flip the argument order in calls to _mm_max_pd, so we have to
|
||||
// resort to inline ASM here. This is supposed to be fixed in gcc6.3,
|
||||
|
||||
@@ -22,10 +22,6 @@ namespace internal
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#endif
|
||||
|
||||
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 32
|
||||
|
||||
template <typename Scalar, int SVEVectorLength>
|
||||
|
||||
@@ -16,7 +16,9 @@ namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
#if !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ >= 12)
|
||||
static Packet4ui p4ui_CONJ_XOR = { 0x00000000, 0x80000000, 0x00000000, 0x80000000 }; //vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO);
|
||||
inline Packet4ui p4ui_CONJ_XOR() {
|
||||
return { 0x00000000, 0x80000000, 0x00000000, 0x80000000 }; //vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO);
|
||||
}
|
||||
#endif
|
||||
|
||||
static Packet2ul p2ul_CONJ_XOR1 = (Packet2ul) vec_sld((Packet4ui) p2d_ZERO_, (Packet4ui) p2l_ZERO, 8);//{ 0x8000000000000000, 0x0000000000000000 };
|
||||
@@ -91,8 +93,18 @@ template<> struct packet_traits<std::complex<double> > : default_packet_traits
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false}; typedef Packet2cf half; };
|
||||
template<> struct unpacket_traits<Packet1cd> { typedef std::complex<double> type; enum {size=1, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false}; typedef Packet1cd half; };
|
||||
template<> struct unpacket_traits<Packet2cf> {
|
||||
typedef std::complex<float> type;
|
||||
enum {size=2, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false};
|
||||
typedef Packet2cf half;
|
||||
typedef Packet4f as_real;
|
||||
};
|
||||
template<> struct unpacket_traits<Packet1cd> {
|
||||
typedef std::complex<double> type;
|
||||
enum {size=1, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false};
|
||||
typedef Packet1cd half;
|
||||
typedef Packet2d as_real;
|
||||
};
|
||||
|
||||
/* Forward declaration */
|
||||
EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet2cf,2>& kernel);
|
||||
@@ -150,7 +162,7 @@ template<> EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::c
|
||||
|
||||
template<> EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet1cd>(const Packet1cd& a)
|
||||
{
|
||||
std::complex<double> EIGEN_ALIGN16 res;
|
||||
EIGEN_ALIGN16 std::complex<double> res;
|
||||
pstore<std::complex<double> >(&res, a);
|
||||
|
||||
return res;
|
||||
@@ -165,47 +177,11 @@ template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const
|
||||
{
|
||||
return pfirst(a);
|
||||
}
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet1cd, Packet1cd, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
|
||||
{
|
||||
// TODO optimize it for AltiVec
|
||||
Packet1cd res = conj_helper<Packet1cd,Packet1cd,false,true>().pmul(a,b);
|
||||
Packet2d s = vec_madd(b.v, b.v, p2d_ZERO_);
|
||||
return Packet1cd(pdiv(res.v, s + vec_perm(s, s, p16uc_REVERSE64)));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pcplxflip/*<Packet1cd>*/(const Packet1cd& x)
|
||||
@@ -228,7 +204,7 @@ template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<f
|
||||
|
||||
template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a)
|
||||
{
|
||||
std::complex<float> EIGEN_ALIGN16 res[2];
|
||||
EIGEN_ALIGN16 std::complex<float> res[2];
|
||||
pstore<std::complex<float> >(res, a);
|
||||
|
||||
return res[0];
|
||||
@@ -258,14 +234,14 @@ template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<flo
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from, Index stride)
|
||||
{
|
||||
std::complex<float> EIGEN_ALIGN16 af[2];
|
||||
EIGEN_ALIGN16 std::complex<float> af[2];
|
||||
af[0] = from[0*stride];
|
||||
af[1] = from[1*stride];
|
||||
return pload<Packet2cf>(af);
|
||||
}
|
||||
template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to, const Packet2cf& from, Index stride)
|
||||
{
|
||||
std::complex<float> EIGEN_ALIGN16 af[2];
|
||||
EIGEN_ALIGN16 std::complex<float> af[2];
|
||||
pstore<std::complex<float> >((std::complex<float> *) af, from);
|
||||
to[0*stride] = af[0];
|
||||
to[1*stride] = af[1];
|
||||
@@ -337,48 +313,11 @@ template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const P
|
||||
return res;
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
// TODO optimize it for AltiVec
|
||||
Packet2cf res;
|
||||
res.cd[0] = pdiv<Packet1cd>(a.cd[0], b.cd[0]);
|
||||
res.cd[1] = pdiv<Packet1cd>(a.cd[1], b.cd[1]);
|
||||
return res;
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pcplxflip/*<Packet2cf>*/(const Packet2cf& x)
|
||||
@@ -408,7 +347,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pcmp_eq(const Packet2cf& a, const Packe
|
||||
Packet4f tmp = { eq[1], eq[0], eq[3], eq[2] };
|
||||
return (Packet2cf)pand<Packet4f>(eq, tmp);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) { return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR))); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) { return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR()))); }
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
Packet4f a_re, a_im, prod, prod_im;
|
||||
@@ -421,7 +360,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, con
|
||||
|
||||
// multiply a_im * b and get the conjugate result
|
||||
prod_im = a_im * b.v;
|
||||
prod_im = pxor<Packet4f>(prod_im, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR));
|
||||
prod_im = pxor<Packet4f>(prod_im, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR()));
|
||||
// permute back to a proper order
|
||||
prod_im = vec_perm(prod_im, prod_im, p16uc_COMPLEX32_REV);
|
||||
|
||||
@@ -456,47 +395,11 @@ template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const P
|
||||
return pfirst<Packet2cf>(prod);
|
||||
}
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return internal::pmul(a, pconj(b));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return internal::pmul(pconj(a), b);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
|
||||
{ return padd(pmul(x,y),c); }
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
|
||||
{
|
||||
return pconj(internal::pmul(a, b));
|
||||
}
|
||||
};
|
||||
|
||||
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f)
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||
{
|
||||
// TODO optimize it for AltiVec
|
||||
Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a, b);
|
||||
Packet4f s = pmul<Packet4f>(b.v, b.v);
|
||||
return Packet2cf(pdiv(res.v, padd<Packet4f>(s, vec_perm(s, s, p16uc_COMPLEX32_REV))));
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x)
|
||||
|
||||
@@ -22,10 +22,6 @@ namespace internal {
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_MADD
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#define EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
|
||||
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 32
|
||||
#endif
|
||||
@@ -94,8 +90,9 @@ static _EIGEN_DECLARE_CONST_FAST_Packet2d(ZERO, 0);
|
||||
static _EIGEN_DECLARE_CONST_FAST_Packet2l(ZERO, 0);
|
||||
static _EIGEN_DECLARE_CONST_FAST_Packet2l(ONE, 1);
|
||||
|
||||
static Packet2d p2d_ONE = { 1.0, 1.0 };
|
||||
static Packet2d p2d_ZERO_ = { -0.0, -0.0 };
|
||||
static Packet2d p2d_ONE = { 1.0, 1.0 };
|
||||
static Packet2d p2d_ZERO_ = { numext::bit_cast<double>(0x8000000000000000ull),
|
||||
numext::bit_cast<double>(0x8000000000000000ull) };
|
||||
|
||||
#if !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ >= 12)
|
||||
#define _EIGEN_DECLARE_CONST_FAST_Packet4f(NAME,X) \
|
||||
@@ -361,7 +358,7 @@ pbroadcast4<Packet2d>(const double *a,
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int, Packet4i>(const int* from, Index stride)
|
||||
{
|
||||
int EIGEN_ALIGN16 ai[4];
|
||||
EIGEN_ALIGN16 int ai[4];
|
||||
ai[0] = from[0*stride];
|
||||
ai[1] = from[1*stride];
|
||||
ai[2] = from[2*stride];
|
||||
@@ -371,7 +368,7 @@ template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int, Packet4i>(const int* f
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet2d pgather<double, Packet2d>(const double* from, Index stride)
|
||||
{
|
||||
double EIGEN_ALIGN16 af[2];
|
||||
EIGEN_ALIGN16 double af[2];
|
||||
af[0] = from[0*stride];
|
||||
af[1] = from[1*stride];
|
||||
return pload<Packet2d>(af);
|
||||
@@ -379,7 +376,7 @@ template<> EIGEN_DEVICE_FUNC inline Packet2d pgather<double, Packet2d>(const dou
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const Packet4i& from, Index stride)
|
||||
{
|
||||
int EIGEN_ALIGN16 ai[4];
|
||||
EIGEN_ALIGN16 int ai[4];
|
||||
pstore<int>((int *)ai, from);
|
||||
to[0*stride] = ai[0];
|
||||
to[1*stride] = ai[1];
|
||||
@@ -389,7 +386,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline void pscatter<double, Packet2d>(double* to, const Packet2d& from, Index stride)
|
||||
{
|
||||
double EIGEN_ALIGN16 af[2];
|
||||
EIGEN_ALIGN16 double af[2];
|
||||
pstore<double>(af, from);
|
||||
to[0*stride] = af[0];
|
||||
to[1*stride] = af[1];
|
||||
@@ -463,8 +460,8 @@ template<> EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const Packet2d&
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { EIGEN_ZVECTOR_PREFETCH(addr); }
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { EIGEN_ZVECTOR_PREFETCH(addr); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { int EIGEN_ALIGN16 x[4]; pstore(x, a); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE double pfirst<Packet2d>(const Packet2d& a) { double EIGEN_ALIGN16 x[2]; pstore(x, a); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { EIGEN_ALIGN16 int x[4]; pstore(x, a); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE double pfirst<Packet2d>(const Packet2d& a) { EIGEN_ALIGN16 double x[2]; pstore(x, a); return x[0]; }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4i preverse(const Packet4i& a)
|
||||
{
|
||||
@@ -642,7 +639,7 @@ pbroadcast4<Packet4f>(const float *a,
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const float* from, Index stride)
|
||||
{
|
||||
float EIGEN_ALIGN16 ai[4];
|
||||
EIGEN_ALIGN16 float ai[4];
|
||||
ai[0] = from[0*stride];
|
||||
ai[1] = from[1*stride];
|
||||
ai[2] = from[2*stride];
|
||||
@@ -652,7 +649,7 @@ template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const floa
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet4f>(float* to, const Packet4f& from, Index stride)
|
||||
{
|
||||
float EIGEN_ALIGN16 ai[4];
|
||||
EIGEN_ALIGN16 float ai[4];
|
||||
pstore<float>((float *)ai, from);
|
||||
to[0*stride] = ai[0];
|
||||
to[1*stride] = ai[1];
|
||||
@@ -788,7 +785,7 @@ template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||
return p;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[2]; vec_st2f(a.v4f[0], &x[0]); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { EIGEN_ALIGN16 float x[2]; vec_st2f(a.v4f[0], &x[0]); return x[0]; }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a)
|
||||
{
|
||||
@@ -946,7 +943,7 @@ pbroadcast4<Packet4f>(const float *a,
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const float* from, Index stride)
|
||||
{
|
||||
float EIGEN_ALIGN16 af[4];
|
||||
EIGEN_ALIGN16 float af[4];
|
||||
af[0] = from[0*stride];
|
||||
af[1] = from[1*stride];
|
||||
af[2] = from[2*stride];
|
||||
@@ -956,7 +953,7 @@ template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const floa
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet4f>(float* to, const Packet4f& from, Index stride)
|
||||
{
|
||||
float EIGEN_ALIGN16 af[4];
|
||||
EIGEN_ALIGN16 float af[4];
|
||||
pstore<float>((float*)af, from);
|
||||
to[0*stride] = af[0];
|
||||
to[1*stride] = af[1];
|
||||
@@ -981,7 +978,7 @@ template<> EIGEN_STRONG_INLINE Packet4f pround<Packet4f> (const Packet4f& a) { r
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pceil<Packet4f> (const Packet4f& a) { return vec_ceil(a); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pfloor<Packet4f> (const Packet4f& a) { return vec_floor(a); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pabs<Packet4f> (const Packet4f& a) { return vec_abs(a); }
|
||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; pstore(x, a); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { EIGEN_ALIGN16 float x[4]; pstore(x, a); return x[0]; }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ struct scalar_sum_op : binary_op_base<LhsScalar,RhsScalar>
|
||||
template<typename LhsScalar,typename RhsScalar>
|
||||
struct functor_traits<scalar_sum_op<LhsScalar,RhsScalar> > {
|
||||
enum {
|
||||
Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2, // rough estimate!
|
||||
Cost = (int(NumTraits<LhsScalar>::AddCost) + int(NumTraits<RhsScalar>::AddCost)) / 2, // rough estimate!
|
||||
PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasAdd && packet_traits<RhsScalar>::HasAdd
|
||||
// TODO vectorize mixed sum
|
||||
};
|
||||
@@ -88,7 +88,7 @@ struct scalar_product_op : binary_op_base<LhsScalar,RhsScalar>
|
||||
template<typename LhsScalar,typename RhsScalar>
|
||||
struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
|
||||
enum {
|
||||
Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
|
||||
Cost = (int(NumTraits<LhsScalar>::MulCost) + int(NumTraits<RhsScalar>::MulCost))/2, // rough estimate!
|
||||
PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
|
||||
// TODO vectorize mixed product
|
||||
};
|
||||
@@ -364,7 +364,7 @@ struct scalar_difference_op : binary_op_base<LhsScalar,RhsScalar>
|
||||
template<typename LhsScalar,typename RhsScalar>
|
||||
struct functor_traits<scalar_difference_op<LhsScalar,RhsScalar> > {
|
||||
enum {
|
||||
Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
|
||||
Cost = (int(NumTraits<LhsScalar>::AddCost) + int(NumTraits<RhsScalar>::AddCost)) / 2,
|
||||
PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasSub && packet_traits<RhsScalar>::HasSub
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,6 +12,28 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// Portable replacements for certain functors.
|
||||
namespace numext {
|
||||
|
||||
template<typename T = void>
|
||||
struct equal_to {
|
||||
typedef bool result_type;
|
||||
EIGEN_DEVICE_FUNC bool operator()(const T& lhs, const T& rhs) const {
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T = void>
|
||||
struct not_equal_to {
|
||||
typedef bool result_type;
|
||||
EIGEN_DEVICE_FUNC bool operator()(const T& lhs, const T& rhs) const {
|
||||
return lhs != rhs;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace internal {
|
||||
|
||||
// default functor traits for STL functors:
|
||||
@@ -68,10 +90,18 @@ template<typename T>
|
||||
struct functor_traits<std::equal_to<T> >
|
||||
{ enum { Cost = 1, PacketAccess = false }; };
|
||||
|
||||
template<typename T>
|
||||
struct functor_traits<numext::equal_to<T> >
|
||||
: functor_traits<std::equal_to<T> > {};
|
||||
|
||||
template<typename T>
|
||||
struct functor_traits<std::not_equal_to<T> >
|
||||
{ enum { Cost = 1, PacketAccess = false }; };
|
||||
|
||||
template<typename T>
|
||||
struct functor_traits<numext::not_equal_to<T> >
|
||||
: functor_traits<std::not_equal_to<T> > {};
|
||||
|
||||
#if (EIGEN_COMP_CXXVER < 11)
|
||||
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||
template<typename T>
|
||||
|
||||
@@ -109,7 +109,7 @@ struct functor_traits<scalar_abs2_op<Scalar> >
|
||||
template<typename Scalar> struct scalar_conjugate_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { using numext::conj; return conj(a); }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::conj(a); }
|
||||
template<typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
|
||||
};
|
||||
@@ -138,7 +138,7 @@ struct functor_traits<scalar_conjugate_op<Scalar> >
|
||||
template<typename Scalar> struct scalar_arg_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_arg_op)
|
||||
typedef typename NumTraits<Scalar>::Real result_type;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { using numext::arg; return arg(a); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::arg(a); }
|
||||
template<typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
|
||||
{ return internal::parg(a); }
|
||||
|
||||
@@ -44,7 +44,7 @@ inline std::ptrdiff_t manage_caching_sizes_helper(std::ptrdiff_t a, std::ptrdiff
|
||||
#endif // defined(EIGEN_DEFAULT_L2_CACHE_SIZE)
|
||||
|
||||
#if defined(EIGEN_DEFAULT_L3_CACHE_SIZE)
|
||||
#define EIGEN_SET_DEFAULT_L3_CACHE_SIZE(val) EIGEN_SET_DEFAULT_L3_CACHE_SIZE
|
||||
#define EIGEN_SET_DEFAULT_L3_CACHE_SIZE(val) EIGEN_DEFAULT_L3_CACHE_SIZE
|
||||
#else
|
||||
#define EIGEN_SET_DEFAULT_L3_CACHE_SIZE(val) val
|
||||
#endif // defined(EIGEN_DEFAULT_L3_CACHE_SIZE)
|
||||
@@ -349,36 +349,6 @@ inline void computeProductBlockingSizes(Index& k, Index& m, Index& n, Index num_
|
||||
computeProductBlockingSizes<LhsScalar,RhsScalar,1,Index>(k, m, n, num_threads);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
|
||||
#define CJMADD(CJ,A,B,C,T) C = CJ.pmadd(A,B,C);
|
||||
#else
|
||||
|
||||
// FIXME (a bit overkill maybe ?)
|
||||
|
||||
template<typename CJ, typename A, typename B, typename C, typename T> struct gebp_madd_selector {
|
||||
EIGEN_ALWAYS_INLINE static void run(const CJ& cj, A& a, B& b, C& c, T& /*t*/)
|
||||
{
|
||||
c = cj.pmadd(a,b,c);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CJ, typename T> struct gebp_madd_selector<CJ,T,T,T,T> {
|
||||
EIGEN_ALWAYS_INLINE static void run(const CJ& cj, T& a, T& b, T& c, T& t)
|
||||
{
|
||||
t = b; t = cj.pmul(a,t); c = padd(c,t);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CJ, typename A, typename B, typename C, typename T>
|
||||
EIGEN_STRONG_INLINE void gebp_madd(const CJ& cj, A& a, B& b, C& c, T& t)
|
||||
{
|
||||
gebp_madd_selector<CJ,A,B,C,T>::run(cj,a,b,c,t);
|
||||
}
|
||||
|
||||
#define CJMADD(CJ,A,B,C,T) gebp_madd(CJ,A,B,C,T);
|
||||
// #define CJMADD(CJ,A,B,C,T) T = B; T = CJ.pmul(A,T); C = padd(C,T);
|
||||
#endif
|
||||
|
||||
template <typename RhsPacket, typename RhsPacketx4, int registers_taken>
|
||||
struct RhsPanelHelper {
|
||||
private:
|
||||
@@ -1673,8 +1643,8 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
||||
EIGEN_GEBGP_ONESTEP(6);
|
||||
EIGEN_GEBGP_ONESTEP(7);
|
||||
|
||||
blB += pk*RhsProgress;
|
||||
blA += pk*3*Traits::LhsProgress;
|
||||
blB += int(pk) * int(RhsProgress);
|
||||
blA += int(pk) * 3 * int(Traits::LhsProgress);
|
||||
|
||||
EIGEN_ASM_COMMENT("end gebp micro kernel 3pX1");
|
||||
}
|
||||
@@ -1885,8 +1855,8 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
||||
EIGEN_GEBGP_ONESTEP(6);
|
||||
EIGEN_GEBGP_ONESTEP(7);
|
||||
|
||||
blB += pk*RhsProgress;
|
||||
blA += pk*2*Traits::LhsProgress;
|
||||
blB += int(pk) * int(RhsProgress);
|
||||
blA += int(pk) * 2 * int(Traits::LhsProgress);
|
||||
|
||||
EIGEN_ASM_COMMENT("end gebp micro kernel 2pX1");
|
||||
}
|
||||
@@ -2060,14 +2030,14 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
||||
|
||||
B_0 = blB[0];
|
||||
B_1 = blB[1];
|
||||
CJMADD(cj,A0,B_0,C0, B_0);
|
||||
CJMADD(cj,A0,B_1,C1, B_1);
|
||||
|
||||
C0 = cj.pmadd(A0,B_0,C0);
|
||||
C1 = cj.pmadd(A0,B_1,C1);
|
||||
|
||||
B_0 = blB[2];
|
||||
B_1 = blB[3];
|
||||
CJMADD(cj,A0,B_0,C2, B_0);
|
||||
CJMADD(cj,A0,B_1,C3, B_1);
|
||||
|
||||
C2 = cj.pmadd(A0,B_0,C2);
|
||||
C3 = cj.pmadd(A0,B_1,C3);
|
||||
|
||||
blB += 4;
|
||||
}
|
||||
res(i, j2 + 0) += alpha * C0;
|
||||
@@ -2092,7 +2062,7 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
||||
{
|
||||
LhsScalar A0 = blA[k];
|
||||
RhsScalar B_0 = blB[k];
|
||||
CJMADD(cj, A0, B_0, C0, B_0);
|
||||
C0 = cj.pmadd(A0, B_0, C0);
|
||||
}
|
||||
res(i, j2) += alpha * C0;
|
||||
}
|
||||
@@ -2101,8 +2071,6 @@ void gebp_kernel<LhsScalar,RhsScalar,Index,DataMapper,mr,nr,ConjugateLhs,Conjuga
|
||||
}
|
||||
|
||||
|
||||
#undef CJMADD
|
||||
|
||||
// pack a block of the lhs
|
||||
// The traversal is as follow (mr==4):
|
||||
// 0 4 8 12 ...
|
||||
@@ -2301,8 +2269,8 @@ EIGEN_DONT_INLINE void gemm_pack_lhs<Scalar, Index, DataMapper, Pack1, Pack2, Pa
|
||||
bool gone_half = false, gone_quarter = false, gone_last = false;
|
||||
|
||||
Index i = 0;
|
||||
int pack = Pack1;
|
||||
int psize = PacketSize;
|
||||
Index pack = Pack1;
|
||||
Index psize = PacketSize;
|
||||
while(pack>0)
|
||||
{
|
||||
Index remaining_rows = rows-i;
|
||||
@@ -2322,21 +2290,21 @@ EIGEN_DONT_INLINE void gemm_pack_lhs<Scalar, Index, DataMapper, Pack1, Pack2, Pa
|
||||
{
|
||||
if (psize == PacketSize) {
|
||||
PacketBlock<Packet> kernel;
|
||||
for (int p = 0; p < psize; ++p) kernel.packet[p] = lhs.template loadPacket<Packet>(i+p+m, k);
|
||||
for (Index p = 0; p < psize; ++p) kernel.packet[p] = lhs.template loadPacket<Packet>(i+p+m, k);
|
||||
ptranspose(kernel);
|
||||
for (int p = 0; p < psize; ++p) pstore(blockA+count+m+(pack)*p, cj.pconj(kernel.packet[p]));
|
||||
for (Index p = 0; p < psize; ++p) pstore(blockA+count+m+(pack)*p, cj.pconj(kernel.packet[p]));
|
||||
} else if (HasHalf && psize == HalfPacketSize) {
|
||||
gone_half = true;
|
||||
PacketBlock<HalfPacket> kernel_half;
|
||||
for (int p = 0; p < psize; ++p) kernel_half.packet[p] = lhs.template loadPacket<HalfPacket>(i+p+m, k);
|
||||
for (Index p = 0; p < psize; ++p) kernel_half.packet[p] = lhs.template loadPacket<HalfPacket>(i+p+m, k);
|
||||
ptranspose(kernel_half);
|
||||
for (int p = 0; p < psize; ++p) pstore(blockA+count+m+(pack)*p, cj.pconj(kernel_half.packet[p]));
|
||||
for (Index p = 0; p < psize; ++p) pstore(blockA+count+m+(pack)*p, cj.pconj(kernel_half.packet[p]));
|
||||
} else if (HasQuarter && psize == QuarterPacketSize) {
|
||||
gone_quarter = true;
|
||||
PacketBlock<QuarterPacket> kernel_quarter;
|
||||
for (int p = 0; p < psize; ++p) kernel_quarter.packet[p] = lhs.template loadPacket<QuarterPacket>(i+p+m, k);
|
||||
for (Index p = 0; p < psize; ++p) kernel_quarter.packet[p] = lhs.template loadPacket<QuarterPacket>(i+p+m, k);
|
||||
ptranspose(kernel_quarter);
|
||||
for (int p = 0; p < psize; ++p) pstore(blockA+count+m+(pack)*p, cj.pconj(kernel_quarter.packet[p]));
|
||||
for (Index p = 0; p < psize; ++p) pstore(blockA+count+m+(pack)*p, cj.pconj(kernel_quarter.packet[p]));
|
||||
}
|
||||
}
|
||||
count += psize*pack;
|
||||
|
||||
@@ -59,9 +59,9 @@ typedef gebp_traits<LhsScalar,RhsScalar> Traits;
|
||||
|
||||
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
||||
static void run(Index rows, Index cols, Index depth,
|
||||
const LhsScalar* _lhs, Index lhsStride,
|
||||
const RhsScalar* _rhs, Index rhsStride,
|
||||
ResScalar* _res, Index resIncr, Index resStride,
|
||||
const LhsScalar* lhs_, Index lhsStride,
|
||||
const RhsScalar* rhs_, Index rhsStride,
|
||||
ResScalar* res_, Index resIncr, Index resStride,
|
||||
ResScalar alpha,
|
||||
level3_blocking<LhsScalar,RhsScalar>& blocking,
|
||||
GemmParallelInfo<Index>* info = 0)
|
||||
@@ -69,9 +69,9 @@ static void run(Index rows, Index cols, Index depth,
|
||||
typedef const_blas_data_mapper<LhsScalar, Index, LhsStorageOrder> LhsMapper;
|
||||
typedef const_blas_data_mapper<RhsScalar, Index, RhsStorageOrder> RhsMapper;
|
||||
typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor,Unaligned,ResInnerStride> ResMapper;
|
||||
LhsMapper lhs(_lhs, lhsStride);
|
||||
RhsMapper rhs(_rhs, rhsStride);
|
||||
ResMapper res(_res, resStride, resIncr);
|
||||
LhsMapper lhs(lhs_, lhsStride);
|
||||
RhsMapper rhs(rhs_, rhsStride);
|
||||
ResMapper res(res_, resStride, resIncr);
|
||||
|
||||
Index kc = blocking.kc(); // cache block size along the K direction
|
||||
Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction
|
||||
|
||||
@@ -60,9 +60,9 @@ template <typename Index, typename LhsScalar, int LhsStorageOrder, bool Conjugat
|
||||
struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,UpLo,Version>
|
||||
{
|
||||
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar;
|
||||
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* _lhs, Index lhsStride,
|
||||
const RhsScalar* _rhs, Index rhsStride,
|
||||
ResScalar* _res, Index resIncr, Index resStride,
|
||||
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* lhs_, Index lhsStride,
|
||||
const RhsScalar* rhs_, Index rhsStride,
|
||||
ResScalar* res_, Index resIncr, Index resStride,
|
||||
const ResScalar& alpha, level3_blocking<LhsScalar,RhsScalar>& blocking)
|
||||
{
|
||||
typedef gebp_traits<LhsScalar,RhsScalar> Traits;
|
||||
@@ -70,9 +70,9 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
|
||||
typedef const_blas_data_mapper<LhsScalar, Index, LhsStorageOrder> LhsMapper;
|
||||
typedef const_blas_data_mapper<RhsScalar, Index, RhsStorageOrder> RhsMapper;
|
||||
typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor, Unaligned, ResInnerStride> ResMapper;
|
||||
LhsMapper lhs(_lhs,lhsStride);
|
||||
RhsMapper rhs(_rhs,rhsStride);
|
||||
ResMapper res(_res, resStride, resIncr);
|
||||
LhsMapper lhs(lhs_,lhsStride);
|
||||
RhsMapper rhs(rhs_,rhsStride);
|
||||
ResMapper res(res_, resStride, resIncr);
|
||||
|
||||
Index kc = blocking.kc();
|
||||
Index mc = (std::min)(size,blocking.mc());
|
||||
@@ -113,7 +113,7 @@ struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,
|
||||
gebp(res.getSubMapper(i2, 0), blockA, blockB, actual_mc, actual_kc,
|
||||
(std::min)(size,i2), alpha, -1, -1, 0, 0);
|
||||
|
||||
sybb(_res+resStride*i2 + resIncr*i2, resIncr, resStride, blockA, blockB + actual_kc*i2, actual_mc, actual_kc, alpha);
|
||||
sybb(res_+resStride*i2 + resIncr*i2, resIncr, resStride, blockA, blockB + actual_kc*i2, actual_mc, actual_kc, alpha);
|
||||
|
||||
if (UpLo==Upper)
|
||||
{
|
||||
@@ -144,11 +144,11 @@ struct tribb_kernel
|
||||
enum {
|
||||
BlockSize = meta_least_common_multiple<EIGEN_PLAIN_ENUM_MAX(mr,nr),EIGEN_PLAIN_ENUM_MIN(mr,nr)>::ret
|
||||
};
|
||||
void operator()(ResScalar* _res, Index resIncr, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, const ResScalar& alpha)
|
||||
void operator()(ResScalar* res_, Index resIncr, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, const ResScalar& alpha)
|
||||
{
|
||||
typedef blas_data_mapper<ResScalar, Index, ColMajor, Unaligned, ResInnerStride> ResMapper;
|
||||
typedef blas_data_mapper<ResScalar, Index, ColMajor, Unaligned> BufferMapper;
|
||||
ResMapper res(_res, resStride, resIncr);
|
||||
ResMapper res(res_, resStride, resIncr);
|
||||
gebp_kernel<LhsScalar, RhsScalar, Index, ResMapper, mr, nr, ConjLhs, ConjRhs> gebp_kernel1;
|
||||
gebp_kernel<LhsScalar, RhsScalar, Index, BufferMapper, mr, nr, ConjLhs, ConjRhs> gebp_kernel2;
|
||||
|
||||
@@ -300,14 +300,19 @@ struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,false>
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, unsigned int UpLo>
|
||||
template<typename ProductType>
|
||||
EIGEN_DEVICE_FUNC TriangularView<MatrixType,UpLo>& TriangularViewImpl<MatrixType,UpLo,Dense>::_assignProduct(const ProductType& prod, const Scalar& alpha, bool beta)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((UpLo&UnitDiag)==0, WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED);
|
||||
template <typename _MatrixType, unsigned int _Mode>
|
||||
template <typename ProductType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename TriangularViewImpl<_MatrixType, _Mode, Dense>::TriangularViewType&
|
||||
TriangularViewImpl<_MatrixType, _Mode, Dense>::_assignProduct(
|
||||
const ProductType& prod, const typename TriangularViewImpl<_MatrixType, _Mode, Dense>::Scalar& alpha, bool beta) {
|
||||
EIGEN_STATIC_ASSERT((_Mode & UnitDiag) == 0, WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED);
|
||||
eigen_assert(derived().nestedExpression().rows() == prod.rows() && derived().cols() == prod.cols());
|
||||
|
||||
general_product_to_triangular_selector<MatrixType, ProductType, UpLo, internal::traits<ProductType>::InnerSize==1>::run(derived().nestedExpression().const_cast_derived(), prod, alpha, beta);
|
||||
general_product_to_triangular_selector<_MatrixType, ProductType, _Mode,
|
||||
internal::traits<ProductType>::InnerSize == 1>::run(derived()
|
||||
.nestedExpression()
|
||||
.const_cast_derived(),
|
||||
prod, alpha, beta);
|
||||
|
||||
return derived();
|
||||
}
|
||||
|
||||
@@ -359,6 +359,11 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
HasQuarter = (int)ResPacketSizeQuarter < (int)ResPacketSizeHalf
|
||||
};
|
||||
|
||||
typedef typename make_unsigned<Index>::type UnsignedIndex;
|
||||
const Index fullColBlockEnd = LhsPacketSize * (UnsignedIndex(cols) / LhsPacketSize);
|
||||
const Index halfColBlockEnd = LhsPacketSizeHalf * (UnsignedIndex(cols) / LhsPacketSizeHalf);
|
||||
const Index quarterColBlockEnd = LhsPacketSizeQuarter * (UnsignedIndex(cols) / LhsPacketSizeQuarter);
|
||||
|
||||
Index i=0;
|
||||
for(; i<n8; i+=8)
|
||||
{
|
||||
@@ -371,8 +376,7 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
c6 = pset1<ResPacket>(ResScalar(0)),
|
||||
c7 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
for (Index j = 0; j < fullColBlockEnd; j += LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket, Unaligned>(j,0);
|
||||
|
||||
@@ -393,7 +397,8 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
ResScalar cc5 = predux(c5);
|
||||
ResScalar cc6 = predux(c6);
|
||||
ResScalar cc7 = predux(c7);
|
||||
for(; j<cols; ++j)
|
||||
|
||||
for (Index j = fullColBlockEnd; j < cols; ++j)
|
||||
{
|
||||
RhsScalar b0 = rhs(j,0);
|
||||
|
||||
@@ -422,8 +427,7 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
c2 = pset1<ResPacket>(ResScalar(0)),
|
||||
c3 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
for (Index j = 0; j < fullColBlockEnd; j += LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket, Unaligned>(j,0);
|
||||
|
||||
@@ -436,7 +440,8 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
ResScalar cc1 = predux(c1);
|
||||
ResScalar cc2 = predux(c2);
|
||||
ResScalar cc3 = predux(c3);
|
||||
for(; j<cols; ++j)
|
||||
|
||||
for(Index j = fullColBlockEnd; j < cols; ++j)
|
||||
{
|
||||
RhsScalar b0 = rhs(j,0);
|
||||
|
||||
@@ -455,8 +460,7 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
for (Index j = 0; j < fullColBlockEnd; j += LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket, Unaligned>(j,0);
|
||||
|
||||
@@ -465,7 +469,8 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
}
|
||||
ResScalar cc0 = predux(c0);
|
||||
ResScalar cc1 = predux(c1);
|
||||
for(; j<cols; ++j)
|
||||
|
||||
for(Index j = fullColBlockEnd; j < cols; ++j)
|
||||
{
|
||||
RhsScalar b0 = rhs(j,0);
|
||||
|
||||
@@ -480,15 +485,15 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0));
|
||||
ResPacketHalf c0_h = pset1<ResPacketHalf>(ResScalar(0));
|
||||
ResPacketQuarter c0_q = pset1<ResPacketQuarter>(ResScalar(0));
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
|
||||
for (Index j = 0; j < fullColBlockEnd; j += LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket,Unaligned>(j,0);
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i,j),b0,c0);
|
||||
}
|
||||
ResScalar cc0 = predux(c0);
|
||||
if (HasHalf) {
|
||||
for(; j+LhsPacketSizeHalf<=cols; j+=LhsPacketSizeHalf)
|
||||
for (Index j = fullColBlockEnd; j < halfColBlockEnd; j += LhsPacketSizeHalf)
|
||||
{
|
||||
RhsPacketHalf b0 = rhs.template load<RhsPacketHalf,Unaligned>(j,0);
|
||||
c0_h = pcj_half.pmadd(lhs.template load<LhsPacketHalf,LhsAlignment>(i,j),b0,c0_h);
|
||||
@@ -496,14 +501,14 @@ EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void general_matrix_vector_product<Index,Lhs
|
||||
cc0 += predux(c0_h);
|
||||
}
|
||||
if (HasQuarter) {
|
||||
for(; j+LhsPacketSizeQuarter<=cols; j+=LhsPacketSizeQuarter)
|
||||
for (Index j = halfColBlockEnd; j < quarterColBlockEnd; j += LhsPacketSizeQuarter)
|
||||
{
|
||||
RhsPacketQuarter b0 = rhs.template load<RhsPacketQuarter,Unaligned>(j,0);
|
||||
c0_q = pcj_quarter.pmadd(lhs.template load<LhsPacketQuarter,LhsAlignment>(i,j),b0,c0_q);
|
||||
}
|
||||
cc0 += predux(c0_q);
|
||||
}
|
||||
for(; j<cols; ++j)
|
||||
for (Index j = quarterColBlockEnd; j < cols; ++j)
|
||||
{
|
||||
cc0 += cj.pmul(lhs(i,j), rhs(j,0));
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ struct symm_pack_lhs
|
||||
for(Index w=0; w<BlockRows; w++)
|
||||
blockA[count++] = numext::conj(lhs(k, i+w)); // transposed
|
||||
}
|
||||
void operator()(Scalar* blockA, const Scalar* _lhs, Index lhsStride, Index cols, Index rows)
|
||||
void operator()(Scalar* blockA, const Scalar* lhs_, Index lhsStride, Index cols, Index rows)
|
||||
{
|
||||
typedef typename unpacket_traits<typename packet_traits<Scalar>::type>::half HalfPacket;
|
||||
typedef typename unpacket_traits<typename unpacket_traits<typename packet_traits<Scalar>::type>::half>::half QuarterPacket;
|
||||
@@ -53,7 +53,7 @@ struct symm_pack_lhs
|
||||
HasHalf = (int)HalfPacketSize < (int)PacketSize,
|
||||
HasQuarter = (int)QuarterPacketSize < (int)HalfPacketSize};
|
||||
|
||||
const_blas_data_mapper<Scalar,Index,StorageOrder> lhs(_lhs,lhsStride);
|
||||
const_blas_data_mapper<Scalar,Index,StorageOrder> lhs(lhs_,lhsStride);
|
||||
Index count = 0;
|
||||
//Index peeled_mc3 = (rows/Pack1)*Pack1;
|
||||
|
||||
@@ -101,11 +101,11 @@ template<typename Scalar, typename Index, int nr, int StorageOrder>
|
||||
struct symm_pack_rhs
|
||||
{
|
||||
enum { PacketSize = packet_traits<Scalar>::size };
|
||||
void operator()(Scalar* blockB, const Scalar* _rhs, Index rhsStride, Index rows, Index cols, Index k2)
|
||||
void operator()(Scalar* blockB, const Scalar* rhs_, Index rhsStride, Index rows, Index cols, Index k2)
|
||||
{
|
||||
Index end_k = k2 + rows;
|
||||
Index count = 0;
|
||||
const_blas_data_mapper<Scalar,Index,StorageOrder> rhs(_rhs,rhsStride);
|
||||
const_blas_data_mapper<Scalar,Index,StorageOrder> rhs(rhs_,rhsStride);
|
||||
Index packet_cols8 = nr>=8 ? (cols/8) * 8 : 0;
|
||||
Index packet_cols4 = nr>=4 ? (cols/4) * 4 : 0;
|
||||
|
||||
@@ -330,8 +330,8 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs
|
||||
|
||||
static EIGEN_DONT_INLINE void run(
|
||||
Index rows, Index cols,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking);
|
||||
};
|
||||
@@ -342,9 +342,9 @@ template <typename Scalar, typename Index,
|
||||
int ResInnerStride>
|
||||
EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs, RhsStorageOrder,false,ConjugateRhs,ColMajor,ResInnerStride>::run(
|
||||
Index rows, Index cols,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
Scalar* _res, Index resIncr, Index resStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res_, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking)
|
||||
{
|
||||
Index size = rows;
|
||||
@@ -355,10 +355,10 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,t
|
||||
typedef const_blas_data_mapper<Scalar, Index, (LhsStorageOrder == RowMajor) ? ColMajor : RowMajor> LhsTransposeMapper;
|
||||
typedef const_blas_data_mapper<Scalar, Index, RhsStorageOrder> RhsMapper;
|
||||
typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor, Unaligned, ResInnerStride> ResMapper;
|
||||
LhsMapper lhs(_lhs,lhsStride);
|
||||
LhsTransposeMapper lhs_transpose(_lhs,lhsStride);
|
||||
RhsMapper rhs(_rhs,rhsStride);
|
||||
ResMapper res(_res, resStride, resIncr);
|
||||
LhsMapper lhs(lhs_,lhsStride);
|
||||
LhsTransposeMapper lhs_transpose(lhs_,lhsStride);
|
||||
RhsMapper rhs(rhs_,rhsStride);
|
||||
ResMapper res(res_, resStride, resIncr);
|
||||
|
||||
Index kc = blocking.kc(); // cache block size along the K direction
|
||||
Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction
|
||||
@@ -425,8 +425,8 @@ struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLh
|
||||
|
||||
static EIGEN_DONT_INLINE void run(
|
||||
Index rows, Index cols,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking);
|
||||
};
|
||||
@@ -437,9 +437,9 @@ template <typename Scalar, typename Index,
|
||||
int ResInnerStride>
|
||||
EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLhs, RhsStorageOrder,true,ConjugateRhs,ColMajor,ResInnerStride>::run(
|
||||
Index rows, Index cols,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
Scalar* _res, Index resIncr, Index resStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res_, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking)
|
||||
{
|
||||
Index size = cols;
|
||||
@@ -448,8 +448,8 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,f
|
||||
|
||||
typedef const_blas_data_mapper<Scalar, Index, LhsStorageOrder> LhsMapper;
|
||||
typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor, Unaligned, ResInnerStride> ResMapper;
|
||||
LhsMapper lhs(_lhs,lhsStride);
|
||||
ResMapper res(_res,resStride, resIncr);
|
||||
LhsMapper lhs(lhs_,lhsStride);
|
||||
ResMapper res(res_,resStride, resIncr);
|
||||
|
||||
Index kc = blocking.kc(); // cache block size along the K direction
|
||||
Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction
|
||||
@@ -466,7 +466,7 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,f
|
||||
{
|
||||
const Index actual_kc = (std::min)(k2+kc,size)-k2;
|
||||
|
||||
pack_rhs(blockB, _rhs, rhsStride, actual_kc, cols, k2);
|
||||
pack_rhs(blockB, rhs_, rhsStride, actual_kc, cols, k2);
|
||||
|
||||
// => GEPP
|
||||
for(Index i2=0; i2<rows; i2+=mc)
|
||||
|
||||
@@ -80,8 +80,8 @@ EIGEN_DEVICE_FUNC SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,U
|
||||
if (IsRowMajor)
|
||||
actualAlpha = numext::conj(actualAlpha);
|
||||
|
||||
typedef typename internal::remove_all<typename internal::conj_expr_if<IsRowMajor ^ UBlasTraits::NeedToConjugate,_ActualUType>::type>::type UType;
|
||||
typedef typename internal::remove_all<typename internal::conj_expr_if<IsRowMajor ^ VBlasTraits::NeedToConjugate,_ActualVType>::type>::type VType;
|
||||
typedef typename internal::remove_all<typename internal::conj_expr_if<int(IsRowMajor) ^ int(UBlasTraits::NeedToConjugate), _ActualUType>::type>::type UType;
|
||||
typedef typename internal::remove_all<typename internal::conj_expr_if<int(IsRowMajor) ^ int(VBlasTraits::NeedToConjugate), _ActualVType>::type>::type VType;
|
||||
internal::selfadjoint_rank2_update_selector<Scalar, Index, UType, VType,
|
||||
(IsRowMajor ? int(UpLo==Upper ? Lower : Upper) : UpLo)>
|
||||
::run(_expression().const_cast_derived().data(),_expression().outerStride(),UType(actualU),VType(actualV),actualAlpha);
|
||||
|
||||
@@ -18,10 +18,10 @@ namespace internal {
|
||||
// struct gemm_pack_lhs_triangular
|
||||
// {
|
||||
// Matrix<Scalar,mr,mr,
|
||||
// void operator()(Scalar* blockA, const EIGEN_RESTRICT Scalar* _lhs, int lhsStride, int depth, int rows)
|
||||
// void operator()(Scalar* blockA, const EIGEN_RESTRICT Scalar* lhs_, int lhsStride, int depth, int rows)
|
||||
// {
|
||||
// conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
|
||||
// const_blas_data_mapper<Scalar, StorageOrder> lhs(_lhs,lhsStride);
|
||||
// const_blas_data_mapper<Scalar, StorageOrder> lhs(lhs_,lhsStride);
|
||||
// int count = 0;
|
||||
// const int peeled_mc = (rows/mr)*mr;
|
||||
// for(int i=0; i<peeled_mc; i+=mr)
|
||||
@@ -96,8 +96,8 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
||||
|
||||
static EIGEN_DONT_INLINE void run(
|
||||
Index _rows, Index _cols, Index _depth,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking);
|
||||
};
|
||||
@@ -110,9 +110,9 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
||||
LhsStorageOrder,ConjugateLhs,
|
||||
RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version>::run(
|
||||
Index _rows, Index _cols, Index _depth,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
Scalar* _res, Index resIncr, Index resStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res_, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking)
|
||||
{
|
||||
// strip zeros
|
||||
@@ -124,9 +124,9 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
||||
typedef const_blas_data_mapper<Scalar, Index, LhsStorageOrder> LhsMapper;
|
||||
typedef const_blas_data_mapper<Scalar, Index, RhsStorageOrder> RhsMapper;
|
||||
typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor, Unaligned, ResInnerStride> ResMapper;
|
||||
LhsMapper lhs(_lhs,lhsStride);
|
||||
RhsMapper rhs(_rhs,rhsStride);
|
||||
ResMapper res(_res, resStride, resIncr);
|
||||
LhsMapper lhs(lhs_,lhsStride);
|
||||
RhsMapper rhs(rhs_,rhsStride);
|
||||
ResMapper res(res_, resStride, resIncr);
|
||||
|
||||
Index kc = blocking.kc(); // cache block size along the K direction
|
||||
Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction
|
||||
@@ -254,8 +254,8 @@ struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
||||
|
||||
static EIGEN_DONT_INLINE void run(
|
||||
Index _rows, Index _cols, Index _depth,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking);
|
||||
};
|
||||
@@ -268,9 +268,9 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
||||
LhsStorageOrder,ConjugateLhs,
|
||||
RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version>::run(
|
||||
Index _rows, Index _cols, Index _depth,
|
||||
const Scalar* _lhs, Index lhsStride,
|
||||
const Scalar* _rhs, Index rhsStride,
|
||||
Scalar* _res, Index resIncr, Index resStride,
|
||||
const Scalar* lhs_, Index lhsStride,
|
||||
const Scalar* rhs_, Index rhsStride,
|
||||
Scalar* res_, Index resIncr, Index resStride,
|
||||
const Scalar& alpha, level3_blocking<Scalar,Scalar>& blocking)
|
||||
{
|
||||
const Index PacketBytes = packet_traits<Scalar>::size*sizeof(Scalar);
|
||||
@@ -283,9 +283,9 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
||||
typedef const_blas_data_mapper<Scalar, Index, LhsStorageOrder> LhsMapper;
|
||||
typedef const_blas_data_mapper<Scalar, Index, RhsStorageOrder> RhsMapper;
|
||||
typedef blas_data_mapper<typename Traits::ResScalar, Index, ColMajor, Unaligned, ResInnerStride> ResMapper;
|
||||
LhsMapper lhs(_lhs,lhsStride);
|
||||
RhsMapper rhs(_rhs,rhsStride);
|
||||
ResMapper res(_res, resStride, resIncr);
|
||||
LhsMapper lhs(lhs_,lhsStride);
|
||||
RhsMapper rhs(rhs_,rhsStride);
|
||||
ResMapper res(res_, resStride, resIncr);
|
||||
|
||||
Index kc = blocking.kc(); // cache block size along the K direction
|
||||
Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction
|
||||
|
||||
@@ -26,30 +26,30 @@ struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
|
||||
HasUnitDiag = (Mode & UnitDiag)==UnitDiag,
|
||||
HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
|
||||
};
|
||||
static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
|
||||
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const RhsScalar& alpha);
|
||||
static EIGEN_DONT_INLINE void run(Index rows_, Index cols_, const LhsScalar* lhs_, Index lhsStride,
|
||||
const RhsScalar* rhs_, Index rhsIncr, ResScalar* res_, Index resIncr, const RhsScalar& alpha);
|
||||
};
|
||||
|
||||
template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int Version>
|
||||
EIGEN_DONT_INLINE void triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,ColMajor,Version>
|
||||
::run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
|
||||
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const RhsScalar& alpha)
|
||||
::run(Index rows_, Index cols_, const LhsScalar* lhs_, Index lhsStride,
|
||||
const RhsScalar* rhs_, Index rhsIncr, ResScalar* res_, Index resIncr, const RhsScalar& alpha)
|
||||
{
|
||||
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
|
||||
Index size = (std::min)(_rows,_cols);
|
||||
Index rows = IsLower ? _rows : (std::min)(_rows,_cols);
|
||||
Index cols = IsLower ? (std::min)(_rows,_cols) : _cols;
|
||||
Index size = (std::min)(rows_,cols_);
|
||||
Index rows = IsLower ? rows_ : (std::min)(rows_,cols_);
|
||||
Index cols = IsLower ? (std::min)(rows_,cols_) : cols_;
|
||||
|
||||
typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,ColMajor>, 0, OuterStride<> > LhsMap;
|
||||
const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride));
|
||||
const LhsMap lhs(lhs_,rows,cols,OuterStride<>(lhsStride));
|
||||
typename conj_expr_if<ConjLhs,LhsMap>::type cjLhs(lhs);
|
||||
|
||||
typedef Map<const Matrix<RhsScalar,Dynamic,1>, 0, InnerStride<> > RhsMap;
|
||||
const RhsMap rhs(_rhs,cols,InnerStride<>(rhsIncr));
|
||||
const RhsMap rhs(rhs_,cols,InnerStride<>(rhsIncr));
|
||||
typename conj_expr_if<ConjRhs,RhsMap>::type cjRhs(rhs);
|
||||
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1> > ResMap;
|
||||
ResMap res(_res,rows);
|
||||
ResMap res(res_,rows);
|
||||
|
||||
typedef const_blas_data_mapper<LhsScalar,Index,ColMajor> LhsMapper;
|
||||
typedef const_blas_data_mapper<RhsScalar,Index,RowMajor> RhsMapper;
|
||||
@@ -84,7 +84,7 @@ EIGEN_DONT_INLINE void triangular_matrix_vector_product<Index,Mode,LhsScalar,Con
|
||||
rows, cols-size,
|
||||
LhsMapper(&lhs.coeffRef(0,size), lhsStride),
|
||||
RhsMapper(&rhs.coeffRef(size), rhsIncr),
|
||||
_res, resIncr, alpha);
|
||||
res_, resIncr, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,30 +97,30 @@ struct triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,C
|
||||
HasUnitDiag = (Mode & UnitDiag)==UnitDiag,
|
||||
HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag
|
||||
};
|
||||
static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
|
||||
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha);
|
||||
static EIGEN_DONT_INLINE void run(Index rows_, Index cols_, const LhsScalar* lhs_, Index lhsStride,
|
||||
const RhsScalar* rhs_, Index rhsIncr, ResScalar* res_, Index resIncr, const ResScalar& alpha);
|
||||
};
|
||||
|
||||
template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs,int Version>
|
||||
EIGEN_DONT_INLINE void triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,RowMajor,Version>
|
||||
::run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride,
|
||||
const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, const ResScalar& alpha)
|
||||
::run(Index rows_, Index cols_, const LhsScalar* lhs_, Index lhsStride,
|
||||
const RhsScalar* rhs_, Index rhsIncr, ResScalar* res_, Index resIncr, const ResScalar& alpha)
|
||||
{
|
||||
static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
|
||||
Index diagSize = (std::min)(_rows,_cols);
|
||||
Index rows = IsLower ? _rows : diagSize;
|
||||
Index cols = IsLower ? diagSize : _cols;
|
||||
Index diagSize = (std::min)(rows_,cols_);
|
||||
Index rows = IsLower ? rows_ : diagSize;
|
||||
Index cols = IsLower ? diagSize : cols_;
|
||||
|
||||
typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,RowMajor>, 0, OuterStride<> > LhsMap;
|
||||
const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride));
|
||||
const LhsMap lhs(lhs_,rows,cols,OuterStride<>(lhsStride));
|
||||
typename conj_expr_if<ConjLhs,LhsMap>::type cjLhs(lhs);
|
||||
|
||||
typedef Map<const Matrix<RhsScalar,Dynamic,1> > RhsMap;
|
||||
const RhsMap rhs(_rhs,cols);
|
||||
const RhsMap rhs(rhs_,cols);
|
||||
typename conj_expr_if<ConjRhs,RhsMap>::type cjRhs(rhs);
|
||||
|
||||
typedef Map<Matrix<ResScalar,Dynamic,1>, 0, InnerStride<> > ResMap;
|
||||
ResMap res(_res,rows,InnerStride<>(resIncr));
|
||||
ResMap res(res_,rows,InnerStride<>(resIncr));
|
||||
|
||||
typedef const_blas_data_mapper<LhsScalar,Index,RowMajor> LhsMapper;
|
||||
typedef const_blas_data_mapper<RhsScalar,Index,RowMajor> RhsMapper;
|
||||
|
||||
@@ -50,18 +50,18 @@ struct triangular_matrix_vector_product_trmv :
|
||||
#define EIGEN_BLAS_TRMV_SPECIALIZE(Scalar) \
|
||||
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
|
||||
struct triangular_matrix_vector_product<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,ColMajor,Specialized> { \
|
||||
static void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
|
||||
const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \
|
||||
static void run(Index rows_, Index cols_, const Scalar* lhs_, Index lhsStride, \
|
||||
const Scalar* rhs_, Index rhsIncr, Scalar* res_, Index resIncr, Scalar alpha) { \
|
||||
triangular_matrix_vector_product_trmv<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,ColMajor>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
rows_, cols_, lhs_, lhsStride, rhs_, rhsIncr, res_, resIncr, alpha); \
|
||||
} \
|
||||
}; \
|
||||
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
|
||||
struct triangular_matrix_vector_product<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,RowMajor,Specialized> { \
|
||||
static void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
|
||||
const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \
|
||||
static void run(Index rows_, Index cols_, const Scalar* lhs_, Index lhsStride, \
|
||||
const Scalar* rhs_, Index rhsIncr, Scalar* res_, Index resIncr, Scalar alpha) { \
|
||||
triangular_matrix_vector_product_trmv<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,RowMajor>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
rows_, cols_, lhs_, lhsStride, rhs_, rhsIncr, res_, resIncr, alpha); \
|
||||
} \
|
||||
};
|
||||
|
||||
@@ -81,23 +81,23 @@ struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
LowUp = IsLower ? Lower : Upper \
|
||||
}; \
|
||||
static void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha) \
|
||||
static void run(Index rows_, Index cols_, const EIGTYPE* lhs_, Index lhsStride, \
|
||||
const EIGTYPE* rhs_, Index rhsIncr, EIGTYPE* res_, Index resIncr, EIGTYPE alpha) \
|
||||
{ \
|
||||
if (ConjLhs || IsZeroDiag) { \
|
||||
triangular_matrix_vector_product<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,ColMajor,BuiltIn>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
rows_, cols_, lhs_, lhsStride, rhs_, rhsIncr, res_, resIncr, alpha); \
|
||||
return; \
|
||||
}\
|
||||
Index size = (std::min)(_rows,_cols); \
|
||||
Index rows = IsLower ? _rows : size; \
|
||||
Index cols = IsLower ? size : _cols; \
|
||||
Index size = (std::min)(rows_,cols_); \
|
||||
Index rows = IsLower ? rows_ : size; \
|
||||
Index cols = IsLower ? size : cols_; \
|
||||
\
|
||||
typedef VectorX##EIGPREFIX VectorRhs; \
|
||||
EIGTYPE *x, *y;\
|
||||
\
|
||||
/* Set x*/ \
|
||||
Map<const VectorRhs, 0, InnerStride<> > rhs(_rhs,cols,InnerStride<>(rhsIncr)); \
|
||||
Map<const VectorRhs, 0, InnerStride<> > rhs(rhs_,cols,InnerStride<>(rhsIncr)); \
|
||||
VectorRhs x_tmp; \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
@@ -121,24 +121,24 @@ struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,
|
||||
diag = IsUnitDiag ? 'U' : 'N'; \
|
||||
\
|
||||
/* call ?TRMV*/ \
|
||||
BLASPREFIX##trmv##BLASPOSTFIX(&uplo, &trans, &diag, &n, (const BLASTYPE*)_lhs, &lda, (BLASTYPE*)x, &incx); \
|
||||
BLASPREFIX##trmv##BLASPOSTFIX(&uplo, &trans, &diag, &n, (const BLASTYPE*)lhs_, &lda, (BLASTYPE*)x, &incx); \
|
||||
\
|
||||
/* Add op(a_tr)rhs into res*/ \
|
||||
BLASPREFIX##axpy##BLASPOSTFIX(&n, (const BLASTYPE*)&numext::real_ref(alpha),(const BLASTYPE*)x, &incx, (BLASTYPE*)_res, &incy); \
|
||||
BLASPREFIX##axpy##BLASPOSTFIX(&n, (const BLASTYPE*)&numext::real_ref(alpha),(const BLASTYPE*)x, &incx, (BLASTYPE*)res_, &incy); \
|
||||
/* Non-square case - doesn't fit to BLAS ?TRMV. Fall to default triangular product*/ \
|
||||
if (size<(std::max)(rows,cols)) { \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
if (size<rows) { \
|
||||
y = _res + size*resIncr; \
|
||||
a = _lhs + size; \
|
||||
y = res_ + size*resIncr; \
|
||||
a = lhs_ + size; \
|
||||
m = convert_index<BlasIndex>(rows-size); \
|
||||
n = convert_index<BlasIndex>(size); \
|
||||
} \
|
||||
else { \
|
||||
x += size; \
|
||||
y = _res; \
|
||||
a = _lhs + size*lda; \
|
||||
y = res_; \
|
||||
a = lhs_ + size*lda; \
|
||||
m = convert_index<BlasIndex>(size); \
|
||||
n = convert_index<BlasIndex>(cols-size); \
|
||||
} \
|
||||
@@ -170,23 +170,23 @@ struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
LowUp = IsLower ? Lower : Upper \
|
||||
}; \
|
||||
static void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha) \
|
||||
static void run(Index rows_, Index cols_, const EIGTYPE* lhs_, Index lhsStride, \
|
||||
const EIGTYPE* rhs_, Index rhsIncr, EIGTYPE* res_, Index resIncr, EIGTYPE alpha) \
|
||||
{ \
|
||||
if (IsZeroDiag) { \
|
||||
triangular_matrix_vector_product<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,RowMajor,BuiltIn>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
rows_, cols_, lhs_, lhsStride, rhs_, rhsIncr, res_, resIncr, alpha); \
|
||||
return; \
|
||||
}\
|
||||
Index size = (std::min)(_rows,_cols); \
|
||||
Index rows = IsLower ? _rows : size; \
|
||||
Index cols = IsLower ? size : _cols; \
|
||||
Index size = (std::min)(rows_,cols_); \
|
||||
Index rows = IsLower ? rows_ : size; \
|
||||
Index cols = IsLower ? size : cols_; \
|
||||
\
|
||||
typedef VectorX##EIGPREFIX VectorRhs; \
|
||||
EIGTYPE *x, *y;\
|
||||
\
|
||||
/* Set x*/ \
|
||||
Map<const VectorRhs, 0, InnerStride<> > rhs(_rhs,cols,InnerStride<>(rhsIncr)); \
|
||||
Map<const VectorRhs, 0, InnerStride<> > rhs(rhs_,cols,InnerStride<>(rhsIncr)); \
|
||||
VectorRhs x_tmp; \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
@@ -210,24 +210,24 @@ struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,
|
||||
diag = IsUnitDiag ? 'U' : 'N'; \
|
||||
\
|
||||
/* call ?TRMV*/ \
|
||||
BLASPREFIX##trmv##BLASPOSTFIX(&uplo, &trans, &diag, &n, (const BLASTYPE*)_lhs, &lda, (BLASTYPE*)x, &incx); \
|
||||
BLASPREFIX##trmv##BLASPOSTFIX(&uplo, &trans, &diag, &n, (const BLASTYPE*)lhs_, &lda, (BLASTYPE*)x, &incx); \
|
||||
\
|
||||
/* Add op(a_tr)rhs into res*/ \
|
||||
BLASPREFIX##axpy##BLASPOSTFIX(&n, (const BLASTYPE*)&numext::real_ref(alpha),(const BLASTYPE*)x, &incx, (BLASTYPE*)_res, &incy); \
|
||||
BLASPREFIX##axpy##BLASPOSTFIX(&n, (const BLASTYPE*)&numext::real_ref(alpha),(const BLASTYPE*)x, &incx, (BLASTYPE*)res_, &incy); \
|
||||
/* Non-square case - doesn't fit to BLAS ?TRMV. Fall to default triangular product*/ \
|
||||
if (size<(std::max)(rows,cols)) { \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
if (size<rows) { \
|
||||
y = _res + size*resIncr; \
|
||||
a = _lhs + size*lda; \
|
||||
y = res_ + size*resIncr; \
|
||||
a = lhs_ + size*lda; \
|
||||
m = convert_index<BlasIndex>(rows-size); \
|
||||
n = convert_index<BlasIndex>(size); \
|
||||
} \
|
||||
else { \
|
||||
x += size; \
|
||||
y = _res; \
|
||||
a = _lhs + size; \
|
||||
y = res_; \
|
||||
a = lhs_ + size; \
|
||||
m = convert_index<BlasIndex>(size); \
|
||||
n = convert_index<BlasIndex>(cols-size); \
|
||||
} \
|
||||
|
||||
@@ -39,90 +39,6 @@ template<typename Index,
|
||||
typename RhsScalar, typename RhsMapper, bool ConjugateRhs, int Version=Specialized>
|
||||
struct general_matrix_vector_product;
|
||||
|
||||
|
||||
template<bool Conjugate> struct conj_if;
|
||||
|
||||
template<> struct conj_if<true> {
|
||||
template<typename T>
|
||||
inline T operator()(const T& x) const { return numext::conj(x); }
|
||||
template<typename T>
|
||||
inline T pconj(const T& x) const { return internal::pconj(x); }
|
||||
};
|
||||
|
||||
template<> struct conj_if<false> {
|
||||
template<typename T>
|
||||
inline const T& operator()(const T& x) const { return x; }
|
||||
template<typename T>
|
||||
inline const T& pconj(const T& x) const { return x; }
|
||||
};
|
||||
|
||||
// Generic implementation for custom complex types.
|
||||
template<typename LhsScalar, typename RhsScalar, bool ConjLhs, bool ConjRhs>
|
||||
struct conj_helper
|
||||
{
|
||||
typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar>::ReturnType Scalar;
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const LhsScalar& x, const RhsScalar& y, const Scalar& c) const
|
||||
{ return padd(c, pmul(x,y)); }
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const LhsScalar& x, const RhsScalar& y) const
|
||||
{ return conj_if<ConjLhs>()(x) * conj_if<ConjRhs>()(y); }
|
||||
};
|
||||
|
||||
template<typename Scalar> struct conj_helper<Scalar,Scalar,false,false>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const { return internal::pmadd(x,y,c); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const { return internal::pmul(x,y); }
|
||||
};
|
||||
|
||||
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, false,true>
|
||||
{
|
||||
typedef std::complex<RealScalar> Scalar;
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
|
||||
{ return c + pmul(x,y); }
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
||||
{ return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::imag(x)*numext::real(y) - numext::real(x)*numext::imag(y)); }
|
||||
};
|
||||
|
||||
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,false>
|
||||
{
|
||||
typedef std::complex<RealScalar> Scalar;
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
|
||||
{ return c + pmul(x,y); }
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
||||
{ return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
|
||||
};
|
||||
|
||||
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,true>
|
||||
{
|
||||
typedef std::complex<RealScalar> Scalar;
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
|
||||
{ return c + pmul(x,y); }
|
||||
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
||||
{ return Scalar(numext::real(x)*numext::real(y) - numext::imag(x)*numext::imag(y), - numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
|
||||
};
|
||||
|
||||
template<typename RealScalar,bool Conj> struct conj_helper<std::complex<RealScalar>, RealScalar, Conj,false>
|
||||
{
|
||||
typedef std::complex<RealScalar> Scalar;
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const RealScalar& y, const Scalar& c) const
|
||||
{ return padd(c, pmul(x,y)); }
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const RealScalar& y) const
|
||||
{ return conj_if<Conj>()(x)*y; }
|
||||
};
|
||||
|
||||
template<typename RealScalar,bool Conj> struct conj_helper<RealScalar, std::complex<RealScalar>, false,Conj>
|
||||
{
|
||||
typedef std::complex<RealScalar> Scalar;
|
||||
EIGEN_STRONG_INLINE Scalar pmadd(const RealScalar& x, const Scalar& y, const Scalar& c) const
|
||||
{ return padd(c, pmul(x,y)); }
|
||||
EIGEN_STRONG_INLINE Scalar pmul(const RealScalar& x, const Scalar& y) const
|
||||
{ return x*conj_if<Conj>()(y); }
|
||||
};
|
||||
|
||||
template<typename From,typename To> struct get_factor {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE To run(const From& x) { return To(x); }
|
||||
};
|
||||
@@ -602,7 +518,7 @@ struct blas_traits<const T>
|
||||
|
||||
template<typename T, bool HasUsableDirectAccess=blas_traits<T>::HasUsableDirectAccess>
|
||||
struct extract_data_selector {
|
||||
static const typename T::Scalar* run(const T& m)
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static const typename T::Scalar* run(const T& m)
|
||||
{
|
||||
return blas_traits<T>::extract(m).data();
|
||||
}
|
||||
@@ -613,7 +529,8 @@ struct extract_data_selector<T,false> {
|
||||
static typename T::Scalar* run(const T&) { return 0; }
|
||||
};
|
||||
|
||||
template<typename T> const typename T::Scalar* extract_data(const T& m)
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const typename T::Scalar* extract_data(const T& m)
|
||||
{
|
||||
return extract_data_selector<T>::run(m);
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
extern "C" {
|
||||
// In theory we should only include immintrin.h and not the other *mmintrin.h header files directly.
|
||||
// Doing so triggers some issues with ICC. However old gcc versions seems to not have this file, thus:
|
||||
#if EIGEN_COMP_ICC >= 1110
|
||||
#if EIGEN_COMP_ICC >= 1110 || EIGEN_COMP_EMSCRIPTEN
|
||||
#include <immintrin.h>
|
||||
#else
|
||||
#include <mmintrin.h>
|
||||
@@ -363,10 +363,11 @@
|
||||
#endif
|
||||
} // end extern "C"
|
||||
|
||||
#elif defined __VSX__
|
||||
#elif defined(__VSX__) && !defined(__APPLE__)
|
||||
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_VSX
|
||||
#define EIGEN_VECTORIZE_VSX 1
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#include <altivec.h>
|
||||
// We need to #undef all these ugly tokens defined in <altivec.h>
|
||||
// => use __vector instead of vector
|
||||
@@ -378,6 +379,7 @@
|
||||
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_ALTIVEC
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#include <altivec.h>
|
||||
// We need to #undef all these ugly tokens defined in <altivec.h>
|
||||
// => use __vector instead of vector
|
||||
@@ -438,13 +440,20 @@
|
||||
#include <arm_fp16.h>
|
||||
#endif
|
||||
|
||||
#if defined(__F16C__) && (!defined(EIGEN_GPUCC) && (!defined(EIGEN_COMP_CLANG) || EIGEN_COMP_CLANG>=380))
|
||||
// Enable FMA for ARM.
|
||||
#if defined(__ARM_FEATURE_FMA)
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#endif
|
||||
|
||||
#if defined(__F16C__) && !defined(EIGEN_GPUCC) && (!EIGEN_COMP_CLANG_STRICT || EIGEN_COMP_CLANG>=380)
|
||||
// We can use the optimized fp16 to float and float to fp16 conversion routines
|
||||
#define EIGEN_HAS_FP16_C
|
||||
|
||||
#if defined(EIGEN_COMP_CLANG)
|
||||
// Workaround for clang: The FP16C intrinsics for clang are included by
|
||||
// immintrin.h, as opposed to emmintrin.h as suggested by Intel:
|
||||
#if EIGEN_COMP_GNUC
|
||||
// Make sure immintrin.h is included, even if e.g. vectorization is
|
||||
// explicitly disabled (see also issue #2395).
|
||||
// Note that FP16C intrinsics for gcc and clang are included by immintrin.h,
|
||||
// as opposed to emmintrin.h as suggested by Intel:
|
||||
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#othertechs=FP16C&expand=1711
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
@@ -134,7 +134,7 @@ const unsigned int LinearAccessBit = 0x10;
|
||||
* Means the expression has a coeffRef() method, i.e. is writable as its individual coefficients are directly addressable.
|
||||
* This rules out read-only expressions.
|
||||
*
|
||||
* Note that DirectAccessBit and LvalueBit are mutually orthogonal, as there are examples of expression having one but note
|
||||
* Note that DirectAccessBit and LvalueBit are mutually orthogonal, as there are examples of expression having one but not
|
||||
* the other:
|
||||
* \li writable expressions that don't have a very simple memory layout as a strided array, have LvalueBit but not DirectAccessBit
|
||||
* \li Map-to-const expressions, for example Map<const Matrix>, have DirectAccessBit but not LvalueBit
|
||||
@@ -157,7 +157,7 @@ const unsigned int DirectAccessBit = 0x40;
|
||||
/** \deprecated \ingroup flags
|
||||
*
|
||||
* means the first coefficient packet is guaranteed to be aligned.
|
||||
* An expression cannot has the AlignedBit without the PacketAccessBit flag.
|
||||
* An expression cannot have the AlignedBit without the PacketAccessBit flag.
|
||||
* In other words, this means we are allow to perform an aligned packet access to the first element regardless
|
||||
* of the expression kind:
|
||||
* \code
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#ifndef EIGEN_WARNINGS_DISABLED
|
||||
#define EIGEN_WARNINGS_DISABLED
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER)
|
||||
// 4100 - unreferenced formal parameter (occurred e.g. in aligned_allocator::destroy(pointer p))
|
||||
// 4101 - unreferenced local variable
|
||||
// 4127 - conditional expression is constant
|
||||
// 4181 - qualifier applied to reference type ignored
|
||||
// 4211 - nonstandard extension used : redefined extern to static
|
||||
// 4244 - 'argument' : conversion from 'type1' to 'type2', possible loss of data
|
||||
@@ -19,7 +20,7 @@
|
||||
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
||||
#pragma warning( push )
|
||||
#endif
|
||||
#pragma warning( disable : 4100 4101 4181 4211 4244 4273 4324 4503 4512 4522 4700 4714 4717 4800)
|
||||
#pragma warning( disable : 4100 4101 4127 4181 4211 4244 4273 4324 4503 4512 4522 4700 4714 4717 4800)
|
||||
|
||||
#elif defined __INTEL_COMPILER
|
||||
// 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
|
||||
@@ -35,25 +36,28 @@
|
||||
#pragma warning disable 2196 279 1684 2259
|
||||
|
||||
#elif defined __clang__
|
||||
// -Wconstant-logical-operand - warning: use of logical && with constant operand; switch to bitwise & or remove constant
|
||||
// this is really a stupid warning as it warns on compile-time expressions involving enums
|
||||
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
||||
#pragma clang diagnostic push
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
||||
#if __clang_major__ >= 3 && __clang_minor__ >= 5
|
||||
#pragma clang diagnostic ignored "-Wabsolute-value"
|
||||
#endif
|
||||
#if __clang_major__ >= 10
|
||||
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
|
||||
#endif
|
||||
#if ( defined(__ALTIVEC__) || defined(__VSX__) ) && __cplusplus < 201103L
|
||||
// warning: generic selections are a C11-specific feature
|
||||
// ignoring warnings thrown at vec_ctf in Altivec/PacketMath.h
|
||||
#pragma clang diagnostic ignored "-Wc11-extensions"
|
||||
#if defined(__has_warning)
|
||||
// -Wconstant-logical-operand - warning: use of logical && with constant operand; switch to bitwise & or remove constant
|
||||
// this is really a stupid warning as it warns on compile-time expressions involving enums
|
||||
#if __has_warning("-Wconstant-logical-operand")
|
||||
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
||||
#endif
|
||||
#if __has_warning("-Wimplicit-int-float-conversion")
|
||||
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
|
||||
#endif
|
||||
#if ( defined(__ALTIVEC__) || defined(__VSX__) ) && __cplusplus < 201103L
|
||||
// warning: generic selections are a C11-specific feature
|
||||
// ignoring warnings thrown at vec_ctf in Altivec/PacketMath.h
|
||||
#if __has_warning("-Wc11-extensions")
|
||||
#pragma clang diagnostic ignored "-Wc11-extensions"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined __GNUC__
|
||||
#elif defined __GNUC__ && !defined(__FUJITSU)
|
||||
|
||||
#if (!defined(EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS)) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
||||
#pragma GCC diagnostic push
|
||||
@@ -74,25 +78,53 @@
|
||||
#endif
|
||||
|
||||
#if defined __NVCC__
|
||||
#pragma diag_suppress boolean_controlling_expr_is_constant
|
||||
// MSVC 14.16 (required by CUDA 9.*) does not support the _Pragma keyword, so
|
||||
// we instead use Microsoft's __pragma extension.
|
||||
#if defined _MSC_VER
|
||||
#define EIGEN_MAKE_PRAGMA(X) __pragma(#X)
|
||||
#else
|
||||
#define EIGEN_MAKE_PRAGMA(X) _Pragma(#X)
|
||||
#endif
|
||||
#if defined __NVCC_DIAG_PRAGMA_SUPPORT__
|
||||
#define EIGEN_NV_DIAG_SUPPRESS(X) EIGEN_MAKE_PRAGMA(nv_diag_suppress X)
|
||||
#else
|
||||
#define EIGEN_NV_DIAG_SUPPRESS(X) EIGEN_MAKE_PRAGMA(diag_suppress X)
|
||||
#endif
|
||||
|
||||
EIGEN_NV_DIAG_SUPPRESS(boolean_controlling_expr_is_constant)
|
||||
// Disable the "statement is unreachable" message
|
||||
#pragma diag_suppress code_is_unreachable
|
||||
EIGEN_NV_DIAG_SUPPRESS(code_is_unreachable)
|
||||
// Disable the "dynamic initialization in unreachable code" message
|
||||
#pragma diag_suppress initialization_not_reachable
|
||||
EIGEN_NV_DIAG_SUPPRESS(initialization_not_reachable)
|
||||
// Disable the "invalid error number" message that we get with older versions of nvcc
|
||||
#pragma diag_suppress 1222
|
||||
EIGEN_NV_DIAG_SUPPRESS(1222)
|
||||
// Disable the "calling a __host__ function from a __host__ __device__ function is not allowed" messages (yes, there are many of them and they seem to change with every version of the compiler)
|
||||
#pragma diag_suppress 2527
|
||||
#pragma diag_suppress 2529
|
||||
#pragma diag_suppress 2651
|
||||
#pragma diag_suppress 2653
|
||||
#pragma diag_suppress 2668
|
||||
#pragma diag_suppress 2669
|
||||
#pragma diag_suppress 2670
|
||||
#pragma diag_suppress 2671
|
||||
#pragma diag_suppress 2735
|
||||
#pragma diag_suppress 2737
|
||||
#pragma diag_suppress 2739
|
||||
EIGEN_NV_DIAG_SUPPRESS(2527)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2529)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2651)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2653)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2668)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2669)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2670)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2671)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2735)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2737)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2739)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2885)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2888)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2976)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2979)
|
||||
EIGEN_NV_DIAG_SUPPRESS(20011)
|
||||
EIGEN_NV_DIAG_SUPPRESS(20014)
|
||||
// Disable the "// __device__ annotation is ignored on a function(...) that is
|
||||
// explicitly defaulted on its first declaration" message.
|
||||
// The __device__ annotation seems to actually be needed in some cases,
|
||||
// otherwise resulting in kernel runtime errors.
|
||||
EIGEN_NV_DIAG_SUPPRESS(2886)
|
||||
EIGEN_NV_DIAG_SUPPRESS(2977)
|
||||
EIGEN_NV_DIAG_SUPPRESS(20012)
|
||||
#undef EIGEN_NV_DIAG_SUPPRESS
|
||||
#undef EIGEN_MAKE_PRAGMA
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
@@ -168,7 +168,7 @@ template<int Size> struct get_compile_time_incr<AllRange<Size> > {
|
||||
* \ingroup Core_Module
|
||||
* Can be used as a parameter to DenseBase::operator()(const RowIndices&, const ColIndices&) to index all rows or columns
|
||||
*/
|
||||
static const Eigen::internal::all_t all; // PLEASE use Eigen::all instead of Eigen::placeholders::all
|
||||
static const Eigen::internal::all_t all;
|
||||
|
||||
|
||||
namespace placeholders {
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
template<int M>
|
||||
FixedInt<N&M> operator&( FixedInt<M>) const { return FixedInt<N&M>(); }
|
||||
|
||||
#if EIGEN_HAS_CXX14
|
||||
#if EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
|
||||
// Needed in C++14 to allow fix<N>():
|
||||
FixedInt operator() () const { return *this; }
|
||||
|
||||
@@ -138,7 +138,7 @@ template<int N,int Default> struct get_fixed_value<FixedInt<N>,Default> {
|
||||
static const int value = N;
|
||||
};
|
||||
|
||||
#if !EIGEN_HAS_CXX14
|
||||
#if !EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
|
||||
template<int N,int Default> struct get_fixed_value<FixedInt<N> (*)(),Default> {
|
||||
static const int value = N;
|
||||
};
|
||||
@@ -154,7 +154,7 @@ struct get_fixed_value<variable_if_dynamic<T,N>,Default> {
|
||||
};
|
||||
|
||||
template<typename T> EIGEN_DEVICE_FUNC Index get_runtime_value(const T &x) { return x; }
|
||||
#if !EIGEN_HAS_CXX14
|
||||
#if !EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
|
||||
template<int N> EIGEN_DEVICE_FUNC Index get_runtime_value(FixedInt<N> (*)()) { return N; }
|
||||
#endif
|
||||
|
||||
@@ -166,7 +166,7 @@ template<typename T, int DynamicKey=Dynamic, typename EnableIf=void> struct clea
|
||||
// Convert any integral type (e.g., short, int, unsigned int, etc.) to Eigen::Index
|
||||
template<typename T, int DynamicKey> struct cleanup_index_type<T,DynamicKey,typename internal::enable_if<internal::is_integral<T>::value>::type> { typedef Index type; };
|
||||
|
||||
#if !EIGEN_HAS_CXX14
|
||||
#if !EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
|
||||
// In c++98/c++11, fix<N> is a pointer to function that we better cleanup to a true FixedInt<N>:
|
||||
template<int N, int DynamicKey> struct cleanup_index_type<FixedInt<N> (*)(), DynamicKey> { typedef FixedInt<N> type; };
|
||||
#endif
|
||||
@@ -184,7 +184,7 @@ template<int N, int DynamicKey> struct cleanup_index_type<std::integral_constant
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
#if EIGEN_HAS_CXX14
|
||||
#if EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
|
||||
template<int N>
|
||||
static const internal::FixedInt<N> fix{};
|
||||
#else
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
#define EIGEN_MAJOR_VERSION 3
|
||||
#define EIGEN_MINOR_VERSION 90
|
||||
#define EIGEN_MAJOR_VERSION 4
|
||||
#define EIGEN_MINOR_VERSION 1
|
||||
|
||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||
@@ -162,8 +162,8 @@
|
||||
|
||||
/// \internal EIGEN_COMP_IBM set to xlc version if the compiler is IBM XL C++
|
||||
// XLC version
|
||||
// 3.1 0x0301
|
||||
// 4.5 0x0405
|
||||
// 3.1 0x0301
|
||||
// 4.5 0x0405
|
||||
// 5.0 0x0500
|
||||
// 12.1 0x0C01
|
||||
#if defined(__IBMCPP__) || defined(__xlc__) || defined(__ibmxl__)
|
||||
@@ -179,6 +179,13 @@
|
||||
#define EIGEN_COMP_PGI 0
|
||||
#endif
|
||||
|
||||
/// \internal EIGEN_COMP_NVHPC set to NVHPC version if the compiler is nvc++
|
||||
#if defined(__NVCOMPILER)
|
||||
#define EIGEN_COMP_NVHPC (__NVCOMPILER_MAJOR__ * 100 + __NVCOMPILER_MINOR__)
|
||||
#else
|
||||
#define EIGEN_COMP_NVHPC 0
|
||||
#endif
|
||||
|
||||
/// \internal EIGEN_COMP_ARM set to 1 if the compiler is ARM Compiler
|
||||
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||
#define EIGEN_COMP_ARM 1
|
||||
@@ -275,7 +282,7 @@
|
||||
|
||||
/// \internal EIGEN_HAS_ARM64_FP16 set to 1 if the architecture provides an IEEE
|
||||
/// compliant Arm fp16 type
|
||||
#if EIGEN_ARCH_ARM64
|
||||
#if EIGEN_ARCH_ARM_OR_ARM64
|
||||
#ifndef EIGEN_HAS_ARM64_FP16
|
||||
#if defined(__ARM_FP16_FORMAT_IEEE)
|
||||
#define EIGEN_HAS_ARM64_FP16 1
|
||||
@@ -287,7 +294,7 @@
|
||||
|
||||
/// \internal EIGEN_HAS_ARM64_FP16_VECTOR_ARITHMETIC set to 1 if the architecture
|
||||
/// supports Neon vector intrinsics for fp16.
|
||||
#if EIGEN_ARCH_ARM64
|
||||
#if EIGEN_ARCH_ARM_OR_ARM64
|
||||
#ifndef EIGEN_HAS_ARM64_FP16_VECTOR_ARITHMETIC
|
||||
#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
|
||||
#define EIGEN_HAS_ARM64_FP16_VECTOR_ARITHMETIC 1
|
||||
@@ -299,7 +306,7 @@
|
||||
|
||||
/// \internal EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC set to 1 if the architecture
|
||||
/// supports Neon scalar intrinsics for fp16.
|
||||
#if EIGEN_ARCH_ARM64
|
||||
#if EIGEN_ARCH_ARM_OR_ARM64
|
||||
#ifndef EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC
|
||||
#if defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC)
|
||||
#define EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC 1
|
||||
@@ -329,7 +336,7 @@
|
||||
#endif
|
||||
|
||||
/// \internal EIGEN_ARCH_PPC set to 1 if the architecture is PowerPC
|
||||
#if defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
|
||||
#if defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC) || defined(__POWERPC__)
|
||||
#define EIGEN_ARCH_PPC 1
|
||||
#else
|
||||
#define EIGEN_ARCH_PPC 0
|
||||
@@ -565,6 +572,32 @@
|
||||
//
|
||||
#endif
|
||||
|
||||
/// \internal EIGEN_HAS_ARM64_FP16_VECTOR_ARITHMETIC set to 1 if the architecture
|
||||
/// supports Neon vector intrinsics for fp16.
|
||||
#if EIGEN_ARCH_ARM64
|
||||
#ifndef EIGEN_HAS_ARM64_FP16_VECTOR_ARITHMETIC
|
||||
// Clang only supports FP16 on aarch64, and not all intrinsics are available
|
||||
// on A32 anyways even in GCC (e.g. vdiv_f16, vsqrt_f16).
|
||||
#if EIGEN_ARCH_ARM64 && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
#define EIGEN_HAS_ARM64_FP16_VECTOR_ARITHMETIC 1
|
||||
#else
|
||||
#define EIGEN_HAS_ARM64_FP16_VECTOR_ARITHMETIC 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// \internal EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC set to 1 if the architecture
|
||||
/// supports Neon scalar intrinsics for fp16.
|
||||
#if EIGEN_ARCH_ARM64
|
||||
#ifndef EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC
|
||||
// Clang only supports FP16 on aarch64, and not all intrinsics are available
|
||||
// on A32 anyways, even in GCC (e.g. vceqh_f16).
|
||||
#if EIGEN_ARCH_ARM64 && defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) && !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
#define EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(EIGEN_USE_SYCL) && defined(__SYCL_DEVICE_ONLY__)
|
||||
// EIGEN_USE_SYCL is a user-defined macro while __SYCL_DEVICE_ONLY__ is a compiler-defined macro.
|
||||
// In most cases we want to check if both macros are defined which can be done using the define below.
|
||||
@@ -637,6 +670,14 @@
|
||||
#define EIGEN_COMP_CXXVER 03
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
|
||||
#if defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304 && EIGEN_MAX_CPP_VER>=14
|
||||
#define EIGEN_HAS_CXX14_VARIABLE_TEMPLATES 1
|
||||
#else
|
||||
#define EIGEN_HAS_CXX14_VARIABLE_TEMPLATES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// The macros EIGEN_HAS_CXX?? defines a rough estimate of available c++ features
|
||||
// but in practice we should not rely on them but rather on the availabilty of
|
||||
@@ -833,7 +874,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// NOTE: the required Apple's clang version is very conservative
|
||||
// NOTE: the required Apple's clang version is very conservative
|
||||
// and it could be that XCode 9 works just fine.
|
||||
// NOTE: the MSVC version is based on https://en.cppreference.com/w/cpp/compiler_support
|
||||
// and not tested.
|
||||
@@ -962,7 +1003,7 @@
|
||||
#endif
|
||||
#define EIGEN_DEVICE_FUNC __attribute__((flatten)) __attribute__((always_inline))
|
||||
// All functions callable from CUDA/HIP code must be qualified with __device__
|
||||
#elif defined(EIGEN_GPUCC)
|
||||
#elif defined(EIGEN_GPUCC)
|
||||
#define EIGEN_DEVICE_FUNC __host__ __device__
|
||||
#else
|
||||
#define EIGEN_DEVICE_FUNC
|
||||
@@ -989,7 +1030,7 @@
|
||||
#else
|
||||
#define eigen_plain_assert(x)
|
||||
#endif
|
||||
#else
|
||||
#else
|
||||
#if EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
@@ -1116,14 +1157,28 @@ namespace Eigen {
|
||||
// directly for std::complex<T>, Eigen::half, Eigen::bfloat16. For these,
|
||||
// you will need to apply to the underlying POD type.
|
||||
#if EIGEN_ARCH_PPC && EIGEN_COMP_GNUC_STRICT
|
||||
// This seems to be broken on clang. Packet4f is loaded into a single
|
||||
// register rather than a vector, zeroing out some entries. Integer
|
||||
// This seems to be broken on clang. Packet4f is loaded into a single
|
||||
// register rather than a vector, zeroing out some entries. Integer
|
||||
// types also generate a compile error.
|
||||
// General, Altivec, VSX.
|
||||
#define EIGEN_OPTIMIZATION_BARRIER(X) __asm__ ("" : "+r,v,wa" (X));
|
||||
#if EIGEN_OS_MAC
|
||||
// General, Altivec for Apple (VSX were added in ISA v2.06):
|
||||
#define EIGEN_OPTIMIZATION_BARRIER(X) __asm__ ("" : "+r,v" (X));
|
||||
#else
|
||||
// General, Altivec, VSX otherwise:
|
||||
#define EIGEN_OPTIMIZATION_BARRIER(X) __asm__ ("" : "+r,v,wa" (X));
|
||||
#endif
|
||||
#elif EIGEN_ARCH_ARM_OR_ARM64
|
||||
// General, NEON.
|
||||
#define EIGEN_OPTIMIZATION_BARRIER(X) __asm__ ("" : "+g,w" (X));
|
||||
// Clang doesn't like "r",
|
||||
// error: non-trivial scalar-to-vector conversion, possible invalid
|
||||
// constraint for vector type
|
||||
// GCC < 5 doesn't like "g",
|
||||
// error: 'asm' operand requires impossible reload
|
||||
#if EIGEN_COMP_GNUC_STRICT && EIGEN_GNUC_AT_MOST(5, 0)
|
||||
#define EIGEN_OPTIMIZATION_BARRIER(X) __asm__ ("" : "+r,w" (X));
|
||||
#else
|
||||
#define EIGEN_OPTIMIZATION_BARRIER(X) __asm__ ("" : "+g,w" (X));
|
||||
#endif
|
||||
#elif EIGEN_ARCH_i386_OR_x86_64
|
||||
// General, SSE.
|
||||
#define EIGEN_OPTIMIZATION_BARRIER(X) __asm__ ("" : "+g,x" (X));
|
||||
@@ -1177,8 +1232,12 @@ namespace Eigen {
|
||||
#define EIGEN_USING_STD(FUNC) using std::FUNC;
|
||||
#endif
|
||||
|
||||
#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || EIGEN_COMP_NVCC)
|
||||
// for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324)
|
||||
#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1916 || (EIGEN_COMP_MSVC == 1916 && EIGEN_COMP_NVCC))
|
||||
// For older MSVC versions, as well as 1900 && CUDA 8, using the base operator is necessary,
|
||||
// otherwise we get duplicate definition errors
|
||||
// For later MSVC versions, we require explicit operator= definition, otherwise we get
|
||||
// use of implicitly deleted operator errors.
|
||||
// (cf Bugs 920, 1000, 1324, 2291)
|
||||
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
||||
using Base::operator =;
|
||||
#elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
||||
@@ -1204,7 +1263,7 @@ namespace Eigen {
|
||||
* This is necessary, because the implicit definition is deprecated if the copy-assignment is overridden.
|
||||
*/
|
||||
#if EIGEN_HAS_CXX11
|
||||
#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS) CLASS(const CLASS&) = default;
|
||||
#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS) EIGEN_DEVICE_FUNC CLASS(const CLASS&) = default;
|
||||
#else
|
||||
#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS)
|
||||
#endif
|
||||
@@ -1229,12 +1288,12 @@ namespace Eigen {
|
||||
*/
|
||||
#if EIGEN_HAS_CXX11
|
||||
#define EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(Derived) \
|
||||
Derived() = default; \
|
||||
~Derived() = default;
|
||||
EIGEN_DEVICE_FUNC Derived() = default; \
|
||||
EIGEN_DEVICE_FUNC ~Derived() = default;
|
||||
#else
|
||||
#define EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(Derived) \
|
||||
Derived() {}; \
|
||||
/* ~Derived() {}; */
|
||||
EIGEN_DEVICE_FUNC Derived() {}; \
|
||||
/* EIGEN_DEVICE_FUNC ~Derived() {}; */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -292,20 +292,59 @@ template<typename T> EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T
|
||||
/** \internal Constructs the elements of an array.
|
||||
* The \a size parameter tells on how many objects to call the constructor of T.
|
||||
*/
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *ptr, std::size_t size)
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* default_construct_elements_of_array(T *ptr, std::size_t size)
|
||||
{
|
||||
std::size_t i;
|
||||
std::size_t i=0;
|
||||
EIGEN_TRY
|
||||
{
|
||||
for (i = 0; i < size; ++i) ::new (ptr + i) T;
|
||||
return ptr;
|
||||
for (i = 0; i < size; ++i) ::new (ptr + i) T;
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
destruct_elements_of_array(ptr, i);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
return NULL;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** \internal Copy-constructs the elements of an array.
|
||||
* The \a size parameter tells on how many objects to copy.
|
||||
*/
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* copy_construct_elements_of_array(T *ptr, const T* src, std::size_t size)
|
||||
{
|
||||
std::size_t i=0;
|
||||
EIGEN_TRY
|
||||
{
|
||||
for (i = 0; i < size; ++i) ::new (ptr + i) T(*(src + i));
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
destruct_elements_of_array(ptr, i);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** \internal Move-constructs the elements of an array.
|
||||
* The \a size parameter tells on how many objects to move.
|
||||
*/
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* move_construct_elements_of_array(T *ptr, T* src, std::size_t size)
|
||||
{
|
||||
std::size_t i=0;
|
||||
EIGEN_TRY
|
||||
{
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
for (i = 0; i < size; ++i) ::new (ptr + i) T(std::move(*(src + i)));
|
||||
#else
|
||||
for (i = 0; i < size; ++i) ::new (ptr + i) T(*(src + i));
|
||||
#endif
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
destruct_elements_of_array(ptr, i);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -326,10 +365,10 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(std::size_t s
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* aligned_new(std::size_t size)
|
||||
{
|
||||
check_size_for_overflow<T>(size);
|
||||
T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
|
||||
T *result = static_cast<T*>(aligned_malloc(sizeof(T)*size));
|
||||
EIGEN_TRY
|
||||
{
|
||||
return construct_elements_of_array(result, size);
|
||||
return default_construct_elements_of_array(result, size);
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
@@ -342,10 +381,10 @@ template<typename T> EIGEN_DEVICE_FUNC inline T* aligned_new(std::size_t size)
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(std::size_t size)
|
||||
{
|
||||
check_size_for_overflow<T>(size);
|
||||
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
|
||||
T *result = static_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
|
||||
EIGEN_TRY
|
||||
{
|
||||
return construct_elements_of_array(result, size);
|
||||
return default_construct_elements_of_array(result, size);
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
@@ -377,21 +416,32 @@ template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned
|
||||
{
|
||||
check_size_for_overflow<T>(new_size);
|
||||
check_size_for_overflow<T>(old_size);
|
||||
if(new_size < old_size)
|
||||
destruct_elements_of_array(pts+new_size, old_size-new_size);
|
||||
T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
|
||||
if(new_size > old_size)
|
||||
|
||||
// If elements need to be explicitly initialized, we cannot simply realloc
|
||||
// (or memcpy) the memory block - each element needs to be reconstructed.
|
||||
// Otherwise, objects that contain internal pointers like mpfr or
|
||||
// AnnoyingScalar can be pointing to the wrong thing.
|
||||
T* result = static_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*new_size));
|
||||
EIGEN_TRY
|
||||
{
|
||||
EIGEN_TRY
|
||||
{
|
||||
construct_elements_of_array(result+old_size, new_size-old_size);
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
conditional_aligned_free<Align>(result);
|
||||
EIGEN_THROW;
|
||||
// Move-construct initial elements.
|
||||
std::size_t copy_size = (std::min)(old_size, new_size);
|
||||
move_construct_elements_of_array(result, pts, copy_size);
|
||||
|
||||
// Default-construct remaining elements.
|
||||
if (new_size > old_size) {
|
||||
default_construct_elements_of_array(result + copy_size, new_size - old_size);
|
||||
}
|
||||
|
||||
// Delete old elements.
|
||||
conditional_aligned_delete<T, Align>(pts, old_size);
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
conditional_aligned_free<Align>(result);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -401,12 +451,12 @@ template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned
|
||||
if(size==0)
|
||||
return 0; // short-cut. Also fixes Bug 884
|
||||
check_size_for_overflow<T>(size);
|
||||
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
|
||||
T *result = static_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
|
||||
if(NumTraits<T>::RequireInitialization)
|
||||
{
|
||||
EIGEN_TRY
|
||||
{
|
||||
construct_elements_of_array(result, size);
|
||||
default_construct_elements_of_array(result, size);
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
@@ -419,24 +469,13 @@ template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned
|
||||
|
||||
template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(T* pts, std::size_t new_size, std::size_t old_size)
|
||||
{
|
||||
if (NumTraits<T>::RequireInitialization) {
|
||||
return conditional_aligned_realloc_new<T, Align>(pts, new_size, old_size);
|
||||
}
|
||||
|
||||
check_size_for_overflow<T>(new_size);
|
||||
check_size_for_overflow<T>(old_size);
|
||||
if(NumTraits<T>::RequireInitialization && (new_size < old_size))
|
||||
destruct_elements_of_array(pts+new_size, old_size-new_size);
|
||||
T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
|
||||
if(NumTraits<T>::RequireInitialization && (new_size > old_size))
|
||||
{
|
||||
EIGEN_TRY
|
||||
{
|
||||
construct_elements_of_array(result+old_size, new_size-old_size);
|
||||
}
|
||||
EIGEN_CATCH(...)
|
||||
{
|
||||
conditional_aligned_free<Align>(result);
|
||||
EIGEN_THROW;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return static_cast<T*>(conditional_aligned_realloc<Align>(static_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
|
||||
}
|
||||
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline void conditional_aligned_delete_auto(T *ptr, std::size_t size)
|
||||
@@ -566,6 +605,17 @@ template<typename T> struct smart_memmove_helper<T,false> {
|
||||
}
|
||||
};
|
||||
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
template<typename T> EIGEN_DEVICE_FUNC T* smart_move(T* start, T* end, T* target)
|
||||
{
|
||||
return std::move(start, end, target);
|
||||
}
|
||||
#else
|
||||
template<typename T> EIGEN_DEVICE_FUNC T* smart_move(T* start, T* end, T* target)
|
||||
{
|
||||
return std::copy(start, end, target);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
||||
@@ -606,7 +656,7 @@ template<typename T> class aligned_stack_memory_handler : noncopyable
|
||||
: m_ptr(ptr), m_size(size), m_deallocate(dealloc)
|
||||
{
|
||||
if(NumTraits<T>::RequireInitialization && m_ptr)
|
||||
Eigen::internal::construct_elements_of_array(m_ptr, size);
|
||||
Eigen::internal::default_construct_elements_of_array(m_ptr, size);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
~aligned_stack_memory_handler()
|
||||
@@ -657,7 +707,7 @@ struct local_nested_eval_wrapper<Xpr,NbEvaluations,true>
|
||||
m_deallocate(ptr==0)
|
||||
{
|
||||
if(NumTraits<Scalar>::RequireInitialization && object.data())
|
||||
Eigen::internal::construct_elements_of_array(object.data(), object.size());
|
||||
Eigen::internal::default_construct_elements_of_array(object.data(), object.size());
|
||||
object = xpr;
|
||||
}
|
||||
|
||||
|
||||
+33
-28
@@ -133,7 +133,10 @@ template<typename T> struct remove_all<T*> { typedef typename remove_all<
|
||||
template<typename T> struct is_arithmetic { enum { value = false }; };
|
||||
template<> struct is_arithmetic<float> { enum { value = true }; };
|
||||
template<> struct is_arithmetic<double> { enum { value = true }; };
|
||||
// GPU devices treat `long double` as `double`.
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<> struct is_arithmetic<long double> { enum { value = true }; };
|
||||
#endif
|
||||
template<> struct is_arithmetic<bool> { enum { value = true }; };
|
||||
template<> struct is_arithmetic<char> { enum { value = true }; };
|
||||
template<> struct is_arithmetic<signed char> { enum { value = true }; };
|
||||
@@ -167,10 +170,8 @@ template<> struct is_integral<signed int> { enum { value = true }; }
|
||||
template<> struct is_integral<unsigned int> { enum { value = true }; };
|
||||
template<> struct is_integral<signed long> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned long> { enum { value = true }; };
|
||||
#if EIGEN_COMP_MSVC
|
||||
template<> struct is_integral<signed __int64> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned __int64> { enum { value = true }; };
|
||||
#endif
|
||||
template<> struct is_integral<signed long long> { enum { value = true }; };
|
||||
template<> struct is_integral<unsigned long long> { enum { value = true }; };
|
||||
#endif
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
@@ -189,21 +190,9 @@ template<> struct make_unsigned<signed int> { typedef unsigned int type; }
|
||||
template<> struct make_unsigned<unsigned int> { typedef unsigned int type; };
|
||||
template<> struct make_unsigned<signed long> { typedef unsigned long type; };
|
||||
template<> struct make_unsigned<unsigned long> { typedef unsigned long type; };
|
||||
#if EIGEN_COMP_MSVC
|
||||
template<> struct make_unsigned<signed __int64> { typedef unsigned __int64 type; };
|
||||
template<> struct make_unsigned<unsigned __int64> { typedef unsigned __int64 type; };
|
||||
#endif
|
||||
|
||||
// Some platforms define int64_t as long long even for C++03. In this case we
|
||||
// are missing the definition for make_unsigned. If we just define it, we get
|
||||
// duplicated definitions for platforms defining int64_t as signed long for
|
||||
// C++03. We therefore add the specialization for C++03 long long for these
|
||||
// platforms only.
|
||||
#if EIGEN_OS_MAC
|
||||
template<> struct make_unsigned<unsigned long long> { typedef unsigned long long type; };
|
||||
template<> struct make_unsigned<long long> { typedef unsigned long long type; };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename T> struct add_const { typedef const T type; };
|
||||
template <typename T> struct add_const<T&> { typedef T& type; };
|
||||
@@ -466,20 +455,32 @@ template<typename T, std::size_t N> struct array_size<std::array<T,N> > {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/** \internal
|
||||
* Analogue of the std::size free function.
|
||||
* It returns the size of the container or view \a x of type \c T
|
||||
* Analogue of the std::ssize free function.
|
||||
* It returns the signed size of the container or view \a x of type \c T
|
||||
*
|
||||
* It currently supports:
|
||||
* - any types T defining a member T::size() const
|
||||
* - plain C arrays as T[N]
|
||||
*
|
||||
* For C++20, this function just forwards to `std::ssize`, or any ADL discoverable `ssize` function.
|
||||
*/
|
||||
template<typename T>
|
||||
EIGEN_CONSTEXPR Index size(const T& x) { return x.size(); }
|
||||
#if EIGEN_COMP_CXXVER < 20
|
||||
template <typename T>
|
||||
EIGEN_CONSTEXPR std::ptrdiff_t index_list_size(const T& x) {
|
||||
return static_cast<std::ptrdiff_t>(x.size());
|
||||
}
|
||||
|
||||
template<typename T,std::size_t N>
|
||||
EIGEN_CONSTEXPR Index size(const T (&) [N]) { return N; }
|
||||
template<typename T, std::ptrdiff_t N>
|
||||
EIGEN_CONSTEXPR std::ptrdiff_t index_list_size(const T (&)[N]) { return N; }
|
||||
#else
|
||||
template <typename T>
|
||||
EIGEN_CONSTEXPR auto index_list_size(T&& x) {
|
||||
using std::ssize;
|
||||
return ssize(std::forward<T>(x));
|
||||
}
|
||||
#endif // EIGEN_COMP_CXXVER
|
||||
|
||||
/** \internal
|
||||
* Convenient struct to get the result type of a nullary, unary, binary, or
|
||||
@@ -696,8 +697,7 @@ struct has_binary_operator
|
||||
template<int Y,
|
||||
int InfX = 0,
|
||||
int SupX = ((Y==1) ? 1 : Y/2),
|
||||
bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
|
||||
// use ?: instead of || just to shut up a stupid gcc 4.3 warning
|
||||
bool Done = ((SupX - InfX) <= 1 || ((SupX * SupX <= Y) && ((SupX + 1) * (SupX + 1) > Y)))>
|
||||
class meta_sqrt
|
||||
{
|
||||
enum {
|
||||
@@ -715,20 +715,25 @@ class meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ?
|
||||
|
||||
|
||||
/** \internal Computes the least common multiple of two positive integer A and B
|
||||
* at compile-time. It implements a naive algorithm testing all multiples of A.
|
||||
* It thus works better if A>=B.
|
||||
* at compile-time.
|
||||
*/
|
||||
template<int A, int B, int K=1, bool Done = ((A*K)%B)==0>
|
||||
template<int A, int B, int K=1, bool Done = ((A*K)%B)==0, bool Big=(A>=B)>
|
||||
struct meta_least_common_multiple
|
||||
{
|
||||
enum { ret = meta_least_common_multiple<A,B,K+1>::ret };
|
||||
};
|
||||
template<int A, int B, int K, bool Done>
|
||||
struct meta_least_common_multiple<A,B,K,Done,false>
|
||||
{
|
||||
enum { ret = meta_least_common_multiple<B,A,K>::ret };
|
||||
};
|
||||
template<int A, int B, int K>
|
||||
struct meta_least_common_multiple<A,B,K,true>
|
||||
struct meta_least_common_multiple<A,B,K,true,true>
|
||||
{
|
||||
enum { ret = A*K };
|
||||
};
|
||||
|
||||
|
||||
/** \internal determines whether the product of two numeric types is allowed and what the return type is */
|
||||
template<typename T, typename U> struct scalar_product_traits
|
||||
{
|
||||
|
||||
@@ -184,19 +184,7 @@ template<typename T> struct functor_traits
|
||||
|
||||
template<typename T> struct packet_traits;
|
||||
|
||||
template<typename T> struct unpacket_traits
|
||||
{
|
||||
typedef T type;
|
||||
typedef T half;
|
||||
enum
|
||||
{
|
||||
size = 1,
|
||||
alignment = 1,
|
||||
vectorizable = false,
|
||||
masked_load_available=false,
|
||||
masked_store_available=false
|
||||
};
|
||||
};
|
||||
template<typename T> struct unpacket_traits;
|
||||
|
||||
template<int Size, typename PacketType,
|
||||
bool Stop = Size==Dynamic || (Size%unpacket_traits<PacketType>::size)==0 || is_same<PacketType,typename unpacket_traits<PacketType>::half>::value>
|
||||
@@ -611,9 +599,9 @@ template<typename ExpressionType, typename Scalar = typename ExpressionType::Sca
|
||||
struct plain_row_type
|
||||
{
|
||||
typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
|
||||
ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
|
||||
int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
|
||||
typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
|
||||
ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
|
||||
int(ExpressionType::PlainObject::Options) | int(RowMajor), 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
|
||||
|
||||
typedef typename conditional<
|
||||
is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
|
||||
|
||||
@@ -316,9 +316,8 @@ void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(RealScalar matrixnorm
|
||||
// Compute V as V = U X; now A = U T U^* = U X D X^(-1) U^* = V D V^(-1)
|
||||
m_eivec.noalias() = m_schur.matrixU() * m_matX;
|
||||
// .. and normalize the eigenvectors
|
||||
for(Index k=0 ; k<n ; k++)
|
||||
{
|
||||
m_eivec.col(k).normalize();
|
||||
for (Index k = 0; k < n; k++) {
|
||||
m_eivec.col(k).stableNormalize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +119,8 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
: m_eivec(),
|
||||
m_alphas(),
|
||||
m_betas(),
|
||||
m_valuesOkay(false),
|
||||
m_vectorsOkay(false),
|
||||
m_computeEigenvectors(false),
|
||||
m_isInitialized(false),
|
||||
m_realQZ()
|
||||
{}
|
||||
|
||||
@@ -134,8 +134,8 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
: m_eivec(size, size),
|
||||
m_alphas(size),
|
||||
m_betas(size),
|
||||
m_valuesOkay(false),
|
||||
m_vectorsOkay(false),
|
||||
m_computeEigenvectors(false),
|
||||
m_isInitialized(false),
|
||||
m_realQZ(size),
|
||||
m_tmp(size)
|
||||
{}
|
||||
@@ -156,8 +156,8 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
: m_eivec(A.rows(), A.cols()),
|
||||
m_alphas(A.cols()),
|
||||
m_betas(A.cols()),
|
||||
m_valuesOkay(false),
|
||||
m_vectorsOkay(false),
|
||||
m_computeEigenvectors(false),
|
||||
m_isInitialized(false),
|
||||
m_realQZ(A.cols()),
|
||||
m_tmp(A.cols())
|
||||
{
|
||||
@@ -177,7 +177,8 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
* \sa eigenvalues()
|
||||
*/
|
||||
EigenvectorsType eigenvectors() const {
|
||||
eigen_assert(m_vectorsOkay && "Eigenvectors for GeneralizedEigenSolver were not calculated.");
|
||||
eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute eigenvectors");
|
||||
eigen_assert(m_computeEigenvectors && "Eigenvectors for GeneralizedEigenSolver were not calculated");
|
||||
return m_eivec;
|
||||
}
|
||||
|
||||
@@ -201,7 +202,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
*/
|
||||
EigenvalueType eigenvalues() const
|
||||
{
|
||||
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||
eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute eigenvalues.");
|
||||
return EigenvalueType(m_alphas,m_betas);
|
||||
}
|
||||
|
||||
@@ -212,7 +213,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
* \sa betas(), eigenvalues() */
|
||||
ComplexVectorType alphas() const
|
||||
{
|
||||
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||
eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute alphas.");
|
||||
return m_alphas;
|
||||
}
|
||||
|
||||
@@ -223,7 +224,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
* \sa alphas(), eigenvalues() */
|
||||
VectorType betas() const
|
||||
{
|
||||
eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
|
||||
eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute betas.");
|
||||
return m_betas;
|
||||
}
|
||||
|
||||
@@ -254,7 +255,7 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
|
||||
ComputationInfo info() const
|
||||
{
|
||||
eigen_assert(m_valuesOkay && "EigenSolver is not initialized.");
|
||||
eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
|
||||
return m_realQZ.info();
|
||||
}
|
||||
|
||||
@@ -277,7 +278,8 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
||||
EigenvectorsType m_eivec;
|
||||
ComplexVectorType m_alphas;
|
||||
VectorType m_betas;
|
||||
bool m_valuesOkay, m_vectorsOkay;
|
||||
bool m_computeEigenvectors;
|
||||
bool m_isInitialized;
|
||||
RealQZ<MatrixType> m_realQZ;
|
||||
ComplexVectorType m_tmp;
|
||||
};
|
||||
@@ -292,8 +294,6 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
|
||||
using std::abs;
|
||||
eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
|
||||
Index size = A.cols();
|
||||
m_valuesOkay = false;
|
||||
m_vectorsOkay = false;
|
||||
// Reduce to generalized real Schur form:
|
||||
// A = Q S Z and B = Q T Z
|
||||
m_realQZ.compute(A, B, computeEigenvectors);
|
||||
@@ -406,10 +406,9 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
m_valuesOkay = true;
|
||||
m_vectorsOkay = computeEigenvectors;
|
||||
}
|
||||
m_computeEigenvectors = computeEigenvectors;
|
||||
m_isInitialized = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ template<typename _MatrixType> class HessenbergDecomposition
|
||||
|
||||
private:
|
||||
|
||||
typedef Matrix<Scalar, 1, Size, Options | RowMajor, 1, MaxSize> VectorType;
|
||||
typedef Matrix<Scalar, 1, Size, int(Options) | int(RowMajor), 1, MaxSize> VectorType;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp);
|
||||
|
||||
|
||||
@@ -435,34 +435,33 @@ inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& ex
|
||||
shiftInfo.coeffRef(1) = m_matT.coeff(iu-1,iu-1);
|
||||
shiftInfo.coeffRef(2) = m_matT.coeff(iu,iu-1) * m_matT.coeff(iu-1,iu);
|
||||
|
||||
// Wilkinson's original ad hoc shift
|
||||
if (iter == 10)
|
||||
{
|
||||
exshift += shiftInfo.coeff(0);
|
||||
for (Index i = 0; i <= iu; ++i)
|
||||
m_matT.coeffRef(i,i) -= shiftInfo.coeff(0);
|
||||
Scalar s = abs(m_matT.coeff(iu,iu-1)) + abs(m_matT.coeff(iu-1,iu-2));
|
||||
shiftInfo.coeffRef(0) = Scalar(0.75) * s;
|
||||
shiftInfo.coeffRef(1) = Scalar(0.75) * s;
|
||||
shiftInfo.coeffRef(2) = Scalar(-0.4375) * s * s;
|
||||
}
|
||||
|
||||
// MATLAB's new ad hoc shift
|
||||
if (iter == 30)
|
||||
{
|
||||
Scalar s = (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
|
||||
s = s * s + shiftInfo.coeff(2);
|
||||
if (s > Scalar(0))
|
||||
{
|
||||
s = sqrt(s);
|
||||
if (shiftInfo.coeff(1) < shiftInfo.coeff(0))
|
||||
s = -s;
|
||||
s = s + (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
|
||||
s = shiftInfo.coeff(0) - shiftInfo.coeff(2) / s;
|
||||
exshift += s;
|
||||
// Alternate exceptional shifting strategy every 16 iterations.
|
||||
if (iter % 16 == 0) {
|
||||
// Wilkinson's original ad hoc shift
|
||||
if (iter % 32 != 0) {
|
||||
exshift += shiftInfo.coeff(0);
|
||||
for (Index i = 0; i <= iu; ++i)
|
||||
m_matT.coeffRef(i,i) -= s;
|
||||
shiftInfo.setConstant(Scalar(0.964));
|
||||
m_matT.coeffRef(i,i) -= shiftInfo.coeff(0);
|
||||
Scalar s = abs(m_matT.coeff(iu,iu-1)) + abs(m_matT.coeff(iu-1,iu-2));
|
||||
shiftInfo.coeffRef(0) = Scalar(0.75) * s;
|
||||
shiftInfo.coeffRef(1) = Scalar(0.75) * s;
|
||||
shiftInfo.coeffRef(2) = Scalar(-0.4375) * s * s;
|
||||
} else {
|
||||
// MATLAB's new ad hoc shift
|
||||
Scalar s = (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
|
||||
s = s * s + shiftInfo.coeff(2);
|
||||
if (s > Scalar(0))
|
||||
{
|
||||
s = sqrt(s);
|
||||
if (shiftInfo.coeff(1) < shiftInfo.coeff(0))
|
||||
s = -s;
|
||||
s = s + (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
|
||||
s = shiftInfo.coeff(0) - shiftInfo.coeff(2) / s;
|
||||
exshift += s;
|
||||
for (Index i = 0; i <= iu; ++i)
|
||||
m_matT.coeffRef(i,i) -= s;
|
||||
shiftInfo.setConstant(Scalar(0.964));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
||||
: m_eivec(),
|
||||
m_eivalues(),
|
||||
m_subdiag(),
|
||||
m_hcoeffs(),
|
||||
m_info(InvalidInput),
|
||||
m_isInitialized(false),
|
||||
m_eigenvectorsOk(false)
|
||||
@@ -147,6 +148,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
||||
: m_eivec(size, size),
|
||||
m_eivalues(size),
|
||||
m_subdiag(size > 1 ? size - 1 : 1),
|
||||
m_hcoeffs(size > 1 ? size - 1 : 1),
|
||||
m_isInitialized(false),
|
||||
m_eigenvectorsOk(false)
|
||||
{}
|
||||
@@ -172,6 +174,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
||||
: m_eivec(matrix.rows(), matrix.cols()),
|
||||
m_eivalues(matrix.cols()),
|
||||
m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1),
|
||||
m_hcoeffs(matrix.cols() > 1 ? matrix.cols() - 1 : 1),
|
||||
m_isInitialized(false),
|
||||
m_eigenvectorsOk(false)
|
||||
{
|
||||
@@ -378,6 +381,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
||||
EigenvectorsType m_eivec;
|
||||
RealVectorType m_eivalues;
|
||||
typename TridiagonalizationType::SubDiagonalType m_subdiag;
|
||||
typename TridiagonalizationType::CoeffVectorType m_hcoeffs;
|
||||
ComputationInfo m_info;
|
||||
bool m_isInitialized;
|
||||
bool m_eigenvectorsOk;
|
||||
@@ -450,7 +454,8 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
||||
if(scale==RealScalar(0)) scale = RealScalar(1);
|
||||
mat.template triangularView<Lower>() /= scale;
|
||||
m_subdiag.resize(n-1);
|
||||
internal::tridiagonalization_inplace(mat, diag, m_subdiag, computeEigenvectors);
|
||||
m_hcoeffs.resize(n-1);
|
||||
internal::tridiagonalization_inplace(mat, diag, m_subdiag, m_hcoeffs, computeEigenvectors);
|
||||
|
||||
m_info = internal::computeFromTridiagonal_impl(diag, m_subdiag, m_maxIterations, computeEigenvectors, m_eivec);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user