Skip to content

Commit 87ca9ff

Browse files
authored
Merge pull request #13 from Lucas-Haubert/topic/expose
Expose additional classes from Eigen (decompositions, solvers, geometry)
2 parents 1948bb9 + ea74840 commit 87ca9ff

File tree

87 files changed

+4728
-356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+4728
-356
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ target_include_directories(
131131
)
132132
target_link_libraries(nanoeigenpy_headers INTERFACE Eigen3::Eigen)
133133

134-
set(${PROJECT_NAME}_SOURCES src/module.cpp src/solvers.cpp)
134+
set(${PROJECT_NAME}_SOURCES src/module.cpp)
135135
nanobind_add_module(nanoeigenpy NB_STATIC NB_SUPPRESS_WARNINGS ${nanoeigenpy_SOURCES} ${nanoeigenpy_HEADERS})
136136
target_link_libraries(nanoeigenpy PRIVATE nanoeigenpy_headers)
137137

include/nanoeigenpy/constants.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ inline void exposeConstants(nb::module_ m) {
3030
._c(Ax_lBx)
3131
._c(ABx_lx)
3232
._c(BAx_lx);
33+
#undef _c
34+
using Eigen::TransformTraits;
35+
#define _c(name) value(#name, TransformTraits::name)
36+
nb::enum_<TransformTraits>(m, "TransformTraits")
37+
._c(Isometry)
38+
._c(Affine)
39+
._c(AffineCompact)
40+
._c(Projective);
3341
#undef _c
3442
}
3543
} // namespace nanoeigenpy

include/nanoeigenpy/decompositions.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,24 @@
1010
#include "nanoeigenpy/decompositions/complete-orthogonal-decomposition.hpp"
1111
#include "nanoeigenpy/decompositions/eigen-solver.hpp"
1212
#include "nanoeigenpy/decompositions/self-adjoint-eigen-solver.hpp"
13+
#include "nanoeigenpy/decompositions/generalized-self-adjoint-eigen-solver.hpp"
14+
#include "nanoeigenpy/decompositions/complex-eigen-solver.hpp"
15+
#include "nanoeigenpy/decompositions/complex-schur.hpp"
16+
#include "nanoeigenpy/decompositions/generalized-eigen-solver.hpp"
17+
#include "nanoeigenpy/decompositions/hessenberg-decomposition.hpp"
18+
#include "nanoeigenpy/decompositions/real-qz.hpp"
19+
#include "nanoeigenpy/decompositions/real-schur.hpp"
20+
#include "nanoeigenpy/decompositions/tridiagonalization.hpp"
1321
#include "nanoeigenpy/decompositions/permutation-matrix.hpp"
22+
#include "nanoeigenpy/decompositions/full-piv-lu.hpp"
23+
#include "nanoeigenpy/decompositions/partial-piv-lu.hpp"
24+
#include "nanoeigenpy/decompositions/bdcsvd.hpp"
25+
#include "nanoeigenpy/decompositions/jacobi-svd.hpp"
1426

1527
#include "nanoeigenpy/decompositions/sparse/simplicial-llt.hpp"
1628
#include "nanoeigenpy/decompositions/sparse/simplicial-ldlt.hpp"
29+
#include "nanoeigenpy/decompositions/sparse/sparse-lu.hpp"
30+
#include "nanoeigenpy/decompositions/sparse/sparse-qr.hpp"
1731

