Compare commits

..

59 Commits
5.0 ... nightly

Author SHA1 Message Date
Rasmus Munk Larsen
7c7d84735e Align temporary array in TensorSelectOp packet evaluator. 2025-11-05 19:44:47 +00:00
Antonio Sánchez
142caf889c Fix MKL enum conversion warning.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Fix MKL enum conversion warning.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->
Fixes #2999.

Closes #2999

See merge request libeigen/eigen!2061
2025-11-05 18:03:22 +00:00
Antonio Sánchez
9e5714b93b Remove deprecated CUDA device properties.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Remove deprecated CUDA device properties.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->
Fixes #3000.

Closes #3000

See merge request libeigen/eigen!2060
2025-11-05 17:12:33 +00:00
Tyler Veness
06f5cb4878 Use wrapper macro for multidimensional subscript feature test
See merge request libeigen/eigen!2059
2025-11-04 22:26:27 +00:00
Rasmus Munk Larsen
63fc0bc8c1 Make TernarySelectOp immune to const differences.
See merge request libeigen/eigen!2058

Co-authored-by: Rasmus Munk Larsen <rmlarsen@google.com>
2025-11-04 21:42:32 +00:00
Rasmus Munk Larsen
71703a9816 Make assume_aligned a no-op on ARM & ARM64 when msan is used, to work around a missing linker symbol. 2025-11-04 20:26:36 +00:00
Tyler Veness
f95b4698fc Add support for C++23 multidimensional subscript operator
I'm not sure where to put tests for this, assuming they're needed. They also wouldn't run in CI anyway since CI only exercises the C++17 codepaths.

See merge request libeigen/eigen!2053
2025-11-04 07:03:04 +00:00
Rasmus Munk Larsen
b6fcddccfc Get rid of pblend packet op.
There was only a single code path left in TensorEvaluator using pblend. We can replace that with a call to the more general TernarySelectOp and get rid of pblend entirely from Core.

Closes #2998

See merge request libeigen/eigen!2056

Co-authored-by: Rasmus Munk Larsen <rmlarsen@google.com>
2025-11-03 23:27:50 +00:00
Rasmus Munk Larsen
ed9a0e59ba Fix more bugs in !2052
Fixes #2998

Closes #2998

See merge request libeigen/eigen!2057

Co-authored-by: Rasmus Munk Larsen <rmlarsen@google.com>
2025-11-03 20:26:17 +00:00
Rasmus Munk Larsen
a20fc40e4e Revert "simplify squaredNorm"
This causes some subtle alignment-related bugs, which @chuckyschluz is currently investigating.

See merge request libeigen/eigen!2055
2025-11-03 18:59:51 +00:00
Antonio Sánchez
04eb06b354 Fix doc references for nullary expressions.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Fix doc references for nullary expressions.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

Fixes #2997.

### Additional information
<!--Any additional information you think is important.-->

Closes #2997

See merge request libeigen/eigen!2054
2025-11-03 18:47:04 +00:00
Rasmus Munk Larsen
bfdbc031c2 Fixes #2998. 2025-11-02 23:58:16 +00:00
Rasmus Munk Larsen
8716f109e4 Implement assume_aligned using the standard API
This implements `Eigen::internal::assume_aligned` to match the API for C++20 standard as best as possible using either `std::assume_aligned` or `__builtin_assume_aligned` if available. If neither is available, the function is a no-op.

The override macro `EIGEN_ASSUME_ALIGNED` was changed to a `EIGEN_DONT_ASSUME_ALIGNED`, which now forces the function to be a no-op.

See merge request libeigen/eigen!2052
2025-11-01 12:04:19 +00:00
Rasmus Munk Larsen
ce70a507c0 Enable more generic packet ops for double.
See merge request libeigen/eigen!2050
2025-10-30 19:14:43 +00:00
Charles Schlosser
fb5bb3e98f simplify squaredNorm
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->
My review of https://gitlab.com/libeigen/eigen/-/merge_requests/2048 reminded me there was a much easier and better way of doing this for complex arrays.


### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

### Additional information
<!--Any additional information you think is important.-->

See merge request libeigen/eigen!2049
2025-10-30 02:51:15 +00:00
Rasmus Munk Larsen
ece9a4c0b6 Always vectorize abs2() for non-complex types.
For several packet types, `abs2` was not vectorized even if it only requires `pmul`. Get rid of the confusing and redundant `HasAbs2` enum and instead check `HasMul` in addition to making sure the scalar type is not complex.

See merge request libeigen/eigen!2048
2025-10-30 02:42:56 +00:00
Antonio Sánchez
60122df698 Allow user to configure if free is allowed at runtime.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Allow user to configure if `free` is allowed at runtime.

Reverts to Eigen 3.4 behavior by default, where `free(...)` is allowed if `EIGEN_RUNTIME_NO_MALLOC` is defined but `set_is_malloc_allowed(true)`.  Adds a separate `set_is_free_allowed(...)` to explicitly control use of `std::free`.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

Fixes #2983.

### Additional information
<!--Any additional information you think is important.-->

Closes #2983

See merge request libeigen/eigen!2047
2025-10-28 22:29:00 +00:00
Tyler Veness
9234883914 Fix SparseVector::insert(Index) assigning int to Scalar
Scalar doesn't necessarily support implicit construction from int or
assignment from int.

Here's the error message I got without this fix:
```
/home/tav/git/Sleipnir/build/_deps/eigen3-src/Eigen/src/SparseCore/SparseVector.h:180:25: error: no match for ‘operator=’ (operand types are ‘Eigen::internal::CompressedStorage<ExplicitDouble, int>::Scalar’ {aka ‘ExplicitDouble’} and ‘int’)
  180 |     m_data.value(p + 1) = 0;
      |     ~~~~~~~~~~~~~~~~~~~~^~~
```

See merge request libeigen/eigen!2046
2025-10-27 22:06:59 +00:00
Tyler Veness
be56fff1ff Fix ambiguous sqrt() overload caused by ADL
Here's the compiler error:
```
/home/tav/git/Sleipnir/build/_deps/eigen3-src/Eigen/src/Householder/Householder.h:82:16: error: call of overloaded ‘sqrt(boost::decimal::decimal64_t)’ is ambiguous
   82 |     beta = sqrt(numext::abs2(c0) + tailSqNorm);
      |            ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/tav/git/Sleipnir/build/_deps/eigen3-src/Eigen/src/Householder/Householder.h:82:16: note: there are 2 candidates
In file included from /home/tav/git/Sleipnir/build/_deps/eigen3-src/Eigen/Core:198,
                 from /home/tav/git/Sleipnir/test/src/optimization/cart_pole_problem_test.cpp:8:
/home/tav/git/Sleipnir/build/_deps/eigen3-src/Eigen/src/Core/MathFunctions.h:1384:75: note: candidate 1: ‘typename Eigen::internal::sqrt_retval<typename Eigen::internal::global_math_functions_filtering_base<Scalar>::type>::type Eigen::numext::sqrt(const Scalar&) [with Scalar = boost::decimal::decimal64_t; typename Eigen::internal::sqrt_retval<typename Eigen::internal::global_math_functions_filtering_base<Scalar>::type>::type = boost::decimal::decimal64_t; typename Eigen::internal::global_math_functions_filtering_base<Scalar>::type = boost::decimal::decimal64_t]’
 1384 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x) {
      |                                                                           ^~~~
In file included from /home/tav/git/Sleipnir/build/_deps/decimal-src/include/boost/decimal/detail/cmath/ellint_1.hpp:16,
                 from /home/tav/git/Sleipnir/build/_deps/decimal-src/include/boost/decimal/cmath.hpp:18,
                 from /home/tav/git/Sleipnir/build/_deps/decimal-src/include/boost/decimal.hpp:33,
                 from /home/tav/git/Sleipnir/test/include/scalar_types_under_test.hpp:6,
                 from /home/tav/git/Sleipnir/test/src/optimization/cart_pole_problem_test.cpp:19:
/home/tav/git/Sleipnir/build/_deps/decimal-src/include/boost/decimal/detail/cmath/sqrt.hpp:167:16: note: candidate 2: ‘constexpr T boost::decimal::sqrt(T) requires  is_decimal_floating_point_v<T> [with T = decimal64_t]’
  167 | constexpr auto sqrt(const T val) noexcept
      |                ^~~~
```

Calling a function via its unqualified name invokes argument-dependent lookup. In this case, since `using numext::sqrt;` was used, both `numext::sqrt()` and `boost::decimal::sqrt()` participated in overload resolution. Since only `numext::sqrt()` was intended, the fix is to call that overload directly instead.

See merge request libeigen/eigen!2044
2025-10-26 02:03:22 +00:00
Rasmus Munk Larsen
2e91853adf Fix a benign bug in ComplexQZ
ComplexQZ would try to apply a Jacobi rotation to an empty block, which triggers a warning in static analyzers, since the corresponding `Eigen::Map` object will contain a `nullptr`.

See merge request libeigen/eigen!2043
2025-10-24 20:54:54 +00:00
Antonio Sánchez
1a5eecd45e Clarify range spanning major versions only works with 3.4.1.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Clarify range spanning major versions only works with 3.4.1.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

Fixes #2994.

Closes #2994

See merge request libeigen/eigen!2042
2025-10-24 19:54:27 +00:00
Antonio Sánchez
b4209fe984 Eliminate use of std::cout in ArpackSelfAdjointEigenSolver.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Eliminate use of std::cout in ArpackSelfAdjointEigenSolver.

Instead set the appropriate error status on failure.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

### Additional information
<!--Any additional information you think is important.-->

See merge request libeigen/eigen!2041
2025-10-24 19:46:57 +00:00
Tyler Veness
ac3ef16f30 Fix SparseVector::insertBack() with custom scalar types
It fixes this compiler error:
```
/home/tav/git/Sleipnir/build/_deps/eigen3-src/Eigen/src/SparseCore/SparseVector.h:143:19: error: cannot convert ‘int’ to ‘const Eigen::internal::CompressedStorage<boost::decimal::decimal64_t, int>::Scalar&’ {aka ‘const boost::decimal::decimal64_t&’}
  143 |     m_data.append(0, i);
      |                   ^
      |                   |
      |                   int
```

This change matches what SparseMatrix does:
https://gitlab.com/libeigen/eigen/-/blob/master/Eigen/src/SparseCore/SparseMatrix.h#L430-L438

See merge request libeigen/eigen!2040
2025-10-23 07:03:37 +00:00
Charles Schlosser
40da5b64ce CI enhancements: visual indication of flaky tests
<!-- 
Thanks for contributing a merge request! Please name and fully describe your MR as you would for a commit message.
If the MR fixes an issue, please include "Fixes #issue" in the commit message and the MR description.

