determinant function??

This is a discussion on determinant function?? within the C++ Programming forums, part of the General Programming Boards category; still on my Matrix class, here's a necessary helper method for getting the determinant: Code: template<typename T, int n> Matrix<T, ...

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

    determinant function??

    still on my Matrix class, here's a necessary helper method for getting the determinant:
    Code:
    template<typename T, int n>
    Matrix<T, n> Matrix<T, n>::scalar_multiply(const T& t) const
    {
    	if (n > 0)
    	{
    		T arr[n][n];
    		for (int i = 0; i < n; ++i) // rows
    		{
    			for (int j = 0; j < n; ++j) // columns
    			{
    				arr[i][j] = t * content[i][j];
    			}
    		}
    		return Matrix<T, n>(arr);
    	}
    	else	// bad value for n
    	{
    		std::cout << "Error! Matrix dimension must be > 0.\n";
    		return Matrix<T, n>();
    	}
    }
    In the attempt to debug, I've spelled out as much as possible in my determinant function (not using a cofactor function that I've also built but doing that by hand), which still doesn't work but looks like this:
    Code:
    template<typename T, int n>
    T Matrix<T, n>::determinant() const
    {
    	if (n == 1)
    		return content[0][0];
    
    	else if (n > 1) // recursive part
    	{
    		T det = 0;
    		// use Laplace expansion on first row
    		for (int i = 1; i <= n; ++i)
    		{
    			Matrix<T, n - 1> temp;	// using this->cofactor(1, i) gives a type conversion error
    				// problem seems to come from decrementing n (?)
    
    			// determine temp Matrix for each column i
    			for (int j = 1; j <= n - 1; ++j) // rows of temp
    			{
    				for (int k = 1; k <= n - 1; ++k)
    				{
    					if (k < i)
    						temp.at(j, k) = content[j][k - 1];
    					else
    						temp.at(j, k) = content[j][k];
    				}
    			}
    			if ((i + 1) % 2)
    				temp = -temp;
    			temp = temp.scalar_multiply(content[0][i - 1]);
    			det += temp.determinant();
    		}
    		return det;
    	}
    	// */
    	else	// abnormal case where n < 1
    		return 0;
    }
    For purposes of comprehension, note that the at() function uses normal matrix indexing (first row/col=1) whereas the content[][] array is using array indexing (first row/col = 0).

    A few notes (in case it's not immediately obvious to you guys what's wrong):
    1) If I comment out the recursive line det += temp.determinant(); it compiles (just obviously not giving the desired value).
    2) The error message I get on this variation is somewhat strange, namely that in line 29 'arr' is missing a subscript. Verbatim:
    Code:
    \matrix.h(29) : error C2087: 'arr' : missing subscript
    1>        c:\users\marshall\documents\mf_program\cpp\matrix\matrix\matrix.h(382) : see reference to class template instantiation 'Matrix<T,n>' being compiled
    1>        with
    1>        [
    1>            T=double,
    1>            n=0
    1>        ]
    This is of course debugging output and not code even though I put it in a code box. In any case, line 29 is completely innocuous, namely the prototype for constructing a Matrix from an array (which works fine until the recursive determinant() function gets used):
    Code:
    Matrix(const T arr[][n]);
    But the error output indicates that the recursion has gotten down to n = 0 when the error occurs--and, yes, that would make for an error. But I thought I had created an endpoint (or starting point, if you will) for the recursion in the first if statement, where I give determinant() an explicit value when n == 1. That is, I thought I'd set it up so that we wouldn't ever get to n == 0 unless we start with a bad n value.

    So... why is this happening and how do I fix it?

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,531
    Your template causes infinite recursion at compile time, unless you specialise it appropriately.

    You need to learn about specialisation of templates, not using tests on n (eg if (n == 0) .... ) in the code.

    Unrelated to your problem, it is probably simpler to compute the determinate using simple gaussian elimination.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy in reply to you, it is likely you deserve it. Suck it up, sunshine, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    242
    ok, i eliminated the n == 0 test from everything after your comment (i thought it looked somehow off from the beginning but somehow felt compelled to throw something in).

    but i'm not familiar with getting a determinant from gaussian elimination, although it's what i always use to solve simultaneous equations (determinants always being insanely complicated to figure).

    now on the "specialisation", i looked a bit in my book to review what i have at least seen up to now and it's rather brief. but it brings up instantiation in the same context. i couldn't see how specialisation (Prata has that as redefining a particular function for certain types, at least under explicit specialization, and then partial specialization as restricting the generality of a template) would be relevant but instantiation certainly is in that the compiler is going to have to create know the relevant instantiations for Matrix<T, i> with i < n in order to run the recursion.

    So, I tried this (and commented it out when it didn't work). this is obviously just the beginning, as i'm trying to start over and get each step to work (i think i'm also going to try create an array of cofactor matrices at each level, then use those in the equation). Anyhow, this at least reflects my current understanding of what the problem might be--although getting something that works isn't quite there yet:
    Code:
    // determinant
    template<typename T, int n>
    T Matrix<T, n>::determinant() const
    {
    	// explicitly instantiate types down to Matrix<T, 1>
    	/*
    	for (int i = 1; i < n; ++i)
    	{
    		template class Matrix<T, i>;
    	}
    	*/
    	if (n == 1)
    		return this->at(1, 1);
    	return 0;
    }
    p.s.: the return 0; at the end is only there to get it to return something during the time the function is still under construction.

  4. #4
    Registered User
    Join Date
    May 2009
    Posts
    242
    btw, attempting the instantiation that's commented out here gives EXACTLY the same error message that occurred in the original--indicating to me that these instantiations are indeed exactly what's getting me into trouble.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,531
    Well, go on then. Google is your friend in this case.

    There are plenty of descriptions out there of template specialisation. Now you know what the problem is (or, at least, what it is called), it is encumbant upon you to find a solution. As I said, your code will not need a test on n (and "if (n == 1)" is a test on n).

    There are also plenty of description of how to compute a determinate (as opposed to determinant) using gaussian eliminations.
    Last edited by grumpy; 03-05-2010 at 02:05 PM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy in reply to you, it is likely you deserve it. Suck it up, sunshine, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling C in Visual Studio 2005
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-16-2009, 04:25 AM
  2. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  3. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 04:06 PM
  4. Replies: 28
    Last Post: 07-17-2006, 12:35 AM
  5. const at the end of a sub routine?
    By Kleid-0 in forum C++ Programming
    Replies: 14
    Last Post: 10-23-2005, 07:44 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21