1832
#ifdef NANOEIGENPY_HAS_CHOLMOD
1933
#include "nanoeigenpy/decompositions/sparse/cholmod/cholmod-simplicial-llt.hpp"
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/// Copyright 2025 INRIA
2+
3+
#pragma once
4+
5+
#include "nanoeigenpy/fwd.hpp"
6+
#include "nanoeigenpy/decompositions/svd-base.hpp"
7+
#include <Eigen/SVD>
8+
9+
namespace nanoeigenpy {
10+
namespace nb = nanobind;
11+
using namespace nb::literals;
12+
13+
template <typename MatrixType, typename MatrixOrVector>
14+
MatrixOrVector solve(const Eigen::BDCSVD<MatrixType> &c,
15+
const MatrixOrVector &vec) {
16+
return c.solve(vec);
17+
}
18+
19+
template <typename _MatrixType>
20+
void exposeBDCSVD(nb::module_ m, const char *name) {
21+
using MatrixType = _MatrixType;
22+
using Solver = Eigen::BDCSVD<MatrixType>;
23+
using Scalar = typename MatrixType::Scalar;
24+
using VectorType = Eigen::Matrix<Scalar, -1, 1>;
25+
26+
if (check_registration_alias<Solver>(m)) {
27+
return;
28+
}
29+
nb::class_<Solver>(
30+
m, name,
31+
"Bidiagonal Divide and Conquer SVD. \n\n"
32+
"This class first reduces the input matrix "
33+
"to bi-diagonal form using class UpperBidiagonalization, "
34+
"and then performs a divide-and-conquer diagonalization. "
35+
"Small blocks are diagonalized using class JacobiSVD. You "
36+
"can control the switching size with the setSwitchSize() "
37+
"method, default is 16. For small matrice (<16), it is thus "
38+
"preferable to directly use JacobiSVD. For larger ones, BDCSVD "
39+
"is highly recommended and can several order of magnitude faster.")
40+
41+
.def(nb::init<>(), "Default constructor.")
42+
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex, unsigned int>(),
43+
"rows"_a, "cols"_a, "computationOptions"_a = 0,
44+
"Default constructor with memory preallocation.")
45+
46+
.def(nb::init<const MatrixType &, unsigned int>(), "matrix"_a,
47+
"computationOptions"_a = 0,
48+
"Constructs a SVD factorization from a given matrix.")
49+
50+
.def(SVDBaseVisitor())
51+
52+
.def(
53+
"compute",
54+
[](Solver &c, const MatrixType &matrix) -> Solver & {
55+
return c.compute(matrix);
56+
},
57+
"matrix"_a, "Computes the SVD of given matrix.",
58+
nb::rv_policy::reference)
59+
.def(
60+
"compute",
61+
[](Solver &c, const MatrixType &matrix, unsigned int) -> Solver & {
62+
return c.compute(matrix);
63+
},
64+
"matrix"_a, "computationOptions"_a,
65+
"Computes the SVD of given matrix.", nb::rv_policy::reference)
66+
67+
.def("setSwitchSize", &Solver::setSwitchSize, "s"_a)
68+
69+
.def(
70+
"solve",
71+
[](const Solver &c, const VectorType &b) -> VectorType {
72+
return solve(c, b);
73+
},
74+
"b"_a,
75+
"Returns the solution x of A x = b using the current "
76+
"decomposition of A.")
77+
.def(
78+
"solve",
79+
[](const Solver &c, const MatrixType &B) -> MatrixType {
80+
return solve(c, B);
81+
},
82+
"B"_a,
83+
"Returns the solution X of A X = B using the current "
84+
"decomposition of A where B is a right hand side matrix.")
85+
86+
.def(IdVisitor());
87+
}
88+
89+
} // namespace nanoeigenpy

include/nanoeigenpy/decompositions/col-piv-householder-qr.hpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
#pragma once
44

55
#include "nanoeigenpy/fwd.hpp"
6-
#include "nanoeigenpy/eigen-base.hpp"
76
#include <Eigen/QR>
87