In addition, we recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen) and [git page](https://eigen.tuxfamily.org/index.php?title=Git), which will help you submit a more standardized MR.

Before submitting the MR, you also need to complete the following checks:
- Make one PR per feature/bugfix (don't mix multiple changes into one PR). Avoid committing unrelated changes.
- Rebase before committing
- For code changes, run the test suite (at least the tests that are likely affected by the change).
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- If possible, add a test (both for bug-fixes as well as new features)
- Make sure new features are documented

Note that we are a team of volunteers; we appreciate your patience during the review process.

Again, thanks for contributing! -->

### Reference issue
<!-- You can link to a specific issue using the gitlab syntax #<issue number>  -->

### What does this implement/fix?
<!--Please explain your changes.-->

Currently, we run each test 3 times to account for flaky tests. Sometimes, the test fails so quickly that the random seed is the same for the subsequent test, which fails the exact same way. 

This MR uses a nanosecond seed which resolves the issue described above. Now, if the test does not pass on the first attempt but passes on the retries, the gitlab job status will be yellow but still be treated as a pass in the ci/cd pipeline. Hopefully, this means we will get more passes and help us identify room for improvement.

### Additional information
<!--Any additional information you think is important.-->

See merge request libeigen/eigen!2025
2025-10-22 04:51:51 +00:00
Antonio Sánchez
8e60d4173c Support AVX for i686.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

Support AVX for i686.

There was an existing work-around for windows.  Added the more generic
architecture comparison to also apply for linux.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

Fixes #2991.

Closes #2991

See merge request libeigen/eigen!2037
2025-10-20 21:47:42 +00:00
Antonio Sánchez
2aa2ff2900 More ComplexQZ fixes.
<!-- 
Thanks for contributing a merge request!

We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).

Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
  See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features.  If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
  This allows us to rebase and merge your change.

Note that we are a team of volunteers; we appreciate your patience during the review process.
-->

### Description
<!--Please explain your changes.-->

More ComplexQZ fixes.

Extra semicolons are triggering some warnings and errors with `-Werror`.
Moved the `Sparse` import up to the umbrella header to avoid IWYU exports.

### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>. 
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->

### Additional information
<!--Any additional information you think is important.-->

See merge request libeigen/eigen!2036
2025-10-20 21:09:53 +00:00
Antonio Sánchez
f5907c5930 Fix commit references in changelog. 2025-10-18 23:48:30 +00:00
Antonio Sánchez
cc8748791c Include required headers with relative paths in ComplexQZ 2025-10-18 23:46:12 +00:00
Antonio Sanchez
73da4623b1 Try disabling the cache again for ROCm. 2025-10-17 15:17:33 -07:00
Antonio Sánchez
d739b9dc60 Set the merge request template to be default. 2025-10-17 22:16:57 +00:00
Antonio Sánchez
e77977e231 Set the merge request template to be default. 2025-10-17 22:06:46 +00:00
Ludwig Striet
4c8744774f Fixes #2987: delete unused variable steps 2025-10-16 13:30:48 +00:00
Charles Schlosser
d426838d01 fix complexqz Wpedantic warnings 2025-10-15 15:12:33 +00:00
Saran Tunyasuvunakool
db02f97850 Add a missing #include <version> to Core. 2025-10-15 15:10:30 +00:00
Rasmus Munk Larsen
da55dd1471 Cleanup: Move 2x2 real SVD into the Jacobi module where it naturally belongs. 2025-10-14 00:58:37 +00:00
Ludwig Striet
99f8512985 ComplexQZ 2025-10-13 17:35:03 +00:00
Antonio Sánchez
e1f1a608be Fix DLL builds and c++ lapack declarations. 2025-10-13 16:25:08 +00:00
Antonio Sánchez
3abaabb999 Streamline merge request and bug templates. 2025-10-12 22:19:03 +00:00
Antonio Sanchez
52358cb93b Grammar fix "must has" --> "must have". 2025-10-12 00:07:41 +00:00
Rasmus Munk Larsen
565db1c603 Optimize ApplyOnTheRight for Jacobi rotations when FMA is available 2025-10-12 00:04:19 +00:00
Antonio Sánchez
3bd0bfe0e0 Disable ROCm job cache. 2025-10-11 23:29:42 +00:00
Charlie Schlosser
cd4f989f8f assume_aligned uses bytes not bits 2025-10-10 14:08:10 -04:00
Antonio Sánchez
ac7c192e1b Add a bunch of useful scripts for planning releases. 2025-10-10 00:49:58 +00:00
Damiano Franzò
5bc944a3ef Fix jacobi svd for TriangularBase 2025-10-10 00:10:50 +00:00
Antonio Sánchez
dbe9e6961e Fix BLAS/LAPACK DLL usage on Windows. 2025-10-10 00:09:45 +00:00
Antonio Sánchez
ef3c5c1d1d Add workaround for using std::fma for scalar multiply-add. 2025-10-09 18:57:46 +00:00
Charles Schlosser
5996176b88 Fix alignment bug in avx pcast<Packet4l, Packet4d> 2025-10-09 02:50:42 +00:00
Laurenz
4bd382df56 Fix SSE PacketMath Compilation Error on QNX 2025-10-08 17:13:16 +00:00
Charles Schlosser
13bd14974d fix errors in windows builds and tests 2025-10-07 22:47:35 +00:00
Jeremy Nimmer
eea6587b0e Fix scalar_inner_product_op when binary ops return a different type 2025-10-05 22:51:50 +00:00
Rasmus Munk Larsen
7eaf9ae68d Add a method to SelfAdjointEigenSolver for computing the matrix exponential 2025-10-05 15:06:04 +00:00
Sergiu Deitsch
32b0f386bc Eliminate possible -Wstringop-overflow warning in .setZero() 2025-10-04 00:03:03 +02:00
Olav
1edf360e3c Fix line endings 2025-10-03 13:21:05 +02:00
Antonio Sánchez
ccde35bcd5 Update dev version number. 2025-10-01 22:58:44 +00:00
Guilhem Saurel
a67f9dabb0 tests: add missing link 2025-10-01 22:38:52 +00:00
Antonio Sánchez
e6792039fb Update changelog to reflect 3.4.1 and 5.0.0 releases. 2025-10-01 18:43:54 +00:00
Antonio Sánchez
4916887f2c Update geo_homogeneous test, add eval() to PermutationMatrix. 2025-10-01 18:01:11 +00:00
Eugene Zhulenev
5c1029be1a The 'CompressedStorageIterator<>' needs to satisfy the RandomAccessIterator 2025-09-30 16:28:41 +00:00
Charles Schlosser
f9f515fb55 get rid of a bunch of windows jobs 2025-09-30 01:44:48 +00:00
52 changed files with 1013 additions and 601 deletions

View File

@@ -1,42 +1,37 @@
<!--
Please read this!
Thank you for submitting an issue!
Before opening a new issue, make sure to search for keywords in the issues
filtered by "bug::confirmed" or "bug::unconfirmed" and "bugzilla" label:
- https://gitlab.com/libeigen/eigen/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=bug%3A%3Aconfirmed
- https://gitlab.com/libeigen/eigen/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=bug%3A%3Aunconfirmed
- https://gitlab.com/libeigen/eigen/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=bugzilla
and verify the issue you're about to submit isn't a duplicate. -->
Before opening a new issue, please search for keywords in the existing [list of issues](https://gitlab.com/libeigen/eigen/-/issues?state=opened) to verify it isn't a duplicate.
-->
### Summary
<!-- Summarize the bug encountered concisely. -->
### Environment
<!-- Please provide your development environment here -->
<!-- Please provide your development environment. -->
- **Operating System** : Windows/Linux
- **Architecture** : x64/Arm64/PowerPC ...
- **Eigen Version** : 3.3.9
- **Compiler Version** : Gcc7.0
- **Eigen Version** : 5.0.0
- **Compiler Version** : gcc-12.0
- **Compile Flags** : -O3 -march=native
- **Vector Extension** : SSE/AVX/NEON ...
### Minimal Example
<!-- If possible, please create a minimal example here that exhibits the problematic behavior.
You can also link to [godbolt](https://godbolt.org). But please note that you need to click
the "Share" button in the top right-hand corner of the godbolt page where you reproduce the sample
code to get the share link instead of in your browser address bar.
<!--
Please create a minimal reproducing example here that exhibits the problematic behavior.
The example should be complete, in that it can fully build and run. See the [the guidelines on stackoverflow](https://stackoverflow.com/help/minimal-reproducible-example) for how to create a good minimal example.
You can read [the guidelines on stackoverflow](https://stackoverflow.com/help/minimal-reproducible-example)
on how to create a good minimal example. -->
You can also link to [godbolt](https://godbolt.org). Note that you need to click
the "Share" button in the top right-hand corner of the godbolt page to get the share link
instead of the URL in your browser address bar.
-->
```cpp
//show your code here
// Insert your code here.
```
### Steps to reproduce
<!-- Describe how one can reproduce the issue - this is very important. Please use an ordered list. -->
### Steps to reproduce the issue
<!-- Describe the necessary steps to reproduce the issue. -->
1. first step
2. second step
@@ -49,21 +44,16 @@ on how to create a good minimal example. -->
<!-- Describe what you should see instead. -->
### Relevant logs
<!-- Add relevant code snippets or program output within blocks marked by " ``` " -->
<!-- Add relevant build logs or program output within blocks marked by " ``` " -->
<!-- OPTIONAL: remove this section if you are not reporting a compilation warning issue.-->
### Warning Messages
<!-- Show us the warning messages you got! -->
<!-- OPTIONAL: remove this section if you are not reporting a performance issue. -->
### Benchmark scripts and results
### [Optional] Benchmark scripts and results
<!-- Please share any benchmark scripts - either standalone, or using [Google Benchmark](https://github.com/google/benchmark). -->
### Anything else that might help
<!-- It will be better to provide us more information to help narrow down the cause.
<!--
It will be better to provide us more information to help narrow down the cause.
Including but not limited to the following:
- lines of code that might help us diagnose the problem.
- potential ways to address the issue.
- last known working/first broken version (release number or commit hash). -->
- [ ] Have a plan to fix this issue.
- last known working/first broken version (release number or commit hash).
-->

View File

@@ -1,6 +1,13 @@
<!--
Thank you for submitting a Feature Request!
If you want to run ideas by the maintainers and the Eigen community first,
you can chat about them on the [Eigen Discord server](https://discord.gg/2SkEJGqZjR).
-->
### Describe the feature you would like to be implemented.
### Would such a feature be useful for other users? Why?
### Why Would such a feature be useful for other users?
### Any hints on how to implement the requested feature?

View File

@@ -0,0 +1,30 @@
<!--
Thanks for contributing a merge request!
We recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen).
Before submitting the MR, please complete the following checks:
- Create one PR per feature or bugfix,
- Run the test suite to verify your changes.
See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- Add tests to cover the bug addressed or any new feature.
- Document new features. If it is a substantial change, add it to the [Changelog](https://gitlab.com/libeigen/eigen/-/blob/master/CHANGELOG.md).
- Leave the following box checked when submitting: `Allow commits from members who can merge to the target branch`.
This allows us to rebase and merge your change.
Note that we are a team of volunteers; we appreciate your patience during the review process.
-->
### Description
<!--Please explain your changes.-->
%{first_multiline_commit}
### Reference issue
<!--
You can link to a specific issue using the gitlab syntax #<issue number>.
If the MR fixes an issue, write "Fixes #<issue number>" to have the issue automatically closed on merge.
-->
### Additional information
<!--Any additional information you think is important.-->

View File

@@ -1,26 +0,0 @@
<!--
Thanks for contributing a merge request! Please name and fully describe your MR as you would for a commit message.
If the MR fixes an issue, please include "Fixes #issue" in the commit message and the MR description.
In addition, we recommend that first-time contributors read our [contribution guidelines](https://eigen.tuxfamily.org/index.php?title=Contributing_to_Eigen) and [git page](https://eigen.tuxfamily.org/index.php?title=Git), which will help you submit a more standardized MR.
Before submitting the MR, you also need to complete the following checks:
- Make one PR per feature/bugfix (don't mix multiple changes into one PR). Avoid committing unrelated changes.
- Rebase before committing
- For code changes, run the test suite (at least the tests that are likely affected by the change).
See our [test guidelines](https://eigen.tuxfamily.org/index.php?title=Tests).
- If possible, add a test (both for bug-fixes as well as new features)
- Make sure new features are documented
Note that we are a team of volunteers; we appreciate your patience during the review process.
Again, thanks for contributing! -->
### Reference issue
<!-- You can link to a specific issue using the gitlab syntax #<issue number> -->
### What does this implement/fix?
<!--Please explain your changes.-->
### Additional information
<!--Any additional information you think is important.-->

View File

@@ -1,15 +1,6 @@
# Changelog
## [5.0.1] - 2025-11-11
A few bug-fixes from the master branch, including
- Dirty git state [#2995]
- Failing geo_homogeneous tests [#2977]
- Alignment issues [#2982, #2984]
- Missing C++20 `<version>` header [#2986]
- BLAS/LAPACK build on windows [#2980]
See the full lists of [addressed bugs](https://gitlab.com/libeigen/eigen/-/issues?state=all&label_name%5B%5D=release%3A%3A5.0.1) and [merge requests](https://gitlab.com/libeigen/eigen/-/merge_requests?state=all&label_name%5B%5D=release%3A%3A5.0.1) for more details.
## [Unreleased]
## [5.0.0] - 2025-09-30
@@ -45,6 +36,14 @@ This release marks a transition to [Semantic Versioning](https://semver.org/). P
* Euler angles are now returned in a more canonical form, potentially resulting in a change of behavior [!1301, !1314].
* Eigen's random number generation has changed, resulting in a change of behavior. Please do not rely on specific random numbers from Eigen - these were never guaranteed to be consistent across Eigen versions, nor are they generally consistent across platforms [!1437].
## [3.4.1] - 2025-09-30
Many bug fixes have been backported from the main branch.
A list of new issues addressed can be found via the [3.4.1](https://gitlab.com/libeigen/eigen/-/issues?state=all&label_name%5B%5D=3.4.1) label on GitLab.
Check the [git commit history](https://gitlab.com/libeigen/eigen/-/commits/3.4.1) for the full list of changes.
## [3.4.0] - 2021-08-18
**Notice:** 3.4.x will be the last major release series of Eigen that will support c++03.
@@ -344,7 +343,7 @@ Changes since 3.3.7:
* Commit dd6de618: Fix a bug with half-precision floats on GPUs.
## [3.3.7] - 2018-12-11
¸¸¸¸
Changes since 3.3.6:
* #1643: Fix compilation with GCC>=6 and compiler optimization turned off.
@@ -528,6 +527,7 @@ Changes since 3.3.2:
* #1378: fix doc (`DiagonalIndex` vs `Diagonal`).
## [3.3.2] - 2017-01-18
Changes since 3.3.1:
* General:
@@ -845,6 +845,7 @@ Changes since 3.2.8:
* #1175: fix index type conversion warnings in sparse to dense conversion.
## [3.2.8] - 2016-02-16
Changes since 3.2.7:
* Main fixes and improvements:
@@ -1268,6 +1269,7 @@ Main changes since 3.2-beta1:
* Many other fixes including #230, #482, #542, #561, #564, #565, #566, #578, #581, #595, #597, #598, #599, #605, #606, #615.
## [3.1.3] - 2013-04-16
Changes since 3.1.2:
* #526 - Fix linear vectorized transversal in linspace.
@@ -1351,6 +1353,7 @@ Changes since 3.1.0:
* Fixed Sparse module compilation under MSVC 2005
## [3.0.6] - 2012-07-09
Changes since 3.0.5:
* #447 - fix infinite recursion in `ProductBase::coeff()`
* #478 - fix RealSchur on a zero matrix
@@ -1507,6 +1510,7 @@ Main changes since 3.0:
## [3.0.4] - 2011-12-06
Changes since 3.0.3:
* #363 - check for integer overflow in size computations

View File

@@ -15,6 +15,7 @@
#include "Householder"
#include "LU"
#include "Geometry"
#include "Sparse" // Needed by ComplexQZ.
#include "src/Core/util/DisableStupidWarnings.h"
@@ -32,8 +33,6 @@
* \endcode
*/
#include "src/misc/RealSvd2x2.h"
// IWYU pragma: begin_exports
#include "src/Eigenvalues/Tridiagonalization.h"
#include "src/Eigenvalues/RealSchur.h"
@@ -44,6 +43,7 @@
#include "src/Eigenvalues/ComplexSchur.h"
#include "src/Eigenvalues/ComplexEigenSolver.h"
#include "src/Eigenvalues/RealQZ.h"
#include "src/Eigenvalues/ComplexQZ.h"
#include "src/Eigenvalues/GeneralizedEigenSolver.h"
#include "src/Eigenvalues/MatrixBaseEigenvalues.h"
#ifdef EIGEN_USE_LAPACKE

View File

@@ -33,7 +33,6 @@
*/
// IWYU pragma: begin_exports
#include "src/misc/RealSvd2x2.h"
#include "src/SVD/UpperBidiagonalization.h"
#include "src/SVD/SVDBase.h"
#include "src/SVD/JacobiSVD.h"

View File

@@ -7,8 +7,8 @@
#define EIGEN_MAJOR_VERSION 5
#define EIGEN_MINOR_VERSION 0
#define EIGEN_PATCH_VERSION 1
#define EIGEN_PRERELEASE_VERSION ""
#define EIGEN_BUILD_VERSION ""
#define EIGEN_VERSION_STRING "5.0.1"
#define EIGEN_PRERELEASE_VERSION "dev"
#define EIGEN_BUILD_VERSION "master"
#define EIGEN_VERSION_STRING "5.0.1-dev+master"
#endif // EIGEN_VERSION_H

View File

@@ -113,6 +113,16 @@ class DenseCoeffsBase<Derived, ReadOnlyAccessors> : public EigenBase<Derived> {
return coeff(row, col);
}
#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
/** \returns the coefficient at given the given row and column.
*
* \sa operator[](Index,Index), operator[](Index)
*/
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType operator[](Index row, Index col) const {
return operator()(row, col);
}
#endif
/** Short version: don't use this function, use
* \link operator[](Index) const \endlink instead.
*
@@ -316,12 +326,21 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
*
* \sa operator[](Index)
*/
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& operator()(Index row, Index col) {
eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
return coeffRef(row, col);
}
#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
/** \returns a reference to the coefficient at given the given row and column.
*
* \sa operator[](Index)
*/
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& operator[](Index row, Index col) {
return operator()(row, col);
}
#endif
/** Short version: don't use this function, use
* \link operator[](Index) \endlink instead.
*

View File

@@ -63,7 +63,6 @@ struct default_packet_traits {
HasArg = 0,
HasAbsDiff = 0,
HasBlend = 0,
// This flag is used to indicate whether packet comparison is supported.
// pcmp_eq and pcmp_lt should be defined for it to be true.
HasCmp = 0,
@@ -1482,21 +1481,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet, 1>& /*kernel*/) {
// Nothing to do in the scalar case, i.e. a 1x1 matrix.
}
/***************************************************************************
* Selector, i.e. vector of N boolean values used to select (i.e. blend)
* words from 2 packets.
***************************************************************************/
template <size_t N>
struct Selector {
bool select[N];
};
template <typename Packet>
EIGEN_DEVICE_FUNC inline Packet pblend(const Selector<unpacket_traits<Packet>::size>& ifPacket,
const Packet& thenPacket, const Packet& elsePacket) {
return ifPacket.select[0] ? thenPacket : elsePacket;
}
/** \internal \returns 1 / a (coeff-wise) */
template <typename Packet>
EIGEN_DEVICE_FUNC inline Packet preciprocal(const Packet& a) {

View File

@@ -89,6 +89,11 @@ class TriangularBase : public EigenBase<Derived> {
return coeffRef(row, col);
}
#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
EIGEN_DEVICE_FUNC inline Scalar operator[](Index row, Index col) const { return operator()(row, col); }
EIGEN_DEVICE_FUNC inline Scalar& operator[](Index row, Index col) { return operator()(row, col); }
#endif
#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); }

View File

@@ -25,8 +25,8 @@ EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_FLOAT(Packet8f)
EIGEN_DOUBLE_PACKET_FUNCTION(atanh, Packet4d)
EIGEN_DOUBLE_PACKET_FUNCTION(log, Packet4d)
EIGEN_DOUBLE_PACKET_FUNCTION(log2, Packet4d)
EIGEN_DOUBLE_PACKET_FUNCTION(exp, Packet4d)
EIGEN_DOUBLE_PACKET_FUNCTION(log2, Packet4d)
EIGEN_DOUBLE_PACKET_FUNCTION(tanh, Packet4d)
EIGEN_DOUBLE_PACKET_FUNCTION(cbrt, Packet4d)
#ifdef EIGEN_VECTORIZE_AVX2
@@ -35,6 +35,8 @@ EIGEN_DOUBLE_PACKET_FUNCTION(cos, Packet4d)
#endif
EIGEN_GENERIC_PACKET_FUNCTION(atan, Packet4d)
EIGEN_GENERIC_PACKET_FUNCTION(exp2, Packet4d)
EIGEN_GENERIC_PACKET_FUNCTION(expm1, Packet4d)
EIGEN_GENERIC_PACKET_FUNCTION(log1p, Packet4d)
// Notice that for newer processors, it is counterproductive to use Newton
// iteration for square root. In particular, Skylake and Zen2 processors

View File

@@ -115,9 +115,9 @@ struct packet_traits<float> : default_packet_traits {
HasATan = 1,
HasATanh = 1,
HasLog = 1,
HasExp = 1,
HasLog1p = 1,
HasExpm1 = 1,
HasExp = 1,
HasPow = 1,
HasNdtri = 1,
HasBessel = 1,
@@ -127,7 +127,6 @@ struct packet_traits<float> : default_packet_traits {
HasTanh = EIGEN_FAST_MATH,
HasErf = EIGEN_FAST_MATH,
HasErfc = EIGEN_FAST_MATH,
HasBlend = 1
};
};
template <>
@@ -146,17 +145,18 @@ struct packet_traits<double> : default_packet_traits {
HasCos = EIGEN_FAST_MATH,
#endif
HasTanh = EIGEN_FAST_MATH,
HasLog = 1,
HasErf = 1,
HasErfc = 1,
HasLog = 1,
HasExp = 1,
HasLog1p = 1,
HasExpm1 = 1,
HasPow = 1,
HasSqrt = 1,
HasRsqrt = 1,
HasCbrt = 1,
HasATan = 1,
HasATanh = 1,
HasBlend = 1
};
};
@@ -179,7 +179,6 @@ struct packet_traits<Eigen::half> : default_packet_traits {
HasCos = EIGEN_FAST_MATH,
HasNegate = 1,
HasAbs = 1,
HasAbs2 = 0,
HasMin = 1,
HasMax = 1,
HasConj = 1,
@@ -192,7 +191,6 @@ struct packet_traits<Eigen::half> : default_packet_traits {
HasRsqrt = 1,
HasTanh = EIGEN_FAST_MATH,
HasErf = EIGEN_FAST_MATH,
HasBlend = 0,
HasBessel = 1,
HasNdtri = 1
};
@@ -218,7 +216,6 @@ struct packet_traits<bfloat16> : default_packet_traits {
HasCos = EIGEN_FAST_MATH,
HasNegate = 1,
HasAbs = 1,
HasAbs2 = 0,
HasMin = 1,
HasMax = 1,
HasConj = 1,
@@ -231,7 +228,6 @@ struct packet_traits<bfloat16> : default_packet_traits {
HasRsqrt = 1,
HasTanh = EIGEN_FAST_MATH,
HasErf = EIGEN_FAST_MATH,
HasBlend = 0,
HasBessel = 1,
HasNdtri = 1
};
@@ -284,7 +280,6 @@ struct packet_traits<uint64_t> : default_packet_traits {
// HasMin = 0,
// HasMax = 0,
HasDiv = 0,
HasBlend = 0,
HasTranspose = 0,
HasNegate = 0,
HasSqrt = 0,
@@ -2070,31 +2065,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet4d, 4>& kernel) {
kernel.packet[2] = _mm256_permute2f128_pd(T1, T3, 49);
}
EIGEN_STRONG_INLINE __m256i avx_blend_mask(const Selector<4>& ifPacket) {
return _mm256_set_epi64x(0 - ifPacket.select[3], 0 - ifPacket.select[2], 0 - ifPacket.select[1],
0 - ifPacket.select[0]);
}
EIGEN_STRONG_INLINE __m256i avx_blend_mask(const Selector<8>& ifPacket) {
return _mm256_set_epi32(0 - ifPacket.select[7], 0 - ifPacket.select[6], 0 - ifPacket.select[5],
0 - ifPacket.select[4], 0 - ifPacket.select[3], 0 - ifPacket.select[2],
0 - ifPacket.select[1], 0 - ifPacket.select[0]);
}
template <>
EIGEN_STRONG_INLINE Packet8f pblend(const Selector<8>& ifPacket, const Packet8f& thenPacket,
const Packet8f& elsePacket) {
const __m256 true_mask = _mm256_castsi256_ps(avx_blend_mask(ifPacket));
return pselect<Packet8f>(true_mask, thenPacket, elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet4d pblend(const Selector<4>& ifPacket, const Packet4d& thenPacket,
const Packet4d& elsePacket) {
const __m256d true_mask = _mm256_castsi256_pd(avx_blend_mask(ifPacket));
return pselect<Packet4d>(true_mask, thenPacket, elsePacket);
}
// Packet math for Eigen::half
#ifndef EIGEN_VECTORIZE_AVX512FP16
template <>

View File

@@ -84,7 +84,6 @@ struct packet_traits<half> : default_packet_traits {
HasDiv = 1,
HasNegate = 1,
HasAbs = 1,
HasAbs2 = 0,
HasMin = 1,
HasMax = 1,
HasConj = 1,
@@ -160,6 +159,8 @@ struct packet_traits<double> : default_packet_traits {
HasCos = EIGEN_FAST_MATH,
HasLog = 1,
HasExp = 1,
HasLog1p = 1,
HasExpm1 = 1,
HasPow = 1,
HasATan = 1,
HasTanh = EIGEN_FAST_MATH,
@@ -2057,27 +2058,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet16i, 4>& kernel) {
PACK_OUTPUT_I32_2(kernel.packet, tmp.packet, 3, 1);
}
template <size_t N>
EIGEN_STRONG_INLINE int avx512_blend_mask(const Selector<N>& ifPacket) {
alignas(__m128i) uint8_t aux[sizeof(__m128i)];
for (size_t i = 0; i < N; i++) aux[i] = static_cast<uint8_t>(ifPacket.select[i]);
__m128i paux = _mm_sub_epi8(_mm_setzero_si128(), _mm_load_si128(reinterpret_cast<const __m128i*>(aux)));
return _mm_movemask_epi8(paux);
}
template <>
EIGEN_STRONG_INLINE Packet16f pblend(const Selector<16>& ifPacket, const Packet16f& thenPacket,
const Packet16f& elsePacket) {
__mmask16 m = avx512_blend_mask(ifPacket);
return _mm512_mask_blend_ps(m, elsePacket, thenPacket);
}
template <>
EIGEN_STRONG_INLINE Packet8d pblend(const Selector<8>& ifPacket, const Packet8d& thenPacket,
const Packet8d& elsePacket) {
__mmask8 m = avx512_blend_mask(ifPacket);
return _mm512_mask_blend_pd(m, elsePacket, thenPacket);
}
// Packet math for Eigen::half
#ifndef EIGEN_VECTORIZE_AVX512FP16
template <>

View File

@@ -42,7 +42,6 @@ struct packet_traits<half> : default_packet_traits {
HasDiv = 1,
HasNegate = 1,
HasAbs = 1,
HasAbs2 = 0,
HasMin = 1,
HasMax = 1,
HasConj = 1,

View File

@@ -109,9 +109,6 @@ struct packet_traits<std::complex<float> > : default_packet_traits {
HasSqrt = 1,
HasLog = 1,
HasExp = 1,
#ifdef EIGEN_VECTORIZE_VSX
HasBlend = 1,
#endif
HasSetLinear = 0
};
};
@@ -364,17 +361,6 @@ EIGEN_STRONG_INLINE Packet2cf pcmp_eq(const Packet2cf& a, const Packet2cf& b) {
return Packet2cf(vec_and(eq, vec_perm(eq, eq, p16uc_COMPLEX32_REV)));
}
#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);

View File

@@ -184,6 +184,8 @@ struct packet_traits<float> : default_packet_traits {
HasATanh = 1,
HasLog = 1,
HasExp = 1,
HasLog1p = 1,
HasExpm1 = 1,
#ifdef EIGEN_VECTORIZE_VSX
HasCmp = 1,
HasPow = 1,
@@ -204,7 +206,6 @@ struct packet_traits<float> : default_packet_traits {
HasErf = 0,
#endif
HasNegate = 1,
HasBlend = 1
};
};
template <>
@@ -241,7 +242,6 @@ struct packet_traits<bfloat16> : default_packet_traits {
HasTanh = 0,
HasErf = 0,
HasNegate = 1,
HasBlend = 1
};
};
@@ -263,7 +263,6 @@ struct packet_traits<int> : default_packet_traits {
#else
HasDiv = 0,
#endif
HasBlend = 1,
HasCmp = 1
};
};
@@ -281,7 +280,6 @@ struct packet_traits<short int> : default_packet_traits {
HasSub = 1,
HasMul = 1,
HasDiv = 0,
HasBlend = 1,
HasCmp = 1
};
};
@@ -299,7 +297,6 @@ struct packet_traits<unsigned short int> : default_packet_traits {
HasSub = 1,
HasMul = 1,
HasDiv = 0,
HasBlend = 1,
HasCmp = 1
};
};
@@ -317,7 +314,6 @@ struct packet_traits<signed char> : default_packet_traits {
HasSub = 1,
HasMul = 1,
HasDiv = 0,
HasBlend = 1,
HasCmp = 1
};
};
@@ -335,7 +331,6 @@ struct packet_traits<unsigned char> : default_packet_traits {
HasSub = 1,
HasMul = 1,
HasDiv = 0,
HasBlend = 1,
HasCmp = 1
};
};
@@ -3053,74 +3048,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet16uc, 16>& kernel) {
kernel.packet[15] = vec_mergel(step3[7], step3[15]);
}
template <typename Packet>
EIGEN_STRONG_INLINE Packet pblend4(const Selector<4>& ifPacket, const Packet& thenPacket, const Packet& elsePacket) {
Packet4ui select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3]};
Packet4ui mask = reinterpret_cast<Packet4ui>(pnegate(reinterpret_cast<Packet4i>(select)));
return vec_sel(elsePacket, thenPacket, mask);
}
template <>
EIGEN_STRONG_INLINE Packet4i pblend(const Selector<4>& ifPacket, const Packet4i& thenPacket,
const Packet4i& elsePacket) {
return pblend4<Packet4i>(ifPacket, thenPacket, elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f& thenPacket,
const Packet4f& elsePacket) {
return pblend4<Packet4f>(ifPacket, thenPacket, elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet8s pblend(const Selector<8>& ifPacket, const Packet8s& thenPacket,
const Packet8s& elsePacket) {
Packet8us select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3],
ifPacket.select[4], ifPacket.select[5], ifPacket.select[6], ifPacket.select[7]};
Packet8us mask = reinterpret_cast<Packet8us>(pnegate(reinterpret_cast<Packet8s>(select)));
Packet8s result = vec_sel(elsePacket, thenPacket, mask);
return result;
}
template <>
EIGEN_STRONG_INLINE Packet8us pblend(const Selector<8>& ifPacket, const Packet8us& thenPacket,
const Packet8us& elsePacket) {
Packet8us select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3],
ifPacket.select[4], ifPacket.select[5], ifPacket.select[6], ifPacket.select[7]};
Packet8us mask = reinterpret_cast<Packet8us>(pnegate(reinterpret_cast<Packet8s>(select)));
return vec_sel(elsePacket, thenPacket, mask);
}
template <>
EIGEN_STRONG_INLINE Packet8bf pblend(const Selector<8>& ifPacket, const Packet8bf& thenPacket,
const Packet8bf& elsePacket) {
return pblend<Packet8us>(ifPacket, thenPacket, elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet16c pblend(const Selector<16>& ifPacket, const Packet16c& thenPacket,
const Packet16c& elsePacket) {
Packet16uc select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3],
ifPacket.select[4], ifPacket.select[5], ifPacket.select[6], ifPacket.select[7],
ifPacket.select[8], ifPacket.select[9], ifPacket.select[10], ifPacket.select[11],
ifPacket.select[12], ifPacket.select[13], ifPacket.select[14], ifPacket.select[15]};
Packet16uc mask = reinterpret_cast<Packet16uc>(pnegate(reinterpret_cast<Packet16c>(select)));
return vec_sel(elsePacket, thenPacket, mask);
}
template <>
EIGEN_STRONG_INLINE Packet16uc pblend(const Selector<16>& ifPacket, const Packet16uc& thenPacket,
const Packet16uc& elsePacket) {
Packet16uc select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3],
ifPacket.select[4], ifPacket.select[5], ifPacket.select[6], ifPacket.select[7],
ifPacket.select[8], ifPacket.select[9], ifPacket.select[10], ifPacket.select[11],
ifPacket.select[12], ifPacket.select[13], ifPacket.select[14], ifPacket.select[15]};
Packet16uc mask = reinterpret_cast<Packet16uc>(pnegate(reinterpret_cast<Packet16c>(select)));
return vec_sel(elsePacket, thenPacket, mask);
}
//---------- double ----------
#ifdef EIGEN_VECTORIZE_VSX
typedef __vector double Packet2d;
@@ -3176,9 +3103,11 @@ struct packet_traits<double> : default_packet_traits {
HasErfc = EIGEN_FAST_MATH,
HasATanh = 1,
HasATan = 0,
HasLog = 0,
HasCmp = 1,
HasLog = 1,
HasExp = 1,
HasLog1p = 1,
HasExpm1 = 1,
HasSqrt = 1,
HasCbrt = 1,
#if !EIGEN_COMP_CLANG
@@ -3187,7 +3116,6 @@ struct packet_traits<double> : default_packet_traits {
HasRsqrt = 0,
#endif
HasNegate = 1,
HasBlend = 1
};
};
@@ -3713,14 +3641,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet2d, 2>& kernel) {
kernel.packet[1] = t1;
}
template <>
EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket,
const Packet2d& elsePacket) {
Packet2l select = {ifPacket.select[0], ifPacket.select[1]};
Packet2ul mask = reinterpret_cast<Packet2ul>(pnegate(reinterpret_cast<Packet2l>(select)));
return vec_sel(elsePacket, thenPacket, mask);
}
#endif // __VSX__
} // end namespace internal

View File

@@ -17,6 +17,9 @@
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 pmsub(const PACKET_REAL& x, const PACKET_CPLX& y, const PACKET_CPLX& c) const { \
return psub(this->pmul(x, y), c); \
} \
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)); \
} \
@@ -27,6 +30,9 @@
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 pmsub(const PACKET_CPLX& x, const PACKET_REAL& y, const PACKET_CPLX& c) const { \
return psub(this->pmul(x, y), c); \
} \
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)); \
} \
@@ -76,6 +82,11 @@ struct conj_helper {
return this->pmul(x, y) + c;
}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType pmsub(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);
}
@@ -104,6 +115,10 @@ struct conj_helper<Packet, Packet, ConjLhs, ConjRhs> {
return Eigen::internal::pmadd(conj_if<ConjLhs>().pconj(x), conj_if<ConjRhs>().pconj(y), c);
}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmsub(const Packet& x, const Packet& y, const Packet& c) const {
return Eigen::internal::pmsub(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));
}
@@ -116,6 +131,9 @@ struct conj_helper<Packet, Packet, true, true> {
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);
}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmsub(const Packet& x, const Packet& y, const Packet& c) const {
return Eigen::internal::pmsub(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));

