66namespace nanoeigenpy {
77namespace nb = nanobind;
88
9+ template <typename MatrixType, typename MatrixOrVector>
10+ MatrixOrVector solve (const Eigen::LDLT<MatrixType> &c, const MatrixOrVector &vec) {
11+ return c.solve (vec);
12+ }
13+
914template <typename MatrixType>
1015void exposeLDLTSolver (nb::module_ m, const char *name) {
1116 using Solver = Eigen::LDLT<MatrixType>;
1217 using Scalar = typename MatrixType::Scalar;
1318 using VectorType = Eigen::Matrix<Scalar, -1 , 1 >;
14- auto cl = nb::class_<Solver>(m, name)
15- .def (nb::init<const MatrixType &>(), nb::arg (" matrix" ))
16- .def (nb::init<Eigen::DenseIndex>(), nb::arg (" size" ))
19+ auto cl = nb::class_<Solver>(m, name,
20+ " Robust Cholesky decomposition of a matrix with pivoting.\n\n "
21+ " Perform a robust Cholesky decomposition of a positive semidefinite or "
22+ " negative semidefinite matrix $ A $ such that $ A = P^TLDL^*P $, where "
23+ " P is a permutation matrix, L is lower triangular with a unit diagonal "
24+ " and D is a diagonal matrix.\n\n "
25+ " The decomposition uses pivoting to ensure stability, so that L will "
26+ " have zeros in the bottom right rank(A) - n submatrix. Avoiding the "
27+ " square root on D also stabilizes the computation." )
28+
29+ .def (nb::init<>(),
30+ " Default constructor." )
31+ .def (nb::init<Eigen::DenseIndex>(), nb::arg (" size" ),
32+ " Default constructor with memory preallocation." )
33+ .def (nb::init<const MatrixType &>(), nb::arg (" matrix" ),
34+ " Constructs a LLT factorization from a given matrix." )
35+
1736 .def (EigenBaseVisitor ())
18- .def (" isNegative" , &Solver::isNegative)
19- .def (" isPositive" , &Solver::isPositive)
37+
38+ .def (" isNegative" , &Solver::isNegative,
39+ " Returns true if the matrix is negative (semidefinite)." )
40+ .def (" isPositive" , &Solver::isPositive,
41+ " Returns true if the matrix is positive (semidefinite)." )
42+
2043 .def (" matrixL" ,
21- [](Solver const &c) -> MatrixType { return c.matrixL (); })
44+ [](Solver const &c) -> MatrixType { return c.matrixL (); },
45+ " Returns the lower triangular matrix L." )
2246 .def (" matrixU" ,
23- [](Solver const &c) -> MatrixType { return c.matrixU (); })
47+ [](Solver const &c) -> MatrixType { return c.matrixU (); },
48+ " Returns the upper triangular matrix U." )
2449 .def (" vectorD" ,
25- [](Solver const &c) -> VectorType { return c.vectorD (); })
50+ [](Solver const &c) -> VectorType { return c.vectorD (); },
51+ " Returns the coefficients of the diagonal matrix D." )
2652 .def (" matrixLDLT" , &Solver::matrixLDLT,
53+ " Returns the LDLT decomposition matrix." ,
2754 nb::rv_policy::reference_internal)
28- .def (
29- " rankUpdate" ,
55+
56+ .def (" transpositionsP" ,
57+ [](Solver const &c) -> MatrixType { return c.transpositionsP () *
58+ MatrixType::Identity (c.matrixL ().rows (), c.matrixL ().rows ()); },
59+ " Returns the permutation matrix P." )
60+
61+ .def (" rankUpdate" ,
3062 [](Solver &c, VectorType const &w, Scalar sigma) {
3163 return c.rankUpdate (w, sigma);
3264 },
33- nb::arg (" w" ), nb::arg (" sigma" ));
65+ nb::arg (" w" ), nb::arg (" sigma" ))
66+
67+ #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
68+ .def (" adjoint" , &Solver::adjoint,
69+ " Returns the adjoint, that is, a reference to the decomposition "
70+ " itself as if the underlying matrix is self-adjoint." ,
71+ nb::rv_policy::reference)
72+ #endif
73+
74+ .def (" compute" ,
75+ [](Solver &c, VectorType const &matrix) {
76+ return c.compute (matrix);
77+ },
78+ nb::arg (" matrix" ),
79+ " Computes the LDLT of given matrix." ,
80+ nb::rv_policy::reference)
81+ .def (" info" , &Solver::info,
82+ " NumericalIssue if the input contains INF or NaN values or "
83+ " overflow occured. Returns Success otherwise." )
84+
85+ #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
86+ .def (" rcond" , &Solver::rcond,
87+ " Returns an estimate of the reciprocal condition number of the "
88+ " matrix." )
89+ #endif
90+
91+ .def (" reconstructedMatrix" , &Solver::reconstructedMatrix,
92+ " Returns the matrix represented by the decomposition, i.e., it "
93+ " returns the product: L L^*. This function is provided for debug "
94+ " purpose." )
95+
96+ .def (" solve" ,
97+ [](Solver const &c, VectorType const &b) -> VectorType { return solve (c, b); },
98+ nb::arg (" b" ),
99+ " Returns the solution x of A x = b using the current "
100+ " decomposition of A." )
101+ .def (" solve" ,
102+ [](Solver const &c, MatrixType const &B) -> MatrixType { return solve (c, B); },
103+ nb::arg (" B" ),
104+ " Returns the solution X of A X = B using the current "
105+ " decomposition of A where B is a right hand side matrix." )
106+
107+ .def (" setZero" , &Solver::setZero,
108+ " Clear any existing decomposition." )
109+
110+ .def (" id" ,
111+ [](Solver const &c) -> int64_t { return reinterpret_cast <int64_t >(&c); },
112+ " Returns the unique identity of an object.\n "
113+ " For objects held in C++, it corresponds to its memory address." );
114+
34115}
35116
36117} // namespace nanoeigenpy
118+
119+
120+ // TODO
121+
122+ // Tests that were not done in eigenpy that we could add in nanoeigenpy: (+ those cited in llt.hpp)
123+ // setZero
124+
125+ // Expose supplementary content:
126+ // setZero in LLT decomp too ? (not done in eigenpy)
127+
128+ // Questions about eigenpy itself:
129+ // Relevant to have the reconstructedMatrix method ? (knowing that we are on LDLT, not LLT)
0 commit comments