Thread: i think my determinant finally works!!!

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

    i think my determinant finally works!!!

    Well, I can't say that I actually got deep enough into template specializations to resolve the issues grumpy was talking about. But I at least figured out a way to get around the problem--namely by creating friend template functions that create cofactors for square arrays of the given type (T), and then recursively arrive at determinants for these.

    So, my array_determinant definition looks like this:
    Code:
    template<typename T>
    T array_determinant(T** arr, const int size)
    {
    	if (size > 1)
    	{
    		T det = 0;
    		T*** cofactor_array = new T**[size];
    		for (int i = 0; i < size; ++i)
    		{
    			cofactor_array[i] = array_cofactor(arr, 0, i, size);
    		}
    		// Laplace expansion on first row
    		for (int i = 0; i < size; ++i)
    		{
    			det += arr[0][i] * array_determinant(cofactor_array[i], size - 1);
    		}
    		for (int i = 0; i < size; ++i)
    		{
    			for (int j = 0; j < size - 1; ++j)
    			{
    				delete [] cofactor_array[i][j];
    			}
    			delete [] cofactor_array[i];
    		}
    
    		delete [] cofactor_array;
    		return det;
    	}
    	else
    		return **arr;
    }
    The big difference here is that size is an INPUT (hence already taken care of when the function compiles) rather than a template parameter.

    I hope it's not a horrible ugliness in this code that I still have "if (size > 1)", which (such is my impression anyway) grumpy didn't seem to want to see.

    I do think it's pretty ugly having to do all of these deletes. But if we're creating cofactors willy-nilly I don't see much of a way around using dynamic memory allocation, and if you do that, you've got to free up the memory again somewhere, right?

    Once you do that, then you get a trivial definition for Matrix determinants:
    Code:
    template<typename T, int n>
    T Matrix<T, n>::determinant() const
    {
    	return array_determinant(content, n);
    }
    So, no doubt not the greatest code, but at least a way of doing it that seems to work...

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Aisthesis View Post
    The big difference here is that size is an INPUT (hence already taken care of when the function compiles) rather than a template parameter.
    It's actually the other way round. If the size was a template parameter, its value would be "taken care of" at compile time.

    You're making the mistake of considering a template to be a runtime mechanism. Passing an argument to a function is a something that happens at run time. Templates are instantiated by the compiler.
    Quote Originally Posted by Aisthesis View Post
    I hope it's not a horrible ugliness in this code that I still have "if (size > 1)", which (such is my impression anyway) grumpy didn't seem to want to see.
    Your impression is wrong. If you had taken the time to understand template specialisation, you would have seen why such a test is irrelevant.

    Quote Originally Posted by Aisthesis View Post
    I do think it's pretty ugly having to do all of these deletes. But if we're creating cofactors willy-nilly I don't see much of a way around using dynamic memory allocation, and if you do that, you've got to free up the memory again somewhere, right?
    Well, yeah, if you dynamically allocate memory you need to release it. However, you could have employed some standard container (eg std::vector) to manage things on your behalf. That does not eliminate dynamic memory allocation (the standard containers do that for you internally) but better to reuse something that works than roll your own.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    242
    You're making the mistake of considering a template to be a runtime mechanism. Passing an argument to a function is a something that happens at run time. Templates are instantiated by the compiler.
    That's really the main thing I've learned from all this. I hope that I can now edit that to "You [were] making the mistake ... "

    I agree fully on using vector, but part of the challenge (from someone else) was not to use higher-level functionality.

    As to template specialization, I've learned something about it through this exercise but feel like it's a bit beyond me right now to try to get a full understanding immediately. Templates and recursion are both pretty new to me, so I have had a lot of trouble with just getting syntax lined up right on the templates. Until I have some routine on that, I feel like getting involved in further intricacies might be more than I can deal with.

    btw, I realized that I had defined minor and cofactor as arrays rather than as values. In actuality, they are the determinant (or signed determinant) of a particular sub-array. I've been working this morning on correcting that problem and working toward solving for inverses.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Now it works, now it won't
    By skytreader in forum C Programming
    Replies: 3
    Last Post: 11-23-2009, 09:56 AM
  2. Replies: 1
    Last Post: 08-04-2009, 08:57 AM
  3. Can anybody show me why this works??
    By tzuch in forum C Programming
    Replies: 2
    Last Post: 03-29-2008, 09:03 AM
  4. Replies: 6
    Last Post: 12-21-2005, 03:49 AM
  5. I finally got...
    By SyntaxBubble in forum Windows Programming
    Replies: 1
    Last Post: 11-18-2001, 07:38 PM