View File

@@ -210,16 +210,18 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet generic_round(const Packet& a);
EIGEN_GENERIC_PACKET_FUNCTION(atan, PACKET)
#define EIGEN_INSTANTIATE_GENERIC_MATH_FUNCS_DOUBLE(PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(atanh, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(log, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(sin, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(cos, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(log, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(log2, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(exp, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(tanh, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(atanh, PACKET) \
EIGEN_DOUBLE_PACKET_FUNCTION(cbrt, PACKET) \
EIGEN_GENERIC_PACKET_FUNCTION(atan, PACKET) \
EIGEN_GENERIC_PACKET_FUNCTION(exp2, PACKET)
EIGEN_GENERIC_PACKET_FUNCTION(expm1, PACKET) \
EIGEN_GENERIC_PACKET_FUNCTION(exp2, PACKET) \
EIGEN_GENERIC_PACKET_FUNCTION(log1p, PACKET) \
EIGEN_GENERIC_PACKET_FUNCTION(atan, PACKET)
} // end namespace internal
} // end namespace Eigen

View File

@@ -152,7 +152,6 @@ struct packet_traits<float> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 0,
HasAbsDiff = 0,
HasMin = 1,
HasMax = 1,

View File

@@ -169,10 +169,8 @@ struct packet_traits<int8_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 16,
HasAbs2 = 0,
HasSetLinear = 0,
HasCmp = 1,
HasBlend = 0
};
};
@@ -185,11 +183,9 @@ struct packet_traits<int16_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 8,
HasAbs2 = 0,
HasSetLinear = 0,
HasCmp = 1,
HasDiv = 1,
HasBlend = 0
};
};
@@ -202,11 +198,9 @@ struct packet_traits<int32_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 4,
HasAbs2 = 0,
HasSetLinear = 0,
HasCmp = 1,
HasDiv = 1,
HasBlend = 0
};
};
@@ -219,11 +213,9 @@ struct packet_traits<int64_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 2,
HasAbs2 = 0,
HasSetLinear = 0,
HasCmp = 1,
HasDiv = 1,
HasBlend = 0
};
};
@@ -236,11 +228,9 @@ struct packet_traits<uint8_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 16,
HasAbs2 = 0,
HasSetLinear = 0,
HasNegate = 0,
HasCmp = 1,
HasBlend = 0
};
};
@@ -253,12 +243,10 @@ struct packet_traits<uint16_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 8,
HasAbs2 = 0,
HasSetLinear = 0,
HasNegate = 0,
HasCmp = 1,
HasDiv = 1,
HasBlend = 0
};
};
@@ -271,12 +259,10 @@ struct packet_traits<uint32_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 4,
HasAbs2 = 0,
HasSetLinear = 0,
HasNegate = 0,
HasCmp = 1,
HasDiv = 1,
HasBlend = 0
};
};
@@ -289,12 +275,10 @@ struct packet_traits<uint64_t> : default_packet_traits {
AlignedOnScalar = 1,
size = 2,
HasAbs2 = 0,
HasSetLinear = 0,
HasNegate = 0,
HasCmp = 1,
HasDiv = 1,
HasBlend = 0
};
};
@@ -307,9 +291,7 @@ struct packet_traits<float> : default_packet_traits {
AlignedOnScalar = 1,
size = 4,
HasAbs2 = 0,
HasSetLinear = 0,
HasBlend = 0,
HasSign = 0,
HasDiv = 1,
HasExp = 1,
@@ -328,9 +310,7 @@ struct packet_traits<double> : default_packet_traits {
AlignedOnScalar = 1,
size = 2,
HasAbs2 = 0,
HasSetLinear = 0,
HasBlend = 0,
HasSign = 0,
HasDiv = 1,
HasSqrt = 1,

View File

@@ -105,7 +105,6 @@ struct packet_traits<std::complex<float> > : default_packet_traits {
HasMin = 0,
HasMax = 0,
HasSetLinear = 0,
HasBlend = 1
};
};
@@ -314,12 +313,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet2cf, 2>& kernel) {
kernel.packet[1].v = tmp;
}
template <>
EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, const Packet2cf& thenPacket,
const Packet2cf& elsePacket) {
return (Packet2cf)(Packet4f)pblend<Packet2d>(ifPacket, (Packet2d)thenPacket.v, (Packet2d)elsePacket.v);
}
//---------- double ----------
struct Packet1cd {

View File

@@ -91,7 +91,6 @@ struct packet_traits<float> : default_packet_traits {
HasExp = 1,
HasSqrt = 1,
HasRsqrt = 1,
HasBlend = 1
};
};
@@ -105,7 +104,6 @@ struct packet_traits<int32_t> : default_packet_traits {
size = 4,
// FIXME check the Has*
HasDiv = 1,
HasBlend = 1
};
};
@@ -802,22 +800,6 @@ EIGEN_STRONG_INLINE Packet4f pround<Packet4f>(const Packet4f& a) {
return v;
}
template <>
EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f& thenPacket,
const Packet4f& elsePacket) {
Packet4ui select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3]};
Packet4i mask = __builtin_msa_ceqi_w((Packet4i)select, 0);
return (Packet4f)__builtin_msa_bsel_v((v16u8)mask, (v16u8)thenPacket, (v16u8)elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet4i pblend(const Selector<4>& ifPacket, const Packet4i& thenPacket,
const Packet4i& elsePacket) {
Packet4ui select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3]};
Packet4i mask = __builtin_msa_ceqi_w((Packet4i)select, 0);
return (Packet4i)__builtin_msa_bsel_v((v16u8)mask, (v16u8)thenPacket, (v16u8)elsePacket);
}
//---------- double ----------
typedef v2f64 Packet2d;
@@ -856,7 +838,6 @@ struct packet_traits<double> : default_packet_traits {
HasExp = 1,
HasSqrt = 1,
HasRsqrt = 1,
HasBlend = 1
};
};
@@ -1222,14 +1203,6 @@ EIGEN_STRONG_INLINE Packet2d pround<Packet2d>(const Packet2d& a) {
return v;
}
template <>
EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket,
const Packet2d& elsePacket) {
Packet2ul select = {ifPacket.select[0], ifPacket.select[1]};
Packet2l mask = __builtin_msa_ceqi_d((Packet2l)select, 0);
return (Packet2d)__builtin_msa_bsel_v((v16u8)mask, (v16u8)thenPacket, (v16u8)elsePacket);
}
} // end namespace internal
} // end namespace Eigen

