From 2aa2ff29002d070aa0f5aa86c06bf93e3bb7eff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20S=C3=A1nchez?= Date: Mon, 20 Oct 2025 21:09:53 +0000 Subject: [PATCH 1/9] More ComplexQZ fixes. ### Description 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 ### Additional information See merge request libeigen/eigen!2036 --- Eigen/Eigenvalues | 1 + Eigen/src/Eigenvalues/ComplexQZ.h | 10 +++------- Eigen/src/SparseCholesky/SimplicialCholesky_impl.h | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Eigen/Eigenvalues b/Eigen/Eigenvalues index c11f42ad4..803900058 100644 --- a/Eigen/Eigenvalues +++ b/Eigen/Eigenvalues @@ -15,6 +15,7 @@ #include "Householder" #include "LU" #include "Geometry" +#include "Sparse" // Needed by ComplexQZ. #include "src/Core/util/DisableStupidWarnings.h" diff --git a/Eigen/src/Eigenvalues/ComplexQZ.h b/Eigen/src/Eigenvalues/ComplexQZ.h index 20f2a77bb..de35698ae 100644 --- a/Eigen/src/Eigenvalues/ComplexQZ.h +++ b/Eigen/src/Eigenvalues/ComplexQZ.h @@ -14,8 +14,6 @@ #ifndef EIGEN_COMPLEX_QZ_H_ #define EIGEN_COMPLEX_QZ_H_ -#include "../../Sparse" - // IWYU pragma: private #include "./InternalHeaderCheck.h" @@ -126,9 +124,7 @@ class ComplexQZ { computeQZ ? n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)), m_ws(2 * n), m_computeQZ(computeQZ), - m_maxIters(maxIters){ - - }; + m_maxIters(maxIters) {} /** \brief Constructor. computes the QZ decomposition of given matrices * upon creation @@ -178,14 +174,14 @@ class ComplexQZ { * * \returns \c Success if computation was successfull, \c NoConvergence otherwise. */ - ComputationInfo info() const { return m_info; }; + 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; diff --git a/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h b/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h index 3c65541b8..97f214201 100644 --- a/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +++ b/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h @@ -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. From 8e60d4173c6d8d5ee216c13ffd6142639be2bcc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20S=C3=A1nchez?= Date: Mon, 20 Oct 2025 21:47:42 +0000 Subject: [PATCH 2/9] Support AVX for i686. ### Description 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 Fixes #2991. Closes #2991 See merge request libeigen/eigen!2037 --- Eigen/src/Core/arch/AVX/PacketMath.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Eigen/src/Core/arch/AVX/PacketMath.h b/Eigen/src/Core/arch/AVX/PacketMath.h index 0cd9e6cd6..b1dfb07ff 100644 --- a/Eigen/src/Core/arch/AVX/PacketMath.h +++ b/Eigen/src/Core/arch/AVX/PacketMath.h @@ -2831,7 +2831,7 @@ inline __m128i segment_mask_4x8(Index begin, Index count) { mask <<= CHAR_BIT * count; mask--; mask <<= CHAR_BIT * begin; -#if defined(_WIN32) && !defined(_WIN64) +#if !EIGEN_ARCH_x86_64 return _mm_loadl_epi64(reinterpret_cast(&mask)); #else return _mm_cvtsi64_si128(mask); @@ -2847,7 +2847,7 @@ inline __m128i segment_mask_8x8(Index begin, Index count) { mask <<= (CHAR_BIT / 2) * count; mask--; mask <<= CHAR_BIT * begin; -#if defined(_WIN32) && !defined(_WIN64) +#if !EIGEN_ARCH_x86_64 return _mm_loadl_epi64(reinterpret_cast(&mask)); #else return _mm_cvtsi64_si128(mask); From 40da5b64ce8db35e09f90733f67932c278808e24 Mon Sep 17 00:00:00 2001 From: Charles Schlosser Date: Wed, 22 Oct 2025 04:51:51 +0000 Subject: [PATCH 3/9] CI enhancements: visual indication of flaky tests ### Reference issue ### What does this implement/fix? 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 See merge request libeigen/eigen!2025 --- ci/build.linux.gitlab-ci.yml | 4 ++-- ci/scripts/test.linux.script.sh | 32 ++++++++++++++++++---------- ci/scripts/test.windows.script.ps1 | 34 +++++++++++++++++++++--------- ci/test.linux.gitlab-ci.yml | 6 ++++-- ci/test.windows.gitlab-ci.yml | 3 ++- cmake/EigenSmokeTestList.cmake | 2 +- test/main.h | 12 ++++++++--- 7 files changed, 63 insertions(+), 30 deletions(-) diff --git a/ci/build.linux.gitlab-ci.yml b/ci/build.linux.gitlab-ci.yml index 2fb7aa115..9e6303488 100644 --- a/ci/build.linux.gitlab-ci.yml +++ b/ci/build.linux.gitlab-ci.yml @@ -290,7 +290,7 @@ build:linux:cross:x86-64:gcc-10:default:smoketest: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" tags: - - saas-linux-small-amd64 + - saas-linux-medium-amd64 build:linux:cross:x86-64:clang-12:default:smoketest: extends: build:linux:cross:x86-64:clang-12:default @@ -299,4 +299,4 @@ build:linux:cross:x86-64:clang-12:default:smoketest: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" tags: - - saas-linux-small-amd64 + - saas-linux-medium-amd64 diff --git a/ci/scripts/test.linux.script.sh b/ci/scripts/test.linux.script.sh index 0bd18a859..6e2e1c58c 100755 --- a/ci/scripts/test.linux.script.sh +++ b/ci/scripts/test.linux.script.sh @@ -13,19 +13,29 @@ elif [[ ${EIGEN_CI_CTEST_LABEL} ]]; then target="-L ${EIGEN_CI_CTEST_LABEL}" fi -# Repeat tests up to three times to ignore flakes. Do not re-run with -T test, -# otherwise we lose test results for those that passed. -# Note: starting with CMake 3.17, we can use --repeat until-pass:3, but we have -# no way of easily installing this on ppc64le. -ctest ${EIGEN_CI_CTEST_ARGS} --parallel ${NPROC} \ - --output-on-failure --no-compress-output \ - --build-no-clean -T test ${target} || \ - ctest ${EIGEN_CI_CTEST_ARGS} --parallel ${NPROC} \ - --output-on-failure --no-compress-output --rerun-failed || \ - ctest ${EIGEN_CI_CTEST_ARGS} --parallel ${NPROC} \ - --output-on-failure --no-compress-output --rerun-failed +set +x + +ctest_cmd="ctest ${EIGEN_CI_CTEST_ARGS} --parallel ${NPROC} --output-on-failure --no-compress-output --build-noclean ${target}" + +echo "Running initial tests..." +if ${ctest_cmd} -T test; then + echo "Tests passed on the first attempt." + exit_code=$? +else + echo "Initial tests failed with exit code $?. Retrying up to ${EIGEN_CI_CTEST_REPEAT} times..." + if ${ctest_cmd} --rerun-failed --repeat until-pass:${EIGEN_CI_CTEST_REPEAT}; then + echo "Tests passed on retry." + exit_code=42 + else + exit_code=$? + fi +fi + +set -x # Return to root directory. cd ${rootdir} set +x + +exit $exit_code diff --git a/ci/scripts/test.windows.script.ps1 b/ci/scripts/test.windows.script.ps1 index 4ea1e30f5..ba46ef1cc 100644 --- a/ci/scripts/test.windows.script.ps1 +++ b/ci/scripts/test.windows.script.ps1 @@ -13,18 +13,32 @@ if (${EIGEN_CI_CTEST_REGEX}) { $target = "-L","${EIGEN_CI_CTEST_LABEL}" } -# Repeat tests up to three times to ignore flakes. Do not re-run with -T test, -# otherwise we lose test results for those that passed. -# Note: starting with CMake 3.17, we can use --repeat until-pass:3, but we have -# no way of easily installing this on ppc64le. -ctest $EIGEN_CI_CTEST_ARGS -j$NPROC --output-on-failure --no-compress-output --build-no-clean -T test $target || ` - ctest $EIGEN_CI_CTEST_ARGS -j$NPROC --output-on-failure --no-compress-output --rerun-failed || ` - ctest $EIGEN_CI_CTEST_ARGS -j$NPROC --output-on-failure --no-compress-output --rerun-failed +$ctest_cmd = { ctest ${EIGEN_CI_CTEST_ARGS} --parallel ${NPROC} --output-on-failure --no-compress-output --build-noclean ${target} } -$success = $LASTEXITCODE +Write-Host "Running initial tests..." + +& $ctest_cmd "-T test" +$exit_code = $LASTEXITCODE + +if ($exit_code -eq 0) { + Write-Host "Tests passed on the first attempt." +} +else { + Write-Host "Initial tests failed with exit code $exit_code. Retrying up to $EIGEN_CI_CTEST_REPEAT times..." + # TODO: figure out how to use --repeat until-pass + for ($i = 1; $i -le $EIGEN_CI_CTEST_REPEAT; $i++) { + & $ctest_cmd "--rerun-failed" + $exit_code = $LASTEXITCODE + + if ($exit_code -eq 0) { + Write-Host "Tests passed on retry." + $exit_code = 42 + break + } + } +} # Return to root directory. cd ${rootdir} -# Explicitly propagate exit code to indicate pass/failure of test command. -if($success -ne 0) { Exit $success } +Exit $exit_code diff --git a/ci/test.linux.gitlab-ci.yml b/ci/test.linux.gitlab-ci.yml index b3599f38f..17c7ee0e2 100644 --- a/ci/test.linux.gitlab-ci.yml +++ b/ci/test.linux.gitlab-ci.yml @@ -11,6 +11,8 @@ - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/" tags: - saas-linux-2xlarge-amd64 + allow_failure: + exit_codes: 42 ##### x86-64 ################################################################### .test:linux:x86-64: @@ -384,7 +386,7 @@ test:linux:x86-64:gcc-10:default:smoketest: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" tags: - - saas-linux-small-amd64 + - saas-linux-medium-amd64 test:linux:x86-64:clang-12:default:smoketest: extends: .test:linux:x86-64:clang-12:default @@ -394,4 +396,4 @@ test:linux:x86-64:clang-12:default:smoketest: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" tags: - - saas-linux-small-amd64 + - saas-linux-medium-amd64 diff --git a/ci/test.windows.gitlab-ci.yml b/ci/test.windows.gitlab-ci.yml index 3c398a4ec..34b1d7424 100644 --- a/ci/test.windows.gitlab-ci.yml +++ b/ci/test.windows.gitlab-ci.yml @@ -9,11 +9,12 @@ - if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen" - if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen" - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/" - tags: - eigen-runner - windows - x86-64 + allow_failure: + exit_codes: 42 ##### MSVC ##################################################################### diff --git a/cmake/EigenSmokeTestList.cmake b/cmake/EigenSmokeTestList.cmake index db7d3ff5e..247b2c4a2 100644 --- a/cmake/EigenSmokeTestList.cmake +++ b/cmake/EigenSmokeTestList.cmake @@ -91,7 +91,7 @@ set(ei_smoke_test_list qr_1 qr_colpivoting_7 qr_fullpivoting_4 - rand + rand_1 real_qz_1 redux_1 ref_1 diff --git a/test/main.h b/test/main.h index db4d484fb..fa7053e96 100644 --- a/test/main.h +++ b/test/main.h @@ -186,7 +186,7 @@ inline void on_temporary_creation(long int size, int) { namespace Eigen { static std::vector g_test_stack; -// level == 0 <=> abort if test fail +// level == 0 <=> return 1 if test fail // level >= 1 <=> warning message to std::cerr if test fail static int g_test_level = 0; static int g_repeat = 1; @@ -356,7 +356,7 @@ inline void verify_impl(bool condition, const char* testname, const char* file, const int test_stack_size = static_cast(Eigen::g_test_stack.size()); for (int i = test_stack_size - 1; i >= 0; --i) std::cerr << " - " << Eigen::g_test_stack[i] << "\n"; std::cerr << "\n"; - if (Eigen::g_test_level == 0) abort(); + if (Eigen::g_test_level == 0) exit(1); } } @@ -858,6 +858,12 @@ inline void set_seed_from_string(const char* str) { g_has_set_seed = true; } +inline void set_seed_from_time() { + using namespace std::chrono; + long long ns = duration_cast(high_resolution_clock::now().time_since_epoch()).count(); + g_seed = static_cast(ns); +} + int main(int argc, char* argv[]) { g_has_set_repeat = false; g_has_set_seed = false; @@ -896,7 +902,7 @@ int main(int argc, char* argv[]) { char* env_EIGEN_SEED = getenv("EIGEN_SEED"); if (!g_has_set_seed && env_EIGEN_SEED) set_seed_from_string(env_EIGEN_SEED); - if (!g_has_set_seed) g_seed = (unsigned int)time(NULL); + if (!g_has_set_seed) set_seed_from_time(); if (!g_has_set_repeat) g_repeat = DEFAULT_REPEAT; std::cout << "Initializing random number generator with seed " << g_seed << std::endl; From ac3ef16f30b7708a3c6c39b964e1f294dd16b8a3 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Thu, 23 Oct 2025 07:03:37 +0000 Subject: [PATCH 4/9] Fix SparseVector::insertBack() with custom scalar types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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::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 --- Eigen/src/SparseCore/SparseVector.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Eigen/src/SparseCore/SparseVector.h b/Eigen/src/SparseCore/SparseVector.h index d19a00dd9..8b34a9ac9 100644 --- a/Eigen/src/SparseCore/SparseVector.h +++ b/Eigen/src/SparseCore/SparseVector.h @@ -140,7 +140,7 @@ class SparseVector : public SparseCompressedBase Date: Fri, 24 Oct 2025 19:46:57 +0000 Subject: [PATCH 5/9] Eliminate use of std::cout in ArpackSelfAdjointEigenSolver. ### Description Eliminate use of std::cout in ArpackSelfAdjointEigenSolver. Instead set the appropriate error status on failure. ### Reference issue ### Additional information See merge request libeigen/eigen!2041 --- .../src/Eigenvalues/ArpackSelfAdjointEigenSolver.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h b/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h index 54db9bf29..bc21d94cc 100644 --- a/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h +++ b/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h @@ -454,8 +454,16 @@ ArpackGeneralizedSelfAdjointEigenSolver::compu } } - if (!(mode == 1 && isBempty) && !(mode == 2 && isBempty) && OP.info() != Success) - std::cout << "Error factoring matrix" << std::endl; + if (!(mode == 1 && isBempty) && !(mode == 2 && isBempty) && OP.info() != Success) { + m_info = OP.info() delete[] v; + delete[] iparam; + delete[] ipntr; + delete[] workd; + delete[] workl; + delete[] resid; + m_isInitialized = false; + return *this; + } do { internal::arpack_wrapper::saupd(&ido, bmat, &n, whch, &nev, &tol, resid, &ncv, v, &ldv, iparam, @@ -572,7 +580,7 @@ ArpackGeneralizedSelfAdjointEigenSolver::compu delete[] workl; delete[] resid; - m_isInitialized = true; + m_isInitialized = (m_info == Success); return *this; } From 1a5eecd45e7ee289c555a8759658bc387afb8445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20S=C3=A1nchez?= Date: Fri, 24 Oct 2025 19:54:27 +0000 Subject: [PATCH 6/9] Clarify range spanning major versions only works with 3.4.1. ### Description Clarify range spanning major versions only works with 3.4.1. ### Reference issue Fixes #2994. Closes #2994 See merge request libeigen/eigen!2042 --- doc/TopicCMakeGuide.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/TopicCMakeGuide.dox b/doc/TopicCMakeGuide.dox index ebbc4a840..dc0d7068c 100644 --- a/doc/TopicCMakeGuide.dox +++ b/doc/TopicCMakeGuide.dox @@ -36,9 +36,9 @@ option in `find_package`: ``` find_package(Eigen3 3.4 REQUIRED NO_MODULE) # Restricts to 3.4.z ``` -or to support a range of versions: +Starting with Eigen 3.4.1, we also support a range spanning major versions: ``` -find_package(Eigen3 3.4...5 REQUIRED NO_MODULE) # Any version >=3.4.0 but <6.0.0. +find_package(Eigen3 3.4...5 REQUIRED NO_MODULE) # Any version >=3.4.1 but <6.0.0. ``` Do not forget to set the \c CMAKE_PREFIX_PATH variable if Eigen is not installed in a default location or if you want to pick a specific version. For instance: From 2e91853adfe1560a5bd1f4c80af7a73d37093b44 Mon Sep 17 00:00:00 2001 From: Rasmus Munk Larsen Date: Fri, 24 Oct 2025 20:54:54 +0000 Subject: [PATCH 7/9] 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 --- Eigen/src/Eigenvalues/ComplexQZ.h | 4 +++- test/complex_qz.cpp | 26 ++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Eigen/src/Eigenvalues/ComplexQZ.h b/Eigen/src/Eigenvalues/ComplexQZ.h index de35698ae..ed32ea3da 100644 --- a/Eigen/src/Eigenvalues/ComplexQZ.h +++ b/Eigen/src/Eigenvalues/ComplexQZ.h @@ -565,7 +565,9 @@ void ComplexQZ::push_down_zero_ST(Index k, Index l) { 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)); - m_T.rightCols(m_n - j - 1).applyOnTheLeft(j - 1, j, J.adjoint()); + 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()); diff --git a/test/complex_qz.cpp b/test/complex_qz.cpp index a6b05dc92..28ab08e93 100644 --- a/test/complex_qz.cpp +++ b/test/complex_qz.cpp @@ -18,11 +18,9 @@ template void generate_random_matrix_pair(const Index dim, MatrixType& A, MatrixType& B) { - A.resize(dim, dim); - B.resize(dim, dim); - A.setRandom(); - B.setRandom(); - // Set each row of B with a probability of 10% to 0 + 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(0, 10) == 0) B.row(i).setZero(); } @@ -59,8 +57,6 @@ void complex_qz(const MatrixType& A, const MatrixType& B) { } EIGEN_DECLARE_TEST(complex_qz) { - // const Index dim1 = 15; - // const Index dim2 = 80; 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; @@ -71,16 +67,18 @@ EIGEN_DECLARE_TEST(complex_qz) { A_3x3.setRandom(); B_3x3.setRandom(); B_3x3.col(i % 3).setRandom(); - // Test for small float complex matrices - Eigen::MatrixXcf A_float, B_float; - const Index dim1 = internal::random(15, 80), dim2 = internal::random(15, 80); - generate_random_matrix_pair(dim1, A_float, B_float); - // Test for a bit larger double complex matrices - Eigen::MatrixXcd A_double, B_double; - generate_random_matrix_pair(dim2, A_double, B_double); 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(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)); } } From be56fff1ff288f83296a78d63314a3eeac3397ae Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Sun, 26 Oct 2025 02:03:22 +0000 Subject: [PATCH 8/9] Fix ambiguous sqrt() overload caused by ADL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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::type>::type Eigen::numext::sqrt(const Scalar&) [with Scalar = boost::decimal::decimal64_t; typename Eigen::internal::sqrt_retval::type>::type = boost::decimal::decimal64_t; typename Eigen::internal::global_math_functions_filtering_base::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 [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 --- Eigen/src/Householder/Householder.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Eigen/src/Householder/Householder.h b/Eigen/src/Householder/Householder.h index 96b1daf5f..e5d2d4fac 100644 --- a/Eigen/src/Householder/Householder.h +++ b/Eigen/src/Householder/Householder.h @@ -65,7 +65,6 @@ template EIGEN_DEVICE_FUNC void MatrixBase::makeHouseholder(EssentialPart& essential, Scalar& tau, RealScalar& beta) const { using numext::conj; - using numext::sqrt; EIGEN_STATIC_ASSERT_VECTOR_ONLY(EssentialPart) VectorBlock tail(derived(), 1, size() - 1); @@ -79,7 +78,7 @@ EIGEN_DEVICE_FUNC void MatrixBase::makeHouseholder(EssentialPart& essen beta = numext::real(c0); essential.setZero(); } else { - beta = sqrt(numext::abs2(c0) + tailSqNorm); + beta = numext::sqrt(numext::abs2(c0) + tailSqNorm); if (numext::real(c0) >= RealScalar(0)) beta = -beta; essential = tail / (c0 - beta); tau = conj((beta - c0) / beta); From 9234883914cc84dd412a3f600d3bfc09e364388c Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Mon, 27 Oct 2025 22:06:59 +0000 Subject: [PATCH 9/9] Fix SparseVector::insert(Index) assigning int to Scalar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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::Scalar’ {aka ‘ExplicitDouble’} and ‘int’) 180 | m_data.value(p + 1) = 0; | ~~~~~~~~~~~~~~~~~~~~^~~ ``` See merge request libeigen/eigen!2046 --- Eigen/src/SparseCore/SparseVector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/SparseCore/SparseVector.h b/Eigen/src/SparseCore/SparseVector.h index 8b34a9ac9..c8d34e318 100644 --- a/Eigen/src/SparseCore/SparseVector.h +++ b/Eigen/src/SparseCore/SparseVector.h @@ -177,7 +177,7 @@ class SparseVector : public SparseCompressedBase