diff --git a/src/core/matrices/codac2_Inversion.cpp b/src/core/matrices/codac2_Inversion.cpp index aa8044e42..568d68c26 100644 --- a/src/core/matrices/codac2_Inversion.cpp +++ b/src/core/matrices/codac2_Inversion.cpp @@ -16,11 +16,6 @@ using namespace std; namespace codac2 { - /** \brief Compute an upper bound of A+A^2+A^3 with A a matrix of intervals - * \param A matrix of intervals (supposed around 0) - * \param mrad the maximum radius of the result added (output argument, not available in Python) - * \return the enclosure. May include (-oo,oo) - */ IntervalMatrix infinite_sum_enclosure(const IntervalMatrix& A, double &mrad) { assert_release(A.is_squared()); Index N = A.rows(); @@ -70,12 +65,6 @@ namespace codac2 return res; } - - /** \brief Enclosure of the inverse of a matrix of intervals - * \param A matrix of intervals - * \return the enclosure. Can have (-oo,oo) coefficients if the - * inversion "failed" - */ IntervalMatrix inverse_enclosure(const IntervalMatrix &A) { assert_release(A.is_squared()); Index N=A.rows(); diff --git a/src/core/matrices/codac2_Inversion.h b/src/core/matrices/codac2_Inversion.h index de4bfa2f2..eca2c2ba6 100644 --- a/src/core/matrices/codac2_Inversion.h +++ b/src/core/matrices/codac2_Inversion.h @@ -17,35 +17,46 @@ namespace codac2 { enum LeftOrRightInv { LEFT_INV, RIGHT_INV }; - /** \brief Compute an upper bound of A+A^2+A^3 with A a matrix of intervals + /** \brief Compute an upper bound of A+A^2+A^3+..., with A a matrix of intervals * as an "error term" (use only bounds on coefficients) - * \param A matrix of intervals (supposed around 0) + * + * The function also returns mrad, which gives an idea of the “magnification” of + * the matrix during calculation (in particular, if mrad = oo, then the inversion + * calculation (e.g., performed by Eigen) has somehow failed and some coefficients + * of the output interval matrix are [-oo,+oo]). + * + * \pre A is a square matrix + * + * \param A a matrix of intervals (supposed around 0) * \param mrad the maximum radius of the result added (output argument) * \return the enclosure. May include (-oo,oo) */ IntervalMatrix infinite_sum_enclosure(const IntervalMatrix& A, double &mrad); /** \brief Correct the approximate inverse of a matrix + * + * \pre A and B are square matrices + * * \tparam O if LEFT_INV, use the inverse of BA (otherwise use the inverse of AB, * left inverse is normally better) - * \param A_ a matrix expression - * \param B_ a (almost punctual) approximation of its inverse, + * \param A a matrix expression + * \param B a (almost punctual) approximation of its inverse, * \return the enclosure */ template - inline IntervalMatrix inverse_correction(const Eigen::MatrixBase& A_, const Eigen::MatrixBase& B_) + inline IntervalMatrix inverse_correction(const Eigen::MatrixBase& A, const Eigen::MatrixBase& B) { - assert_release(A_.is_squared()); - assert_release(B_.is_squared()); + assert_release(A.is_squared()); + assert_release(B.is_squared()); - auto A = A_.template cast(); - auto B = B_.template cast(); + auto A_ = A.template cast(); + auto B_ = B.template cast(); - Index N = A.rows(); - assert_release(N==B.rows()); + Index N = A_.rows(); + assert_release(N==B_.rows()); auto Id = IntervalMatrix::Identity(N,N); - auto erMat = [&]() { if constexpr(O == LEFT_INV) return -B*A+Id; else return -A*B+Id; }(); + auto erMat = [&]() { if constexpr(O == LEFT_INV) return -B_*A_+Id; else return -A_*B_+Id; }(); double mrad=0.0; IntervalMatrix E = infinite_sum_enclosure(erMat,mrad); @@ -53,10 +64,10 @@ namespace codac2 /* one could use several iterations here, either using mrad, or directly */ - auto res = (O == LEFT_INV) ? IntervalMatrix(Ep*B) : IntervalMatrix(B*Ep); + auto res = (O == LEFT_INV) ? IntervalMatrix(Ep*B_) : IntervalMatrix(B_*Ep); - /* small problem with the matrix product : 0*oo = 0. We correct that - "by hand" (?) */ + // We want the presence of non-invertible matrices to + // result in coefficients of the form [-oo,+oo]. if (mrad==oo) { for (Index c=0;c