View File

@@ -189,13 +189,11 @@ struct packet_traits<float> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0,
HasDiv = 1,
HasSin = EIGEN_FAST_MATH,
HasCos = EIGEN_FAST_MATH,
@@ -205,6 +203,8 @@ struct packet_traits<float> : default_packet_traits {
HasATanh = 1,
HasLog = 1,
HasExp = 1,
HasLog1p = 1,
HasExpm1 = 1,
HasPow = 1,
HasSqrt = 1,
HasRsqrt = 1,
@@ -235,12 +235,10 @@ struct packet_traits<int8_t> : default_packet_traits {
HasAbs = 1,
HasAbsDiff = 1,
HasArg = 0,
HasAbs2 = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0
};
};
@@ -262,12 +260,10 @@ struct packet_traits<uint8_t> : default_packet_traits {
HasAbs = 1,
HasAbsDiff = 1,
HasArg = 0,
HasAbs2 = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0,
HasSqrt = 1
};
@@ -291,12 +287,10 @@ struct packet_traits<int16_t> : default_packet_traits {
HasAbs = 1,
HasAbsDiff = 1,
HasArg = 0,
HasAbs2 = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0
};
};
@@ -318,12 +312,10 @@ struct packet_traits<uint16_t> : default_packet_traits {
HasAbs = 1,
HasAbsDiff = 1,
HasArg = 0,
HasAbs2 = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0,
HasSqrt = 1
};
};
@@ -345,13 +337,11 @@ struct packet_traits<int32_t> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0
};
};
@@ -372,13 +362,11 @@ struct packet_traits<uint32_t> : default_packet_traits {
HasNegate = 0,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0,
HasSqrt = 1
};
@@ -401,13 +389,11 @@ struct packet_traits<int64_t> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0
};
};
@@ -428,13 +414,11 @@ struct packet_traits<uint64_t> : default_packet_traits {
HasNegate = 0,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0
};
};
@@ -4631,13 +4615,11 @@ struct packet_traits<bfloat16> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0,
HasDiv = 1,
HasSin = EIGEN_FAST_MATH,
HasCos = EIGEN_FAST_MATH,
@@ -5016,19 +4998,19 @@ struct packet_traits<double> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0,
HasDiv = 1,
#if EIGEN_ARCH_ARM64 && !EIGEN_APPLE_DOUBLE_NEON_BUG
HasExp = 1,
HasLog = 1,
HasLog1p = 1,
HasExpm1 = 1,
HasPow = 1,
HasATan = 1,
HasATanh = 1,
@@ -5390,13 +5372,11 @@ struct packet_traits<Eigen::half> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasAbsDiff = 0,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 1,
HasBlend = 0,
HasInsert = 1,
HasReduxp = 1,
HasDiv = 1,

View File

@@ -49,7 +49,6 @@ struct packet_traits<std::complex<float> > : default_packet_traits {
HasMin = 0,
HasMax = 0,
HasSetLinear = 0,
HasBlend = 1
};
};
#endif
@@ -413,13 +412,6 @@ EIGEN_STRONG_INLINE Packet1cd pcmp_eq(const Packet1cd& a, const Packet1cd& b) {
return Packet1cd(pand<Packet2d>(eq, vec2d_swizzle1(eq, 1, 0)));
}
template <>
EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, const Packet2cf& thenPacket,
const Packet2cf& elsePacket) {
__m128d result = pblend<Packet2d>(ifPacket, _mm_castps_pd(thenPacket.v), _mm_castps_pd(elsePacket.v));
return Packet2cf(_mm_castpd_ps(result));
}
template <>
EIGEN_STRONG_INLINE Packet1cd psqrt<Packet1cd>(const Packet1cd& a) {
return psqrt_complex<Packet1cd>(a);

View File

@@ -218,10 +218,12 @@ struct packet_traits<double> : default_packet_traits {
HasSin = EIGEN_FAST_MATH,
HasCos = EIGEN_FAST_MATH,
HasTanh = EIGEN_FAST_MATH,
HasLog = 1,
HasErf = EIGEN_FAST_MATH,
HasErfc = EIGEN_FAST_MATH,
HasLog = 1,
HasExp = 1,
HasLog1p = 1,
HasExpm1 = 1,
HasPow = 1,
HasSqrt = 1,
HasRsqrt = 1,
@@ -290,7 +292,6 @@ struct packet_traits<bool> : default_packet_traits {
HasCmp = 1,
HasShift = 0,
HasAbs = 0,
HasAbs2 = 0,
HasMin = 0,
HasMax = 0,
HasConj = 0,
@@ -1998,44 +1999,6 @@ EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet16b, 16>& kernel) {
kernel.packet[15] = _mm_unpackhi_epi64(u7, uf);
}
EIGEN_STRONG_INLINE __m128i sse_blend_mask(const Selector<2>& ifPacket) {
return _mm_set_epi64x(0 - ifPacket.select[1], 0 - ifPacket.select[0]);
}
EIGEN_STRONG_INLINE __m128i sse_blend_mask(const Selector<4>& ifPacket) {
return _mm_set_epi32(0 - ifPacket.select[3], 0 - ifPacket.select[2], 0 - ifPacket.select[1], 0 - ifPacket.select[0]);
}
template <>
EIGEN_STRONG_INLINE Packet2l pblend(const Selector<2>& ifPacket, const Packet2l& thenPacket,
const Packet2l& elsePacket) {
const __m128i true_mask = sse_blend_mask(ifPacket);
return pselect<Packet2l>(true_mask, thenPacket, elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet4i pblend(const Selector<4>& ifPacket, const Packet4i& thenPacket,
const Packet4i& elsePacket) {
const __m128i true_mask = sse_blend_mask(ifPacket);
return pselect<Packet4i>(true_mask, thenPacket, elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet4ui pblend(const Selector<4>& ifPacket, const Packet4ui& thenPacket,
const Packet4ui& elsePacket) {
return (Packet4ui)pblend(ifPacket, (Packet4i)thenPacket, (Packet4i)elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f& thenPacket,
const Packet4f& elsePacket) {
const __m128i true_mask = sse_blend_mask(ifPacket);
return pselect<Packet4f>(_mm_castsi128_ps(true_mask), thenPacket, elsePacket);
}
template <>
EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket,
const Packet2d& elsePacket) {
const __m128i true_mask = sse_blend_mask(ifPacket);
return pselect<Packet2d>(_mm_castsi128_pd(true_mask), thenPacket, elsePacket);
}
// Scalar path for pmadd with FMA to ensure consistency with vectorized path.
#if defined(EIGEN_VECTORIZE_FMA)
template <>
@@ -2194,7 +2157,6 @@ struct packet_traits<Eigen::half> : default_packet_traits {
HasDiv = 1,
HasNegate = 0,
HasAbs = 0,
HasAbs2 = 0,
HasMin = 0,
HasMax = 0,
HasConj = 0,

View File

@@ -49,12 +49,10 @@ struct packet_traits<numext::int32_t> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 0,
HasBlend = 0,
HasReduxp = 0 // Not implemented in SVE
};
};
@@ -344,12 +342,10 @@ struct packet_traits<float> : default_packet_traits {
HasNegate = 1,
HasAbs = 1,
HasArg = 0,
HasAbs2 = 1,
HasMin = 1,
HasMax = 1,
HasConj = 1,
HasSetLinear = 0,
HasBlend = 0,
HasReduxp = 0, // Not implemented in SVE
HasDiv = 1,

View File

@@ -542,31 +542,6 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void ptranspose(PacketBlock<cl::sycl::cl_d
kernel.packet[1].x() = tmp;
}
template <>
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE cl::sycl::cl_half8 pblend(
const Selector<unpacket_traits<cl::sycl::cl_half8>::size>& ifPacket, const cl::sycl::cl_half8& thenPacket,
const cl::sycl::cl_half8& elsePacket) {
cl::sycl::cl_short8 condition(ifPacket.select[0] ? 0 : -1, ifPacket.select[1] ? 0 : -1, ifPacket.select[2] ? 0 : -1,
ifPacket.select[3] ? 0 : -1, ifPacket.select[4] ? 0 : -1, ifPacket.select[5] ? 0 : -1,
ifPacket.select[6] ? 0 : -1, ifPacket.select[7] ? 0 : -1);
return cl::sycl::select(thenPacket, elsePacket, condition);
}
template <>
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE cl::sycl::cl_float4 pblend(
const Selector<unpacket_traits<cl::sycl::cl_float4>::size>& ifPacket, const cl::sycl::cl_float4& thenPacket,
const cl::sycl::cl_float4& elsePacket) {
cl::sycl::cl_int4 condition(ifPacket.select[0] ? 0 : -1, ifPacket.select[1] ? 0 : -1, ifPacket.select[2] ? 0 : -1,
ifPacket.select[3] ? 0 : -1);
return cl::sycl::select(thenPacket, elsePacket, condition);
}
template <>
inline cl::sycl::cl_double2 pblend(const Selector<unpacket_traits<cl::sycl::cl_double2>::size>& ifPacket,
const cl::sycl::cl_double2& thenPacket, const cl::sycl::cl_double2& elsePacket) {
cl::sycl::cl_long2 condition(ifPacket.select[0] ? 0 : -1, ifPacket.select[1] ? 0 : -1);
return cl::sycl::select(thenPacket, elsePacket, condition);
}
#endif // SYCL_DEVICE_ONLY
} // end namespace internal

View File

@@ -72,7 +72,6 @@ struct packet_traits<std::complex<float> > : default_packet_traits {
HasAbs2 = 0,
HasMin = 0,
HasMax = 0,
HasBlend = 1,
HasSetLinear = 0
};
};
@@ -469,14 +468,6 @@ EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet2cf, 2>& kernel) {
kernel.packet[1].cd[0] = tmp;
}
template <>
EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, const Packet2cf& thenPacket,
const Packet2cf& elsePacket) {
Packet2cf result;
const Selector<4> ifPacket4 = {ifPacket.select[0], ifPacket.select[0], ifPacket.select[1], ifPacket.select[1]};
result.v = pblend<Packet4f>(ifPacket4, thenPacket.v, elsePacket.v);
return result;
}
#else
template <>
EIGEN_STRONG_INLINE Packet2cf pcmp_eq(const Packet2cf& a, const Packet2cf& b) {
@@ -553,14 +544,6 @@ EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet2cf, 2>& kernel) {
kernel.packet[0].v = tmp;
}
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
} // end namespace internal

View File

@@ -167,7 +167,6 @@ struct packet_traits<int> : default_packet_traits {
HasSub = 1,
HasMul = 1,
HasDiv = 1,
HasBlend = 1
};
};
@@ -197,7 +196,6 @@ struct packet_traits<float> : default_packet_traits {
HasTanh = 1,
HasErf = 1,
HasNegate = 1,
HasBlend = 1
};
};
@@ -224,7 +222,6 @@ struct packet_traits<double> : default_packet_traits {
HasSqrt = 1,
HasRsqrt = 1,
HasNegate = 1,
HasBlend = 1
};
};
@@ -594,41 +591,32 @@ EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) {
template <int N>
EIGEN_STRONG_INLINE Packet2l parithmetic_shift_right(const Packet2l& a) {
return Packet2l { parithmetic_shift_right<N>(a[0]), parithmetic_shift_right<N>(a[1]) };
return Packet2l{parithmetic_shift_right<N>(a[0]), parithmetic_shift_right<N>(a[1])};
}
template <int N>
EIGEN_STRONG_INLINE Packet4i parithmetic_shift_right(const Packet4i& a) {
return Packet4i {
parithmetic_shift_right<N>(a[0]),
parithmetic_shift_right<N>(a[1]),
parithmetic_shift_right<N>(a[2]),
parithmetic_shift_right<N>(a[3]) };
return Packet4i{parithmetic_shift_right<N>(a[0]), parithmetic_shift_right<N>(a[1]), parithmetic_shift_right<N>(a[2]),
parithmetic_shift_right<N>(a[3])};
}
template <int N>
EIGEN_STRONG_INLINE Packet2l plogical_shift_right(const Packet2l& a) {
return Packet2l { plogical_shift_right<N>(a[0]), plogical_shift_right<N>(a[1]) };
return Packet2l{plogical_shift_right<N>(a[0]), plogical_shift_right<N>(a[1])};
}
template <int N>
EIGEN_STRONG_INLINE Packet4i plogical_shift_right(const Packet4i& a) {
return Packet4i {
plogical_shift_right<N>(a[0]),
plogical_shift_right<N>(a[1]),
plogical_shift_right<N>(a[2]),
plogical_shift_right<N>(a[3]) };
return Packet4i{plogical_shift_right<N>(a[0]), plogical_shift_right<N>(a[1]), plogical_shift_right<N>(a[2]),
plogical_shift_right<N>(a[3])};
}
template <int N>
EIGEN_STRONG_INLINE Packet2l plogical_shift_left(const Packet2l& a) {
return Packet2l { plogical_shift_left<N>(a[0]), plogical_shift_left<N>(a[1]) };
return Packet2l{plogical_shift_left<N>(a[0]), plogical_shift_left<N>(a[1])};
}
template <int N>
EIGEN_STRONG_INLINE Packet4i plogical_shift_left(const Packet4i& a) {
return Packet4i {
plogical_shift_left<N>(a[0]),
plogical_shift_left<N>(a[1]),
plogical_shift_left<N>(a[2]),
plogical_shift_left<N>(a[3]) };
return Packet4i{plogical_shift_left<N>(a[0]), plogical_shift_left<N>(a[1]), plogical_shift_left<N>(a[2]),
plogical_shift_left<N>(a[3])};
}
template <>
@@ -747,22 +735,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet2d, 2>& kernel) {
kernel.packet[1] = t1;
}
template <>
EIGEN_STRONG_INLINE Packet4i pblend(const Selector<4>& ifPacket, const Packet4i& thenPacket,
const Packet4i& elsePacket) {
Packet4ui select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3]};
Packet4ui mask = vec_cmpeq(select, reinterpret_cast<Packet4ui>(p4i_ONE));
return vec_sel(elsePacket, thenPacket, mask);
}
template <>
EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket,
const Packet2d& elsePacket) {
Packet2ul select = {ifPacket.select[0], ifPacket.select[1]};
Packet2ul mask = vec_cmpeq(select, reinterpret_cast<Packet2ul>(p2l_ONE));
return vec_sel(elsePacket, thenPacket, mask);
}
/* z13 has no vector float support so we emulate that with double
z14 has proper vector float support.
*/
@@ -1068,19 +1040,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet4f, 4>& kernel) {
kernel.packet[3].v4f[1] = t3.packet[1];
}
template <>
EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f& thenPacket,
const Packet4f& elsePacket) {
Packet2ul select_hi = {ifPacket.select[0], ifPacket.select[1]};
Packet2ul select_lo = {ifPacket.select[2], ifPacket.select[3]};
Packet2ul mask_hi = vec_cmpeq(select_hi, reinterpret_cast<Packet2ul>(p2l_ONE));
Packet2ul mask_lo = vec_cmpeq(select_lo, reinterpret_cast<Packet2ul>(p2l_ONE));
Packet4f result;
result.v4f[0] = vec_sel(elsePacket.v4f[0], thenPacket.v4f[0], mask_hi);
result.v4f[1] = vec_sel(elsePacket.v4f[1], thenPacket.v4f[1], mask_lo);
return result;
}
template <>
Packet4f EIGEN_STRONG_INLINE pcmp_le<Packet4f>(const Packet4f& a, const Packet4f& b) {
Packet4f res;
@@ -1288,14 +1247,6 @@ EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet4f, 4>& kernel) {
kernel.packet[3] = vec_mergel(t1, t3);
}
template <>
EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f& thenPacket,
const Packet4f& elsePacket) {
Packet4ui select = {ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3]};
Packet4ui mask = vec_cmpeq(select, reinterpret_cast<Packet4ui>(p4i_ONE));
return vec_sel(elsePacket, thenPacket, mask);
}
#endif
template <>
@@ -1338,62 +1289,51 @@ EIGEN_STRONG_INLINE Packet4f plset<Packet4f>(const float& a) {
}
#if !defined(vec_float) || !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ < 13)
#pragma GCC warning \
"float->int and int->float conversion is simulated. compile for z15 for improved performance"
#pragma GCC warning "float->int and int->float conversion is simulated. compile for z15 for improved performance"
template <>
struct cast_impl<Packet4i, Packet4f> {
EIGEN_DEVICE_FUNC static inline Packet4f run(const Packet4i& a) {
return Packet4f{float(a[0]), float(a[1]), float(a[2]), float(a[3]) };
return Packet4f{float(a[0]), float(a[1]), float(a[2]), float(a[3])};
}
};
template <>
struct cast_impl<Packet4f, Packet4i> {
EIGEN_DEVICE_FUNC static inline Packet4i run(const Packet4f& a) {
return Packet4i{int(a[0]), int(a[1]), int(a[2]), int(a[3]) };
return Packet4i{int(a[0]), int(a[1]), int(a[2]), int(a[3])};
}
};
template <>
struct cast_impl<Packet2l, Packet2d> {
EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) {
return Packet2d{double(a[0]), double(a[1]) };
}
EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) { return Packet2d{double(a[0]), double(a[1])}; }
};
template <>
struct cast_impl<Packet2d, Packet2l> {
EIGEN_DEVICE_FUNC static inline Packet2l run(const Packet2d& a) {
return Packet2l{(long long)(a[0]), (long long)(a[1]) };
return Packet2l{(long long)(a[0]), (long long)(a[1])};
}
};
#else
template <>
struct cast_impl<Packet4i, Packet4f> {
EIGEN_DEVICE_FUNC static inline Packet4f run(const Packet4i& a) {
return vec_float(a);
}
EIGEN_DEVICE_FUNC static inline Packet4f run(const Packet4i& a) { return vec_float(a); }
};
template <>
struct cast_impl<Packet4f, Packet4i> {
EIGEN_DEVICE_FUNC static inline Packet4i run(const Packet4f& a) {
return vec_signed(a);
}
EIGEN_DEVICE_FUNC static inline Packet4i run(const Packet4f& a) { return vec_signed(a); }
};
template <>
struct cast_impl<Packet2l, Packet2d> {
EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) {
return vec_double(a);
}
EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) { return vec_double(a); }
};
template <>
struct cast_impl<Packet2d, Packet2l> {
EIGEN_DEVICE_FUNC static inline Packet2l run(const Packet2d& a) {
return vec_signed(a);
}
EIGEN_DEVICE_FUNC static inline Packet2l run(const Packet2d& a) { return vec_signed(a); }
};
#endif

View File

@@ -21,7 +21,8 @@ namespace internal {
template <typename ThenScalar, typename ElseScalar, typename ConditionScalar>
struct scalar_boolean_select_op {
static constexpr bool ThenElseAreSame = is_same<ThenScalar, ElseScalar>::value;
static constexpr bool ThenElseAreSame =
is_same<std::remove_const_t<ThenScalar>, std::remove_const_t<ElseScalar>>::value;
EIGEN_STATIC_ASSERT(ThenElseAreSame, THEN AND ELSE MUST BE SAME TYPE)
using Scalar = ThenScalar;
using result_type = Scalar;

View File

@@ -100,7 +100,10 @@ struct scalar_abs2_op {
};
template <typename Scalar>
struct functor_traits<scalar_abs2_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 };
enum {
Cost = NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasMul && !NumTraits<Scalar>::IsComplex
};
};
template <typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>

View File

