diff --git a/CMakeLists.txt b/CMakeLists.txt
index fe859582faa995cff49c742fec3cfdc482f5e690..89d3ad7e784d46f4e150935828711a90623b6af1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -142,7 +142,8 @@ set(${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_CHOLMOD_HEADERS
 set(${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_HEADERS
     include/eigenpy/decompositions/sparse/LLT.hpp
     include/eigenpy/decompositions/sparse/LDLT.hpp
-    include/eigenpy/decompositions/sparse/SimplicialCholesky.hpp)
+    include/eigenpy/decompositions/sparse/SimplicialCholesky.hpp
+    include/eigenpy/decompositions/sparse/SparseSolverBase.hpp)
 
 if(BUILD_WITH_CHOLMOD_SUPPORT)
   list(APPEND ${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_HEADERS
diff --git a/include/eigenpy/decompositions/sparse/SimplicialCholesky.hpp b/include/eigenpy/decompositions/sparse/SimplicialCholesky.hpp
index 3bbdd18020b5f938bfbec6c3aea9ab57dbf4a3a3..ad109140b08eeb79e8705ce419086203bd6a6721 100644
--- a/include/eigenpy/decompositions/sparse/SimplicialCholesky.hpp
+++ b/include/eigenpy/decompositions/sparse/SimplicialCholesky.hpp
@@ -7,6 +7,7 @@
 
 #include "eigenpy/eigenpy.hpp"
 #include "eigenpy/eigen/EigenBase.hpp"
+#include "eigenpy/decompositions/sparse/SparseSolverBase.hpp"
 
 #include <Eigen/SparseCholesky>
 
@@ -37,6 +38,7 @@ struct SimplicialCholeskyVisitor
            "problems having the same structure.")
 
         .def(EigenBaseVisitor<Solver>())
+        .def(SparseSolverBaseVisitor<Solver>())
 
         .def("matrixL", &matrixL, bp::arg("self"),
              "Returns the lower triangular matrix L.")
@@ -74,33 +76,17 @@ struct SimplicialCholeskyVisitor
              "scale=1.",
              bp::return_self<>())
 
-        .def("solve", &solve<DenseVectorXs>, bp::args("self", "b"),
-             "Returns the solution x of A x = b using the current "
-             "decomposition of A.")
-        .def("solve", &solve<DenseMatrixXs>, bp::args("self", "B"),
-             "Returns the solution X of A X = B using the current "
-             "decomposition of A where B is a right hand side matrix.")
-
         .def("permutationP", &Solver::permutationP, bp::arg("self"),
              "Returns the permutation P.",
              bp::return_value_policy<bp::copy_const_reference>())
         .def("permutationPinv", &Solver::permutationPinv, bp::arg("self"),
              "Returns the inverse P^-1 of the permutation P.",
-             bp::return_value_policy<bp::copy_const_reference>())
-
-        .def("solve", &solve<MatrixType>, bp::args("self", "B"),
-             "Returns the solution X of A X = B using the current "
-             "decomposition of A where B is a right hand side matrix.");
+             bp::return_value_policy<bp::copy_const_reference>());
   }
 
  private:
   static MatrixType matrixL(const Solver &self) { return self.matrixL(); }
   static MatrixType matrixU(const Solver &self) { return self.matrixU(); }
-
-  template <typename MatrixOrVector>
-  static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
-    return self.solve(vec);
-  }
 };
 
 }  // namespace eigenpy
