Re: matrix multiplication

to start with, your matrix isnt the right size

Quote:

Code:

`float *pfaMatrix = new float[nColumnCount `**+** nRowCount];

as for your question, do you know how to multiply matrices? can you convert that into a series of 'mechanical actions'?

Re: matrix multiplication

thanks for your quick response!

why do you think that the size is wrong? because it works well for me (doing matrix additions etc.).

i know how to multiply matrices, but heres the problem better illustrated:

Code:

`a b * y = n`

c d z m

the program would have to do:

[code]n=a*y+b*z and m=c*y+d*z

i figured that it has to be somewhat like this:

for(int nRo = 0; nRow

Re: matrix multiplication

the program would have to do:

Code:

`n=a*y+b*z and m=c*y+d*z`

i figured that it has to be somewhat like this:

for(int nRo = 0; nRow < resmatrix.m_nRowCount; nRow++)

{

for(int nCol = 0; nCol < resmatrix.m_nColumnCount; nCol++)

{

now i have acces to the matrix element holding the resolution(n)

resmatrix.pfaMatrix[nRow * resmatrix.m_nColumnCount + nCol] = /*What should the equation be here*/

}

}

sorry for the screwed up double post.. no edit button.

Re: matrix multiplication

Quote:

why do you think that the size is wrong? because it works well for me (doing matrix additions etc.).

if your matrix is 3x3 how many elements are there? what is 3 + 3?

Two matrices, A(i,j) and B(k,l) can only be multiplied if the inner dimensions are the same, i.e. j==k. The resulting matrix will be of size i x l.

therefore

M(i,l) = A(i,j) * B (k,l)

the 'i,j th' element of M is the sum over r of (A_ir * B_rj).

so you have too loop over row and column for each element of M (as you have already got), and then to calculate the value, you need *another* loop.

Re: matrix multiplication

thanks again.

You were of course right with the size, I always tested with 2x2 matrices.

as for

Quote:

Originally Posted by

**Amleto**
M(i,l) = A(i,j) * B (k,l)

the 'i,j th' element of M is the **sum over r of (A_ir * B_rj)**.

so you have too loop over row and column for each element of M (as you have already got), and then to calculate the value, you need *another* loop.

could you maybe explain the text in bold a little bit further? thanks

yours sincerely,

replax

Re: matrix multiplication

Code:

`A=`

1 2 3

0 0 0

0 0 0

B =

0 3 0

0 2 0

0 1 0

it means something like multiply the elements of the *i*th row of A with the elements of the *j*th column of B to get the *i-j*th element of M (where M = AB).

e.g.

Code:

`M_12 = A_`**1**1 * B_1**2** + A_**1**2 * B_2**2** + A_**1**3 * B_3**2**

M_12 = (1 * 3) + ( 2 * 2) + ( 3 * 1)

Re: matrix multiplication

thanks, I got that part.

now I am a little further, still I am getting not total correct results

Code:

`Matrix operator*(const Matrix &cObj1, const Matrix &cObj2)`

{

float *pfaResMat = new float[cObj1.m_nRowCount * cObj2.m_nColCount];

int i, k, j;

for(i = 0; i < cObj1.m_nRowCount; i++)

{

for(j = 0; j < cObj2.m_nColCount; j++)

{

for(k = 0; k < cObj1.m_nColCount; k++)

{

pfaResMat[i * cObj2.m_nColCount + j] += cObj1.m_pfMatrix[i * cObj1.m_nColCount + k] * cObj2.m_pfMatrix[k * cObj2.m_nColCount + j];

}

}

}

return Matrix(cObj1.m_nRowCount, cObj2.m_nColCount, pfaResMat);

}

with that code, when cObj1 and Obj2 are 2x2 matrices with 1 2 \n3 4 , the result is:

2 4

6 8 instead of

7 10

15 22

do you see the flaw in the code?

yours sincerely,

replax

Re: matrix multiplication

Quote:

Originally Posted by

**replax**
thanks, I got that part.

now I am a little further, still I am getting not total correct results

1) Are you using a debugger to solve your problems? If not, I recommend you do so.

2) Why doesn't your Matrix constructor generate the memory?

Code:

`Matrix operator*(const Matrix &cObj1, const Matrix &cObj2)`

{

float *pfaResMat = new float[cObj1.m_nRowCount * cObj2.m_nColCount]; // This line.

I would have expected something like this:

Code:

`Matrix operator*(const Matrix &cObj1, const Matrix &cObj2)`

{

Matrix temp(cObj1.m_nRowCount, cObj2.m_nColCount); // creates a matrix

And then, you manipulate temp. Having the client generate the memory for the matrix is disjoint and bad design.

3) Stemming from this problem is the reason why your code doesn't work. Where do you initialize this "new" memory to 0?

Code:

`float *pfaResMat = new float[cObj1.m_nRowCount * cObj2.m_nColCount];`

This does not set the data to 0. Then you do this:

Code:

`pfaResMat[i * cObj2.m_nColCount + j] += cObj1.m_pfMatrix[i * cObj1.m_nColCount + k] * cObj2.m_pfMatrix[k * cObj2.m_nColCount + j];`

You are adding something to junk, giving you junk.

If you designed the matrix where it did its own memory handling, then you probably would have noticed this problem sooner.

Regards,

Paul McKenzie

Re: matrix multiplication

thank you for your answer!

Quote:

Originally Posted by

**Paul McKenzie**
2) Why doesn't your Matrix constructor generate the memory?

