Computer Science Canada

Creating and manipulating a m x n matrix

Author:  np_123 [ Sat May 16, 2015 5:50 pm ]
Post subject:  Creating and manipulating a m x n matrix

Goal: I am trying to write a program that can store and manipulate matrices.
My idea was to write a Matrix class and then when I call the constructor, create an instance of the class and also continue on to initialize the matrix values using user input.
After reading this tutorial by wtd about using the vector class instead of arrays, I decided to try using it. Though you'll notice I did kinda use array as well.

Problem/Difficulty: At the moment, I do not fully understand how to use static variables - I think that might be very relevant to what I am trying to achieve. I'm trying to figure out where and how I should create and initialize the vector/array that will contain the matrix.

Intuition as well as some programming experience in Python and Java tell me that I have the declaration of the vector in entirely the wrong spot(currently in the constructor):
code:
Matrix(){
        vector<double> matrix[row];
        cout << "Matrix Builder \n";
        init_size();
        init_matrix(matrix);
}


This is the code I currently have, and it does actually compile fine:

code:
#include <iostream>
#include <vector>


using namespace std;

class Matrix {

        int row;
        int column;

        void init_size() {

                cout << "Please enter the number of rows: ";
                cin >> row;

                cout << "Please enter the number of columns: ";
                cin >> column;
        }

        void init_matrix(vector<double> matrix[]) {

                double data;

                for (int counter1 = 0; counter1 < row; counter1++) {
                        cout << "Please enter row " << counter1 + 1 << endl;

                        for (int counter2 = 0; counter2 < column; counter2++) {
                                cout << "Enter Row " << counter1 + 1 << " Column " << counter2 + 1 << ": ";
                                cin >> data;
                                matrix[counter1].push_back(data);
                        };
                };
        };

        public:
                Matrix(){
                        vector<double> matrix[row];
                        cout << "Matrix Builder \n";
                        init_size();
                        init_matrix(matrix);
                }

                int row_size() {
                        return row;
                }

                int column_size() {
                        return column;
                }

};

int main () {

        Matrix m;

        return 0;
}


And I would also like to add other public methods, which I am pretty confident cannot be done "properly" given where I have the vector declared.
An example of a method I would like to add:

code:
void toString() {
        for (int x = 0; x < row; x++) {
                for (int y = 0; y < column; y++) {
                        cout << matrix[x].at(y) << " ";
                }
        cout << endl;
        }
}


side note: I think the code tag may have messed up my indentation when I copy/pasted my code. Also, though I doubt it makes a difference, I'm using Eclipse IDE and set that up with MinGW compiler.

