/* * Copyright (C) 2009 * Robert Bosch LLC * Research and Technology Center North America * Palo Alto, California * * All rights reserved. * *------------------------------------------------------------------------------ * project ....: Autonomous Technologies * file .......: rtcMat.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_MAT_H #define RTC_MAT_H //== INCLUDES ================================================================== #include #include "rtcMath.h" #include "rtcVec.h" #include "rtcSMat.h" //== NAMESPACES ================================================================ namespace rtc { // Forward declarations template class Vec; // M-d vector template class Mat; // MxN Matrix template class SMat; // MxM Matrix /** * An MxN matrix. */ template class Mat : public IOObject { public: // Data T x[M*N]; ///< storage array // Constructors Mat(); Mat(const T* d); Mat(const T a); Mat(const Mat& m); // Cast Operation template Mat(const Mat& m); // Mutators void set(const T* d); void set(const T a); void set(const Mat& m); Mat& operator = (const T* d); Mat& operator = (const T a); Mat& operator = (const Mat& m); void setRow(const int i, const Vec& v); void setCol(const int j, const Vec& v); template void setSubMat(const int r, const int c, const Mat& m); // Casting Mutators template void set(const Mat& m); template Mat& operator = (const Mat& m); // Accessors T operator () (const int r, const int c) const; T& operator () (const int r, const int c); Vec getRow(int r) const; Vec getCol(int c) const; template Mat getSubMat(const int i, const int j); // Addition and subtraction: +/- Mat& add(const Mat& m); Mat& subtract(const Mat& m); Mat operator + (const Mat& m) const; void operator += (const Mat& m); Mat operator - (const Mat& m) const; void operator -= (const Mat& m); Mat operator - () const; // Addition and subtraction: +/- Mat& add(const T a); Mat& subtract(const T a); Mat operator + (const T a) const; void operator += (const T a); Mat operator - (const T a) const; void operator -= (const T a); // Multiplication and division: *// Mat operator * (const T a) const; void operator *= (const T a); Mat operator / (const T a) const; void operator /= (const T a); // Multiplication: * Vec operator * (const Vec& v) const; template Mat operator * (const Mat& m) const; void operator *= (const Mat& m); // Equality and inequality tests Mat operator == (const Mat& m) const; Mat operator != (const Mat& m) const; Mat operator >= (const Mat& m) const; Mat operator <= (const Mat& m) const; Mat operator > (const Mat& m) const; Mat operator < (const Mat& m) const; int compareTo(const Mat& m) const; bool equalTo(const Mat& m, const T tol = T(0)) const; // Other matrix operations Mat transposed() const; // Random matrix static Mat uniformRand(const T a = T(0), const T b = T(1)); static Mat normalRand(const T mean = T(0), const T stdev = T(1)); static Mat multivariateGauss(const Vec& mean, const SMat& cov); // General elementwise operations void perform(T (*mathFun)(T)); //void perform(T (*mathFun)(T,T), const T arg2); //void perform(T (*mathFun)(T,T), const Vec& v); //Vec performed(T (*mathFun)(T)); //Vec performed(T (*mathFun)(T,T), const T arg2); //Vec performed(T (*mathFun)(T,T), const Vec& v); // Reductions: Max/Min, Sum/Product //T max() const; //T min() const; Vec sum() const; //T prod() const; // Bilinear Interpolation T interpolate(const float i, const float j) const; // statistical operations Vec meanOfRows() const; SMat covarianceMatrixOfRows() const; // Serialization virtual bool write(OutputHandler& oh) const; virtual bool read(InputHandler& ih); }; // Global operators to for cases where Mat // is the second argument in a binary operator template Mat operator * (const T a, const Mat &m); template Vec operator * (const Vec& v, const Mat &m); // ASCII stream IO template std::ostream& operator<<(std::ostream& os, const Mat& vec); template std::istream& operator>>(std::istream& is, Mat& vec); //============================================================================== // Mat //============================================================================== // Constructors /** Ctor that doesn't initialize anything. */ template inline Mat::Mat() {} /** Ctor that initializes from an array. * @param d the (row major) data array of length M*N */ template inline Mat::Mat(const T* d) { set(d); } /** Ctor that initializes ALL ELEMENTS to a scalar value. * @param a the value to which all elements will be set */ template inline Mat::Mat(const T a) { set(a); } /** Ctor that initializes from passed matrix. * @param m the matrix to be copied. */ template inline Mat::Mat(const Mat& m) { set(m); } // Casting Operation /** Casting Ctor that initializes from passed matrix with type cast. * @param m the matrix to replicate. */ template template inline Mat::Mat(const Mat& m) { set(m); } // Mutators /** Set from an array. * @param d the (row major) data array of length M*N */ template inline void Mat::set(const T* d) { for (int k=0;k inline void Mat::set(const T a) { if (a == T(0)) memset(x,0,M*N*sizeof(T)); else for (int i=0;i inline void Mat::set(const Mat& m) { memcpy((void*)x,(void*)m.x,M*N*sizeof(T)); } /** Set from an array. * @param d the (row major) data array of length M*N */ template inline Mat& Mat::operator = (const T* d) { set(d); return *this; } /** Set all elements to a scalar value. * @param a the value to which all elements will be set */ template inline Mat& Mat::operator = (const T a) { set(a); return *this; } /** Set from another matrix. * @param m the matrix to replicate. */ template inline Mat& Mat::operator = (const Mat& m) { set(m); return *this; } /** Set a row. * Does bounds checking if MATMATH_CHECK_BOUNDS is set * @param i zero based index of row to set * @param v source vector */ template inline void Mat::setRow(const int i, const Vec& v) { #if MATMATH_CHECK_BOUNDS if (i < 0 || i > M) { std::stringstream ss; ss << "Mat<" << M << "," << N << ">::setRow(" << i; ss << ", v): index out of range\n"; ss << std::flush; throw Exception(ss.str()); } #endif for (int j=0,k=i*N;j inline void Mat::setCol(const int j, const Vec& v) { #if MATMATH_CHECK_BOUNDS if (j < 0 || j > N) { std::stringstream ss; ss << "Mat<" << M << "," << N << ">::setCol(" << j; ss << ", v) out of range\n"; ss << std::flush; throw Exception(ss.str()); } #endif for (int i=0,k=j;i template inline void Mat::setSubMat(const int i, const int j, const Mat& m) { #if MATMATH_CHECK_BOUNDS if (i < 0 || i+P > M || j < 0 || j+Q > N) { std::stringstream ss; ss << "Mat<" << M << "," << N << ">::setSubMat(" << i; ss << ", " << j << ", m): index out of range\n"; ss << std::flush; throw Exception(ss.str()); } #endif for (int id=i,is=0;id template inline void Mat::set(const Mat& m) { for (int k=0;k template inline Mat& Mat::operator = (const Mat& m) { set(m); } // Accessors /** Reference operator (value). * Gets an element of the vector by value. * Does bounds checking if MATMATH_CHECK_BOUNDS is set * @param i zero based row index * @param j zero based col index */ template inline T Mat::operator () (const int i, const int j) const { #if MATMATH_CHECK_BOUNDS if (i<0 || i>M || j<0 || j>N) { std::stringstream ss; ss << "Mat<" << M << "," << N << ">::operator (" << i; ss << ", " << j << "): index out of range\n"; ss << std::flush; throw Exception(ss.str()); } #endif return x[i*N + j]; } /** Reference operator (reference). * Gets an element of the vector by reference. * Does bounds checking if MATMATH_CHECK_BOUNDS is set * @param i zero based row index * @param j zero based col index */ template inline T& Mat::operator () (const int i, const int j) { #if MATMATH_CHECK_BOUNDS if (i<0 || i>M || j<0 || j>N) { std::stringstream ss; ss << "&Mat<" << M << "," << N << ">::operator (" << i; ss << ", " << j << "): index out of range\n"; ss << std::flush; puma::Exception e(ss.str()); throw e; } #endif return x[i*N + j]; } /** Get a row. * Does bounds checking if MATMATH_CHECK_BOUNDS is set * @param i zero based index of row to get */ template inline Vec Mat::getRow(int i) const { #if MATMATH_CHECK_BOUNDS if (i < 0 || i >= M) { std::stringstream ss; ss << "Mat<" << M << "," << N << ">::getRow(" << i; ss << "): index out of range\n"; ss << std::cerr << std::flush; throw Exception(ss.str()); } #endif Vec v; for (int j=0,k=i*N;j inline Vec Mat::getCol(int j) const { #if MATMATH_CHECK_BOUNDS if (j < 0 || j >= N) { std::stringstream ss; ss << "Mat<" << M << "," << N << ">::getCol(" << j; ss << "): index out of range\n"; ss << std::flush; throw Exception(ss.str()); } #endif Vec v; for (int i=0,k=j;i template inline Mat Mat::getSubMat(const int i, const int j) { #if MATMATH_CHECK_BOUNDS if (i < 0 || i+P > M || j < 0 || j+Q > N) { std::stringstream ss; ss << "Mat<" << M << "," << N << ">::getSubMat(" << i; ss << ", " << j << "): index out of range\n"; ss << std::flush; throw Exception(ss.str()); } #endif Mat m(T(0)); for (int id=i,is=0;id +/- /** Addition. */ template inline Mat& Mat::add(const Mat& m) { for (int k=0;k inline Mat& Mat::subtract(const Mat& m) { for (int k=0;k +/- /** Addition operator. */ template inline Mat Mat::operator + (const Mat& m) const { Mat mp; for (int k=0;k inline void Mat::operator += (const Mat& m) { for (int k=0;k inline Mat Mat::operator - (const Mat& m) const { Mat mp; for (int k=0;k inline void Mat::operator -= (const Mat& m) { for (int k=0;k inline Mat Mat::operator - () const { Mat mp; for (int k=0;k +/- /** Addition. */ template inline Mat& Mat::add(const T a) { for (int k=0;k inline Mat& Mat::subtract(const T a) { for (int k=0;k +/- inline Mat Mat::operator + (const T a) const { Mat mp; for (int k=0;k inline void Mat::operator += (const T a) { for (int k=0;k inline Mat Mat::operator - (const T a) const { Mat mp; for (int k=0;k inline void Mat::operator -= (const T a) { for (int k=0;k *// /** Matrix-Scalar multiplication operator. */ template inline Mat Mat::operator * (const T a) const { Mat m; for (int k=0;k inline void Mat::operator *= (const T a) { for (int k=0;k inline Mat Mat::operator / (const T a) const { Mat m; for (int k=0;k inline void Mat::operator /= (const T a) { for (int k=0;k Mat operator * (const T a, const Mat &m) { Mat mp; for (int k=0;k * /** Matrix-Vector multiplication operator. */ template inline Vec Mat::operator * (const Vec& v) const { Vec vp(T(0)); for (int i=0,k=0;i Vec operator * (const Vec& v, const Mat &m) { Vec vp(T(0)); for (int i=0,k=0;i * /** Matrix-Matrix multiplication operator. */ template template inline Mat Mat::operator * (const Mat& m) const { Mat mp(T(0)); for (int i=0;i inline void Mat::operator *= (const Mat& m) { (*this) = (*this)*m; } // Equality and inequality tests. /** Element-wise test for equality. * @return matrix of boolean results */ template inline Mat Mat::operator == (const Mat& m) const { Mat b(false); for (int i=0;i inline Mat Mat::operator != (const Mat& m) const { Mat b(false); for (int i=0;i inline Mat Mat::operator >= (const Mat& m) const { Mat b(false); for (int i=0;i= m.x[i]) b.x[i] = true; return b; } /** Element-wise test for less or equal. * @return matrix of boolean results */ template inline Mat Mat::operator <= (const Mat& m) const { Mat b(false); for (int i=0;i inline Mat Mat::operator > (const Mat& m) const { Mat b(false); for (int i=0;i m.x[i]) b.x[i] = true; return b; } /** Element-wise test for less. * @return matrix of boolean results */ template inline Mat Mat::operator < (const Mat& m) const { Mat b(false); for (int i=0;i inline int Mat::compareTo(const Mat& m) const { int g=0, l=0; for (int i=0;i m.x[i]) g++; } if (l==(M*N)) return -1; else if (g==(M*N)) return 1; else return 0; } /** Compare the entire matrix to the passed matrix. * @returns true of all corresponding elements are within the given tolerance */ template inline bool Mat::equalTo(const Mat& m, const T tol) const { bool t = true; for (int i=0;i tol) t = false; return t; } // Transpose /** Return the transpose of the matrix without modifying matrix. */ template inline Mat Mat::transposed() const { Mat mp; for (int i=0;i inline Mat Mat::uniformRand(const T a, const T b) { Mat m; for (int i=0;i(a,b); return m; } /** Create matrix of samples from a normal distribution. * @param mean mean of normal distribution * @param stdev standard deviation of normal distribution * @return matrix of normal samples */ template inline Mat Mat::normalRand(const T mean, const T stdev) { Mat m; for (int i=0;i(mean,stdev); return m; } /** Create matrix of samples from a multivariate gaussian distribution. * @param mean mean of normal distribution * @param cov covariance normal distribution * @return matrix of normal samples */ template inline Mat Mat::multivariateGauss(const Vec& mean, const SMat& cov) { Mat m; SMat S(cov); int n=S.choleskyDecomp(); S.transpose(); Mat X = normalRand(); for(int j=0;j inline void Mat::perform(T (*mathFun)(T)) { for (int i=0;i inline Vec Mat::sum() const { Vec s(T(0)); for (int j=0;j inline T Mat::interpolate(const float i, const float j) const { const int truncR = rtc_clamp(static_cast(i),0,M-1); const int truncR1 = rtc_clamp(truncR+1,0,M-1); const float fractR = i - static_cast(truncR); const int truncC = rtc_clamp(static_cast(j),0,N-1); const int truncC1 = rtc_clamp(truncC+1,0,N-1); const float fractC = j - static_cast(truncC); // do the interpolation const T syx = x[truncR*N+truncC]; const T syx1 = x[truncR*N+truncC1]; const T sy1x = x[truncR1*N+truncC]; const T sy1x1 = x[truncR1*N+truncC1]; // normal interpolation within range const T tmp1 = syx + (syx1-syx)*T(fractC); const T tmp2 = sy1x + (sy1x1-sy1x)*T(fractC); return (tmp1 + (tmp2-tmp1)*T(fractR)); } /** The meanOfRows means the mean of all rows, i.e. a row vector containing * (for the arithmetical mean) the sum of all row vectors divided by the * number of rows. * @returns the mean of all rows */ template inline Vec Mat::meanOfRows() const { Vec m(T(0)); for (int j=0;j(M); return m; } /* * This is a new, faster version, written by Gu Xin: */ template inline SMat Mat::covarianceMatrixOfRows() const { SMat dest(T(0)); //Implementation for the sum of Matrix[X]; if (M<2) { //just one row throw Exception("matrix has to have more than one row"); } // mean vector Vec mu(T(0)); /* * the loop gets out the result of the Matrix[X]; * Matrix[X]=sum(Matrix[X(i)]);-- i from 0 to n-1-- */ for(int i=0;i tmpV = getRow(i); mu.add(tmpV); SMat tmp = tmpV.outer(tmpV); dest.add(tmp); //add the Matrix[X(i)] to Matrix[sumMatrix]; } //End of the Implementation for the sum of Matrix[X]; //Implementation for the Matrix[meanOf]; mu/=static_cast(M); SMat tmp = mu.outer(mu); tmp *= static_cast(M); //get the result of the difference from Matrix[X] and Matrix[meanOf]; dest.subtract(tmp); dest/=static_cast(M-1); return dest; } // Serialization routines /** Write state to a stream. */ template inline bool Mat::write(OutputHandler& oh) const { return oh.stream().write((char *)(x),M*N*sizeof(T)); } /** Restore state from a stream. */ template inline bool Mat::read(InputHandler& ih) { return ih.stream().read((char *)(x),M*N*sizeof(T)); } /** Write state to stream as formated ASCII */ template std::ostream& operator<<(std::ostream& os, const Mat& mat) { int minFieldWidth = os.precision()+2; //case with 1 row if (M == 1){ os << "[" ; for (int i=0; i std::istream& operator>>(std::istream& is, Mat& mat){ using namespace std; vector data; string matString; stringstream matStringStream; string rowString; stringstream rowStringStream; getline(is, matString, ']'); int sPos = matString.find('['); if (sPos == (int)string::npos) throw Exception("format error: expecting formated matrix to start with '['"); //erase the starting '[' //note the ending ']' was removed by the getline function as the delim matString.erase(0,sPos+1); matStringStream.str(matString); //determine num of rows and cols int rowCount = 0, colCount = 0; int cols = -1; float tmpVal; while(getline(matStringStream, rowString, ';')){ rowStringStream << rowString; colCount = 0; while(rowStringStream.good()){ rowStringStream >> tmpVal; data.push_back(tmpVal); ++colCount; } rowStringStream.clear(); //check that we have same num of entries in each row if (cols == -1) cols = colCount; else{ if (colCount != cols){ throw Exception("format error: different number of elements in rows."); } } ++rowCount; } //check that dimensions agree if (rowCount != M || colCount != N){ std::stringstream ss; ss << "format error: formated text is " << rowCount << "x" << colCount; ss << " while destination matrix is " << M << "x" << N << endl; throw Exception(ss.str()); } //copy extracted data for (int i=0;i bool rtc_write(OutputHandler& oh, const Mat& data) { return data.write(oh); }; /** * handler functions with standard storable interface */ template bool rtc_read(InputHandler& ih, Mat& data) { return data.read(ih); }; //============================================================================== } // NAMESPACE rtc //============================================================================== #endif // RTC_MAT_H defined //==============================================================================