the problem is, if I use my Matrix constructor to construct a matrix, it will call the destructor before returning the matrix value. thus crashing the programm.

the constructor is:

Code:

`Matrix::Matrix(int nRowCount, int nColCount = 1) : m_nColCount(nColCount), m_nRowCount(nRowCount)`

{

m_pfMatrix = new float[m_nColCount * m_nRowCount];

for(int nRow = 0; nRow < m_nRowCount; nRow++)

{

for(int nCol = 0; nCol < m_nColCount; nCol++)

m_pfMatrix[nRow * m_nColCount + nCol] = 0;

}

}

Matrix::Matrix(int nRowCount, int nColCount, float *fMatrix) : m_nColCount(nColCount), m_nRowCount(nRowCount)

{

m_pfMatrix = new float[m_nColCount * m_nRowCount];

for(int nRow = 0; nRow < m_nRowCount; nRow++)

{

for(int nCol = 0; nCol < m_nColCount; nCol++)

{

m_pfMatrix[nRow * m_nColCount + nCol] = fMatrix[nRow * m_nColCount + nCol];

}

}

}

and the destructor is:

Code:

`Matrix::~Matrix()`

{

if(m_pfMatrix)

{

delete[] m_pfMatrix;

m_pfMatrix = 0; //NULL

}

}

i solved the problem, i did an unbelievably stupid error. in the main.cpp file where i did execute the arithmic expressions i typed '+' instead of '*', which of course gives me my matrix addition instead of multiplication.

thanks to all of you for your kind help!

regards,

replax

Re: matrix multiplication

Quote:

Originally Posted by **replax**

the problem is, if I use my Matrix constructor to construct a matrix, it will call the destructor before returning the matrix value. thus crashing the programm.

That does not really make sense. The destructor will not normally be called from the constructor.

On a hunch: did you implement the copy constructor and copy assignment operator?

Re: matrix multiplication

no, I did not implent the copy constructor.

So when doing

return does copy the matrix and then returns the copy because the original matrix goes out of scope, right? and when the matrix goes out of scope (after the curly braces) it calles the destructor, correct?

so I would need to write a copy constructor, so that return knows how to copy a matrix? buy why do I not need to do that when I use:

Code:

`return Matrix(nRowCount, nColCount, pfaResMat);`

because the returned type is a matrix, too.

Or did I get something essential completly wrong?

regards,

replax

Re: matrix multiplication

Quote:

Originally Posted by

**replax**
no, I did not implent the copy constructor.

So when doing

return does copy the matrix and then returns the copy because the original matrix goes out of scope, right? and when the matrix goes out of scope (after the curly braces) it calles the destructor, correct?

so I would need to write a copy constructor, so that return knows how to copy a matrix? buy why do I not need to do that when I use:

Code:

`return Matrix(nRowCount, nColCount, pfaResMat);`

because the returned type is a matrix, too.

Or did I get something essential completly wrong?

regards,

replax

The principle of the matter is robust code, that means that you should minimise the number of places that you allocate and deallocate memory in your class - when you get on to the subject of exception saftey you will appreciate this point more. A proven pattern for a safe/robust way of allocation and deallocation of resources is the RAII (Resource Acquisition Is Initialization) idiom. This would be a good thing for you to look up, as well as the Rule of Three - i.e. if you write one of the following for your class, then you should probably write all three:

- destructor

- copy constructor

- copy assignment operator

The point in hand, is that you could save yourself a lot of bother and bugs if you adhere to the advice that you are being given with respect to memory management.

Here is an example pattern that you could follow:

Code:

`class matrix`

{

public:

matrix()

:rows_(0)

,columns_(0)

,data_(0)

{}

matrix(size_t rows, size_t columns)

:rows_(rows)

,columns_(columns)

,data_(new float[rows_*columns_])

{

for(size_t i = 0; i<rows_*columns_; i++)

{

data_[i] = 0;

}

}

matrix(const matrix& other)

:rows_(other.rows_)

,columns_(other.columns_)

,data_(new float[rows_*columns_])

{

size_t size = rows_*columns_;

std::copy(other.data_, other.data_+size, data_);

}

void swap(matrix& other)

{

std::swap(rows_, other.rows_);

std::swap(columns_, other.columns_);

std::swap(data_, other.data_);

}

matrix& operator=(const matrix& rhs)

{

matrix tmp(rhs);

swap(tmp);

return *this;

}

~matrix()

{

delete [] data_;

}

float& operator()(size_t row, size_t column)

{

return data_[row*columns_+column];

}

const float& operator()(size_t row, size_t column) const

{

return data_[row*columns_+column];

}

private:

size_t rows_;

size_t columns_;

float* data_;

};

