//-*-c++-*- #ifndef MAT_H #define MAT_H /** * @file mat.h * @brief Basic static matric type, templated in type and size * @author James R. Diebel, Stanford University * * - History: * - 31 July 2005 - Started (JD) * - 30 Aug 2005 - Commented and tested (KH) * - 30 Aug 2005 - forked off from matmath.h */ #include #include #include #include #include #include #include /** * @namespace sla * @brief Simple Linear Algebra - library of matrix and vector classes */ namespace sla { ///////////////////////////////////////////////////////////////////////////// // DECLARATIONS ///////////////////////////////////////////////////////////////////////////// // Forward declarations template class Vec; // M-d vector template class Mat; // MxN Matrix //////////////////// Mat //////////////////// /** * An MxN matrix. */ template class Mat { 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 i, const int j, const Mat& m); template void addToSubMat(const int i, const int j, const Mat& m); // Casting Mutators template void set(const Mat& m); template Mat& operator = (const Mat& m); // Accessors T operator () (const int i, const int j) const; T& operator () (const int i, const int j); Vec getRow(int i) const; Vec getCol(int j) const; template Mat getSubMat(const int i, const int j); // Convenience bool contains(const T element, const int active_m = M, const int active_n = N) const; // Addition and subtraction: +/- 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; // 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); Mat inner() const; template Mat inner(const Mat& m) const; // Equality and inequality tests int compareTo(const Mat& m) const; bool equalTo(const Mat& m) const; bool nearTo(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)); // Serialization void writeTo(std::ostream& os) const; void readFrom(std::istream& is); void print(std::ostream& os = std::cout, const int active_m = M, const int active_n = N) const; void matlab_print(const std::string name, std::ostream& os = std::cout, const int active_m = M, const int active_n = N) const; }; // 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& mat); //////////////////////////////////////////////////////////////////////////// // DEFINITIONS //////////////////////////////////////////////////////////////////////////// //////////////////// 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 a the value to assign to all elements */ 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) { 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::cerr << "Mat<" << M << "," << N << ">::setRow(" << i << ", v): index out of range\n"; std::cerr << std::flush; exit(1); } #endif for (int j=0,k=i;j inline void Mat::setCol(const int j, const Vec& v) { #if MATMATH_CHECK_BOUNDS if (j < 0 || j >= N) { std::cerr << "Mat<" << M << "," << N << ">::setCol(" << j << ", v) out of range\n"; std::cerr << std::flush; exit(1); } #endif for (int i=0,k=j*M;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::cerr << "Mat<" << M << "," << N << ">::setSubMat(" << i << ", " << j << ", m): index out of range\n"; std::cerr << std::flush; exit(1); } #endif for (int id=i,is=0;id template inline void Mat::addToSubMat(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::cerr << "Mat<" << M << "," << N << ">::setSubMat(" << i << ", " << j << ", m): index out of range\n"; std::cerr << std::flush; exit(1); } #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::cerr << "Mat<" << M << "," << N << ">::operator (" << i << ", " << j << "): index out of range\n"; std::cerr << std::flush; exit(1); } #endif return x[i+j*M]; } /** 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::cerr << "&Mat<" << M << "," << N << ">::operator (" << i << ", " << j << "): index out of range\n"; std::cerr << std::flush; exit(1); } #endif return x[i+j*M]; } /** 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::cerr << "Mat<" << M << "," << N << ">::getRow(" << i << "): index out of range\n"; std::cerr << std::flush; exit(1); } #endif Vec v; for (int j=0,k=i;j inline Vec Mat::getCol(int j) const { #if MATMATH_CHECK_BOUNDS if (j < 0 || j >= N) { std::cerr << "Mat<" << M << "," << N << ">::getCol(" << j << "): index out of range\n"; std::cerr << std::flush; exit(1); } #endif Vec v; for (int i=0,k=j*M;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::cerr << "Mat<" << M << "," << N << ">::getSubMat(" << i << ", " << j << "): index out of range\n"; std::cerr << std::flush; exit(1); } #endif Mat m(T(0)); for (int id=i,is=0;id inline bool Mat::contains(const T element, const int active_m, const int active_n) const { for (int j=0;j +/- /** 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 *// /** 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 j=0,k=0;j Vec operator * (const Vec& v, const Mat &m) { Vec vp(T(0)); for (int j=0,k=0;j * /** Matrix-Matrix multiplication operator. */ template template inline Mat Mat::operator * (const Mat& m) const { Mat mp(T(0)); for (int j=0;j inline void Mat::operator *= (const Mat& m) { (*this) = (*this)*m; } /** Inner product of this matrix with itself, i.e., A'*A */ template inline Mat Mat::inner() const { Mat mp(T(0)); for (int i=0;i template inline Mat Mat::inner(const Mat& m) const { Mat mp(T(0)); 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 equal */ template inline bool Mat::equalTo(const Mat& m) const { for (int i=0;i inline bool Mat::nearTo(const Mat& m, const T tol) const { for (int i=0;i tol) return false; return true; } // 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; } // Serialization routines /** Write state to a binary stream. */ template inline void Mat::writeTo(std::ostream& os) const { os.write((char *)(x),M*N*sizeof(T)); } /** Restore state from a binary stream. */ template inline void Mat::readFrom(std::istream& is) { is.read((char *)(x),M*N*sizeof(T)); } /** Write state to stream as formated ASCII */ template void Mat::print(std::ostream& os, const int active_m, const int active_n) const { os.precision(8); int minFieldWidth = os.precision()+2; os << "[" ; for (int i=0;i void Mat::matlab_print(const std::string name, std::ostream& os, const int active_m, const int active_n) const { os << std::endl << name << " = ... " << std::endl; print(os, active_m, active_n); os << ";" << std::endl; } /** Write state to stream as formated ASCII */ template std::ostream& operator<<(std::ostream& os, const Mat& mat) { mat.print(os); return os; } } // end namespace sla #endif