Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e1c1d68
decompositions: Expose classes
Lucas-Haubert Jul 8, 2025
c6c9e72
Reordered test list in CMakeLists and module.cpp
Lucas-Haubert Jul 9, 2025
89d935d
module: Renamed and reorganized code
Lucas-Haubert Jul 10, 2025
cb43e0b
solvers: MINRES and BiCGSTAB
Lucas-Haubert Jul 10, 2025
ff4d280
tests: Fixed dim and removed seed
Lucas-Haubert Jul 11, 2025
31f3e12
Removed comments for EigenBase
Lucas-Haubert Jul 11, 2025
7fbcea1
module: Option Lower in IterativeLinearSolvers and preconditioner opt…
Lucas-Haubert Jul 11, 2025
d29e3b0
Removed useless includes
Lucas-Haubert Jul 11, 2025
686c02b
decompositions: Added setThreshold with default arg
Lucas-Haubert Jul 15, 2025
f3b3944
geometry: Expose classes
Lucas-Haubert Jul 16, 2025
64e5387
solvers: IncompleteLUT and IncompleteCholesky
Lucas-Haubert Jul 18, 2025
0564c5d
decompositions: FullPivLUand PartialPivLU: completed tests with permu…
Lucas-Haubert Jul 19, 2025
d04127b
geometry: Rotation2D: Added toRotationMatrix
Lucas-Haubert Jul 21, 2025
65537f6
Clean code: Management of prints, includes, arguments
Lucas-Haubert Jul 20, 2025
f958a9e
CI: Fix
Lucas-Haubert Jul 21, 2025
1e83941
is_approx: Remove the remaining np.allclose in tests and use nanoeige…
Lucas-Haubert Jul 21, 2025
2bd7c59
is_approx: Set precision as was proposed in eigenpy
Lucas-Haubert Jul 21, 2025
06b1ed3
is_approx: Set precision at 1e-9 for iterative solvers with dim = 100
Lucas-Haubert Jul 21, 2025
1ed6c91
const in lambdas: Use convention const ReturnType &arg
Lucas-Haubert Jul 22, 2025
b4835f5
SparseQR: Add matrixQ method
Lucas-Haubert Jul 22, 2025
c9a1abe
CI: Set prec 1e-9 to 1e-6 in iterative solvers
Lucas-Haubert Jul 22, 2025
3e38169
Set rows and cols in exposeMatrixQ with def and not prop
Lucas-Haubert Jul 23, 2025
54b6ee9
Add matrixU and matrixL in SparseLU
Lucas-Haubert Jul 23, 2025
6e9e640
SparseLU: Add adjoint and transpose in unit test
Lucas-Haubert Jul 24, 2025
bf345c3
Removed ill coded adjoint and transpose in SparseLU
Lucas-Haubert Jul 25, 2025
ea74840
Reduce computation time in unit tests
Lucas-Haubert Jul 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ target_include_directories(
)
target_link_libraries(nanoeigenpy_headers INTERFACE Eigen3::Eigen)

set(${PROJECT_NAME}_SOURCES src/module.cpp src/solvers.cpp)
set(${PROJECT_NAME}_SOURCES src/module.cpp)
nanobind_add_module(nanoeigenpy NB_STATIC NB_SUPPRESS_WARNINGS ${nanoeigenpy_SOURCES} ${nanoeigenpy_HEADERS})
target_link_libraries(nanoeigenpy PRIVATE nanoeigenpy_headers)

