Thread: more matrix problems

  1. #1
    Registered User
    Join Date
    May 2009
    Posts
    242

    more matrix problems

    same template class as in the other thread, but i'll post the current prototypes first for orientation:

    Code:
    template<typename T, int n> // n is the Matrix height/width
    class Matrix
    {
    private:
    	T** content;	// 2-dimensional array of T objects
    public:
    	// default constructor should use default T object if there is one
    	Matrix();
    	// creates uniform Matrix (all values = t)
    	Matrix(const T& t);
    	// construct a Matrix from an array
    	Matrix(const T arr[][n]);
    	// copy constructor
    	Matrix(const Matrix& m);
    	// destructor
    	~Matrix();
    
    	// assignment
    	Matrix<T, n>& operator=(const Matrix<T, n>& m);
    	// 'at' function (indexing)
    	T at(const int i, const int j);
    
    	// basic matrix operations
    	// addition
    	Matrix<T, n> operator+(const Matrix<T, n>& m) const;
    	// scalar multiplication
    	friend Matrix<T, n> operator*(T t, const Matrix<T, n>& m);
    	//Matrix<T, n> scalar_mult(const T& t) const;
    
    	// other methods
    	void show();
    };
    The 'at' function is my current problem. I'd obviously like to have a prototype of the form
    T& at(const int i, const int j);
    but I can't get it to work that way. Here's the definition:
    Code:
    template<typename T, int n>
    T Matrix<T, n>::at(const int i, const int j)
    {
    	if (1 <= i && i <= n && 1 <= j && j <= n)
    		return content[i - 1][j - 1];
    	else
    	{
    		std::cout << "Invalid index!\n";
    		return NULL;
    	}
    }
    Aside from whether or not the else part will even work, this stops working as soon as I change the return type to T& and then in the if part use return &content[i - 1][j - 1]; (I thought it was kind of nice to convert to standard matrix notation.

    How do I get a reference here so that I can not only show what the value is but also use this function to assign values inside my matrix?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well if you're returning a reference, you can't return NULL.

    My guess is you throw an exception instead.
    Perhaps follow what std::vector.at() does when it has a problem.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    242
    fair enough, so something like this?
    Code:
    // 'at' function: indexing using normal MATRIX notation (starting at row/col 1 not 0)
    template<typename T, int n>
    T Matrix<T, n>::at(const int i, const int j) throw(std::out_of_range)
    {
    	if (i < 1 || n < i || j < 1 || n < j)
    		throw std::out_of_range("Matrix index out of range");
    	else
    		return content[i - 1][j - 1];
    }
    That still leaves the problem of returning a reference so that we can not only look at the value but also assign it-- and this doesn't work:
    Code:
    template<typename T, int n>
    T& Matrix<T, n>::at(const int i, const int j) throw(std::out_of_range)
    {
    	if (i < 1 || n < i || j < 1 || n < j)
    		throw std::out_of_range("Matrix index out of range");
    	else
    		return &content[i - 1][j - 1];
    }

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You do not need to change anything other than the return type when changing to return a reference. What you did is to change the return type to a reference type, but then you changed the return statement to return the address. Therefore, there is a type mismatch.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    I'd want to see how you'll perform matrix multiplication with this class....

  6. #6
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    I prepare using 1D arrays for multiplication. They are, at my opinion, simpler.

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    242
    I was thinking multiplication would be hard, too, but that turned out to work easily.
    Code:
    template<typename T, int n>
    Matrix<T, n> Matrix<T, n>::operator*(const Matrix<T, n>& m) const
    {
    	T arr[n][n];
    	for (int i = 0; i < n; ++i)
    	{
    		for (int j = 0; j < n; ++j)
    		{
    			arr[i][j] = 0;	// initialize before doing multiplication
    			for (int k = 0; k < n; ++k)
    			{
    				arr[i][j] += content[i][k] * m.content[k][j];
    			}
    		}
    	}
    	return Matrix<T, n>(arr);
    }
    Where i'm bogging down is with the recursive def of determinants (which also suffers from a clunky version of scalar multiplication). More on those later.

    Weird that I could get matrix multiplication to work with no problem but that scalar multiplication is looking very ugly.

    Also need to try laser's suggestion on at and see what happens (if i'm understanding it right).

  8. #8
    Registered User
    Join Date
    May 2009
    Posts
    242
    right on again, laser. it at least compiled when i just changed the return types in prototype and definition to T&. Now i'll have to make sure it also allows me to make assignments.

  9. #9
    Registered User
    Join Date
    May 2009
    Posts
    242
    assigment worked, too! tx!!
    now just scalar multiplication and determinants (which i knew would be hard as i'm a recursion novice) left to go.

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    242
    here's the current "at", just to close that one out for now:
    Code:
    template<typename T, int n>
    T& Matrix<T, n>::at(const int i, const int j) throw(std::out_of_range)
    {
    	if (i < 1 || n < i || j < 1 || n < j)
    		throw std::out_of_range("Matrix index out of range");
    	return content[i - 1][j - 1];
    }

  11. #11
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Well, even if your class is correct, it's useless! Only 3x3 and 4x4 matrices are useful, for me, as i'm building a 3D maths library

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Declaring the 'row' for my matrix - problems
    By qwertysingh in forum C Programming
    Replies: 3
    Last Post: 04-14-2009, 01:12 PM
  2. Simple operator overloading issue
    By Desolation in forum C++ Programming
    Replies: 1
    Last Post: 05-09-2007, 08:56 PM
  3. Replies: 1
    Last Post: 03-06-2006, 07:57 PM
  4. Matrix and vector operations on computers
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 11
    Last Post: 05-11-2004, 06:36 AM