@@ -830,6 +830,11 @@
#endif
#endif
// Multidimensional subscript operator feature test
#if defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202110L
#define EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
#endif
//------------------------------------------------------------------------------------------
// Preprocessor programming helpers
//------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,651 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Alexey Korepanov
// Copyright (C) 2025 Ludwig Striet <ludwig.striet@mathematik.uni-freiburg.de>
//
// 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
// https://mozilla.org/MPL/2.0/.
//
// Derived from: Eigen/src/Eigenvalues/RealQZ.h
#ifndef EIGEN_COMPLEX_QZ_H_
#define EIGEN_COMPLEX_QZ_H_
// IWYU pragma: private
#include "./InternalHeaderCheck.h"
/** \eigenvalues_module \ingroup Eigenvalues_Module
*
*
* \class ComplexQZ
*
* \brief Performs a QZ decomposition of a pair of matrices A, B
*
* \tparam MatrixType_ the type input type of the matrix.
*
* Given to complex square matrices A and B, this class computes the QZ decomposition
* \f$ A = Q S Z \f$, \f$ B = Q T Z\f$ where Q and Z are unitary matrices and
* S and T a re upper-triangular matrices. More precisely, Q and Z fulfill
* \f$ Q Q* = Id\f$ and \f$ Z Z* = Id\f$. The generalized Eigenvalues are then
* obtained as ratios of corresponding diagonal entries, lambda(i) = S(i,i) / T(i, i).
*
* The QZ algorithm was introduced in the seminal work "An Algorithm for
* Generalized Matrix Eigenvalue Problems" by Moler & Stewart in 1973. The matrix
* pair S = A, T = B is first transformed to Hessenberg-Triangular form where S is an
* upper Hessenberg matrix and T is an upper Triangular matrix.
*
* This pair is subsequently reduced to the desired form using implicit QZ shifts as
* described in the original paper. The algorithms to find small entries on the
* diagonals and subdiagonals are based on the variants in the implementation
* for Real matrices in the RealQZ class.
*
* \sa class RealQZ
*/
namespace Eigen {
template <typename MatrixType_>
class ComplexQZ {
public:
using MatrixType = MatrixType_;
using Scalar = typename MatrixType_::Scalar;
using RealScalar = typename MatrixType_::RealScalar;
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
Options = internal::traits<MatrixType>::Options,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
using Vec = Matrix<Scalar, Dynamic, 1>;
using Vec2 = Matrix<Scalar, 2, 1>;
using Vec3 = Matrix<Scalar, 3, 1>;
using Row2 = Matrix<Scalar, 1, 2>;
using Mat2 = Matrix<Scalar, 2, 2>;
/** \brief Returns matrix Q in the QZ decomposition.
*
* \returns A const reference to the matrix Q.
*/
const MatrixType& matrixQ() const {
eigen_assert(m_isInitialized && "ComplexQZ is not initialized.");
eigen_assert(m_computeQZ && "The matrices Q and Z have not been computed during the QZ decomposition.");
return m_Q;
}
/** \brief Returns matrix Z in the QZ decomposition.
*
* \returns A const reference to the matrix Z.
*/
const MatrixType& matrixZ() const {
eigen_assert(m_isInitialized && "ComplexQZ is not initialized.");
eigen_assert(m_computeQZ && "The matrices Q and Z have not been computed during the QZ decomposition.");
return m_Z;
}
/** \brief Returns matrix S in the QZ decomposition.
*
* \returns A const reference to the matrix S.
*/
const MatrixType& matrixS() const {
eigen_assert(m_isInitialized && "ComplexQZ is not initialized.");
return m_S;
}
/** \brief Returns matrix S in the QZ decomposition.
*
* \returns A const reference to the matrix S.
*/
const MatrixType& matrixT() const {
eigen_assert(m_isInitialized && "ComplexQZ is not initialized.");
return m_T;
}
/** \brief Constructor
*
* \param[in] n size of the matrices whose QZ decomposition we compute
*
* This constructor is used when we use the compute(...) method later,
* especially when we aim to compute the decomposition of two sparse
* matrices.
*/
ComplexQZ(Index n, bool computeQZ = true, unsigned int maxIters = 400)
: m_n(n),
m_S(n, n),
m_T(n, n),
m_Q(computeQZ ? n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime),
computeQZ ? n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)),
m_Z(computeQZ ? n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime),
computeQZ ? n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)),
m_ws(2 * n),
m_computeQZ(computeQZ),
m_maxIters(maxIters) {}
/** \brief Constructor. computes the QZ decomposition of given matrices
* upon creation
*
* \param[in] A input matrix A
* \param[in] B input matrix B
* \param[in] computeQZ If false, the matrices Q and Z are not computed
*
* This constructor calls the compute() method to compute the QZ decomposition.
* If input matrices are sparse, call the constructor that uses only the
* size as input the computeSparse(...) method.
*/
ComplexQZ(const MatrixType& A, const MatrixType& B, bool computeQZ = true, unsigned int maxIters = 400)
: m_n(A.rows()),
m_maxIters(maxIters),
m_computeQZ(computeQZ),
m_S(A.rows(), A.cols()),
m_T(A.rows(), A.cols()),
m_Q(computeQZ ? m_n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime),
computeQZ ? m_n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)),
m_Z(computeQZ ? m_n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime),
computeQZ ? m_n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)),
m_ws(2 * m_n) {
compute(A, B, computeQZ);
}
/** \brief Compute the QZ decomposition of complex input matrices
*
* \param[in] A Matrix A.
* \param[in] B Matrix B.
* \param[in] computeQZ If false, the matrices Q and Z are not computed.
*/
void compute(const MatrixType& A, const MatrixType& B, bool computeQZ = true);
/** \brief Compute the decomposition of sparse complex input matrices.
* Main difference to the compute(...) method is that it computes a
* SparseQR decomposition of B
*
* \param[in] A Matrix A.
* \param[in] B Matrix B.
* \param[in] computeQZ If false, the matrices Q and Z are not computed.
*/
template <typename SparseMatrixType_>
void computeSparse(const SparseMatrixType_& A, const SparseMatrixType_& B, bool computeQZ = true);
/** \brief Reports whether the last computation was successfull.
*
* \returns \c Success if computation was successfull, \c NoConvergence otherwise.
*/
ComputationInfo info() const { return m_info; }
/** \brief number of performed QZ steps
*/
unsigned int iterations() const {
eigen_assert(m_isInitialized && "ComplexQZ is not initialized.");
return m_global_iter;
}
private:
Index m_n;
const unsigned int m_maxIters;
unsigned int m_global_iter;
bool m_isInitialized;
bool m_computeQZ;
ComputationInfo m_info;
MatrixType m_S, m_T, m_Q, m_Z;
RealScalar m_normOfT, m_normOfS;
Vec m_ws;
// Test if a Scalar is 0 up to a certain tolerance
static bool is_negligible(const Scalar x, const RealScalar tol = NumTraits<RealScalar>::epsilon()) {
return numext::abs(x) <= tol;
}
void do_QZ_step(Index p, Index q);
inline Mat2 computeZk2(const Row2& b);
// This is basically taken from from Eigen3::RealQZ
void hessenbergTriangular(const MatrixType& A, const MatrixType& B);
// This function can be called when m_Q and m_Z are initialized and m_S, m_T
// are in hessenberg-triangular form
void reduceHessenbergTriangular();
// Sparse variant of the above method.
template <typename SparseMatrixType_>
void hessenbergTriangularSparse(const SparseMatrixType_& A, const SparseMatrixType_& B);
void computeNorms();
Index findSmallSubdiagEntry(Index l);
Index findSmallDiagEntry(Index f, Index l);
void push_down_zero_ST(Index k, Index l);
void reduceDiagonal2x2block(Index i);
};
template <typename MatrixType_>
void ComplexQZ<MatrixType_>::compute(const MatrixType& A, const MatrixType& B, bool computeQZ) {
m_computeQZ = computeQZ;
m_n = A.rows();
eigen_assert(m_n == A.cols() && "A is not a square matrix");
eigen_assert(m_n == B.rows() && m_n == B.cols() && "B is not a square matrix or B is not of the same size as A");
m_isInitialized = true;
m_global_iter = 0;
// This will initialize m_Q and m_Z and bring m_S, m_T to hessenberg-triangular form
hessenbergTriangular(A, B);
// We assume that we already have that S is upper-Hessenberg and T is
// upper-triangular. This is what the hessenbergTriangular(...) method does
reduceHessenbergTriangular();
}
// This is basically taken from from Eigen3::RealQZ
template <typename MatrixType_>
void ComplexQZ<MatrixType_>::hessenbergTriangular(const MatrixType& A, const MatrixType& B) {
// Copy A and B, these will be the matrices on which we operate later
m_S = A;
m_T = B;
// Perform QR decomposition of the matrix Q
HouseholderQR<MatrixType> qr(m_T);
m_T = qr.matrixQR();
m_T.template triangularView<StrictlyLower>().setZero();
if (m_computeQZ) m_Q = qr.householderQ();
// overwrite S with Q* x S
m_S.applyOnTheLeft(qr.householderQ().adjoint());
if (m_computeQZ) m_Z = MatrixType::Identity(m_n, m_n);
// reduce S to upper Hessenberg with Givens rotations
for (Index j = 0; j <= m_n - 3; j++) {
for (Index i = m_n - 1; i >= j + 2; i--) {
JacobiRotation<Scalar> G;
// delete S(i,j)
if (!numext::is_exactly_zero(m_S.coeff(i, j))) {
G.makeGivens(m_S.coeff(i - 1, j), m_S.coeff(i, j), &m_S.coeffRef(i - 1, j));
m_S.coeffRef(i, j) = Scalar(0);
m_T.rightCols(m_n - i + 1).applyOnTheLeft(i - 1, i, G.adjoint());
m_S.rightCols(m_n - j - 1).applyOnTheLeft(i - 1, i, G.adjoint());
// This is what we want to achieve
if (!is_negligible(m_S(i, j)))
m_info = ComputationInfo::NumericalIssue;
else
m_S(i, j) = Scalar(0);
// update Q
if (m_computeQZ) m_Q.applyOnTheRight(i - 1, i, G);
}
if (!numext::is_exactly_zero(m_T.coeff(i, i - 1))) {
// Compute rotation and update matrix T
G.makeGivens(m_T.coeff(i, i), m_T.coeff(i, i - 1), &m_T.coeffRef(i, i));
m_T.topRows(i).applyOnTheRight(i - 1, i, G.adjoint());
m_T.coeffRef(i, i - 1) = Scalar(0);
// Update matrix S
m_S.applyOnTheRight(i - 1, i, G.adjoint());
// update Z
if (m_computeQZ) m_Z.applyOnTheLeft(i - 1, i, G);
}
}
}
}
template <typename MatrixType>
template <typename SparseMatrixType_>
void ComplexQZ<MatrixType>::hessenbergTriangularSparse(const SparseMatrixType_& A, const SparseMatrixType_& B) {
m_S = A.toDense();
SparseQR<SparseMatrix<Scalar, ColMajor>, NaturalOrdering<Index>> sparseQR;
eigen_assert(B.isCompressed() &&
"SparseQR requires a sparse matrix in compressed mode."
"Call .makeCompressed() before passing it to SparseQR");
// Computing QR decomposition of T...
sparseQR.setPivotThreshold(RealScalar(0)); // This prevends algorithm from doing pivoting
sparseQR.compute(B);
// perform QR decomposition of T, overwrite T with R, save Q
// HouseholderQR<Mat> qrT(m_T);
m_T = sparseQR.matrixR();
m_T.template triangularView<StrictlyLower>().setZero();
if (m_computeQZ) m_Q = sparseQR.matrixQ();
// overwrite S with Q* S
m_S = sparseQR.matrixQ().adjoint() * m_S;
if (m_computeQZ) m_Z = MatrixType::Identity(m_n, m_n);
// reduce S to upper Hessenberg with Givens rotations
for (Index j = 0; j <= m_n - 3; j++) {
for (Index i = m_n - 1; i >= j + 2; i--) {
JacobiRotation<Scalar> G;
// kill S(i,j)
// if(!numext::is_exactly_zero(_S.coeff(i, j)))
if (m_S.coeff(i, j) != Scalar(0)) {
// This is the adapted code
G.makeGivens(m_S.coeff(i - 1, j), m_S.coeff(i, j), &m_S.coeffRef(i - 1, j));
m_S.coeffRef(i, j) = Scalar(0);
m_T.rightCols(m_n - i + 1).applyOnTheLeft(i - 1, i, G.adjoint());
m_S.rightCols(m_n - j - 1).applyOnTheLeft(i - 1, i, G.adjoint());
// This is what we want to achieve
if (!is_negligible(m_S(i, j))) {
m_info = ComputationInfo::NumericalIssue;
}
m_S(i, j) = Scalar(0);
// update Q
if (m_computeQZ) m_Q.applyOnTheRight(i - 1, i, G);
}
if (!numext::is_exactly_zero(m_T.coeff(i, i - 1))) {
// Compute rotation and update matrix T
G.makeGivens(m_T.coeff(i, i), m_T.coeff(i, i - 1), &m_T.coeffRef(i, i));
m_T.topRows(i).applyOnTheRight(i - 1, i, G.adjoint());
m_T.coeffRef(i, i - 1) = Scalar(0);
// Update matrix S
m_S.applyOnTheRight(i - 1, i, G.adjoint());
// update Z
if (m_computeQZ) m_Z.applyOnTheLeft(i - 1, i, G);
}
}
}
}
template <typename MatrixType>
template <typename SparseMatrixType_>
void ComplexQZ<MatrixType>::computeSparse(const SparseMatrixType_& A, const SparseMatrixType_& B, bool computeQZ) {
m_computeQZ = computeQZ;
m_n = A.rows();
eigen_assert(m_n == A.cols() && "A is not a square matrix");
eigen_assert(m_n == B.rows() && m_n == B.cols() && "B is not a square matrix or B is not of the same size as A");
m_isInitialized = true;
m_global_iter = 0;
hessenbergTriangularSparse(A, B);
// We assume that we already have that A is upper-Hessenberg and B is
// upper-triangular. This is what the hessenbergTriangular(...) method does
reduceHessenbergTriangular();
}
template <typename MatrixType_>
void ComplexQZ<MatrixType_>::reduceHessenbergTriangular() {
Index l = m_n - 1, f;
unsigned int local_iter = 0;
computeNorms();
while (l > 0 && local_iter < m_maxIters) {
f = findSmallSubdiagEntry(l);
// Subdiag entry is small -> can be safely set to 0
if (f > 0) {
m_S.coeffRef(f, f - 1) = Scalar(0);
}
if (f == l) { // One root found
l--;
local_iter = 0;
} else if (f == l - 1) { // Two roots found
// We found an undesired non-zero at (f+1,f) in S and eliminate it immediately
reduceDiagonal2x2block(f);
l -= 2;
local_iter = 0;
} else {
Index z = findSmallDiagEntry(f, l);
if (z >= f) {
push_down_zero_ST(z, l);
} else {
do_QZ_step(f, m_n - l - 1);
local_iter++;
m_global_iter++;
}
}
}
m_info = (local_iter < m_maxIters) ? Success : NoConvergence;
}
template <typename MatrixType_>
inline typename ComplexQZ<MatrixType_>::Mat2 ComplexQZ<MatrixType_>::computeZk2(const Row2& b) {
Mat2 S;
S << Scalar(0), Scalar(1), Scalar(1), Scalar(0);
Vec2 bprime = S * b.adjoint();
JacobiRotation<Scalar> J;
J.makeGivens(bprime(0), bprime(1));
Mat2 Z = S;
Z.applyOnTheLeft(0, 1, J);
Z = S * Z;
return Z;
}
template <typename MatrixType_>
void ComplexQZ<MatrixType_>::do_QZ_step(Index p, Index q) {
// This is certainly not the most efficient way of doing this,
// but a readable one.
const auto a = [p, this](Index i, Index j) { return m_S(p + i - 1, p + j - 1); };
const auto b = [p, this](Index i, Index j) { return m_T(p + i - 1, p + j - 1); };
const Index m = m_n - p - q; // Size of the inner block
Scalar x, y, z;
// We could introduce doing exceptional shifts from time to time.
Scalar W1 = a(m - 1, m - 1) / b(m - 1, m - 1) - a(1, 1) / b(1, 1), W2 = a(m, m) / b(m, m) - a(1, 1) / b(1, 1),
W3 = a(m, m - 1) / b(m - 1, m - 1);
x = (W1 * W2 - a(m - 1, m) / b(m, m) * W3 + W3 * b(m - 1, m) / b(m, m) * a(1, 1) / b(1, 1)) * b(1, 1) / a(2, 1) +
a(1, 2) / b(2, 2) - a(1, 1) / b(1, 1) * b(1, 2) / b(2, 2);
y = (a(2, 2) / b(2, 2) - a(1, 1) / b(1, 1)) - a(2, 1) / b(1, 1) * b(1, 2) / b(2, 2) - W1 - W2 +
W3 * (b(m - 1, m) / b(m, m));
z = a(3, 2) / b(2, 2);
Vec3 X;
const PermutationMatrix<3, 3, int> S3(Vector3i(2, 0, 1));
for (Index k = p; k < p + m - 2; k++) {
X << x, y, z;
Vec2 ess;
Scalar tau;
RealScalar beta;
X.makeHouseholder(ess, tau, beta);
// The permutations are needed because the makeHouseHolder-method computes
// the householder transformation in a way that the vector is reflected to
// (1 0 ... 0) instead of (0 ... 0 1)
m_S.template middleRows<3>(k)
.rightCols((std::min)(m_n, m_n - k + 1))
.applyHouseholderOnTheLeft(ess, tau, m_ws.data());
m_T.template middleRows<3>(k).rightCols(m_n - k).applyHouseholderOnTheLeft(ess, tau, m_ws.data());
if (m_computeQZ) m_Q.template middleCols<3>(k).applyHouseholderOnTheRight(ess, std::conj(tau), m_ws.data());
// Compute Matrix Zk1 s.t. (b(k+2,k) ... b(k+2, k+2)) Zk1 = (0,0,*)
Vec3 bprime = (m_T.template block<1, 3>(k + 2, k) * S3).adjoint();
bprime.makeHouseholder(ess, tau, beta);
m_S.template middleCols<3>(k).topRows((std::min)(k + 4, m_n)).applyOnTheRight(S3);
m_S.template middleCols<3>(k)
.topRows((std::min)(k + 4, m_n))
.applyHouseholderOnTheRight(ess, std::conj(tau), m_ws.data());
m_S.template middleCols<3>(k).topRows((std::min)(k + 4, m_n)).applyOnTheRight(S3.transpose());
m_T.template middleCols<3>(k).topRows((std::min)(k + 3, m_n)).applyOnTheRight(S3);
m_T.template middleCols<3>(k)
.topRows((std::min)(k + 3, m_n))
.applyHouseholderOnTheRight(ess, std::conj(tau), m_ws.data());
m_T.template middleCols<3>(k).topRows((std::min)(k + 3, m_n)).applyOnTheRight(S3.transpose());
if (m_computeQZ) {
m_Z.template middleRows<3>(k).applyOnTheLeft(S3.transpose());
m_Z.template middleRows<3>(k).applyHouseholderOnTheLeft(ess, tau, m_ws.data());
m_Z.template middleRows<3>(k).applyOnTheLeft(S3);
}
Mat2 Zk2 = computeZk2(m_T.template block<1, 2>(k + 1, k));
m_S.template middleCols<2>(k).topRows((std::min)(k + 4, m_n)).applyOnTheRight(Zk2);
m_T.template middleCols<2>(k).topRows((std::min)(k + 3, m_n)).applyOnTheRight(Zk2);
if (m_computeQZ) m_Z.template middleRows<2>(k).applyOnTheLeft(Zk2.adjoint());
x = m_S(k + 1, k);
y = m_S(k + 2, k);
if (k < p + m - 3) {
z = m_S(k + 3, k);
}
};
// Find a Householdermartirx Qn1 s.t. Qn1 (x y)^T = (* 0)
JacobiRotation<Scalar> J;
J.makeGivens(x, y);
m_S.template middleRows<2>(p + m - 2).applyOnTheLeft(0, 1, J.adjoint());
m_T.template middleRows<2>(p + m - 2).applyOnTheLeft(0, 1, J.adjoint());
if (m_computeQZ) m_Q.template middleCols<2>(p + m - 2).applyOnTheRight(0, 1, J);
// Find a Householdermatrix Zn1 s.t. (b(n,n-1) b(n,n)) * Zn1 = (0 *)
Mat2 Zn1 = computeZk2(m_T.template block<1, 2>(p + m - 1, p + m - 2));
m_S.template middleCols<2>(p + m - 2).applyOnTheRight(Zn1);
m_T.template middleCols<2>(p + m - 2).applyOnTheRight(Zn1);
if (m_computeQZ) m_Z.template middleRows<2>(p + m - 2).applyOnTheLeft(Zn1.adjoint());
}
/** \internal we found an undesired non-zero at (i+1,i) on the subdiagonal of S and reduce the block */
template <typename MatrixType_>
void ComplexQZ<MatrixType_>::reduceDiagonal2x2block(Index i) {
// We have found a non-zero on the subdiagonal and want to eliminate it
Mat2 Si = m_S.template block<2, 2>(i, i), Ti = m_T.template block<2, 2>(i, i);
if (is_negligible(Ti(0, 0)) && !is_negligible(Ti(1, 1))) {
Eigen::JacobiRotation<Scalar> G;
G.makeGivens(m_S(i, i), m_S(i + 1, i));
m_S.applyOnTheLeft(i, i + 1, G.adjoint());
m_T.applyOnTheLeft(i, i + 1, G.adjoint());
if (m_computeQZ) m_Q.applyOnTheRight(i, i + 1, G);
} else if (!is_negligible(Ti(0, 0)) && is_negligible(Ti(1, 1))) {
Eigen::JacobiRotation<Scalar> G;
G.makeGivens(m_S(i + 1, i + 1), m_S(i + 1, i));
m_S.applyOnTheRight(i, i + 1, G.adjoint());
m_T.applyOnTheRight(i, i + 1, G.adjoint());
if (m_computeQZ) m_Z.applyOnTheLeft(i, i + 1, G);
} else if (!is_negligible(Ti(0, 0)) && !is_negligible((Ti(1, 1)))) {
Scalar mu = Si(0, 0) / Ti(0, 0);
Scalar a12_bar = Si(0, 1) - mu * Ti(0, 1);
Scalar a22_bar = Si(1, 1) - mu * Ti(1, 1);
Scalar p = Scalar(0.5) * (a22_bar / Ti(1, 1) - Ti(0, 1) * Si(1, 0) / (Ti(0, 0) * Ti(1, 1)));
RealScalar sgn_p = p.real() >= RealScalar(0) ? RealScalar(1) : RealScalar(-1);
Scalar q = Si(1, 0) * a12_bar / (Ti(0, 0) * Ti(1, 1));
Scalar r = p * p + q;
Scalar lambda = mu + p + sgn_p * numext::sqrt(r);
Mat2 E = Si - lambda * Ti;
Index l;
E.rowwise().norm().maxCoeff(&l);
JacobiRotation<Scalar> G;
G.makeGivens(E(l, 1), E(l, 0));
m_S.applyOnTheRight(i, i + 1, G.adjoint());
m_T.applyOnTheRight(i, i + 1, G.adjoint());
if (m_computeQZ) m_Z.applyOnTheLeft(i, i + 1, G);
Mat2 tildeSi = m_S.template block<2, 2>(i, i), tildeTi = m_T.template block<2, 2>(i, i);
Mat2 C = tildeSi.norm() < (lambda * tildeTi).norm() ? tildeSi : lambda * tildeTi;
G.makeGivens(C(0, 0), C(1, 0));
m_S.applyOnTheLeft(i, i + 1, G.adjoint());
m_T.applyOnTheLeft(i, i + 1, G.adjoint());
if (m_computeQZ) m_Q.applyOnTheRight(i, i + 1, G);
}
if (!is_negligible(m_S(i + 1, i), m_normOfS * NumTraits<RealScalar>::epsilon())) {
m_info = ComputationInfo::NumericalIssue;
} else {
m_S(i + 1, i) = Scalar(0);
}
}
/** \internal We found a zero at T(k,k) and want to "push it down" to T(l,l) */
template <typename MatrixType_>
void ComplexQZ<MatrixType_>::push_down_zero_ST(Index k, Index l) {
// Test Preconditions
JacobiRotation<Scalar> J;
for (Index j = k + 1; j <= l; j++) {
// Create a 0 at _T(j, j)
J.makeGivens(m_T(j - 1, j), m_T(j, j), &m_T.coeffRef(j - 1, j));
if (m_n - j - 1 > 0) {
m_T.rightCols(m_n - j - 1).applyOnTheLeft(j - 1, j, J.adjoint());
}
m_T.coeffRef(j, j) = Scalar(0);
m_S.applyOnTheLeft(j - 1, j, J.adjoint());
if (m_computeQZ) m_Q.applyOnTheRight(j - 1, j, J);
// Delete the non-desired non-zero at _S(j, j-2)
if (j > 1) {
J.makeGivens(std::conj(m_S(j, j - 1)), std::conj(m_S(j, j - 2)));
m_S.applyOnTheRight(j - 1, j - 2, J);
m_S(j, j - 2) = Scalar(0);
m_T.applyOnTheRight(j - 1, j - 2, J);
if (m_computeQZ) m_Z.applyOnTheLeft(j - 1, j - 2, J.adjoint());
}
}
// Assume we have the desired structure now, up to the non-zero entry at
// _S(l, l-1) which we will delete through a last right-jacobi-rotation
J.makeGivens(std::conj(m_S(l, l)), std::conj(m_S(l, l - 1)));
m_S.topRows(l + 1).applyOnTheRight(l, l - 1, J);
if (!is_negligible(m_S(l, l - 1), m_normOfS * NumTraits<Scalar>::epsilon())) {
m_info = ComputationInfo::NumericalIssue;
} else {
m_S(l, l - 1) = Scalar(0);
}
m_T.topRows(l + 1).applyOnTheRight(l, l - 1, J);
if (m_computeQZ) m_Z.applyOnTheLeft(l, l - 1, J.adjoint());
// Ensure postconditions
if (!is_negligible(m_T(l, l)) || !is_negligible(m_S(l, l - 1))) {
m_info = ComputationInfo::NumericalIssue;
} else {
m_T(l, l) = Scalar(0);
m_S(l, l - 1) = Scalar(0);
}
}
/** \internal Computes vector L1 norms of S and T when in Hessenberg-Triangular form already */
template <typename MatrixType_>
void ComplexQZ<MatrixType_>::computeNorms() {
const Index size = m_S.cols();
m_normOfS = RealScalar(0);
m_normOfT = RealScalar(0);
for (Index j = 0; j < size; ++j) {
m_normOfS += m_S.col(j).segment(0, (std::min)(size, j + 2)).cwiseAbs().sum();
m_normOfT += m_T.row(j).segment(j, size - j).cwiseAbs().sum();
}
}
/** \internal Look for single small sub-diagonal element S(res, res-1) and return res (or 0). Copied from Eigen3 RealQZ
* implementation */
template <typename MatrixType_>
inline Index ComplexQZ<MatrixType_>::findSmallSubdiagEntry(Index iu) {
Index res = iu;
while (res > 0) {
RealScalar s = numext::abs(m_S.coeff(res - 1, res - 1)) + numext::abs(m_S.coeff(res, res));
if (s == Scalar(0)) s = m_normOfS;
if (numext::abs(m_S.coeff(res, res - 1)) < NumTraits<RealScalar>::epsilon() * s) break;
res--;
}
return res;
}
//
/** \internal Look for single small diagonal element T(res, res) for res between f and l, and return res (or f-1).
* Copied from Eigen3 RealQZ implementation. */
template <typename MatrixType_>
inline Index ComplexQZ<MatrixType_>::findSmallDiagEntry(Index f, Index l) {
Index res = l;
while (res >= f) {
if (numext::abs(m_T.coeff(res, res)) <= NumTraits<RealScalar>::epsilon() * m_normOfT) break;
res--;
}
return res;
}
} // namespace Eigen
#endif // _COMPLEX_QZ_H_