Expand Down
8 changes: 8 additions & 0 deletions include/nanoeigenpy/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ inline void exposeConstants(nb::module_ m) {
._c(Ax_lBx)
._c(ABx_lx)
._c(BAx_lx);
#undef _c
using Eigen::TransformTraits;
#define _c(name) value(#name, TransformTraits::name)
nb::enum_<TransformTraits>(m, "TransformTraits")
._c(Isometry)
._c(Affine)
._c(AffineCompact)
._c(Projective);
#undef _c
}
} // namespace nanoeigenpy
14 changes: 14 additions & 0 deletions include/nanoeigenpy/decompositions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,24 @@
#include "nanoeigenpy/decompositions/complete-orthogonal-decomposition.hpp"
#include "nanoeigenpy/decompositions/eigen-solver.hpp"
#include "nanoeigenpy/decompositions/self-adjoint-eigen-solver.hpp"
#include "nanoeigenpy/decompositions/generalized-self-adjoint-eigen-solver.hpp"
#include "nanoeigenpy/decompositions/complex-eigen-solver.hpp"
#include "nanoeigenpy/decompositions/complex-schur.hpp"
#include "nanoeigenpy/decompositions/generalized-eigen-solver.hpp"
#include "nanoeigenpy/decompositions/hessenberg-decomposition.hpp"
#include "nanoeigenpy/decompositions/real-qz.hpp"
#include "nanoeigenpy/decompositions/real-schur.hpp"
#include "nanoeigenpy/decompositions/tridiagonalization.hpp"
#include "nanoeigenpy/decompositions/permutation-matrix.hpp"
#include "nanoeigenpy/decompositions/full-piv-lu.hpp"
#include "nanoeigenpy/decompositions/partial-piv-lu.hpp"
#include "nanoeigenpy/decompositions/bdcsvd.hpp"
#include "nanoeigenpy/decompositions/jacobi-svd.hpp"

#include "nanoeigenpy/decompositions/sparse/simplicial-llt.hpp"
#include "nanoeigenpy/decompositions/sparse/simplicial-ldlt.hpp"
#include "nanoeigenpy/decompositions/sparse/sparse-lu.hpp"
#include "nanoeigenpy/decompositions/sparse/sparse-qr.hpp"

#ifdef NANOEIGENPY_HAS_CHOLMOD
#include "nanoeigenpy/decompositions/sparse/cholmod/cholmod-simplicial-llt.hpp"
Expand Down
89 changes: 89 additions & 0 deletions include/nanoeigenpy/decompositions/bdcsvd.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/// Copyright 2025 INRIA

#pragma once

#include "nanoeigenpy/fwd.hpp"
#include "nanoeigenpy/decompositions/svd-base.hpp"
#include <Eigen/SVD>

namespace nanoeigenpy {
namespace nb = nanobind;
using namespace nb::literals;

template <typename MatrixType, typename MatrixOrVector>
MatrixOrVector solve(const Eigen::BDCSVD<MatrixType> &c,
const MatrixOrVector &vec) {
return c.solve(vec);
}

template <typename _MatrixType>
void exposeBDCSVD(nb::module_ m, const char *name) {
using MatrixType = _MatrixType;
using Solver = Eigen::BDCSVD<MatrixType>;
using Scalar = typename MatrixType::Scalar;
using VectorType = Eigen::Matrix<Scalar, -1, 1>;

if (check_registration_alias<Solver>(m)) {
return;
}
nb::class_<Solver>(
m, name,
"Bidiagonal Divide and Conquer SVD. \n\n"
"This class first reduces the input matrix "
"to bi-diagonal form using class UpperBidiagonalization, "
"and then performs a divide-and-conquer diagonalization. "
"Small blocks are diagonalized using class JacobiSVD. You "
"can control the switching size with the setSwitchSize() "
"method, default is 16. For small matrice (<16), it is thus "
"preferable to directly use JacobiSVD. For larger ones, BDCSVD "
"is highly recommended and can several order of magnitude faster.")

.def(nb::init<>(), "Default constructor.")
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex, unsigned int>(),
"rows"_a, "cols"_a, "computationOptions"_a = 0,
"Default constructor with memory preallocation.")

.def(nb::init<const MatrixType &, unsigned int>(), "matrix"_a,
"computationOptions"_a = 0,
"Constructs a SVD factorization from a given matrix.")

.def(SVDBaseVisitor())

.def(
"compute",
[](Solver &c, const MatrixType &matrix) -> Solver & {
return c.compute(matrix);
},
"matrix"_a, "Computes the SVD of given matrix.",
nb::rv_policy::reference)
.def(
"compute",
[](Solver &c, const MatrixType &matrix, unsigned int) -> Solver & {
return c.compute(matrix);
},
"matrix"_a, "computationOptions"_a,
"Computes the SVD of given matrix.", nb::rv_policy::reference)

.def("setSwitchSize", &Solver::setSwitchSize, "s"_a)

.def(
"solve",
[](const Solver &c, const VectorType &b) -> VectorType {
return solve(c, b);
},
"b"_a,
"Returns the solution x of A x = b using the current "
"decomposition of A.")
.def(
"solve",
[](const Solver &c, const MatrixType &B) -> MatrixType {
return solve(c, B);
},
"B"_a,
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.")

.def(IdVisitor());
}

} // namespace nanoeigenpy
33 changes: 19 additions & 14 deletions include/nanoeigenpy/decompositions/col-piv-householder-qr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
#pragma once

