0

I have been given the following code in a test.cpp file to implement:

cout << "Case 2: the non-static Transpose function" << endl;
{
    double column[4] = {2, 1, 0, -1};
    double row[3] = {2, 0, -1};
    Matrix matrix = Matrix::Toeplitz(column, 4, row, 3);
    cout << "The original Matrix = " << endl;
    cout << matrix << endl;  //This part of the code works


    matrix.Transpose();  //How do I implement this?
    cout << "The transposed version = " << endl;
    cout << matrix << endl;
    cout << "Press any key to continue ..." << flush;
    system("read");
    cout << endl;
}

The way Matrix::Toeplitz(column, 4, row, 3) works is as follows:

Matrix Matrix::Toeplitz(const double* column, const int noOfRows, const double* row, const int noOfColumns){
    Matrix outT(column, noOfRows, row, noOfColumns);
    return outT;
}

So how would I implement matrix.Transpose()? My code so far is as follows:

Matrix& Matrix::Transpose () {

double newrow[noOfRows];
for(int i=0; i<noOfRows; i++){
    int index = GetIndex(i,0);
    newrow[i] = data[index];
}

double newcol[noOfColumns];
for(int i=0; i<noOfColumns; i++){
    int index = GetIndex(0,i);
    newcol[i] = data[index];
}

Matrix outT(newcol, noOfColumns, newrow, noOfRows);
}

This has no effect on cout<<matrix<<endl;

I was thinking that Matrix outT(newcol, noOfColumns, newrow, noOfRows); should give new information (i.e. switching the column and row arrays) to the matrix object when implementing matrix.Transpose but it hasn't been working.

Is this the correct format Matrix& Matrix::Transpose () for implementing matrix.Transpose()?

1 Answers1

2

Matrix::Transpose can't return a reference to a locally declared object. This will lead to many problems.

See C++ Returning reference to local variable.

It must return by copy (then, function can be const, as current object is not being modified):

Matrix Matrix::Transpose() const
{
    double newrow[noOfRows];
    for(int i=0; i<noOfRows; i++){
        int index = GetIndex(i,0);
        newrow[i] = data[index];
    }

    double newcol[noOfColumns];
    for(int i=0; i<noOfColumns; i++){
        int index = GetIndex(0,i);
        newcol[i] = data[index];
    }

    return Matrix(newcol, noOfColumns, newrow, noOfRows);
}

Then, you use it this way:

Matrix transposed = matrix.Transpose(); // does not modify matrix object
cout << "The transposed version = " << endl;
cout << transposed << endl;

If returning Matrix&, you need to have your method transpose the current object and return it (return *this), only useful to help caller to chain many operators (like doing m.Transpose().Transpose() for instance).

Then, it could be (not tested):

Matrix& Matrix::Transpose() 
{
    // backup old content
    double* backupData = new double[noOfRows*noOfColumns];
    memcpy( backupData, data, sizeof(double)*noOfRows*noOfColumns );

    // change matrix geometry
    int oldRowCount = noOfRows;
    noOfRows = noOfColumns;
    noOfColumns = oldRowCount ;

    // transpose matrix by copying from backup content
    for ( unsigned int line = 0; line < noOfRows ; ++line )
    {
        for ( unsigned int col = line; col < noOfColumns; ++col )
        {
            data[line * noOfColumns + col] = backupData[col * noOfRows  + line];
        }
    }

    delete [] backupData;

    return *this;
}

Then, you use it this way:

matrix.Transpose(); // modifies matrix object
cout << "The transposed version = " << endl;
cout << transposed << endl;
Community
  • 1
  • 1
jpo38
  • 20,821
  • 10
  • 70
  • 151
  • This still doesn't change my matrix to being transposed. It seems like my destructor is being called before the transposed version has been printed – MachoSkinny Jan 06 '16 at 14:14
  • For the first part it calls the Matrix(colarray, noRows, rowarray, noCols) function and prints the original Matrix then when I try to implement the second part matrix.Transpose the Matrix(colarray, noRows, rowarray, noCols) function is called again as expected but then a destructor is called before the exact same matrix is printed again – MachoSkinny Jan 06 '16 at 14:25
  • Looks like you're completely lost in the notion of class and object. You don't seem to realize which objects you are modifying (a `Transpose` method returning a new transposed `Matrix`is different than a `Transpose` method transposing the current object). I would recommened that you read somes tutorial on C++ before trying complex operations like this. Anyway, I updated my post to show how Transpose can modify the current object. – jpo38 Jan 06 '16 at 14:44
  • I've got it working, but in a bit of a different way and it's a bit of a mess so I'll need to tidy it up before I post what actually worked on here – MachoSkinny Jan 08 '16 at 16:18
  • I assume you meant to write row instead of line in your first for loop? Everything else is the same for it to work apart from GetIndex(col, row) used for backupData index doesn't work as the GetIndex(row, col) used for the data actually has to use a different formula. – MachoSkinny Jan 10 '16 at 22:43
  • data[index = rowIdx + columnIdx*noOfRows] = backupData[rowIdx*noOfColumns + columnIdx] works for me – MachoSkinny Jan 10 '16 at 22:44
  • Depends if you swapped `noOfRows` and `noOfColumns` before opr after the loop. If so, `data[rowIdx + columnIdxnoOfRows]` can't be correct, at this point, you may use `GetIndex`, and it does not return `rowIdx + columnIdxnoOfRows`. Check your solution works with square and non square random matrixes, I doubt it will. – jpo38 Jan 11 '16 at 07:41