99 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
| /**
 | |
|  * @file    Matrix-inl.h
 | |
|  * @brief   
 | |
|  * @author  Richard Roberts
 | |
|  * @created Sep 26, 2010
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <gtsam/base/Matrix.h>
 | |
| 
 | |
| #include <iostream>
 | |
| 
 | |
| namespace gtsam {
 | |
| 
 | |
| using namespace std;
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| /**
 | |
|  * backSubstitute U*x=b
 | |
|  * @param U an upper triangular matrix
 | |
|  * @param b an RHS vector
 | |
|  * @return the solution x of U*x=b
 | |
|  */
 | |
| template<class MatrixAE, class VectorAE>
 | |
| Vector backSubstituteUpper(const boost::numeric::ublas::matrix_expression<MatrixAE>& _U,
 | |
|     const boost::numeric::ublas::vector_expression<VectorAE>& _b, bool unit=false) {
 | |
|   const MatrixAE& U((const MatrixAE&)_U);
 | |
|   const VectorAE& b((const VectorAE&)_b);
 | |
|   size_t n = U.size2();
 | |
| #ifndef NDEBUG
 | |
|   size_t m = U.size1();
 | |
|   if (m!=n)
 | |
|     throw invalid_argument("backSubstituteUpper: U must be square");
 | |
| #endif
 | |
| 
 | |
|   Vector result(n);
 | |
|   for (size_t i = n; i > 0; i--) {
 | |
|     double zi = b(i-1);
 | |
|     for (size_t j = i+1; j <= n; j++)
 | |
|       zi -= U(i-1,j-1) * result(j-1);
 | |
| #ifndef NDEBUG
 | |
|     if(!unit && fabs(U(i-1,i-1)) <= numeric_limits<double>::epsilon()) {
 | |
|       stringstream ss;
 | |
|       ss << "backSubstituteUpper: U is singular,\n";
 | |
|       print(U, "U: ", ss);
 | |
|       throw invalid_argument(ss.str());
 | |
|     }
 | |
| #endif
 | |
|     if (!unit) zi /= U(i-1,i-1);
 | |
|     result(i-1) = zi;
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| /**
 | |
|  * backSubstitute x'*U=b'
 | |
|  * @param U an upper triangular matrix
 | |
|  * @param b an RHS vector
 | |
|  * @param unit, set true if unit triangular
 | |
|  * @return the solution x of x'*U=b'
 | |
|  * TODO: use boost
 | |
|  */
 | |
| template<class VectorAE, class MatrixAE>
 | |
| Vector backSubstituteUpper(const boost::numeric::ublas::vector_expression<VectorAE>& _b,
 | |
|     const boost::numeric::ublas::matrix_expression<MatrixAE>& _U, bool unit=false) {
 | |
|   const VectorAE& b((const VectorAE&)_b);
 | |
|   const MatrixAE& U((const MatrixAE&)_U);
 | |
|   size_t n = U.size2();
 | |
| #ifndef NDEBUG
 | |
|   size_t m = U.size1();
 | |
|   if (m!=n)
 | |
|     throw invalid_argument("backSubstituteUpper: U must be square");
 | |
| #endif
 | |
| 
 | |
|   Vector result(n);
 | |
|   for (size_t i = 1; i <= n; i++) {
 | |
|     double zi = b(i-1);
 | |
|     for (size_t j = 1; j < i; j++)
 | |
|       zi -= U(j-1,i-1) * result(j-1);
 | |
| #ifndef NDEBUG
 | |
|     if(!unit && fabs(U(i-1,i-1)) <= numeric_limits<double>::epsilon()) {
 | |
|       stringstream ss;
 | |
|       ss << "backSubstituteUpper: U is singular,\n";
 | |
|       print(U, "U: ", ss);
 | |
|       throw invalid_argument(ss.str());
 | |
|     }
 | |
| #endif
 | |
|     if (!unit) zi /= U(i-1,i-1);
 | |
|     result(i-1) = zi;
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| }
 |