View File

@@ -325,6 +325,22 @@ class SelfAdjointEigenSolver {
return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint();
}
/** \brief Computes the matrix exponential the matrix.
*
* \returns the matrix exponential the matrix.
*
* \pre The eigenvalues and eigenvectors of a positive-definite matrix
* have been computed before.
*
* \sa operatorInverseSqrt(), operatorSqrt(),
* <a href="unsupported/group__MatrixFunctions__Module.html">MatrixFunctions Module</a>
*/
EIGEN_DEVICE_FUNC MatrixType operatorExp() const {
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
return m_eivec * m_eivalues.array().exp().matrix().asDiagonal() * m_eivec.adjoint();
}
/** \brief Computes the inverse square root of the matrix.
*
* \returns the inverse positive-definite square root of the matrix

View File

@@ -365,6 +365,15 @@ class Transform {
* \sa MatrixBase::operator(Index,Index) */
EIGEN_DEVICE_FUNC inline Scalar& operator()(Index row, Index col) { return m_matrix(row, col); }
#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
/** shortcut for m_matrix(row,col);
* \sa MatrixBase::operator(Index,Index) const */
EIGEN_DEVICE_FUNC inline Scalar operator[](Index row, Index col) const { return m_matrix[row, col]; }
/** shortcut for m_matrix(row,col);
* \sa MatrixBase::operator(Index,Index) */
EIGEN_DEVICE_FUNC inline Scalar& operator[](Index row, Index col) { return m_matrix[row, col]; }
#endif
/** \returns a read-only expression of the transformation matrix */
EIGEN_DEVICE_FUNC inline const MatrixType& matrix() const { return m_matrix; }
/** \returns a writable expression of the transformation matrix */

View File

