CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com

1. ## Re: Sparse Matrix Operations

Code:
R.elems[nr].Linie = new int[nr];
R.elems[nr].Coloana = new int[nr];
R.elems[nr].Valoare = new double[nr];
I think you require
Code:
R.elems.resize(nr);
since elems is a vector.

2. ## Re: Sparse Matrix Operations

Unless I've misunderstood what you are trying to achieve, you seem to be making very heavy weather of doing this. Consider the code below which reads in 2 files in the .mtx format, displays their contents, produces a new matrix which is their sum and displays this matrix. Various improvements could be made to this code which I'll leave to you.

Code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

const string fa = "mata.mtx";
const string fb = "matb.mtx";

class matrix {
public:
matrix(int col, int row) : cols(col), rows(row), elems(new double[col * row])
{
memset(elems, 0, sizeof(double) * col * row);
}

~matrix() {
delete[] elems;
}

matrix(const string& fn)
{
ifstream fma(fn);
if (!fma.is_open()) {
cout << "Cannot open " << fn << endl;
return;
}

string tmp;
while (fma.peek() == '%')
getline(fma, tmp);

int noelems;

fma >> rows >> cols >> noelems;
elems = new double[cols * rows];
memset(elems, 0, sizeof(double) * cols * rows);

int r, c;
double v;

while (fma >> r >> c >> v)
operator()(c - 1, r - 1) = v;

fma.close();
}

matrix(const matrix& ma)
{
cols = ma.cols;
rows = ma.rows;
elems = new double[cols * rows];
memcpy(elems, ma.elems, sizeof(double) * cols * rows);
}

matrix(matrix&& ma)
{
cols = ma.cols;
rows = ma.rows;
elems = ma.elems;
ma.elems = nullptr;
}

double& operator()(int c, int r)
{
return elems[c * cols + r];
}

const double& operator()(int c, int r) const
{
return elems[c * cols + r];
}

int noRows() const
{
return rows;
}

int noCols() const
{
return cols;
}

matrix operator=(matrix&&) = delete;
matrix operator=(const matrix&) = delete;

private:
int cols = 0;
int rows = 0;
double *elems = nullptr;
};

ostream& operator<<(ostream& os, const matrix& ma)
{
for (int r = 0; r < ma.noRows(); ++r) {
for (int c = 0; c < ma.noCols(); ++c)
os << ma(c, r) << " ";

os << endl;
}

return os;
}

matrix operator+(const matrix& ma, const matrix& mb)
{
if ((ma.noCols() != mb.noCols()) || (ma.noRows() != mb.noRows())) {
cout << "cols/rows don't match" << endl;
return matrix(0, 0);
}

matrix s(ma.noCols(), ma.noRows());

for (int r = 0; r < ma.noRows(); ++r)
for (int c = 0; c < ma.noCols(); ++c)
s(c, r) = ma(c, r) + mb(c, r);

return s;
}

int main()
{
matrix A(fa);

if (A.noCols() == 0)
return 1;

cout << "Matrix A" << endl;
cout << A;

matrix B(fb);

if (B.noCols() == 0)
return 2;

cout << endl << "Matrix B" << endl;
cout << B;

matrix S = A + B;

if (S.noCols() != 0) {
cout << endl << "Matrix sum" << endl;
cout << S;
}
}
Last edited by 2kaud; May 3rd, 2016 at 04:36 PM.

3. Elite Member Power Poster
Join Date
Aug 2000
Location
West Virginia
Posts
7,716

## Re: Sparse Matrix Operations

1) Since you are using std::vector, you will not need to
do a "new" to increase the size of sum matrix. You can
simply push_back() the element.

2) As a first pass, I would choose a simple method:

a) set the sum matrix equal to the first matrix.

b) loop thru the second matrix ... for each (i,j) combination
in the second matrix, see if the combination is in the first
matrix. If it is, add the values. If it is not, create a
new element and do a push_back() to the sum matrix. There
are other containers besides std::vector that would make this
step faster.

Code:
MatriceRara Sum(const MatriceRara& M1, const MatriceRara& M2)
{
MatriceRara R;

if (M1.nrLinii != M2.nrLinii || M1.nrColoane != M2.nrColoane)
{
cout << "Eroare: Matricele trebuie sa aiba dimensiuni egale." << endl;

return R;
}

R = M1;  // set the sum equal to the first matrix

// loop thru the second matrix ... if the element exists
// in the first matrix, add it to the sum.  If it does
// not exist, create a new element in the sum.

for (int j = 0; j<M2.nrElemente; ++j)
{
bool found = false;
for (int i = 0; i<M1.nrElemente; ++i)
{
if (M1.elems[i].Linie == M2.elems[j].Linie &&
M1.elems[i].Coloana == M2.elems[j].Coloana)
{
found = true;
R.elems[i].Valoare += M2.elems[j].Valoare;
break;
}
}

if (!found) // element is in M2, but not in M1
{
Elems el;
el.Linie = M2.elems[j].Linie;
el.Coloana = M2.elems[j].Coloana;
el.Valoare = M2.elems[j].Valoare;

R.elems.push_back(el);
}
}

// remove elements that equal 0.0
auto value_0 = [](const Elems & el) { return el.Valoare == 0.0; };
R.elems.erase(remove_if(R.elems.begin(), R.elems.end(), value_0), R.elems.end());

R.nrElemente = R.elems.size();

return R;
}

4. Junior Member
Join Date
Apr 2016
Posts
8

## Re: Sparse Matrix Operations

Thank you very much !
Now, work OK

5. ## Re: Sparse Matrix Operations

Originally Posted by 2kaud
Unless I've misunderstood what you are trying to achieve, you seem to be making very heavy weather of doing this.
I believe the original goal was to get this working for sparse matrix implementations?

6. ## Re: Sparse Matrix Operations

Originally Posted by monarch_dodra
I believe the original goal was to get this working for sparse matrix implementations?
Yes, but the OP's post #15 mentions converting sparse matrix to full matrix. If the full matrices can be held in memory and depending upon the size of the matrices and the number of used elements, the operations on a full matrix may be more efficient than on a sparse matrix structure. The best method in a particular situation will depend upon the size of the matrices and number of used elements.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•