#include "nanoeigenpy/fwd.hpp"
#include "nanoeigenpy/eigen-base.hpp"
#include <Eigen/QR>

namespace nanoeigenpy {
namespace nb = nanobind;
using namespace nb::literals;

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

template <typename _MatrixType>
void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
void exposeColPivHouseholderQR(nb::module_ m, const char *name) {
using MatrixType = _MatrixType;
using Solver = Eigen::ColPivHouseholderQR<MatrixType>;
using Scalar = typename MatrixType::Scalar;
Expand All @@ -48,12 +48,11 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
"The default constructor is useful in cases in which the "
"user intends to perform decompositions via "
"HouseholderQR.compute(matrix).")
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), nb::arg("rows"),
nb::arg("cols"),
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), "rows"_a, "cols"_a,
"Default constructor with memory preallocation.\n"
"Like the default constructor but with preallocation of the "
"internal data according to the specified problem size. ")
.def(nb::init<const MatrixType &>(), nb::arg("matrix"),
.def(nb::init<const MatrixType &>(), "matrix"_a,
"Constructs a QR factorization from a given matrix.\n"
"This constructor computes the QR factorization of the matrix "
"matrix by calling the method compute().")
Expand Down Expand Up @@ -128,10 +127,10 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {

.def(
"setThreshold",
[](Solver &c, RealScalar const &threshold) {
[](Solver &c, const RealScalar &threshold) {
return c.setThreshold(threshold);
},
nb::arg("threshold"),
"threshold"_a,
"Allows to prescribe a threshold to be used by certain methods, "
"such as rank(), who need to determine when pivots are to be "
"considered nonzero. This is not used for the QR decomposition "
Expand All @@ -147,6 +146,12 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {
"is strictly greater than |pivot| ⩽ threshold×|maxpivot| where "
"maxpivot is the biggest pivot.",
nb::rv_policy::reference)
.def(
"setThreshold",
[](Solver &c) { return c.setThreshold(Eigen::Default); },
"Allows to come back to the default behavior, letting Eigen use "
"its default formula for determining the threshold.",
nb::rv_policy::reference)
.def("threshold", &Solver::threshold,
"Returns the threshold that will be used by certain methods such "
"as rank().")
Expand All @@ -161,31 +166,31 @@ void exposeColPivHouseholderQRSolver(nb::module_ m, const char *name) {

.def(
"compute",
[](Solver &c, MatrixType const &matrix) -> Solver & {
[](Solver &c, const MatrixType &matrix) -> Solver & {
return c.compute(matrix);
},
nb::arg("matrix"), "Computes the QR factorization of given matrix.",
"matrix"_a, "Computes the QR factorization of given matrix.",
nb::rv_policy::reference)

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

.def(
"solve",
[](Solver const &c, VectorType const &b) -> VectorType {
[](const Solver &c, const VectorType &b) -> VectorType {
return solve(c, b);
},
nb::arg("b"),
"b"_a,
"Returns the solution x of A x = B using the current "
"decomposition of A where b is a right hand side vector.")
.def(
"solve",
[](Solver const &c, MatrixType const &B) -> MatrixType {
[](const Solver &c, const MatrixType &B) -> MatrixType {
return solve(c, B);
},
nb::arg("B"),
"B"_a,
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
#pragma once

#include "nanoeigenpy/fwd.hpp"
#include "nanoeigenpy/eigen-base.hpp"
#include <Eigen/QR>

namespace nanoeigenpy {
namespace nb = nanobind;
using namespace nb::literals;

template <typename MatrixType, typename MatrixOrVector>
MatrixOrVector solve(
Expand All @@ -23,8 +23,7 @@ MatrixType pseudoInverse(
}

template <typename _MatrixType>
void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
const char *name) {
void exposeCompleteOrthogonalDecomposition(nb::module_ m, const char *name) {
using MatrixType = _MatrixType;
using Solver = Eigen::CompleteOrthogonalDecomposition<MatrixType>;
using Scalar = typename MatrixType::Scalar;
Expand All @@ -50,12 +49,11 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
"The default constructor is useful in cases in which the "
"user intends to perform decompositions via "
"HouseholderQR.compute(matrix).")
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), nb::arg("rows"),
nb::arg("cols"),
.def(nb::init<Eigen::DenseIndex, Eigen::DenseIndex>(), "rows"_a, "cols"_a,
"Default constructor with memory preallocation.\n"
"Like the default constructor but with preallocation of the "
"internal data according to the specified problem size. ")
.def(nb::init<const MatrixType &>(), nb::arg("matrix"),
.def(nb::init<const MatrixType &>(), "matrix"_a,
"Constructs a QR factorization from a given matrix.\n"
"This constructor computes the QR factorization of the matrix "
"matrix by calling the method compute().")
Expand Down Expand Up @@ -137,10 +135,10 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,

.def(
"setThreshold",
[](Solver &c, RealScalar const &threshold) {
[](Solver &c, const RealScalar &threshold) {
return c.setThreshold(threshold);
},
nb::arg("threshold"),
"threshold"_a,
"Allows to prescribe a threshold to be used by certain methods, "
"such as rank(), who need to determine when pivots are to be "
"considered nonzero. This is not used for the complete "
Expand All @@ -158,6 +156,12 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,
"is strictly greater than |pivot| ⩽ threshold×|maxpivot| where "
"maxpivot is the biggest pivot.",
nb::rv_policy::reference)
.def(
"setThreshold",
[](Solver &c) { return c.setThreshold(Eigen::Default); },
"Allows to come back to the default behavior, letting Eigen use "
"its default formula for determining the threshold.",
nb::rv_policy::reference)
.def("threshold", &Solver::threshold,
"Returns the threshold that will be used by certain methods such "
"as rank().")
Expand All @@ -174,32 +178,32 @@ void exposeCompleteOrthogonalDecompositionSolver(nb::module_ m,

.def(
"compute",
[](Solver &c, MatrixType const &matrix) { return c.compute(matrix); },
nb::arg("matrix"),
[](Solver &c, const MatrixType &matrix) { return c.compute(matrix); },
"matrix"_a,
"Computes the complete orthogonal factorization of given matrix.",
nb::rv_policy::reference)

.def(
"pseudoInverse",
[](Solver const &c) -> MatrixType { return pseudoInverse(c); },
[](const Solver &c) -> MatrixType { return pseudoInverse(c); },
"Returns the pseudo-inverse of the matrix associated with the "
"complete orthogonal "
"decomposition.")

.def(
"solve",
[](Solver const &c, VectorType const &b) -> VectorType {
[](const Solver &c, const VectorType &b) -> VectorType {
return solve(c, b);
},
nb::arg("b"),
"b"_a,
"Returns the solution x of A x = B using the current "
"decomposition of A where b is a right hand side vector.")
.def(
"solve",
[](Solver const &c, MatrixType const &B) -> MatrixType {
[](const Solver &c, const MatrixType &B) -> MatrixType {
return solve(c, B);
},
nb::arg("B"),
"B"_a,
"Returns the solution X of A X = B using the current "
"decomposition of A where B is a right hand side matrix.")

Expand Down
Loading
Loading