Matrix

Hello everyone,

Here you will find an useful class.


Recently, I have been working in the developing because I'll need it. In fact, I still developing it so if you are interested take care of my updates.

You can use it as you like. The only thing I ask you is to be recognized myself.



/* 
  * File:   Matrix.h
  * Author: Aikon
  *
  * Created on 20 de febrero de 2012, 22:43
  */

#ifndef MATRIX_H
#define MATRIX_H

#include <vector>
#include <iostream>
#include <stdexcept>


template<typename T>
class Matrix {
    private:
       std::vector<T> _elements;
    public:
       unsigned _rows;
       unsigned _cols;
       
    public:
       T& operator()( unsigned i, unsigned j ) {
          return _elements[i*_cols+j];
       }
       const T& operator()( unsigned i, unsigned j ) const {
          return _elements[i*_cols+j];
       }
       const T& operator()( unsigned i) const {
          return _elements[i];
       }
       
    public:
         // constructors
         Matrix( unsigned rows, unsigned cols);
         Matrix( unsigned rows, unsigned cols, T element);
         
         template<typename Function>
         Matrix( unsigned rows, unsigned cols, Function f)
         : _rows(rows), _cols(cols), _elements(rows*cols,T(0.0)){
             if( rows == 0 || cols == 0 )
                 throw std::range_error("attempt to create a degenerate matrix");

             for (int i=0 ;i < rows*cols ;i++) _elements[i] = f();
          }
       //Matrix( Matrix& );
       
       
       // destructor
       ~Matrix();

       
       // assignment
       Matrix<T>& operator=( const Matrix<T>& );

       
       // comparison
       bool operator==( const Matrix<T>& ) const;
       bool operator!=( const Matrix<T>& cmp) const{
           return ((*this)==(cmp))? false : true;
       }
       
       // scalar multiplication
       Matrix<T>& operator*=( const T& a );
       Matrix<T> operator*( const T& a ) const {
          return Matrix<T>(*this).operator*=(a);
       }
   
       Matrix<T> operator-() const{
           return Matrix<T>(*this)*(-1);
       }
       
       
       // addition/subtraction
       Matrix<T>& operator+=( const Matrix<T>& );
       Matrix<T>& operator-=( const Matrix<T>& );
       Matrix<T> operator+( const Matrix<T>& M ) const {
          return Matrix<T>(*this).operator+=(M);
       }
       Matrix<T> operator-( const Matrix<T>& M ) const {
          return Matrix<T>(*this).operator-=(M);
       }
       
       // Matrix multiplication
       Matrix<T> operator*( const Matrix<T>& ) const;
       Matrix<T>& operator*=( const Matrix<T>& M ) {
          return *this = *this * M;
       }
       
       
       /*
       
       Matrix<T> getcol( unsigned i ) const;
       Matrix<T> getrow( unsigned j ) const;
       Matrix<T>& setcol( unsigned j, const Matrix<T>& C );
       Matrix<T>& setrow( unsigned i, const Matrix<T>& R );
       Matrix<T> delrow( unsigned i ) const;
       Matrix<T> delcol( unsigned j ) const;

       Matrix<T> transpose() const;
       */
       void set( unsigned i, unsigned j, T in){
           _elements[i*_cols+j] = in;
       }
};


#endif     /* MATRIX_H */


//constructors
template<class T>
Matrix<T>::Matrix( unsigned rows, unsigned cols)
: _rows(rows), _cols(cols), _elements(rows*cols,T(0.0)){
     //_elements(rows*cols,T(0.0) init with 0 values
     
     if( rows == 0 || cols == 0 )
         throw std::range_error("attempt to create a degenerate matrix");
};

template<class T>
Matrix<T>::Matrix( unsigned rows, unsigned cols, T element)
: _rows(rows), _cols(cols), _elements(rows*cols,T(element)){
     if( rows == 0 || cols == 0 )
         throw std::range_error("attempt to create a degenerate matrix");
};


// destructor

//Erases all the elements. Note that this function only erases 
//the elements, and that if the elements themselves are pointers, 
//the pointed-to memory is not touched in any way. Managing 
//the pointer is the user's responsibility.
template<class T>
Matrix<T>::~Matrix(){
     _elements.clear();
}

template<class T>
Matrix<T>& Matrix<T>::operator=( const Matrix<T>& cp ){
     _elements.clear();
     for(int i = 0;i < cp._cols * cp._rows ;i++)
         _elements.push_back(cp(i));
     _cols = cp._cols;
     _rows = cp._rows;
    
    return *this;
}

template<class T>
bool Matrix<T>::operator==( const Matrix<T>& cmp) const{
     if(cmp._rows != _rows && cmp._cols != _cols )
         return false;
     for(unsigned i=0 ; i < _rows*_cols ; i++)
       if(_elements[i] != cmp._elements[i])
           return false;
     return true;
}

template<class T>
Matrix<T>& Matrix<T>::operator*=( const T& a ){
     for(int i=0; i < _rows * _cols ; i++)
         _elements[i] *= a;
     return *this; 
}



// addition/subtraction
template<class T>
Matrix<T>& Matrix<T>::operator+=( const Matrix<T>& in){
     if(in._rows != _rows && in._cols != _cols )
       throw std::domain_error("diferent size");
     for(unsigned i=0 ; i < _rows*_cols ; i++)
       _elements[i] += in._elements[i];
     return *this;
}

template<class T>
Matrix<T>& Matrix<T>::operator-=( const Matrix<T>& in){
     if(in._rows != _rows && in._cols != _cols )
       throw std::domain_error("diferent size");
     for(unsigned i=0 ; i < _rows*_cols ; i++)
       _elements[i] -= in._elements[i];
     return *this;
}


// Matrix multiplication
//(this)*B = C sizeX(files de this), sizeY = columnes de B sizeY
template<class T>
Matrix<T> Matrix<T>::operator*( const Matrix<T>& in) const{
     Matrix<T> aux(_rows,in._cols);
     
     if(_cols != in._rows)
         throw std::domain_error("diferent size");
     
     for(int i=0;i<_rows;i++)
         for(int j=0 ; j<in._cols ; j++)
             for(int k=0 ; k<_cols ; k++)
                 (aux)(i, j) += (*this)(i,k)*in(k,j);
         
     return aux;
}

template<typename T>
std::ostream& operator<<(std::ostream& out,Matrix<T>& M){
     out << std::endl;
     for(int i = 0 ; i< M._rows ; i++){
         for(int j = 0 ; j < M._cols ; j++)
             out << " " << M(i,j) << " ";
         out << std::endl;
     }
     return out;
}
#include <cstdlib>
#include <ctime>

double myfunction () {
     return (rand()%10)+1;
}
int main(){
     try{
     srand (time(0));

     Matrix<double> m(4,2,myfunction);
     Matrix<double> m2(2,4,double(1));
     
     
     //If the third argument is not an double (as the type of Matrix)
     //it will try to apply a "Function" instead of asigning the value
     //we could apply double(2)
     //Can I improve this
     std::cout << "isEqual: " << (m == m) << std::endl;
     
     std::cout << m << m2;
     
     m = m * m2;
     std::cout << m;
     
     m*=m;//m^2
     m= -m;
     std::cout << m;
     
     }catch(const std::exception& in){
         std::cout << in.what() << std::endl;
     }
}


No comments:

Post a Comment