Skip to content

Commit 25343da

Browse files
committed
sparse: add exposition of Accelerate solvers
This feature is only available on Mac OS X, with Eigen >= 3.4.90
1 parent aef9d5a commit 25343da

File tree

5 files changed

+164
-0
lines changed

5 files changed

+164
-0
lines changed

CMakeLists.txt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ option(GENERATE_PYTHON_STUBS
5858

5959
option(BUILD_WITH_CHOLMOD_SUPPORT "Build EigenPy with the Cholmod support" OFF)
6060

61+
if(APPLE)
62+
option(BUILD_WITH_ACCELERATE_SUPPORT
63+
"Build EigenPy with the Accelerate support" OFF)
64+
else(APPLE)
65+
set(BUILD_WITH_ACCELERATE_SUPPORT FALSE)
66+
endif(APPLE)
67+
6168
string(REPLACE "-pedantic" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
6269

6370
# If needed, fix CMake policy for APPLE systems
@@ -112,6 +119,24 @@ if(BUILD_WITH_CHOLMOD_SUPPORT)
112119
add_definitions(-DEIGENPY_WITH_CHOLMOD_SUPPORT)
113120
endif(BUILD_WITH_CHOLMOD_SUPPORT)
114121

122+
if(BUILD_WITH_ACCELERATE_SUPPORT)
123+
if(NOT ${Eigen3_VERSION} VERSION_GREATER_EQUAL "3.4.90")
124+
message(
125+
FATAL_ERROR
126+
"Your version of Eigen is too low. Should be at least 3.4.90. Current version is ${Eigen3_VERSION}."
127+
)
128+
endif()
129+
130+
set(CMAKE_MODULE_PATH ${JRL_CMAKE_MODULES}/find-external/Accelerate
131+
${CMAKE_MODULE_PATH})
132+
add_project_dependency(
133+
Accelerate REQUIRED # FIND_EXTERNAL "Accelerate" # We don't export yet as
134+
# there might be an issue on AMR64 platforms
135+
)
136+
message(STATUS "Build with Accelerate support framework.")
137+
add_definitions(-DEIGENPY_WITH_ACCELERATE_SUPPORT)
138+
endif(BUILD_WITH_ACCELERATE_SUPPORT)
139+
115140
# ----------------------------------------------------
116141
# --- INCLUDE ----------------------------------------
117142
# ----------------------------------------------------
@@ -139,6 +164,9 @@ set(${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_CHOLMOD_HEADERS
139164
include/eigenpy/decompositions/sparse/cholmod/CholmodSimplicialLLT.hpp
140165
include/eigenpy/decompositions/sparse/cholmod/CholmodSupernodalLLT.hpp)
141166

167+
set(${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_ACCELERATE_HEADERS
168+
include/eigenpy/decompositions/sparse/accelerate/accelerate.hpp)
169+
142170
set(${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_HEADERS
143171
include/eigenpy/decompositions/sparse/LLT.hpp
144172
include/eigenpy/decompositions/sparse/LDLT.hpp
@@ -150,6 +178,11 @@ if(BUILD_WITH_CHOLMOD_SUPPORT)
150178
${${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_CHOLMOD_HEADERS})
151179
endif(BUILD_WITH_CHOLMOD_SUPPORT)
152180

181+
if(BUILD_WITH_ACCELERATE_SUPPORT)
182+
list(APPEND ${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_HEADERS
183+
${${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_ACCELERATE_HEADERS})
184+
endif(BUILD_WITH_ACCELERATE_SUPPORT)
185+
153186
set(${PROJECT_NAME}_DECOMPOSITIONS_HEADERS
154187
${${PROJECT_NAME}_DECOMPOSITIONS_SPARSE_HEADERS}
155188
include/eigenpy/decompositions/decompositions.hpp
@@ -229,6 +262,11 @@ if(BUILD_WITH_CHOLMOD_SUPPORT)
229262
src/decompositions/cholmod.cpp)
230263
endif(BUILD_WITH_CHOLMOD_SUPPORT)
231264

265+
if(BUILD_WITH_ACCELERATE_SUPPORT)
266+
list(APPEND ${PROJECT_NAME}_DECOMPOSITIONS_SOURCES
267+
src/decompositions/accelerate.cpp)
268+
endif(BUILD_WITH_ACCELERATE_SUPPORT)
269+
232270
set(${PROJECT_NAME}_SOURCES
233271
${${PROJECT_NAME}_SOLVERS_SOURCES}
234272
${${PROJECT_NAME}_DECOMPOSITIONS_SOURCES}
@@ -280,10 +318,19 @@ modernize_target_link_libraries(
280318
${NUMPY_INCLUDE_DIRS}
281319
${PYTHON_INCLUDE_DIR})
282320

321+
# Links against CholMod
283322
if(BUILD_WITH_CHOLMOD_SUPPORT)
284323
modernize_target_link_libraries(${PROJECT_NAME} SCOPE PUBLIC TARGETS
285324
CHOLMOD::CHOLMOD)
286325
endif(BUILD_WITH_CHOLMOD_SUPPORT)
326+
327+
# Links against accelerate
328+
if(BUILD_WITH_ACCELERATE_SUPPORT)
329+
# modernize_target_link_libraries(${PROJECT_NAME} SCOPE PUBLIC TARGETS
330+
# Accelerate)
331+
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework accelerate")
332+
endif(BUILD_WITH_ACCELERATE_SUPPORT)
333+
287334
if(SUFFIX_SO_VERSION)
288335
set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
289336
endif(SUFFIX_SO_VERSION)

include/eigenpy/decompositions/decompositions.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ void EIGENPY_DLLAPI exposeDecompositions();
1414
void EIGENPY_DLLAPI exposeCholmod();
1515
#endif
1616

17+
#ifdef EIGENPY_WITH_ACCELERATE_SUPPORT
18+
void EIGENPY_DLLAPI exposeAccelerate();
19+
#endif
20+
1721
} // namespace eigenpy
1822

1923
#endif // define __eigenpy_decompositions_decompositions_hpp__
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2024 INRIA
3+
*/
4+
5+
#ifndef __eigenpy_decomposition_sparse_accelerate_accelerate_hpp__
6+
#define __eigenpy_decomposition_sparse_accelerate_accelerate_hpp__
7+
8+
#include "eigenpy/eigenpy.hpp"
9+
#include "eigenpy/eigen/EigenBase.hpp"
10+
#include "eigenpy/decompositions/sparse/SparseSolverBase.hpp"
11+
12+
#include <Eigen/AccelerateSupport>
13+
14+
namespace eigenpy {
15+
16+
template <typename AccelerateDerived>
17+
struct AccelerateImplVisitor : public boost::python::def_visitor<
18+
AccelerateImplVisitor<AccelerateDerived> > {
19+
typedef AccelerateDerived Solver;
20+
21+
typedef typename AccelerateDerived::MatrixType MatrixType;
22+
typedef typename MatrixType::Scalar Scalar;
23+
typedef typename MatrixType::RealScalar RealScalar;
24+
typedef MatrixType CholMatrixType;
25+
typedef typename MatrixType::StorageIndex StorageIndex;
26+
27+
template <class PyClass>
28+
void visit(PyClass &cl) const {
29+
cl
30+
31+
.def("analyzePattern", &Solver::analyzePattern,
32+
bp::args("self", "matrix"),
33+
"Performs a symbolic decomposition on the sparcity of matrix.\n"
34+
"This function is particularly useful when solving for several "
35+
"problems having the same structure.")
36+
37+
.def(EigenBaseVisitor<Solver>())
38+
.def(SparseSolverBaseVisitor<Solver>())
39+
40+
.def("compute",
41+
(Solver & (Solver::*)(const MatrixType &matrix)) & Solver::compute,
42+
bp::args("self", "matrix"),
43+
"Computes the sparse Cholesky decomposition of a given matrix.",
44+
bp::return_self<>())
45+
46+
.def("factorize", &Solver::factorize, bp::args("self", "matrix"),
47+
"Performs a numeric decomposition of a given matrix.\n"
48+
"The given matrix must has the same sparcity than the matrix on "
49+
"which the symbolic decomposition has been performed.\n"
50+
"See also analyzePattern().")
51+
52+
.def("info", &Solver::info, bp::arg("self"),
53+
"NumericalIssue if the input contains INF or NaN values or "
54+
"overflow occured. Returns Success otherwise.")
55+
56+
.def("setOrder", &Solver::setOrder, bp::arg("self"), "Set order");
57+
}
58+
59+
static void expose(const std::string &name, const std::string &doc = "") {
60+
bp::class_<Solver, boost::noncopyable>(name.c_str(), doc.c_str(),
61+
bp::no_init)
62+
.def(AccelerateImplVisitor())
63+
64+
.def(bp::init<>(bp::arg("self"), "Default constructor"))
65+
.def(bp::init<MatrixType>(bp::args("self", "matrix"),
66+
"Constructs and performs the "
67+
"factorization from a given matrix."));
68+
}
69+
};
70+
71+
} // namespace eigenpy
72+
73+
#endif // ifndef __eigenpy_decomposition_sparse_accelerate_accelerate_hpp__

src/decompositions/accelerate.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2024 INRIA
3+
*/
4+
5+
#include "eigenpy/fwd.hpp"
6+
#include "eigenpy/decompositions/decompositions.hpp"
7+
8+
#include "eigenpy/decompositions/sparse/accelerate/accelerate.hpp"
9+
10+
namespace eigenpy {
11+
12+
void exposeAccelerate() {
13+
using namespace Eigen;
14+
15+
typedef Eigen::SparseMatrix<double, Eigen::ColMajor> ColMajorSparseMatrix;
16+
// typedef Eigen::SparseMatrix<double,Eigen::RowMajor> RowMajorSparseMatrix;
17+
18+
bp::enum_<SparseOrder_t>("SparseOrder")
19+
.value("SparseOrderUser", SparseOrderUser)
20+
.value("SparseOrderAMD", SparseOrderAMD)
21+
.value("SparseOrderMetis", SparseOrderMetis)
22+
.value("SparseOrderCOLAMD", SparseOrderCOLAMD);
23+
24+
#define EXPOSE_ACCELERATE_DECOMPOSITION(name) \
25+
AccelerateImplVisitor<name<ColMajorSparseMatrix> >::expose( \
26+
EIGENPY_STRINGIZE(name))
27+
28+
EXPOSE_ACCELERATE_DECOMPOSITION(AccelerateLLT);
29+
EXPOSE_ACCELERATE_DECOMPOSITION(AccelerateLDLT);
30+
EXPOSE_ACCELERATE_DECOMPOSITION(AccelerateLDLTUnpivoted);
31+
EXPOSE_ACCELERATE_DECOMPOSITION(AccelerateLDLTSBK);
32+
EXPOSE_ACCELERATE_DECOMPOSITION(AccelerateLDLTTPP);
33+
EXPOSE_ACCELERATE_DECOMPOSITION(AccelerateQR);
34+
EXPOSE_ACCELERATE_DECOMPOSITION(AccelerateCholeskyAtA);
35+
}
36+
} // namespace eigenpy

src/decompositions/decompositions.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,9 @@ void exposeDecompositions() {
5252
#ifdef EIGENPY_WITH_CHOLMOD_SUPPORT
5353
exposeCholmod();
5454
#endif
55+
56+
#ifdef EIGENPY_WITH_ACCELERATE_SUPPORT
57+
exposeAccelerate();
58+
#endif
5559
}
5660
} // namespace eigenpy

0 commit comments

Comments
 (0)