gtsam/base/Matrix-inl.h

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;
}
}