@@ -335,8 +335,8 @@ struct apply_rotation_in_the_plane_selector<Scalar, OtherScalar, SizeAtCompileTi
for (Index i = alignedStart; i < alignedEnd; i += PacketSize) {
Packet xi = pload<Packet>(px);
Packet yi = pload<Packet>(py);
pstore(px, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi)));
pstore(py, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi)));
pstore(px, pm.pmadd(pc, xi, pcj.pmul(ps, yi)));
pstore(py, pcj.pmsub(pc, yi, pm.pmul(ps, xi)));
px += PacketSize;
py += PacketSize;
}
@@ -347,18 +347,18 @@ struct apply_rotation_in_the_plane_selector<Scalar, OtherScalar, SizeAtCompileTi
Packet xi1 = ploadu<Packet>(px + PacketSize);
Packet yi = pload<Packet>(py);
Packet yi1 = pload<Packet>(py + PacketSize);
pstoreu(px, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi)));
pstoreu(px + PacketSize, padd(pm.pmul(pc, xi1), pcj.pmul(ps, yi1)));
pstore(py, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi)));
pstore(py + PacketSize, psub(pcj.pmul(pc, yi1), pm.pmul(ps, xi1)));
pstoreu(px, pm.pmadd(pc, xi, pcj.pmul(ps, yi)));
pstoreu(px + PacketSize, pm.pmadd(pc, xi1, pcj.pmul(ps, yi1)));
pstore(py, pcj.pmsub(pc, yi, pm.pmul(ps, xi)));
pstore(py + PacketSize, pcj.pmsub(pc, yi1, pm.pmul(ps, xi1)));
px += Peeling * PacketSize;
py += Peeling * PacketSize;
}
if (alignedEnd != peelingEnd) {
Packet xi = ploadu<Packet>(x + peelingEnd);
Packet yi = pload<Packet>(y + peelingEnd);
pstoreu(x + peelingEnd, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi)));
pstore(y + peelingEnd, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi)));
pstoreu(x + peelingEnd, pm.pmadd(pc, xi, pcj.pmul(ps, yi)));
pstore(y + peelingEnd, pcj.pmsub(pc, yi, pm.pmul(ps, xi)));
}
}
@@ -381,8 +381,8 @@ struct apply_rotation_in_the_plane_selector<Scalar, OtherScalar, SizeAtCompileTi
for (Index i = 0; i < size; i += PacketSize) {
Packet xi = pload<Packet>(px);
Packet yi = pload<Packet>(py);
pstore(px, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi)));
pstore(py, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi)));
pstore(px, pm.pmadd(pc, xi, pcj.pmul(ps, yi)));
pstore(py, pcj.pmsub(pc, yi, pm.pmul(ps, xi)));
px += PacketSize;
py += PacketSize;
}
@@ -420,6 +420,34 @@ EIGEN_DEVICE_FUNC void inline apply_rotation_in_the_plane(DenseBase<VectorX>& xp
x, incrx, y, incry, size, c, s);
}
template <typename MatrixType, typename RealScalar, typename Index>
void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q, JacobiRotation<RealScalar>* j_left,
JacobiRotation<RealScalar>* j_right) {
using std::abs;
using std::sqrt;
Matrix<RealScalar, 2, 2> m;
m << numext::real(matrix.coeff(p, p)), numext::real(matrix.coeff(p, q)), numext::real(matrix.coeff(q, p)),
numext::real(matrix.coeff(q, q));
JacobiRotation<RealScalar> rot1;
RealScalar t = m.coeff(0, 0) + m.coeff(1, 1);
RealScalar d = m.coeff(1, 0) - m.coeff(0, 1);
if (abs(d) < (std::numeric_limits<RealScalar>::min)()) {
rot1.s() = RealScalar(0);
rot1.c() = RealScalar(1);
} else {
// If d!=0, then t/d cannot overflow because the magnitude of the
// entries forming d are not too small compared to the ones forming t.
RealScalar u = t / d;
RealScalar tmp = sqrt(RealScalar(1) + numext::abs2(u));
rot1.s() = RealScalar(1) / tmp;
rot1.c() = u / tmp;
}
m.applyOnTheLeft(0, 1, rot1);
j_right->makeJacobi(m, 0, 1);
*j_left = rot1 * j_right->transpose();
}
} // end namespace internal
} // end namespace Eigen

View File

@@ -89,7 +89,7 @@ struct simpl_chol_helper {
m_set[u] = v;
u = next;
}
};
}
};
// Computes the higher adjacency pattern by transposing the input lower adjacency matrix.

View File

@@ -1,53 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2013-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_REALSVD2X2_H
#define EIGEN_REALSVD2X2_H
// IWYU pragma: private
#include "./InternalHeaderCheck.h"
namespace Eigen {
namespace internal {
template <typename MatrixType, typename RealScalar, typename Index>
void real_2x2_jacobi_svd(const MatrixType &matrix, Index p, Index q, JacobiRotation<RealScalar> *j_left,
JacobiRotation<RealScalar> *j_right) {
using std::abs;
using std::sqrt;
Matrix<RealScalar, 2, 2> m;
m << numext::real(matrix.coeff(p, p)), numext::real(matrix.coeff(p, q)), numext::real(matrix.coeff(q, p)),
numext::real(matrix.coeff(q, q));
JacobiRotation<RealScalar> rot1;
RealScalar t = m.coeff(0, 0) + m.coeff(1, 1);
RealScalar d = m.coeff(1, 0) - m.coeff(0, 1);
if (abs(d) < (std::numeric_limits<RealScalar>::min)()) {
rot1.s() = RealScalar(0);
rot1.c() = RealScalar(1);
} else {
// If d!=0, then t/d cannot overflow because the magnitude of the
// entries forming d are not too small compared to the ones forming t.
RealScalar u = t / d;
RealScalar tmp = sqrt(RealScalar(1) + numext::abs2(u));
rot1.s() = RealScalar(1) / tmp;
rot1.c() = u / tmp;
}
m.applyOnTheLeft(0, 1, rot1);
j_right->makeJacobi(m, 0, 1);
*j_left = rot1 * j_right->transpose();
}
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_REALSVD2X2_H

View File

@@ -12,7 +12,6 @@
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
cache:
key: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG-BUILD"
@@ -110,7 +109,7 @@ build:linux:docs:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"

View File

@@ -17,7 +17,6 @@
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
cache:

View File

@@ -36,6 +36,6 @@ deploy:docs:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
variables:
PAGES_PREFIX: docs-$CI_COMMIT_REF_NAME

View File

@@ -8,7 +8,6 @@
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
tags:
- saas-linux-2xlarge-amd64

View File

@@ -8,7 +8,6 @@
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
tags:
- eigen-runner

View File

@@ -257,6 +257,7 @@ ei_add_test(eigensolver_selfadjoint)
ei_add_test(eigensolver_generic)
ei_add_test(eigensolver_complex)
ei_add_test(real_qz)
ei_add_test(complex_qz)
ei_add_test(eigensolver_generalized_real)
ei_add_test(jacobi)
ei_add_test(jacobisvd)

84
test/complex_qz.cpp Normal file
View File

@@ -0,0 +1,84 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 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/.
#define EIGEN_RUNTIME_NO_MALLOC
#include "main.h"
#include <Eigen/Eigenvalues>
/* this test covers the following files:
ComplexQZ.h
*/
template <typename MatrixType>
void generate_random_matrix_pair(const Index dim, MatrixType& A, MatrixType& B) {
A.setRandom(dim, dim);
B.setRandom(dim, dim);
// Zero out each row of B to with a probability of 10%.
for (int i = 0; i < dim; i++) {
if (internal::random<int>(0, 10) == 0) B.row(i).setZero();
}
}
template <typename MatrixType>
void complex_qz(const MatrixType& A, const MatrixType& B) {
using std::abs;
const Index dim = A.rows();
ComplexQZ<MatrixType> qz(A, B);
VERIFY_IS_EQUAL(qz.info(), Success);
auto T = qz.matrixT(), S = qz.matrixS();
bool is_all_zero_T = true, is_all_zero_S = true;
using RealScalar = typename MatrixType::RealScalar;
RealScalar tol = dim * 10 * NumTraits<RealScalar>::epsilon();
for (Index j = 0; j < dim; j++) {
for (Index i = j + 1; i < dim; i++) {
if (std::abs(T(i, j)) > tol) {
std::cerr << std::abs(T(i, j)) << std::endl;
is_all_zero_T = false;
}
if (std::abs(S(i, j)) > tol) {
std::cerr << std::abs(S(i, j)) << std::endl;
is_all_zero_S = false;
}
}
}
VERIFY_IS_EQUAL(is_all_zero_T, true);
VERIFY_IS_EQUAL(is_all_zero_S, true);
VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixS() * qz.matrixZ(), A);
VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixT() * qz.matrixZ(), B);
VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixQ().adjoint(), MatrixType::Identity(dim, dim));
VERIFY_IS_APPROX(qz.matrixZ() * qz.matrixZ().adjoint(), MatrixType::Identity(dim, dim));
}
EIGEN_DECLARE_TEST(complex_qz) {
for (int i = 0; i < g_repeat; i++) {
// Check for very small, fixed-sized double- and float complex matrices
Eigen::Matrix2cd A_2x2, B_2x2;
A_2x2.setRandom();
B_2x2.setRandom();
B_2x2.row(1).setZero();
Eigen::Matrix3cf A_3x3, B_3x3;
A_3x3.setRandom();
B_3x3.setRandom();
B_3x3.col(i % 3).setRandom();
CALL_SUBTEST_1(complex_qz(A_2x2, B_2x2));
CALL_SUBTEST_2(complex_qz(A_3x3, B_3x3));
// Test for float complex matrices
const Index dim = internal::random<Index>(15, 80);
Eigen::MatrixXcf A_float, B_float;
generate_random_matrix_pair(dim, A_float, B_float);
CALL_SUBTEST_3(complex_qz(A_float, B_float));
// Test for double complex matrices
Eigen::MatrixXcd A_double, B_double;
generate_random_matrix_pair(dim, A_double, B_double);
CALL_SUBTEST_4(complex_qz(A_double, B_double));
}
}

View File

@@ -13,6 +13,7 @@
#include <limits>
#include <Eigen/Eigenvalues>
#include <Eigen/SparseCore>
#include <unsupported/Eigen/MatrixFunctions>
template <typename MatrixType>
void selfadjointeigensolver_essential_check(const MatrixType& m) {
@@ -135,11 +136,13 @@ void selfadjointeigensolver(const MatrixType& m) {
VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorExp());
eiSymmUninitialized.compute(symmA, false);
VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorExp());
// test Tridiagonalization's methods
Tridiagonalization<MatrixType> tridiag(symmC);
@@ -167,6 +170,14 @@ void selfadjointeigensolver(const MatrixType& m) {
eiSymmTridiag.eigenvectors().real().transpose());
}
// Test matrix expponential from eigendecomposition.
// First scale to avoid overflow.
symmB = symmB / symmB.norm();
eiSymm.compute(symmB);
MatrixType expSymmB = eiSymm.operatorExp();
symmB = symmB.template selfadjointView<Lower>();
VERIFY_IS_APPROX(expSymmB, symmB.exp());
if (rows > 1 && rows < 20) {
// Test matrix with NaN
symmC(0, 0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();

View File

@@ -747,22 +747,6 @@ void packetmath() {
}
}
if (PacketTraits::HasBlend) {
Packet thenPacket = internal::pload<Packet>(data1);
Packet elsePacket = internal::pload<Packet>(data2);
EIGEN_ALIGN_MAX internal::Selector<PacketSize> selector;
for (int i = 0; i < PacketSize; ++i) {
selector.select[i] = i;
}
Packet blend = internal::pblend(selector, thenPacket, elsePacket);
EIGEN_ALIGN_MAX Scalar result[size];
internal::pstore(result, blend);
for (int i = 0; i < PacketSize; ++i) {
VERIFY(test::isApproxAbs(result[i], (selector.select[i] ? data1[i] : data2[i]), refvalue));
}
}
{
for (int i = 0; i < PacketSize; ++i) {
// "if" mask

View File

@@ -117,6 +117,10 @@ class SimpleTensorContractionMapper {
return m_tensor.coeff(computeIndex(row, col));
}
#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator[](Index row, Index col) const { return operator()(row, col); }
#endif
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index computeIndex(Index row, Index col) const {
const bool left = (side == Lhs);
EIGEN_UNUSED_VARIABLE(left); // annoying bug in g++8.1: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85963

View File

@@ -691,9 +691,9 @@ struct TensorEvaluator<const TensorSelectOp<IfArgType, ThenArgType, ElseArgType>
static constexpr int Layout = TensorEvaluator<IfArgType, Device>::Layout;
enum {
IsAligned = TensorEvaluator<ThenArgType, Device>::IsAligned & TensorEvaluator<ElseArgType, Device>::IsAligned,
PacketAccess = (TensorEvaluator<ThenArgType, Device>::PacketAccess &&
TensorEvaluator<ElseArgType, Device>::PacketAccess && PacketType<Scalar, Device>::HasBlend) ||
TernaryPacketAccess,
PacketAccess =
(TensorEvaluator<ThenArgType, Device>::PacketAccess && TensorEvaluator<ElseArgType, Device>::PacketAccess) ||
TernaryPacketAccess,
BlockAccess = TensorEvaluator<IfArgType, Device>::BlockAccess &&
TensorEvaluator<ThenArgType, Device>::BlockAccess &&
TensorEvaluator<ElseArgType, Device>::BlockAccess,
@@ -789,13 +789,14 @@ struct TensorEvaluator<const TensorSelectOp<IfArgType, ThenArgType, ElseArgType>
template <int LoadMode, bool UseTernary = TernaryPacketAccess, std::enable_if_t<!UseTernary, bool> = true>
EIGEN_DEVICE_FUNC PacketReturnType packet(Index index) const {
internal::Selector<PacketSize> select;
EIGEN_ALIGN_TO_BOUNDARY(sizeof(PacketReturnType)) std::remove_const_t<Scalar> arr[PacketSize];
EIGEN_UNROLL_LOOP
for (Index i = 0; i < PacketSize; ++i) {
select.select[i] = m_condImpl.coeff(index + i);
arr[i] = m_condImpl.coeff(index + i) ? Scalar(-1) : Scalar(0);
}
return internal::pblend(select, m_thenImpl.template packet<LoadMode>(index),
m_elseImpl.template packet<LoadMode>(index));
return TernarySelectOp().template packetOp<PacketReturnType>(m_thenImpl.template packet<LoadMode>(index),
m_elseImpl.template packet<LoadMode>(index),
internal::pload<PacketReturnType>(arr));
}
template <int LoadMode, bool UseTernary = TernaryPacketAccess, std::enable_if_t<UseTernary, bool> = true>

View File

@@ -63,6 +63,10 @@ class companion {
}
}
#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
EIGEN_STRONG_INLINE const Scalar_ operator[](Index row, Index col) const { return operator()(row, col); }
#endif
public:
template <typename VectorType>
void setPolynomial(const VectorType& poly) {

View File

@@ -280,6 +280,11 @@ class RandomSetter {
return m_hashmaps[outerMajor][key].value;
}
#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
/** \returns a reference to the coefficient at given coordinates \a row, \a col */
Scalar& operator[](Index row, Index col) { return operator()(row, col); }
#endif
/** \returns the number of non zero coefficients
*
* \note According to the underlying map/hash_map implementation,