0
votes

I have this basic template matrix class:

template<class T, unsigned N>
class Matrix {
private:
    static const unsigned Stride = N;
    static const unsigned Size = Stride * Stride;
    T data[Size] = {};

public:
    Matrix() {};
    Matrix( const T* dataIn ) {
        fillMatrix( dataIn );
    }

    void fillMatrix( const T* dataIn );
    void printMatrix();
};

template<class T, unsigned N>
void Matrix<T, N>::fillMatrix( const T* dataIn ) {
    for( unsigned int i = 0; i < Size; i++ ) {
        this->data[i] = dataIn[i];
    }
}

template<class T, unsigned N>
void Matrix<T, N>::printMatrix() {
    for( unsigned int i = 0; i < Stride; i++ ) {
        for( unsigned int j = 0; j < Stride; j++ ) {
            std::cout << this->data[i*Stride + j] << " ";
        }
        std::cout << '\n';
    }
}

Which works fine! The data is populated correctly and it displays correctly. However, when I try to expand the above Square 2D Matrix to a MxN Matrix as such:

template<class T, unsigned M, unsigned N>
class Matrix {
private:
    static const unsigned Row = M;
    static const unsigned Col = N;
    static const unsigned Size = M * N;
    T data[Size] = {};

public:
    Matrix() {};
    Matrix( const T* dataIn ) {
        fillMatrix( dataIn );
    }

    void fillMatrix( const T* dataIn );
    void printMatrix();
};

template<class T, unsigned M, unsigned N>
void Matrix<T,M,N>::fillMatrix( const T* dataIn ) {
    for( unsigned int i = 0; i < Size; i++ ) {
        this->data[i] = dataIn[i];
    }
}

template<class T, unsigned M, unsigned N>
void Matrix<T,M,N>::printMatrix() {
    for( unsigned int i = 0; i < Row; i++ ) {
        for( unsigned int j = 0; j < Col; j++ ) {
            std::cout << this->data[i*Row + j] << " ";
        }
        std::cout << '\n';
    }
}

I'm not getting the proper values: For example if I pass into this class template an array as such double data[6] = { 1,2,3,4,5,6 }; With an instantiation of a Matrix<double, 2,3> to be a 2x3 Matrix I'm getting the values and printout as:

1 2 3
3 4 5

I would be expecting the data and output to be.

1 2 3
4 5 6

For some reason it is applying 3 twice and not adding 6 at all to the matrix.

Am I populating this MxN matrix wrong in the fillMatrix() function and or displaying it wrong by indexing in the printMatrix() function. I know this is fairly trivial but I'm overlooking this and can not seem to find what I'm missing.


EDIT

I was working with the debugger and looking at the class's member data[Size] and it was populated with the correct values, so this was leading me to think or suspect that the issue is within the printMatrix() function. Just as I was doing this a few users had posted useful answers! My logic seemed right at first but the ordering was wrong.

User: RandomBits's answer actually solves the issue. User: Matthieu Brucher's answer explains the issue.

I would like to accept both answers but can only accept one. Thank you both for the informative information. I will leave this question open for now.

2
Fyi, if done correctly, you should be able to get pretty close to a 2D matrix using your 1D implementation just by doing template<class T, size_t M, size_t N> using Matrix2D = Matrix<Matrix<T,N>,M>; or something similar.WhozCraig
@WhozCraig I'm sure it can be done; but I'm using the later or 2nd Matrix to answer another question so I just wanted it to be simple. To answer their question the 2D square matrix isn't sufficient enough, so I was expanding it to be an arbitrary MxN matrix and I don't want to add confusion to using the first to create the later.Francis Cugler

2 Answers

2
votes

The double vector you pass in has the elements in C order if you interpret it as a 2-d array while your print function is printing the elements in Fortran order. Change i*Row + j to i*Col+j.

1
votes

You have the wrong display. i is your row index, you need to multiply it with Col, not Row.

Think about the indices, j moves from 0 to Col-1, so when you move to another row, you need to increase the index according to this.