diff --git a/include/eigenpy/decompositions/sparse/SparseSolverBase.hpp b/include/eigenpy/decompositions/sparse/SparseSolverBase.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2afc1b917d1060ef037f5186f3b885f340cfc87d
--- /dev/null
+++ b/include/eigenpy/decompositions/sparse/SparseSolverBase.hpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2024 INRIA
+ */
+
+#ifndef __eigenpy_decomposition_sparse_sparse_solver_base_hpp__
+#define __eigenpy_decomposition_sparse_sparse_solver_base_hpp__
+
+#include "eigenpy/eigenpy.hpp"
+#include "eigenpy/eigen/EigenBase.hpp"
+
+#include <Eigen/SparseCholesky>
+
+namespace eigenpy {
+
+template <typename SimplicialDerived>
+struct SparseSolverBaseVisitor
+    : public boost::python::def_visitor<
+          SparseSolverBaseVisitor<SimplicialDerived> > {
+  typedef SimplicialDerived Solver;
+
+  typedef typename SimplicialDerived::MatrixType MatrixType;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+
+  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
+      DenseVectorXs;
+  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
+                        MatrixType::Options>
+      DenseMatrixXs;
+
+  template <class PyClass>
+  void visit(PyClass &cl) const {
+    cl.def("solve", &solve<DenseVectorXs>, bp::args("self", "b"),
+           "Returns the solution x of A x = b using the current "
+           "decomposition of A.")
+        .def("solve", &solve<DenseMatrixXs>, bp::args("self", "B"),
+             "Returns the solution X of A X = B using the current "
+             "decomposition of A where B is a right hand side matrix.")
+
+        .def("solve", &solve<MatrixType>, bp::args("self", "B"),
+             "Returns the solution X of A X = B using the current "
+             "decomposition of A where B is a right hand side matrix.");
+  }
+
+ private:
+  template <typename MatrixOrVector>
+  static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
+    return self.solve(vec);
+  }
+};
+
+}  // namespace eigenpy
+
+#endif  // ifndef __eigenpy_decomposition_sparse_sparse_solver_base_hpp__
diff --git a/include/eigenpy/decompositions/sparse/cholmod/CholmodBase.hpp b/include/eigenpy/decompositions/sparse/cholmod/CholmodBase.hpp
index bca0e7f19838cfc77eae9bc89a3cfefd14c6701c..9df15099ee9b361614d4fa576702ee6ec5412f9b 100644
--- a/include/eigenpy/decompositions/sparse/cholmod/CholmodBase.hpp
+++ b/include/eigenpy/decompositions/sparse/cholmod/CholmodBase.hpp
@@ -7,6 +7,7 @@
 
 #include "eigenpy/eigenpy.hpp"
 #include "eigenpy/eigen/EigenBase.hpp"
+#include "eigenpy/decompositions/sparse/SparseSolverBase.hpp"
 
 #include <Eigen/CholmodSupport>
 
@@ -23,12 +24,6 @@ struct CholmodBaseVisitor
   typedef MatrixType CholMatrixType;
   typedef typename MatrixType::StorageIndex StorageIndex;
 
-  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, MatrixType::Options>
-      DenseVectorXs;
-  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic,
-                        MatrixType::Options>
-      DenseMatrixXs;
-
   template <class PyClass>
   void visit(PyClass &cl) const {
     cl.def("analyzePattern", &Solver::analyzePattern,
@@ -38,6 +33,7 @@ struct CholmodBaseVisitor
            "problems having the same structure.")
 
         .def(EigenBaseVisitor<Solver>())
+        .def(SparseSolverBaseVisitor<Solver>())
 
         .def("compute",
              (Solver & (Solver::*)(const MatrixType &matrix)) & Solver::compute,
@@ -70,24 +66,7 @@ struct CholmodBaseVisitor
              "are transformed by the following linear model: d_ii = offset + "
              "d_ii.\n"
              "The default is the identity transformation with offset=0.",
-             bp::return_self<>())
-
-        .def("solve", &solve<DenseVectorXs>, bp::args("self", "b"),
-             "Returns the solution x of A x = b using the current "
-             "decomposition of A.")
-        .def("solve", &solve<DenseMatrixXs>, bp::args("self", "B"),
-             "Returns the solution X of A X = B using the current "
-             "decomposition of A where B is a right hand side matrix.")
-
-        .def("solve", &solve<MatrixType>, bp::args("self", "B"),
-             "Returns the solution X of A X = B using the current "
-             "decomposition of A where B is a right hand side matrix.");
-  }
-
- private:
-  template <typename MatrixOrVector>
-  static MatrixOrVector solve(const Solver &self, const MatrixOrVector &vec) {
-    return self.solve(vec);
+             bp::return_self<>());
   }
 };