Home > front end >  Matrix Class Mem Allocating & Overloading
Matrix Class Mem Allocating & Overloading

Time:11-06

I want to dinamically alocate memory for the matrix, in the constructor.I want mData to be a pointer to double values.

getvalue() setValue() the getter should return the value at row_x and column_x, and the setter should set the value at row_x and column_x, but getter and setter doesn't seem to work;

operator have to check for 2 same sized matrix, and summing element by element.

Operator * also needs to check for 2 same sized matrix, and multiply element by element.

Operator ^ needs to check if it is possible to multiply row by column 2 matrix, and then do that.

Here is my code:

class Mat{
private:
    uint16_t mRows;
    uint16_t mCols;
    double * mData;
public:
    Mat(uint16_t r, uint16_t c){
        mRows = r;
        mCols = c;
        mData = new double[mRows * mCols];
    }
    Mat(uint16_t c){
        mCols = c;
        mRows = 1;
        mData = new double [mCols];
    }
    Mat(){
        mRows = 0;
        mCols = 0;
    }
    Mat(const Mat &mat) : mRows(mat.mRows), mCols(mat.mCols), mData(mat.mData){

    }
    double getValue(uint16_t r, uint16_t c){

        double val = mData [r*c   c];
        return val;
    }
    void setValue(uint16_t r, uint16_t c,double value){
        mData[r*c   c] = value;
    }
    ~Mat(){
        
    }
    Mat operator   (const Mat &mat){
        Mat result;
        int ok=0;
        if(mat.mRows == mRows && mat.mCols == mCols){
            ok=1;
            result.mData[mRows*mCols ] = mData[mRows*mCols ]   mat.mData[mat.mRows*mat.mCols];
        }
        if(ok == 0)
           return result.mData[0];
        else
            return result;
    }
    Mat operator * (const Mat &mat){
        Mat result;
        int ok=0;
        if(mat.mRows == mRows && mat.mCols == mCols){
            ok=1;
            result.mData[mRows*mCols] = mData[mRows*mCols] * mat.mData[mat.mRows*mat.mCols];
        }
        if(ok == 0)
            return result.mData[0];
        else
            return result.mData[mRows*mCols];
    }
     Mat operator ^ (const Mat &mat){
        Mat result;
        int ok=0;
        if(mat.mRows == mCols && mat.mCols == mRows){
            ok=1;
            result.mData[mRows] = mData[mRows] * mat.mData[mat.mCols];
        }
        if(ok == 0)
            return result.mData[0];
        else
            return result.mData[mRows];
    }


};

I want to continue with this idea, but i am not sure what i am missing

CodePudding user response:

Using std::vector<double> instead of double* makes the memory management and copying significant easier and less error prone. I've also noticed an error in element wise access, where one should use r*mCols c instead of r*c c. To solve the problem with element wise matrix operations, you need to walk over all elements:

for (size_t r = 0; r < mRows;   r)
   for (size_t c = 0; c < mCols;   c)
      result[r*mCols c] = src1[r*mCols c]   src2[r*mCols c]

Here is an example implementation of Mat. I've only done operator so far, but should easily extend to the other operators:

class Mat
{
private:
    size_t mRows;
    size_t mCols;
    std::vector<double> mData;
public:
    // constructors
    Mat(size_t rows, size_t cols, double v = 0.0f)
        : mRows(rows), mCols(cols), mData(mRows*mCols, v)
    {}
    Mat(size_t cols, double v = 0.0f)
        : mRows(1), mCols(cols), mData(mRows*mCols,v)
    {}
    Mat()
        : mRows(0), mCols(0), mData()
    {} 

    // automatic copy & move construction just works^TM using std::vector
    Mat(const Mat&) = default;
    Mat(Mat&&) = default;
    // same with automatic copy & move assignment
    Mat& operator= (const Mat&) = default;
    Mat& operator= (Mat&&) = default;

    // element access
    double getValue(size_t r, size_t c) const
    {
        return mData[r*mCols   c];
    }
    void setValue(size_t r, size_t c, double value)
    {
        mData[r*mCols   c] = value;
    }

    // element access through operator():
    // Mat m(3,3); m(1,2)=5.0f;
    double& operator()(size_t r, size_t c)
    {
        return mData[r*mCols   c];
    }
    const double& operator()(size_t r, size_t c) const
    {
        return mData[r*mCols   c];
    }

    // in place addition saves unnecessary memory allocation & copying
    Mat& operator  = (const Mat& m)
    {
        if (m.mRows != mRows || m.mCols != mCols)
            throw std::runtime_error("Mat: dimensions don't match");
        // since all matrix elements are contiguous in memory, we can simply to a single for loop
        for (size_t i = 0; i < mData.size();   i)
            mData[i]  = m.mData[i];
        return *this;
    }

    
    Mat operator   (const Mat& m) const
    {
        if (m.mRows != mRows || m.mCols != mCols)
            throw std::runtime_error("Mat: dimensions don't match");
        // copy this Mat into a new Mat
        Mat result(*this);
        // add m to result in place and return result
        result  = m;
        return result;
    }
};

CodePudding user response:

Your memory management is broken.

In your copy constructor, you have to copy the contents of mData, not just the pointer. So you need to allocate a new buffer and copy the input data to that.

Your destructor needs to delete mData, you are leaking memory.

In your operators, you can't use a default constructed matrix as the target. You have to create your target with the correct dimensions or it doesn't have a buffer allocated!

The return values of your operators are illegal. You must always return the type specified in the signature. You must not return result.mData[0], not even in the error case! You can either return a default constructed Mat or throw an exception in such case.

  • Related