I am working on math / matrix library that will be open source (non-computer scientist) engineer friendly and capable of managing really big computations on shared memory machines.
I have created a few template classes describing matrices. The most basic matrix object looks like this:
template <class DATA_TYPE,class INT_TYPE=std::size_t>
class Matrix
{
//--------------------------------------------------------------------------
private:
INT_TYPE Rows, Cols;
DATA_TYPE *Data;
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
public:
Matrix(); //basic constructor
Matrix(const Matrix<DATA_TYPE,INT_TYPE> &M); //copy cnstructor
~Matrix(); //destructor
//--------------------------------------------------------------------------
inline void Alloc(INT_TYPE _Rows,INT_TYPE _Cols);
inline void Free();
inline void Resize(INT_TYPE _Rows,INT_TYPE _Cols);
inline void ResizeCopyNoFill(INT_TYPE _Rows,INT_TYPE _Cols);
inline void ResizeNoCopyNoFill(INT_TYPE _Rows,INT_TYPE _Cols);
inline void Fill(DATA_TYPE Value=DATA_TYPE());
inline void Copy(const Matrix<DATA_TYPE,INT_TYPE> &M);
//--------------------------------------------------------------------------
inline bool IsEmpty() const;
inline bool IsValid() const;
inline bool IsScalar() const;
inline bool IsVector() const;
inline bool IsRowVector() const;
inline bool IsColumnVector() const;
//--------------------------------------------------------------------------
inline Matrix<DATA_TYPE,INT_TYPE>& operator =(const Matrix<DATA_TYPE,INT_TYPE>& M); //A=B; Direct assignment operator
inline Matrix<DATA_TYPE,INT_TYPE>& operator +=(const Matrix<DATA_TYPE,INT_TYPE>& M); //A+=B; Addition operator
inline Matrix<DATA_TYPE,INT_TYPE>& operator -=(const Matrix<DATA_TYPE,INT_TYPE>& M); //A-=B; Substraction operator
inline Matrix<DATA_TYPE,INT_TYPE>& operator *=(const Matrix<DATA_TYPE,INT_TYPE>& M); //A*=B; Matrix multiplication operator
inline Matrix<DATA_TYPE,INT_TYPE>& operator /=(const Matrix<DATA_TYPE,INT_TYPE>& M); //A/=B; <=> A*=Inverse(B);
inline Matrix<DATA_TYPE,INT_TYPE>& operator ^=(const Matrix<DATA_TYPE,INT_TYPE>& M); //A^=B; Matrix elements to the power A^B
//--------------------------------------------------------------------------
inline Matrix<DATA_TYPE,INT_TYPE>& operator =(DATA_TYPE s); //M=s; Fills the matrix with s entries
inline Matrix<DATA_TYPE,INT_TYPE>& operator +=(DATA_TYPE s); //M+=s; Adds s to every element of M
inline Matrix<DATA_TYPE,INT_TYPE>& operator -=(DATA_TYPE s); //M-=s; Substracts s from every M element
inline Matrix<DATA_TYPE,INT_TYPE>& operator *=(DATA_TYPE s); //M*=s; Multiplies matrix elements by s
inline Matrix<DATA_TYPE,INT_TYPE>& operator /=(DATA_TYPE s); //M/=s; Divides matrix elements by s
inline Matrix<DATA_TYPE,INT_TYPE>& operator ^=(DATA_TYPE s); //A^=s; Matrix elements to the power A^s
//--------------------------------------------------------------------------
inline DATA_TYPE operator ()(INT_TYPE _Row,INT_TYPE _Col) const; // a=M(i,j);
inline DATA_TYPE& operator ()(INT_TYPE _Row,INT_TYPE _Col); // M(i,j)=a;
inline DATA_TYPE operator ()(INT_TYPE ElementIndex) const; // a=M(i);
inline DATA_TYPE& operator ()(INT_TYPE ElementIndex); // M(i)=a;
//--------------------------------------------------------------------------
inline DATA_TYPE* GetDataPtr() const {return Data;}
inline void SetDataPtr(DATA_TYPE* DataPtr) { Data=DataPtr;} //use with extreme caution
//--------------------------------------------------------------------------
inline DATA_TYPE GetElement(INT_TYPE _Row,INT_TYPE _Col) const; //returns element, but index checking is done
inline void SetElement(INT_TYPE _Row,INT_TYPE _Col,DATA_TYPE Value); //sets element, but index checking is done
inline DATA_TYPE GetElement(INT_TYPE ElementIndex) const; //returns element, but index checking is done
inline void SetElement(INT_TYPE ElementIndex,DATA_TYPE Value); //sets element, but no index checking is done
//--------------------------------------------------------------------------
inline INT_TYPE NumOfElements()const {return Rows*Cols;}
inline INT_TYPE NumOfRows() const {return Rows;}
inline INT_TYPE NumOfCols() const {return Cols;}
inline INT_TYPE SetNumOfRows(INT_TYPE _Rows) const { Rows=_Rows;}
inline INT_TYPE SetNumOfCols(INT_TYPE _Cols) const { Cols=_Cols;}
//--------------------------------------------------------------------------
inline DATA_TYPE Sum() const;
inline DATA_TYPE Product() const;
inline DATA_TYPE Max() const;
inline DATA_TYPE Min() const;
inline std::tuple<DATA_TYPE,DATA_TYPE> MinMax() const;
//--------------------------------------------------------------------------
inline void Transpose();
inline void Inverse();
void Print();
//--------------------------------------------------------------------------
};
Of course it needs a lot of work, as I am at the very beginning. My problem is:
How to define and implement operators like multiplication, addition etc to avoid copying the matrix. For now the multiplication
operator looks like that:
template <class DATA_TYPE,class INT_TYPE>
inline Matrix<DATA_TYPE,INT_TYPE> operator *(const Matrix<DATA_TYPE,INT_TYPE>& A,const Matrix<DATA_TYPE,INT_TYPE>& B)
{
Matrix<DATA_TYPE,INT_TYPE> C;
Multiply<DATA_TYPE,INT_TYPE>(A,B,C);
return C;
}
How to avoid copyying the whole C matrix when such expression is used:
M=A*B;
If for example I would modify direct assignment operator, to copy only *Data, Rows and Cols, that would do, but then A=B would remind more the reference than copy, as it would refer to the same place in memory. What do You think about allowing to use pointers only, like
Matrix<float,int> *M=new Matrix();
Than it would work, as all operations would be done on pointers to matrices, but I somehow have feeling that I didn't notice some kind of disadvantage of such solution (except that using a variable again would require using delete M; first).
So, please help me with even absolutely general ideas about solving this problem, so it would look elegant and be fast (in the sense of avoiding of copying matrices).
Regards,
Misery