/* * Copyright (C) 2009 * Robert Bosch LLC * Research and Technology Center North America * Palo Alto, California * * All rights reserved. * *------------------------------------------------------------------------------ * project ....: Autonomous Technologies * file .......: rtcVarSMat.h * authors ....: Benjamin Pitzer * organization: Robert Bosch LLC * creation ...: 08/16/2006 * modified ...: $Date: 2009-01-21 18:19:16 -0800 (Wed, 21 Jan 2009) $ * changed by .: $Author: benjaminpitzer $ * revision ...: $Revision: 14 $ */ #ifndef RTC_VARSMAT_H #define RTC_VARSMAT_H //== INCLUDES ================================================================== #include "rtcMath.h" #include "rtcVarVec.h" #include "rtcVarMat.h" #include "rtcArray2.h" //== NAMESPACES ================================================================ namespace rtc { // Forward declarations template class VarVec; // r-d vector template class VarMat; // MxN Matrix template class VarSMat; // MxM Square Matrix /** * A square matrix. * A specialization of a general matrix that provides operations only * possible on square matrices like guassian elimination and Cholesky * decomposition. */ template class VarSMat: public VarMat { public: // Data using VarMat::x; using VarMat::set; using VarMat::rows; // Constructors VarSMat(); VarSMat(int size); VarSMat(int size, const T* d); VarSMat(int size, const T diagVal); VarSMat(int size, const VarVec& diagVec); VarSMat(const Array2& m); // Casting Operation template VarSMat(const VarMat& m); // Mutators void setSize(int size); void setIdentity(); void setDiag(const T a); void setDiag(const VarVec& diagVec); // Accessors VarVec getDiag(); int size() const; // Basic square matrix functions T trace() const; void transpose(); VarSMat minorMat(const int ip, const int jp) const; T det() const; VarSMat inverted() const; int invert(); // Decompositions void luDecomp(VarVec& indx, T* d = NULL); void luSolve(const VarVec& indx, VarVec& b); void choleskyDecomp(); void choleskyDecomp(VarSMat& r); void choleskySolve(VarVec& b); }; // end class VarSMat // Declare a few common typdefs typedef VarSMat VarSMatb; typedef VarSMat VarSMatc; typedef VarSMat VarSMatuc; typedef VarSMat VarSMati; typedef VarSMat VarSMatf; typedef VarSMat VarSMatd; //============================================================================== // VarSMat //============================================================================== // Constructors /** default Ctor */ template inline VarSMat::VarSMat() : VarMat() {} /** Ctor that doesn't initialize anything. */ template inline VarSMat::VarSMat(int size) : VarMat(size,size) {} /** Ctor that initializes from an array. * @param size is the number of rows/columns * @param d the (row major) data array of length r*r */ template inline VarSMat::VarSMat(int size, const T* d) : VarMat(size,size,d) {} /** Ctor that makes a multiple of the identity matrix. * @param size is the number of rows/columns * @param diagVal the value to which all diagonal entries will be set */ template inline VarSMat::VarSMat(int size, const T diagVal) : VarMat(size,size) { set(T(0)); setDiag(diagVal); } /** Ctor that makes a (mostly) zero matrix with diagonal entries from vec. * @param size is the number of rows/columns * @param diagVec the vector of values that should appear on the diagonal */ template inline VarSMat::VarSMat(int size, const VarVec& diagVec) : VarMat(size,size) { set(T(0)); setDiag(diagVec); } /** Ctor that initializes from a Mat */ template inline VarSMat::VarSMat(const Array2& m) : VarMat(m) {} // Casting Operation /** Casting Ctor that initializes from a Mat */ template template inline VarSMat::VarSMat(const VarMat& m) : VarMat(m) {} // Mutators /** Sets matrix to specific size * @param size is the number of rows/columns */ template inline void VarSMat::setSize(int size) { VarMat::setSize(size,size); } /** Sets matrix to an identiy matrix, where the diagonal elements are equal to * 1 and every other element equals 0. */ template inline void VarSMat::setIdentity() { set(T(0)); setDiag(T(1)); } /** Sets matrix to a multiple of the identity matrix. * @param diagVal the value to which all diagonal entries will be set */ template inline void VarSMat::setDiag(const T diagVal) { for (int i=0,k=0;i inline void VarSMat::setDiag(const VarVec& diagVec) { #if MATMATH_CHECK_BOUNDS if (size()!=diagVec.length()) { std::stringstream ss; ss << "VarSMat<" << size() << "," << size() << ">::setDiag ("; ss << "VarVec<" << diagVec.length() << ">): not a valid operation\n"; ss << std::flush; throw Exception(ss.str()); } #endif for (int i=0,k=0;i inline VarVec VarSMat::getDiag() { VarVec v(size()); for (int i=0,k=0;i inline int VarSMat::size() const { return rows(); } // Some basic square matrix functions /** Return the trace of the matrix */ template inline T VarSMat::trace() const { T sum = T(0); for (int i=0,k=0;i inline void VarSMat::transpose() { for (int i=0;i inline VarSMat VarSMat::minorMat(const int ip, const int jp) const { #if MATMATH_CHECK_BOUNDS if (ip<0 || ip>size() || jp<0 || jp>size()) { std::stringstream ss; ss << "VarSMat<" << size() << ">::minorMat(" << ip; ss << ", " << jp << "): index out of range\n"; ss << std::flush; throw Exception(ss.str()); } #endif VarSMat m(size()-1); for (int i=0,k=0;i inline T VarSMat::det() const { VarSMat tmp(*this); VarVec indx(size()); T d; tmp.luDecomp(indx,&d); return d*tmp.getDiag().prod(); } /** Return the inverse of this matrix * This uses the LU decomposition */ template inline VarSMat VarSMat::inverted() const { VarSMat tmp(*this); VarVec indx(size()); T d; try { tmp.luDecomp(indx,&d); } catch (Exception e) { throw Exception( "VarSMat::invert(): error, can't take inverse of singular matrix."); } VarSMat inv(size()); for (int i=0;i col(size(),T(0)); col(i) = T(1); tmp.luSolve(indx,col); inv.setCol(i,col); } return inv; } /** Return the inverse of this matrix * This uses the LU decomposition */ template inline int VarSMat::invert() { VarSMat tmp(*this); VarVec indx(size()); T d; try { tmp.luDecomp(indx,&d); } catch (Exception e) { throw Exception( "VarSMat::inverted(): error, can't take inverse of singular matrix."); } for (int i=0;i col(size(),T(0)); col(i) = T(1); tmp.luSolve(indx,col); this->setCol(i,col); } return 0; } // Decomposition and Solve Routines (compliments of Numerical Recipes in C) /** Perform the LU Decomposition in place * @return indx output vector that records the row permutation effected by * the partial pivoting * @return d (optional) is +/- 1 depending on if there were an even (+) or * odd (-) number of row-interchanges (used to compute determinant). * @returns 1 on failure (matrix singular), 0 on success */ template inline void VarSMat::luDecomp(VarVec& indx, T* d) { int r = size(); if(r!=indx.length()) indx.setSize(r); int i,imax=0,j,k; T big,dum,sum,temp; VarVec vv(r); if (d) *d=1.0; for (i=0; i big) big=temp; if (big == 0.0) { std::stringstream ss; ss << "VarSMat<" << r << "," << r << ">::luDecomp(VarVec<" << r << ">& indx, T* d)"; ss << ": matrix is singular."; throw Exception(ss.str()); } vv(i)=T(1)/big; } for (j=0; j= big) { big=dum; imax=i; } } if (j != imax) { for (k=0; k inline void VarSMat::luSolve(const VarVec& indx, VarVec& b) { #if MATMATH_CHECK_BOUNDS if (size()!=indx.length() || size()!=b.length()) { std::stringstream ss; ss << "VarSMat<" << size() << "," << size() << ">::luSolve ("; ss << "VarVec<" << indx.length() << ">, VarVec<" << b.length() << ">): not a valid operation\n"; throw Exception(ss.str()); } #endif int i,ii=-1,ip,j; T sum; for (i=0;i=0) for (j=ii;j=0;i--) { sum=b.x[i]; for (j=i+1;j inline void VarSMat::choleskyDecomp() { int r = size(); T sum; T p[r]; for (int i=0; i=0; k--) sum -= x[i*r+k]*x[j*r+k]; if (i == j) { if (sum <= T(0)) { std::stringstream ss; ss << "VarSMat<" << r << "," << r << ">::choleskyDecomp()"; ss << ": matrix is not positive definite."; throw Exception(ss.str()); } p[i] = sqrt(double(sum)); } else x[j*r+i] = sum/p[i]; } for (int i=0; i inline void VarSMat::choleskyDecomp(VarSMat& _r) { _r.set(*this); _r.choleskyDecomp(); for (int i=0;i inline void VarSMat::choleskySolve(VarVec& b) { #if MATMATH_CHECK_BOUNDS if (size()!=b.length()) { std::stringstream ss; ss << "VarSMat<" << size() << "," << size() << ">::choleskySolve ("; ss << "VarVec<" << b.length() << ">): not a valid operation\n"; throw Exception(ss.str()); } #endif T sum; for (int i=0,k;i=0;k--) sum -= x[i*size()+k]*b.x[k]; b.x[i] = sum/x[i*size()+i]; } for (int i=size()-1,k;i>=0;i--) { for (sum=b.x[i],k=i+1;k