dimanche 1 novembre 2015

Segmentation fault (core dumped) - matrix class

I'm trying to implement matrix class to handle sparse matrices. Basically I store matrix as two vectors of vectors: the first one stores values (of type double) row-wise and the second one stores respective column indices (thus type is int) of these values. For example, matrix A = {{5,0,0},{0,0,7},{3,1,0}} is stored as entries_ = {{5},{7},{3,1}} and columnIndices_ = {{1},{3},{1,2}}.

My code so far is as follows:

class SparseMatrix
{
    private:
        vector<vector<double> > entries_;
        vector<vector<int> > columnIndices_;
    public:
        SparseMatrix();
        SparseMatrix(vector<vector<double> >,vector<vector<int> >);
        ~SparseMatrix();

        // getters
        vector<vector<double> > getEntries();
        vector<vector<int> > getColIndices();

        vector<int> size();
        void add_entry(double,unsigned int,unsigned int);
};

Method add_entry(double value, unsigned int i, unsigned int j) is supposed to put value on (i,j) coordinate of the matrix. I want this method to be able to extend the matrix if given coordinates are beyond its scope. I (partially) wrote it, but extension does not seem to work (causes segmentation fault). This is the code I came up with:

void SparseMatrix::add_entry(double value, unsigned int i, unsigned int j)
{
    int M = (*this).size()[0]; // current number of rows
    int N = (*this).size()[1]; // current number of columns

    if(i>M || j>N)
    {
        int diff_rows = i-M;
        int diff_cols = j-N;

        if(diff_rows > 0) // extend by adding rows
        {
            entries_.resize(i); // resize current entries_ so it can store more elements
            columnIndices_.resize(i); // same for columnIndices_

            vector<vector<double> >::iterator iterVal;
            iterVal = entries_.begin() + i; 

            vector<vector<int> >::iterator iterInd;
            iterInd = columnIndices_.begin() + i;

            entries_.insert(iterVal,{value});
            columnIndices_.insert(iterInd,{j});
        }
        if(diff_cols > 0) // extend by adding columns
        {
            entries_[i].push_back(value);
            columnIndices_[i].push_back(j);
        }
    }
    else
    {
        if(find(columnIndices_[i].begin(),columnIndices_[i].end(), j) != columnIndices_[i].end()) 
        /* check if index j is in columnIndices_[i]; if it is, then there is a non-zero value there,
           if it is NOT there, it means that on (i,j) position is zero
        */
        {
            char choice;
            cout << "There is a non-zero element on (" << i << ", " << j << ") position." << endl;
            cout << "Would you like to replace it by " << value << "? [Y/n]: ";

            do
            {   
                cin >> choice;
                if(choice == 'n' || choice == 'N')
                {
                    cout << "Element was not replaced." << endl;
                    return;
                }
                if(choice == 'y' || choice == 'Y')
                {
                    // how to get (i,j) element from existing representation??...
                    return;
                }
                else
                    cout << "Invalid choice. Try again..." << endl;
            }
            while(choice == 'n' || choice == 'N' || choice == 'y' || choice == 'Y');
        }
        else
        {
            entries_[i].push_back(value); // push value at the end of i-th vector (row)
            columnIndices_[i].push_back(j); // store index of newly added value at the end of i-th row
            cout << "Matrix has been updated." << endl;
        }   
    }
}

And main() function:

int main(int argc, char const *argv[])
{
    vector<vector<double> > values {{3.0, 1.0}, {2.0}, {5.0, 4.0}};
    vector<vector<int> > columns {{1,3}, {1}, {2,3}};

    SparseMatrix A(values,columns);

    cout << "Matrix A has dimensions " << A.size()[0] << "x" << A.size()[1] << "." << endl;
    A.add_entry(7.0,8,0); // segmentation fault happens here...
    cout << "Matrix A has dimensions " << A.size()[0] << "x" << A.size()[1] << "." << endl;

    return 0;
}

My compiler is g++ with flag -std=c++11 and I'm writing my code on Ubuntu 14.04.

Thanks for any help.

Aucun commentaire:

Enregistrer un commentaire