I think you requireCode:R.elems[nr].Linie = new int[nr];
R.elems[nr].Coloana = new int[nr];
R.elems[nr].Valoare = new double[nr];
since elems is a vector.Code:R.elems.resize(nr);
Printable View
I think you requireCode:R.elems[nr].Linie = new int[nr];
R.elems[nr].Coloana = new int[nr];
R.elems[nr].Valoare = new double[nr];
since elems is a vector.Code:R.elems.resize(nr);
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;
}
}
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:// ADDITION A + B
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;
}
Thank you very much !
Now, work OK :)
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.