Of course, you could save yourself even more if you use std::vector:

Code:

`#include <vector>`

class matrix

{

public:

matrix()

:rows_(0)

,columns_(0)

,data_()

{}

matrix(size_t rows, size_t columns)

:rows_(rows)

,columns_(columns)

,data_(rows_*columns_)

{}

float& operator()(size_t row, size_t column)

{

return data_[row*columns_+column];

}

const float& operator()(size_t row, size_t column) const

{

return data_[row*columns_+column];

}

private:

size_t rows_;

size_t columns_;

std::vector<float> data_;

};

std::vector will handle the allocation and deallocation for you - you also do not need to write a destructor, a copy assignment operator or a copy constructor, since the default generated ones will be perfectly fine.

Note that the operator()(size_t rows, size_t columns) allows you to access the relevent matrix element.

Code:

`int main()`

{

matrix m(3,3); //create a 3x3 matrix

m(1,1) = 5.2f; //set the central element to 5.2

}

Re: matrix multiplication

Quote:

Originally Posted by

**replax**
thank you for your answer!

the problem is, if I use my Matrix constructor to construct a matrix, it will call the destructor before returning the matrix value. thus crashing the programm.

That is because you didn't write an appropriate copy constructor and assignment operator. How many C++ classes have you used, where your code needs to allocate the memory for the class? I bet none, except only yours.

For example std::string -- why is it that we don't need to allocate memory for the string data? What is the magic that std::string does that your Matrix class is not doing? The answer is that the std::string has implemented proper copy semantics, and your Matrix class hasn't.

Code:

`#include <string>`

std::string DoStuff()

{

std::string s = "abc123";

s += "456";

s = s.substr(0,1);

return s;

}

There is no crash, because on return, the std::string copy constructor makes a copy of s and returns it. Without a user-defined copy constructor, the std::string would suffer the same problem that your Matrix class suffers from.

To correct the problem, I could start naively allocating memory all over the place to make sure the crash doesn't happen, or I give std::string some intelligence and write functions (copy/assignment operator) that tells std::string what to do when making copies of itself.

When you create an object, that object is supposed to handle its own memory, and clean up its own memory. The user of the object shouldn't be doing this work -- it the user has to do this work, then that class is basically useless in a program. The user has to jump through hoops keeping the object valid, doing work the class should be doing. That defeats the whole purpose of using the class to begin with.

Quote:

i solved the problem, i did an unbelievably stupid error. in the main.cpp file where i did execute the arithmic expressions i typed '+' instead of '*', which of course gives me my matrix addition instead of multiplication.

That doesn't mention the problem I pointed out to you, and that is you are allocating memory that is not initialized to 0. Did you fix that problem?

Regards,

Paul McKenzie

Re: matrix multiplication

thanks for the very constructive input!

as for now, I got it working as far as I can see it. Now my constructors are the same, I just fixed the allocation that was not initialized to 0 and added the copy constructor:

Code:

`Matrix::Matrix(Matrix &cSource)`

{

m_nRowCount = cSource.m_nRowCount;

m_nColCount = cSource.m_nColCount;

m_pfMatrix = new float[m_nRowCount * m_nColCount];

for(int nRow = 0; nRow < m_nRowCount; nRow++)

{

for(int nCol = 0; nCol < m_nColCount; nCol++)

m_pfMatrix[nRow * m_nColCount + nCol] = cSource(nRow, nCol);

}

}

and also the overloaded assingment operator:

Code:

`Matrix& Matrix::operator=(Matrix &cSource)`

{

if(this == &cSource)

return *this;

m_nRowCount = cSource.m_nRowCount;

m_nColCount = cSource.m_nColCount;

for(int nRow = 0; nRow < m_nRowCount; nRow++)

{

for(int nCol = 0; nCol < m_nColCount; nCol++)

m_pfMatrix[nRow * m_nColCount + nCol] = cSource(nRow, nCol);

}

return *this;

}

so that my multiplication algorithm now looks like this:

Code:

`Matrix operator*(Matrix &cObj1, Matrix &cObj2)`

{

Matrix pfaResMat(cObj1.m_nRowCount, cObj2.m_nColCount);

int i, k, j;

for(i = 0; i < pfaResMat.m_nRowCount; i++)

{

for(j = 0; j < pfaResMat.m_nColCount; j++)

{

pfaResMat(i, j) = 0;

for(k = 0; k < cObj1.m_nColCount; k++)

pfaResMat(i, j) += cObj1(i, k) * cObj2(k, j);

}

}

return pfaResMat;

}

and it works like a charm as far as I can tell.

all other overloaded operators( (), *(by int or float), +) also work perfectly well.

if you see some flaws, leaks or anything that should be inprooved, I would be very happy to know :)

regards,

replax