98
namespace nanoeigenpy {
109
namespace nb = nanobind;
10+
using namespace nb::literals;
1111

1212
template <typename MatrixType, typename MatrixOrVector>
1313
MatrixOrVector solve(const Eigen::ColPivHouseholderQR<MatrixType> &c,
@@ -21,7 +21,7 @@ MatrixType inverse(const Eigen::ColPivHouseholderQR<MatrixType> &c) {
2121
}
2222

2323
template <typename _MatrixType>
24-
void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
24+
void exposeColPivHouseholderQR(nb::module_ m, const char *name) {
2525
using MatrixType = _MatrixType;
2626
using Solver = Eigen::ColPivHouseholderQR<MatrixType>;
2727
using Scalar = typename MatrixType::Scalar;
@@ -48,12 +48,11 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
4848
"The default constructor is useful in cases in which the "
4949
"user intends to perform decompositions via "
5050
"HouseholderQR.compute(matrix).")
51-
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), nb::arg("rows"),
52-
nb::arg("cols"),
51+
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), "rows"_a, "cols"_a,
5352
"Default constructor with memory preallocation.\n"
5453
"Like the default constructor but with preallocation of the "
5554
"internal data according to the specified problem size. ")
56-
.def(nb::init<const MatrixType &>(), nb::arg("matrix"),
55+
.def(nb::init<const MatrixType &>(), "matrix"_a,
5756
"Constructs a QR factorization from a given matrix.\n"
5857
"This constructor computes the QR factorization of the matrix "
5958
"matrix by calling the method compute().")
@@ -128,10 +127,10 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
128127

129128
.def(
130129
"setThreshold",
131-
[](Solver &c, RealScalar const &threshold) {
130+
[](Solver &c, const RealScalar &threshold) {
132131
return c.setThreshold(threshold);
133132
},
134-
nb::arg("threshold"),
133+
"threshold"_a,
135134
"Allows to prescribe a threshold to be used by certain methods, "
136135
"such as rank(), who need to determine when pivots are to be "
137136
"considered nonzero. This is not used for the QR decomposition "
@@ -147,6 +146,12 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
147146
"is strictly greater than |pivot| ⩽ threshold×|maxpivot| where "
148147
"maxpivot is the biggest pivot.",
149148
nb::rv_policy::reference)
149+
.def(
150+
"setThreshold",
151+
[](Solver &c) { return c.setThreshold(Eigen::Default); },
152+
"Allows to come back to the default behavior, letting Eigen use "
153+
"its default formula for determining the threshold.",
154+
nb::rv_policy::reference)
150155
.def("threshold", &Solver::threshold,
151156
"Returns the threshold that will be used by certain methods such "
152157
"as rank().")
@@ -161,31 +166,31 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
161166

162167
.def(
163168
"compute",
164-
[](Solver &c, MatrixType const &matrix) -> Solver & {
169+
[](Solver &c, const MatrixType &matrix) -> Solver & {
165170
return c.compute(matrix);
166171
},
167-
nb::arg("matrix"), "Computes the QR factorization of given matrix.",
172+
"matrix"_a, "Computes the QR factorization of given matrix.",
168173
nb::rv_policy::reference)
169174

170175
.def(
171-
"inverse", [](Solver const &c) -> MatrixType { return inverse(c); },
176+
"inverse", [](const Solver &c) -> MatrixType { return inverse(c); },
172177
"Returns the inverse of the matrix associated with the QR "
173178
"decomposition.")
174179

175180
.def(
176181
"solve",
177-
[](Solver const &c, VectorType const &b) -> VectorType {
182+
[](const Solver &c, const VectorType &b) -> VectorType {
178183
return solve(c, b);
179184
},
180-
nb::arg("b"),
185+
"b"_a,
181186
"Returns the solution x of A x = B using the current "
182187
"decomposition of A where b is a right hand side vector.")
183188
.def(
184189
"solve",
185-
[](Solver const &c, MatrixType const &B) -> MatrixType {
190+
[](const Solver &c, const MatrixType &B) -> MatrixType {
186191
return solve(c, B);
187192
},
188-
nb::arg("B"),
193+
"B"_a,
189194
"Returns the solution X of A X = B using the current "
190195
"decomposition of A where B is a right hand side matrix.")
191196

include/nanoeigenpy/decompositions/complete-orthogonal-decomposition.hpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
#pragma once
44

55
#include "nanoeigenpy/fwd.hpp"
6-
#include "nanoeigenpy/eigen-base.hpp"
76
#include <Eigen/QR>
87

98
namespace nanoeigenpy {
109
namespace nb = nanobind;
10+
using namespace nb::literals;
1111

1212
template <typename MatrixType, typename MatrixOrVector>
1313
MatrixOrVector solve(
@@ -23,8 +23,7 @@ MatrixType pseudoInverse(
2323
}
2424

2525
template <typename _MatrixType>
26-
void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
27-
const char *name) {
26+
void exposeCompleteOrthogonalDecomposition(nb::module_ m, const char *name) {
2827
using MatrixType = _MatrixType;
2928
using Solver = Eigen::CompleteOrthogonalDecomposition<MatrixType>;
3029
using Scalar = typename MatrixType::Scalar;
@@ -50,12 +49,11 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
5049
"The default constructor is useful in cases in which the "
5150
"user intends to perform decompositions via "
5251
"HouseholderQR.compute(matrix).")
53-
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), nb::arg("rows"),
54-
nb::arg("cols"),
52+
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), "rows"_a, "cols"_a,
5553
"Default constructor with memory preallocation.\n"
5654
"Like the default constructor but with preallocation of the "
5755
"internal data according to the specified problem size. ")
58-
.def(nb::init<const MatrixType &>(), nb::arg("matrix"),
56+
.def(nb::init<const MatrixType &>(), "matrix"_a,
5957
"Constructs a QR factorization from a given matrix.\n"
6058
"This constructor computes the QR factorization of the matrix "
6159
"matrix by calling the method compute().")
@@ -137,10 +135,10 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
137135

138136
.def(
139137
"setThreshold",
140-
[](Solver &c, RealScalar const &threshold) {
138+
[](Solver &c, const RealScalar &threshold) {
141139
return c.setThreshold(threshold);
142140
},
143-
nb::arg("threshold"),
141+
"threshold"_a,
144142
"Allows to prescribe a threshold to be used by certain methods, "
145143
"such as rank(), who need to determine when pivots are to be "
146144
"considered nonzero. This is not used for the complete "
@@ -158,6 +156,12 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
158156
"is strictly greater than |pivot| ⩽ threshold×|maxpivot| where "
159157
"maxpivot is the biggest pivot.",
160158
nb::rv_policy::reference)
159+
.def(
160+
"setThreshold",
161+
[](Solver &c) { return c.setThreshold(Eigen::Default); },
162+
"Allows to come back to the default behavior, letting Eigen use "
163+
"its default formula for determining the threshold.",
164+
nb::rv_policy::reference)
161165
.def("threshold", &Solver::threshold,
162166
"Returns the threshold that will be used by certain methods such "
163167
"as rank().")
@@ -174,32 +178,32 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
174178

175179
.def(
176180
"compute",
177-
[](Solver &c, MatrixType const &matrix) { return c.compute(matrix); },
178-
nb::arg("matrix"),
181+
[](Solver &c, const MatrixType &matrix) { return c.compute(matrix); },
182+
"matrix"_a,
179183
"Computes the complete orthogonal factorization of given matrix.",
180184
nb::rv_policy::reference)
181185

182186
.def(
183187
"pseudoInverse",
184-
[](Solver const &c) -> MatrixType { return pseudoInverse(c); },
188+
[](const Solver &c) -> MatrixType { return pseudoInverse(c); },
185189
"Returns the pseudo-inverse of the matrix associated with the "
186190
"complete orthogonal "
187191
"decomposition.")
188192

189193
.def(
190194
"solve",
191-
[](Solver const &c, VectorType const &b) -> VectorType {
195+
[](const Solver &c, const VectorType &b) -> VectorType {
192196
return solve(c, b);
193197
},
194-
nb::arg("b"),
198+
"b"_a,
195199
"Returns the solution x of A x = B using the current "
196200
"decomposition of A where b is a right hand side vector.")
197201
.def(
198202
"solve",
199-
[](Solver const &c, MatrixType const &B) -> MatrixType {
203+
[](const Solver &c, const MatrixType &B) -> MatrixType {
200204
return solve(c, B);
201205
},
202-
nb::arg("B"),
206+
"B"_a,
203207
"Returns the solution X of A X = B using the current "
204208
"decomposition of A where B is a right hand side matrix.")
205209

0 commit comments

Comments
 (0)