I have implemented a matrix class. It dynamically allocates memory for an arbitrarily sized matrix.When using my matrix multiplication function, it only works under specific conditions. If you have two N*M matrices, M of the first matrix must equal N of the second matrix. Example:
//matrix constructor 'matrix M(n, m)
matrix A(2, 3), matrix B(3, 4);
//A and B can be multiplied because A_m == B_n
A * B; //this works!
//changing the size of n of the first matrix causes this to fail if n > m
matrix C(4, 3), matrix D(3, 5);
C * D; // program becomes unresponsive for unknown reasons, only happens when C_n > C_m
My matrix class and the multiplication function.
#include <iostream>
class matrix{
private:
int rows, cols;
public:
int ** data;
int row();
int col();
matrix();
matrix(int, int);
//~matrix();
matrix operator*(matrix M);
matrix operator%(matrix M);
friend std::ostream & operator<<(std::ostream & os, matrix M);
};
Functions:
#include "matrix.h"
using std::cout;
using std::endl;
matrix::matrix(int r, int c){
rows = r;
cols = c;
data = new int*[rows];
for (int i = 0; i< rows; i++){
data[i] = new int[cols];
}
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
data[i][j] = 0;
}
}
}
matrix::row(){
return rows;
}
matrix::col(){
return cols;
}
matrix matrix::operator*(matrix M){
if (this->col() == M.row()){
matrix result(this->row(), M.col());
int var = 0;
for (int i = 0; i < result.row(); i++){
for (int j = 0; j < result.col(); j++){
for (int k = 0; k < result.row(); k++){
var += this->data[i][k] * M.data[k][j];
}
result.data[i][j] = var;
var = 0;
}
}
return result;
}
else cout << "FAILED";
}
std::ostream & operator<<(std::ostream & os, matrix M){
for (int i = 0; i < M.row(); i++){
os << '|';
for (int j = 0; j < M.col(); j++){
os << M.data[i][j] << ' ';
}
os << "|\n";
}
os << '\n';
return os;
}
Why is the program not working under these circumstances?
First off, props for
using std::cout;
using std::endl;
Good to see someone not pulling in all of std for a simple job like this.
Now let's take a walk through the algorithm.
matrix C(4, 3) * matrix D(3, 5) will give matrix result (4,5)
for (int i = 0; i < result.row(); i++){
for (int j = 0; j < result.col(); j++){
for (int k = 0; k < result.row(); k++){
resolves to
for (int i = 0; i < 4; i++){
for (int j = 0; j < 5; j++){
for (int k = 0; k < 4; k++){
var += this->data[i][k] * M.data[k][j];
Array size: 4 3 3 5
k is going to run 0 .. 3. Valid range for k is 0 .. 2.
What you want is:
for (int i = 0; i < result.row(); i++){
for (int j = 0; j < result.col(); j++){
for (int k = 0; k < this->cols; k++){
Three suggestions:
Learn to use a debugger. This sort of problem is utterly trivial if you step through the code.
Then learn to test with testable inputs so you can see when the math does not work. Multiplying 0 by 0 will prove absolutely nothing.
I recommend replacing
int ** data;
with
std::vector<std::vector<int> > data;
You can initialize it in a constructor like this:
matrix::matrix(int r, int c):rows(r), cols(c), data(r, std::vector<int>(c))
{
}
No need to loop through it to zero it. The vector constructor does it for you. If you don't want to load with zeroes, you can specify another value.
matrix::matrix(int r, int c):
rows(r),
cols(c),
data(r, std::vector<int>(c, <starting value goes here>))
{
}