Author:  DemonWasp [ Sat May 16, 2015 6:23 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

I don't think you want to use static variables.

I think you want to put your vector (or array, or whatever) with your other member variables (row, column).

I think you also want your constructor to accept a number of rows and columns as arguments rather than using cin or cout. Put your cin/cout stuff somewhere else (your main method?) and call the Matrix constructor only when you know the size of the matrix you plan to construct. Constructors should only be responsible for setting up an object correctly -- not necessarily knowing what parameters it needs to have.

Hint: your main method should look more like this:
code:

int main () {
    int row, column;
    cout << "Please enter the number of rows: ";
    cin >> row;
    cout << "Please enter the number of columns: ";
    cin >> column;

    Matrix m ( r, c );
    return 0;
}

Author:  np_123 [ Sat May 16, 2015 7:09 pm ]
Post subject:  Re: Creating and manipulating a m x n matrix

ok, yeah that makes a lot more sense than the way I had it. I've changed that, and it seems working properly and ready for me to add some more methods and stuff to it.
And actually, I think by making those changes I can change it from being an array of vectors, to a 2D vector which can be initialized just as easily, and hopefully manipulated easier than an array.

Author:  wtd [ Mon May 18, 2015 5:15 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

Yes, you want the place where you actually store your matrix to be a member variable. Assuming we make the class templated with type T... then you want the following member function, such that it doesn't matter how you store the matrix, be it a vector, or a simple array.

code:
T valueAt(int column, int row)
{
   // ...
}

Author:  np_123 [ Thu May 21, 2015 5:02 pm ]
Post subject:  Re: Creating and manipulating a m x n matrix

So it's been a couple days and I've added a lot to my code. I was wondering if it is okay/safe to assign *this to a variable and also pass *this to a method.

*this is a pointer/reference to the current instance, right? Somewhat similar to self in python?

code:
Matrix exponent(int exp){

        if (num_rows() != num_cols()){
                throw "Error: Must be a square matrix to multiply by itself";
        }

        Matrix product = *this;
        for (int x = 1; x < exp; x++){
                product = product.multiply(*this);
        }
        return product;
}

Author:  DemonWasp [ Thu May 21, 2015 5:37 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

This line:

code:
Matrix product = *this;


means "please create a Matrix on the stack, and call the assignment operator on that matrix, using this matrix as an argument".

Similarly, the line:

code:
product = product.multiply(*this)


means "please pass a copy (copy-ctor) of this matrix to product.multiply() and then call the assignment operator on product with the result matrix as an argument"

And then:

code:
return product;


means "please return a Matrix object, which must then be consumed by a copy constructor or assignment operator or other method call".

Fortunately, your class has trivial copy constructors and assignment operators, so the compiler has been nice enough to build them for you, and your code as-written is correct. (Probably--I haven't actually checked).

Even more fortunately, a lot of your copies are being elided (see http://en.wikipedia.org/wiki/Copy_elision and http://en.wikipedia.org/wiki/Return_value_optimization ). That means that you don't have to pay (in performance) for them!

You'll still have some copies, but if your matrices are smallish (eg 4x4, and not 1000x1000 or larger), then those copies will be very fast. If you are intending to work with larger matrices / objects, then you might consider return-by-reference or return-by-pointer (as opposed to return-by-value, which you are currently using). There are other drawbacks to those approaches, and they can make it a lot harder to write correct programs which don't leak memory everywhere. Start with return-by-value until you're more comfortable in the language.

Author:  np_123 [ Fri May 22, 2015 3:43 pm ]
Post subject:  Re: Creating and manipulating a m x n matrix

so then the way i have the code there, this line creates one copy:
code:
Matrix product = *this;


does each iteration of the for loop result in a new copy being created, as this line executes?
code:
product = product.multiply(*this)

Or is it just a single copy being made and passed as an argument there, and referencing the same memory address each time?

Author:  DemonWasp [ Fri May 22, 2015 5:57 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

Officially (that is, ignoring copy elision / return value optimization), you get a copy each time you pass *this into product.multiply(...), and you get an assignment operator from the result of that function call into product.

...I think. I'm not a C++ expert, so I'm not 100% sure.

Many of those copies / assignments can be skipped, and so RVO helps you out a lot there. It can be tough to know how much, though, because some compilers are better than others. You could try overriding the copy constructor yourself and outputting some string every time the copy-constructor is called. While you're at it, override the destructor and assignment operator the same way. The results will almost certainly surprise you.

Author:  wtd [ Fri May 22, 2015 10:44 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

Your multiply member function can be declared as either taking a Matrix object, or as taking a pointer to a Matrix object. If it takes a pointer, then no copying is necessary.

Author:  np_123 [ Sat May 23, 2015 11:07 am ]
Post subject:  RE:Creating and manipulating a m x n matrix

I'm still pretty new to C++ so I don't really know how pointers work. And I've looked in the tutorial section and didn't see a tutorial that covers them much so I'll have to look around to read up on it.

This matrix calculator is actually the first program I'm writing in C++ so I still got loads to learn

Author:  wtd [ Sat May 23, 2015 11:35 am ]
Post subject:  RE:Creating and manipulating a m x n matrix

Pointers are basically an address to another place in memory. From your perspective, passing objects around as values is simpler and cleaner, but it mans that values are getting copied around on the stack, and quite possibly unnecessarily.

With a pointer, you're allocating the memory for your object on the heap, then passing its address in memory to functions. The function can then dereference the pointer to get to the actual memory for the object.

Author:  wtd [ Sat May 23, 2015 11:56 am ]
Post subject:  RE:Creating and manipulating a m x n matrix

Something I'd like you to consider and try to figure out before asking questions. I no we don't normally like to give out easy answers, but I'm guessing it'll take you a bit to sort this one out.

code:
template <typename T> class Matrix
{
        public:
                Matrix(int _rows, int _columns);
                ~Matrix();

                T get(int _row, int _column);
                void set(int _row, int _column, T value);

        private:
                int rows;
                int columns;

                T* storage;
};

template <typename T>
Matrix<T>::Matrix(int _rows, int _columns)
: rows(_rows), columns(_columns)
{
        storage = new T[rows * columns];
}

template <typename T>
Matrix<T>::~Matrix
{
        delete[] storage;
}

template <typename T>
T Matrix<T>::get(int _row, int _column)
{
        return storage[_row * _column];
}

template <typename T>
void Matrix<T>::set(int _row, int _column, T value)
{
        storage[_row * _column] = value;
}


Also, it's been awhile since I've written anything in C++, and I didn't test this code, so it may not actually work.

Author:  np_123 [ Sat May 23, 2015 3:21 pm ]
Post subject:  Re: Creating and manipulating a m x n matrix

wtd wrote:
I no we don't normally like to give out easy answers

Not exactly sure what you mean there by 'easy answers'. Are you referring to my questions, the answers given above, the code you posted, or what?

In any case, yeah, it did take some time for me to try and work out how the template and pointer works. here's what I make of the code:

T is a type to be specified when the constructor is called. It allows the class to deal with various datatypes rather than just a single one. And that's why you have
code:
T get(int _r, int _column);
This means that the return value will be of whatever type is specified, be it int, double, char, etc. - which makes me wonder though if there is much advantage to be gained if writing a class where you will be dealing with only one type of data.

storage is a pointer that will point to a memory address storing a value of type T
code:
T* storage;


The constructor for the class, including arguments for initializing rows and columns. Double semicolon shows that it is a member of the class, but just defined outside of the class declaration.
code:
Matrix<T>::Matrix(int _rows, int _columns)
: rows(_rows), columns(_columns)


This is telling storage what memory address to point to? Perhaps allocating the memory, but not actually initializing any values yet:
code:
storage = new T[rows * columns];


The destructor for the class, wherein you delete/clear the memory address that storage points to:
code:
Matrix<T>::~Matrix
{
        delete[] storage;
}
And then there's the get and set methods to access and assign values, respectively. Pretty sure that covers it all?

Author:  DemonWasp [ Sat May 23, 2015 3:51 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

I have to point out: the get and set implementations that wtd gave are incorrect. The correct index is _row * columns + _column.

Author:  wtd [ Sat May 23, 2015 7:09 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

Doh!

Author:  wtd [ Sat May 23, 2015 7:11 pm ]
Post subject:  RE:Creating and manipulating a m x n matrix

I mean, that was a test to see if you were paying attention.

Yeah, that's it.

Definitely didn't just make a silly mistake.

Good job, DemonWasp. You pass the test.

:shiftyeyes:


: