From a64334c3ddbdd9ffd9f3b65a0b9c1e0d1d2b8c96 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Sun, 28 Sep 2025 19:16:32 +0200 Subject: [PATCH 1/5] decompositions/SparseLU: fix compatibility with Eigen 5+ --- include/eigenpy/decompositions/sparse/SparseLU.hpp | 6 ++++++ src/decompositions/sparse-lu-solver.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/eigenpy/decompositions/sparse/SparseLU.hpp b/include/eigenpy/decompositions/sparse/SparseLU.hpp index 045b3f44..3b7ed3af 100644 --- a/include/eigenpy/decompositions/sparse/SparseLU.hpp +++ b/include/eigenpy/decompositions/sparse/SparseLU.hpp @@ -98,8 +98,14 @@ struct SparseLUVisitor : public boost::python::def_visitor< typedef typename Solver::SCMatrix SCMatrix; typedef typename MatrixType::StorageIndex StorageIndex; + +#if EIGEN_VERSION_AT_LEAST(3, 4, 90) + typedef Eigen::Map> + MappedSparseMatrix; +#else typedef Eigen::MappedSparseMatrix MappedSparseMatrix; +#endif typedef Eigen::SparseLUMatrixLReturnType LType; typedef Eigen::SparseLUMatrixUReturnType UType; diff --git a/src/decompositions/sparse-lu-solver.cpp b/src/decompositions/sparse-lu-solver.cpp index 763a7559..44eca4fa 100644 --- a/src/decompositions/sparse-lu-solver.cpp +++ b/src/decompositions/sparse-lu-solver.cpp @@ -15,8 +15,14 @@ void exposeSparseLUSolver() { typedef typename SparseLUType::Scalar Scalar; typedef typename SparseLUType::SCMatrix SCMatrix; - typedef Eigen::MappedSparseMatrix + +#if EIGEN_VERSION_AT_LEAST(3, 4, 90) + typedef Eigen::Map> + MappedSparseMatrix; +#else + typedef Eigen::MappedSparseMatrix MappedSparseMatrix; +#endif SparseLUMatrixLReturnTypeVisitor::expose( ("SparseLUMatrixLReturnType")); From 2a4adb8af92eebd1dac321010db040797100b91d Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Sun, 28 Sep 2025 19:17:02 +0200 Subject: [PATCH 2/5] desompositions/SVD: fix compatibility with Eigen 5 --- include/eigenpy/decompositions/BDCSVD.hpp | 37 ++++++++++-------- include/eigenpy/decompositions/JacobiSVD.hpp | 40 +++++++++++--------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/include/eigenpy/decompositions/BDCSVD.hpp b/include/eigenpy/decompositions/BDCSVD.hpp index 9f9eb75e..564372df 100644 --- a/include/eigenpy/decompositions/BDCSVD.hpp +++ b/include/eigenpy/decompositions/BDCSVD.hpp @@ -35,22 +35,27 @@ struct BDCSVDVisitor .def("cols", &Solver::cols, bp::arg("self"), "Returns the number of columns. ") - .def("compute", - (Solver & (Solver::*)(const MatrixType &matrix)) & Solver::compute, - bp::args("self", "matrix"), - "Method performing the decomposition of given matrix. Computes " - "Thin/Full " - "unitaries U/V if specified using the Options template parameter " - "or the class constructor. ", - bp::return_self<>()) - .def("compute", - (Solver & (Solver::*)(const MatrixType &matrix, - unsigned int computationOptions)) & - Solver::compute, - bp::args("self", "matrix", "computationOptions"), - "Method performing the decomposition of given matrix, as " - "specified by the computationOptions parameter. ", - bp::return_self<>()) + .def( + "compute", + +[](Solver &self, const MatrixType &matrix) -> Solver & { + return self.compute(matrix); + }, + bp::args("self", "matrix"), + "Method performing the decomposition of given matrix. Computes " + "Thin/Full " + "unitaries U/V if specified using the Options template parameter " + "or the class constructor. ", + bp::return_self<>()) + .def( + "compute", + +[](Solver &self, const MatrixType &matrix, + unsigned int computationOptions) -> Solver & { + return self.compute(matrix, computationOptions); + }, + bp::args("self", "matrix", "computationOptions"), + "Method performing the decomposition of given matrix, as " + "specified by the computationOptions parameter. ", + bp::return_self<>()) .def("rows", &Solver::rows, bp::arg("self"), "Returns the number of rows. ") .def("setSwitchSize", &Solver::setSwitchSize, bp::args("self", "s")) diff --git a/include/eigenpy/decompositions/JacobiSVD.hpp b/include/eigenpy/decompositions/JacobiSVD.hpp index 1ea45ed1..3580f15a 100644 --- a/include/eigenpy/decompositions/JacobiSVD.hpp +++ b/include/eigenpy/decompositions/JacobiSVD.hpp @@ -18,7 +18,9 @@ namespace eigenpy { template struct JacobiSVDVisitor : public boost::python::def_visitor> { + typedef JacobiSVD Solver; typedef typename JacobiSVD::MatrixType MatrixType; + typedef Eigen::MatrixBase MatrixBaseType; typedef typename MatrixType::Scalar Scalar; template @@ -34,23 +36,27 @@ struct JacobiSVDVisitor .def("cols", &JacobiSVD::cols, bp::arg("self"), "Returns the number of columns. ") - .def("compute", - (JacobiSVD & (JacobiSVD::*)(const MatrixType &matrix)) & - JacobiSVD::compute, - bp::args("self", "matrix"), - "Method performing the decomposition of given matrix. Computes " - "Thin/Full " - "unitaries U/V if specified using the Options template parameter " - "or the class constructor. ", - bp::return_self<>()) - .def("compute", - (JacobiSVD & (JacobiSVD::*)(const MatrixType &matrix, - unsigned int computationOptions)) & - JacobiSVD::compute, - bp::args("self", "matrix", "computationOptions"), - "Method performing the decomposition of given matrix, as " - "specified by the computationOptions parameter. ", - bp::return_self<>()) + .def( + "compute", + +[](Solver &self, const MatrixType &matrix) -> Solver & { + return self.compute(matrix); + }, + bp::args("self", "matrix"), + "Method performing the decomposition of given matrix. Computes " + "Thin/Full " + "unitaries U/V if specified using the Options template parameter " + "or the class constructor. ", + bp::return_self<>()) + .def( + "compute", + +[](Solver &self, const MatrixType &matrix, + unsigned int computationOptions) -> Solver & { + return self.compute(matrix, computationOptions); + }, + bp::args("self", "matrix", "computation_options"), + "Method performing the decomposition of given matrix, as " + "specified by the computationOptions parameter. ", + bp::return_self<>()) .def("rows", &JacobiSVD::rows, bp::arg("self"), "Returns the number of rows.") From 3d33cf4c9e24a744b0ddf10a078042de4f472b4a Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Wed, 1 Oct 2025 08:49:19 +0200 Subject: [PATCH 3/5] changelog: sync --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebe0519e..e89b3114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - Fix partly the support of the change of API of GeneralizedEigenSolver in Eigen 5+ ([#594](https://github.com/stack-of-tasks/eigenpy/pull/594)) +- Fix Eigen decompositions and solvers for Eigen 5 ([#596](https://github.com/stack-of-tasks/eigenpy/pull/596)) ## [3.12.0] - 2025-08-12 From 09bd2f68a0b0c91311d2ee2593f2d44bae22efe9 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Fri, 3 Oct 2025 09:37:01 +0200 Subject: [PATCH 4/5] CI: switch Nix to eigen v5.0.0 --- flake.nix | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/flake.nix b/flake.nix index a0b48c61..c023f756 100644 --- a/flake.nix +++ b/flake.nix @@ -20,13 +20,16 @@ devShells.default = pkgs.mkShell { inputsFrom = [ self'.packages.default ]; }; packages = { default = self'.packages.eigenpy; - eigen = pkgs.eigen.overrideAttrs { - # Apply https://gitlab.com/libeigen/eigen/-/merge_requests/977 - postPatch = '' - substituteInPlace Eigen/src/SVD/BDCSVD.h \ - --replace-fail "if (l == 0) {" "if (i >= k && l == 0) {" - ''; - }; + # Test eigen v5 + eigen = pkgs.eigen.overrideAttrs (super: { + src = pkgs.fetchFromGitLab { + inherit (super.src) owner repo; + tag = "5.0.0"; + hash = "sha256-L1KUFZsaibC/FD6abTXrT3pvaFhbYnw+GaWsxM2gaxM="; + }; + patches = [ ]; + postPatch = ""; + }); eigenpy = (pkgs.python3Packages.eigenpy.override { inherit (self'.packages) eigen; }).overrideAttrs (_: { From e4a9c0daa26e5248f1768279b44f12b1ab5e2357 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Fri, 3 Oct 2025 11:06:10 +0200 Subject: [PATCH 5/5] Nix: eigen 3.4.1 + 5.0.0 --- .github/workflows/nix.yml | 3 ++- flake.nix | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 47437ec0..af3db8fd 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -16,6 +16,7 @@ jobs: fail-fast: false matrix: os: [ubuntu, macos] + eigen: [3, 5] steps: - uses: actions/checkout@v5 - uses: cachix/install-nix-action@v31 @@ -23,7 +24,7 @@ jobs: with: name: gepetto authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - run: nix build -L + - run: nix build -L ".#eigenpy-eigen${{ matrix.eigen }}" check: if: always() diff --git a/flake.nix b/flake.nix index c023f756..7d038298 100644 --- a/flake.nix +++ b/flake.nix @@ -19,19 +19,27 @@ }; devShells.default = pkgs.mkShell { inputsFrom = [ self'.packages.default ]; }; packages = { - default = self'.packages.eigenpy; - # Test eigen v5 - eigen = pkgs.eigen.overrideAttrs (super: { + default = self'.packages.eigenpy-eigen5; + eigen3 = pkgs.eigen.overrideAttrs (super: rec { + version = "3.4.1"; src = pkgs.fetchFromGitLab { inherit (super.src) owner repo; - tag = "5.0.0"; - hash = "sha256-L1KUFZsaibC/FD6abTXrT3pvaFhbYnw+GaWsxM2gaxM="; + tag = version; + hash = "sha256-NSq1tUfy2thz5gtsyASsKeYE4vMf71aSG4uXfrX86rk="; }; patches = [ ]; postPatch = ""; }); - eigenpy = - (pkgs.python3Packages.eigenpy.override { inherit (self'.packages) eigen; }).overrideAttrs + eigen5 = self'.packages.eigen3.overrideAttrs (super: rec { + version = "5.0.0"; + src = pkgs.fetchFromGitLab { + inherit (super.src) owner repo; + tag = version; + hash = "sha256-L1KUFZsaibC/FD6abTXrT3pvaFhbYnw+GaWsxM2gaxM="; + }; + }); + eigenpy-eigen3 = + (pkgs.python3Packages.eigenpy.override { eigen = self'.packages.eigen3; }).overrideAttrs (_: { src = pkgs.lib.fileset.toSource { root = ./.; @@ -46,6 +54,7 @@ ]; }; }); + eigenpy-eigen5 = self'.packages.eigenpy-eigen3.override { eigen = self'.packages.eigen5; }; }; }; };