Skip to main content
GameDev.net gamedev.net
🔒 Locked

Matrix inverse

Started by Endar Dec 25, 2005 at 3:35 AM 44 replies 13.6k views
Original Post
Endar
Endar
It's probably about time that I added this to my matrix class (just a 4x4 for 3d graphics). Here's my problem. Not sure where to start. I've been looking on mathworld, and that gives an example for a 2x2 and a 3x3, where the 3x3 has a nice picture of each element being made by the determinant. But I seem to remember from math class that anything bigger than a 3x3, you have to get the determinant of the determinant. For example, in a 4x4, to get the determinant for the first element, you need to block out the row and column of the element and then what's left is a 3x3, then to get the deteminant of that, don't you need to get the deteminant for every single element of that 3x3 matrix? Please stop me if I have no idea what I'm talking about.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
tomcant
tomcant
There is a simple explanation here (you'll have to scroll down a little): http://easyweb.easynet.co.uk/~mrmeanie/matrix/matrices.htm
______Tom
rmdeboer82
rmdeboer82
i think the determinant when using the first row of this matrix

|x y z w|
|1 2 3 4|
|5 6 7 8|
|9 0 a b|

is:

x
*
|2 3 4|
|6 7 8|
|0 a b|
-
y
*
|1 3 4|
|5 7 8|
|9 a b|
+
z
*
|1 2 4|
|5 6 8|
|9 0 b|
-
w
*
|1 2 3|
|5 6 7|
|9 0 a|

you should use this pattern

+-+-
-+-+
+-+-
-+-+

using the element multiplied with the 3x3 matrix that doesn't have a row and column in common.

and then calculate the determinant of the 3x3 (should be much easier) etc.
Be creative, don't copy...Greets from Holland!
SiCrane
SiCrane
You can also use gaussian reduction in order to calculate the matrix inverse. Start with a matrix like:
[ a b c d 1 0 0 0 ][ e f g h 0 1 0 0 ][ i j k l 0 0 1 0 ][ m n o p 0 0 0 1 ]

And do the gaussian reduction on it. You'll get a matrix like:
[ 1 0 0 0 a' b' c' d' ][ 0 1 0 0 e' f' g' h' ][ 0 0 1 0 i' j' k' l' ][ 0 0 0 1 m' n' o' p' ]

And the a' - p' elements form the matrix inverse.
haegarr
haegarr
If you know your matrix being build of affine transformations only (say e.g. no perspective, what is often the case in 3D scene graphs and such) then you could use the following scheme (written in column vector format)
[ L  T ] -1    [ L'  -L'*T ][      ]     = [           ]   with L' := L^-1[ 0  1 ]       [  0    1   ]with the proove[ L  T ]   [ L'  -L'*T ]   [ L*L'  L*(-L'*T)+T ]   [ I  -(L*L')*T+T ]   [ I  0 ][      ] * [           ] = [                   ] = [                ] = [      ]  q.e.d.[ 0  1 ]   [  0    1   ]   [  0          1     ]   [ 0        1     ]   [ 0  1 ]

where L denotes the linear transformations part (rotation, scale) and T the translation part.
So you would need to compute the inverse of a 3x3 matrix and a matrix-vector product for inversion of the entire matrix.
Zakwayda
Zakwayda
Just to add a couple things to (or perhaps just reinforce) what has already been said, most common types of transformations have 'shortcuts' for the inverse, as haegarr suggests. If you're going to need the inverse of such matrices often, some special-case functions might be appropriate.

If it's just a few times per frame, a general inverse function will probably suffice. In the libraries I've seen, the most common methods for 4x4 inversion appear to be Gauss-Jordan elimination (as suggested by SiCrane) and adjoint/determinant (the method you are probably referring to).

I'm not an expert on performance issues, but the latter method does have the potential advantage of being branchless (except for checking the determinant), whereas Gauss-Jordan is loop-based. Whether this is important from a performance standpoint I'll leave to others, but it's something to keep in mind. Note however that adj/det doesn't scale particularly well, and probably isn't a good first choice for larger matrices.

As for how to do it, a google for '4x4 matrix inverse' will probably turn up several implementations of both methods. If you're happy using someone else's code, you should be able to find one you can use. Otherwise, adj/det is fairly straightforward to figure out, although it requires a bit of bookkeeping. The key thing to remember is that the 2x2 subdeterminants are shared among the 3x3 subdeterminants, and so should only be calculated once. Also, the determinant of the matrix as a whole can be calculated from a subset of the subdeterminants.
haegarr
haegarr
If interested in: I use my AffineMap class heavily in scene graph stuff (hence supporting no projection at that level) and also expect scaling not often to occur, so I'm able to distinct different use cases easily. I actually track the kind of involved transformations and use that infos at runtime like here:
result._rotating = _rotating;result._scaling = _scaling;if(_rotating && _scaling) {	// presetting linear sub-matrix w/ adjoint of linear sub-matrix of self	result._b0 = _b1.cross(_b2);	result._b1 = _b2.cross(_b0);	result._b2 = _b0.cross(_b1);	// scaling adjoint sub-matrix by inverse of determinant results in inverse sub-matrix; the determinant is expected	// to never be zero since that would not represent a valid affine transformation	const register scalar_g inverseOfDet = 1.0f/_b0.dot(result._b0);	result._b0.multiply(inverseOfDet);	result._b1.multiply(inverseOfDet);	result._b2.multiply(inverseOfDet);} else if(_rotating) {	// rotating only: inverse is identical to transpose	result._b0.set(_b0.s0,_b1.s0,_b2.s0);	result._b1.set(_b0.s1,_b1.s1,_b2.s1);	result._b2.set(_b0.s2,_b1.s2,_b2.s2);} else if(_scaling) {	// scaling only: matrix is diagonal, and so is its inverse; assuming that there is no zero	result._b0.set(scalar_g(1)/_b0.s0,0,0);	result._b1.set(0,scalar_g(1)/_b1.s1,0);	result._b2.set(0,0,scalar_g(1)/_b2.s2);} else {	// identity	result._b0 = Vector_t::UNIT_0;	result._b1 = Vector_t::UNIT_1;	result._b2 = Vector_t::UNIT_2;}

where _b[0-2] are the 3x1 column vectors of the linear sub-matrix (L in my post above). Herein I use the adjoint/determinant method (in case that both rotation and scaling is given) mentioned by jyk.
biki_
biki_
here is simple 4x4 inversion
for larger matrices gauss elimination or something similar would be better i guess.


void matrix4f::Inversion (matrix4f &n) {float wg;float b1,b2,b3,b4,b5,b6;    b1=n[2][2]*n[3][3]-n[2][3]*n[3][2]; b2=n[2][0]*n[3][3]-n[2][3]*n[3][0];    b3=n[2][0]*n[3][1]-n[2][1]*n[3][0]; b4=n[2][2]*n[3][1]-n[2][1]*n[3][2];    b5=n[2][3]*n[3][1]-n[2][1]*n[3][3]; b6=n[2][2]*n[3][0]-n[2][0]*n[3][2];        m[0][0]=n[1][1]*b1+n[1][2]*b5-n[1][3]*b4;    m[1][0]=n[1][2]*b2+n[1][3]*b6-n[1][0]*b1;    m[2][0]=n[1][3]*b3-n[1][0]*b5-n[1][1]*b2;    m[3][0]=n[1][0]*b4-n[1][1]*b6-n[1][2]*b3;    wg=m[0][0]*n[0][0]+m[1][0]*n[0][1]+m[2][0]*n[0][2]+m[3][0]*n[0][3];    if (wg==0) return;    wg=1.0f/wg;    m[0][0]*=wg; m[1][0]*=wg; m[2][0]*=wg; m[3][0]*=wg;    b1=n[3][2]*n[0][3]-n[3][3]*n[0][2]; b2=n[3][0]*n[0][3]-n[3][3]*n[0][0];    b3=n[3][0]*n[0][1]-n[3][1]*n[0][0]; b4=n[3][2]*n[0][1]-n[3][1]*n[0][2];    b5=n[3][3]*n[0][1]-n[3][1]*n[0][3]; b6=n[3][2]*n[0][0]-n[3][0]*n[0][2];        m[0][1]=wg*(-n[2][1]*b1-n[2][2]*b5+n[2][3]*b4);    m[1][1]=wg*(-n[2][2]*b2-n[2][3]*b6+n[2][0]*b1);    m[2][1]=wg*(-n[2][3]*b3+n[2][0]*b5+n[2][1]*b2);    m[3][1]=wg*(-n[2][0]*b4+n[2][1]*b6+n[2][2]*b3);    b1=n[0][2]*n[1][3]-n[0][3]*n[1][2]; b2=n[0][0]*n[1][3]-n[0][3]*n[1][0];    b3=n[0][0]*n[1][1]-n[0][1]*n[1][0]; b4=n[0][2]*n[1][1]-n[0][1]*n[1][2];    b5=n[0][3]*n[1][1]-n[0][1]*n[1][3]; b6=n[0][2]*n[1][0]-n[0][0]*n[1][2];        m[0][2]=wg*(n[3][1]*b1+n[3][2]*b5-n[3][3]*b4);    m[1][2]=wg*(n[3][2]*b2+n[3][3]*b6-n[3][0]*b1);    m[2][2]=wg*(n[3][3]*b3-n[3][0]*b5-n[3][1]*b2);    m[3][2]=wg*(n[3][0]*b4-n[3][1]*b6-n[3][2]*b3);    b1=n[1][2]*n[2][3]-n[1][3]*n[2][2]; b2=n[1][0]*n[2][3]-n[1][3]*n[2][0];    b3=n[1][0]*n[2][1]-n[1][1]*n[2][0]; b4=n[1][2]*n[2][1]-n[1][1]*n[2][2];    b5=n[1][3]*n[2][1]-n[1][1]*n[2][3]; b6=n[1][2]*n[2][0]-n[1][0]*n[2][2];        m[0][3]=wg*(-n[0][1]*b1-n[0][2]*b5+n[0][3]*b4);    m[1][3]=wg*(-n[0][2]*b2-n[0][3]*b6+n[0][0]*b1);    m[2][3]=wg*(-n[0][3]*b3+n[0][0]*b5+n[0][1]*b2);    m[3][3]=wg*(-n[0][0]*b4+n[0][1]*b6+n[0][2]*b3);}
Endar
Endar
I'm working off this site which was given ealier in this thread.

I'm a little confused here.
Quote:

To calculate the determinant of a larger matrix (ie 3x3 or 4x4) you "exclude" the top row of the matrix, and each column in turn.


Okay, fine.

Quote:

The inverse of a matrix is a matrix of the same size, which undoes any transformation performed by the original matrix. The determinant of the matrix is involved in finding the inverse. Also, the matrix has NO inverse if it's determinant is 0. You will see why. To find the value of a particular position (column i, row j) you generate a submatrix by excluding the appropriate rows.


Okay, so, first I have to find the determinant of the matrix, which I do by finding the determinant of smaller 3x3 matrices which I construct by ignoring the top row and each column one by one from the 4x4 matrix.

Then if the determinant is not 0, I have to go and basically calculate the determinant of every possible 3x3 matrix in the 4x4 matrix that is constructed by ignoring every row and column in turn.

Right?

So I don't have to do one by one ignore every column and row in the 3x3 submatrix? Just the larger 4x4?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Zipster
Zipster
Quote:
Original post by Endar
So I don't have to do one by one ignore every column and row in the 3x3 submatrix? Just the larger 4x4?

That's correct, you don't have to ignore every row and every column in the 3x3 submatrix. But in order to find the determinant of the 3x3 submatrix you need to ignore every element in the top row and basically follow the same process you did with the 4x4 matrix - also known as determinant expansion by minors. It's a recursive procedure. Calculating inverses by hand can be a little confusing because you need to calculate the determinant of the 4x4, which involves finding the determinant of the 3x3 submatrices, and then to get the adjoint matrix you need to go back and calculate the determinant of more 3x3 submatrices; however this time you construct the 3x3 matrices differently to find the adjoint that you would to find the 4x4 determinant.

Personally I just use Gauss-Jordan elimination for any inverse over 3x3, and Gaussian elimination for any determinant over 4x4. For larger matrices it's more efficient, with maybe the exception of 4x4 - 6x6 which are borderline and can go either way. At some point I'll also switch to an explicit formulation for the inverse 4x4 case however at the time I was too lazy to write it out and I don't do much 4x4 inversion anyway.
Endar
Endar
Yet another problem.

Whatever random matrix I give my program it keeps returning that the determinant is 0, so the matrix has no inverse.

I've tried a couple. I've tried some I've found on the net that I've used online inverse calculators and they gave an inverse.

My matrix is a 1d array of 16 floats, and is column-major.

I've tested the split function, which really isn't too hard to test, and as far as I can see, it works. I'm almost certain that the problem is in my maths.

/** * This function sets 'this' matrix to the inverse of 'this' matrix. * \return 'true' if the matrix has an inverse and it was set to the inverse, else 'false' * and the matrix isn't changed. */bool CMatrix::setInverse(){	// first split the matrix using the top row and each column to find the determinant	// save the values for the inverse	float temp[16];		// temp for the inverse matrix	float deter = 0.0f;	// determinant for the matrix	// calculate the determinant of the matrix (top row of the matrix)	float m[9];	// temp 3x3 submatrix	// keep in mind deter * (-1)^(j+1) where j is the column that is being ignored	split(m, 0, 0);	temp[0] = -calcDeter(m, 3);	// first deter bit * (-1)^1	split(m, 1, 0);	temp[1] = calcDeter(m, 3);	// second deter bit * (-1)^(1+1)			split(m, 2, 0);	temp[2] = -calcDeter(m, 3);	// third deter bit * (-1)^(2+1)	split(m, 3, 0);	temp[3] = calcDeter(m, 3);	// last deter bit * (-1)^(3+1)	// calc matrix determinanat	deter = temp[0] + temp[1] + temp[2] + temp[3];	// if there is no determinanat for this matrix	if( deter == 0.0f )		return false;	/* Calculating the inverse of a matrix */	/* 	 * To calculate the inverse of a matrix we have to split	 * the 4x4 into submatrices for each element (ignore row and column).	 * Then we take the determinant of the submatrix, and divide that by	 * the determinant of the whole matrix. Then muliply by (-1)^(r+c)	 * where r is the row and c is the column. NOTE: both of these should	 * start at 1, not 0.	 */	// calculate the inverse bit for the top row of the matrix (what	// we just calculated to find the determinant of the 4x4)	for(int i=0; i < 4; i++){		temp /= deter;		// For the first row, the row is always the same (1), and		// only the column changes.		// (i+1) to get it to one indexed instead of zero indexed,		// and the extra 1 because the row stays the same all the time.		// Also, (-1)^(even number) is always positive and		// (-1)^(odd number) is always negative.		if( (i+1)+1 % 2 )			temp = -temp;	}	int el = 0;	// now split the rest of the matrix into 3x3 submatrices	for(i=1; i < 4; i++){		for(int j=0; j < 4; j++){			el = i*4 + j;			split(m, j, i);			temp[el] = calcDeter(m, 3) / deter;						// negify is needed (yeah, that's probably not a real word)			if( (i+1)+(j+1) % 2 )				temp[el] = -temp[el];		}// for j < 4	}// 	// copy across	memcpy(m_mat, temp, sizeof(float)*16);	(*this).transpose();	// to finally get the inverse	// FIXME - not finished yet 3/01/06	return true;	// the inverse was successful}/** * Calculate the deteminant of a 3x3 or 2x2 matrix * \param m A pointer to the matrix values in an array * \param size The size of the matrix (can only be a square matrix) */float CMatrix::calcDeter(const float* m, int size) const{	// calculate the determinant of a 2x2	if( size == 2 ){		return (m[0] * m[1]) - (m[2] * m[3]);	}	// calculate the deteminant of a 3x3	else if( size == 3 ){		float d[3];	// hold the determinant at each stage		float a[4];	// the temp array to hold each 2x2 submatrix		// NOTE: in maths the first column of an array is column 1		// NOT 0. It is only 0 because arrays in C are zero-indexed,		// whereas matrix math appears to be one indexed.		// block top and column 1, so (deter * (-1)^(1+1))		a[0] = m[4];	a[1] = m[5];		a[2] = m[7];	a[3] = m[8];		d[0] = calcDeter(a,2);		// block top and column 2, so (deter * (-1)^(2+1))		a[0] = m[3];	// don't have to change		a[2] = m[6];	// el 1 or el 3		d[1] = -calcDeter(a,2);		// block top and column 3, so (deter * (-1)^(3+1))		a[1] = m[4];	// don't have to change		a[3] = m[7];	// el 0 or el 3		d[2] = calcDeter(a,2);		// calc the determinant of the 3x3 submatrix		return d[0] + d[1] + d[2];	}// if size == 3	// problem. Given an invalid size return 0 as the deteminant	return 0;}/** * Split 'this' 4x4 matrix into a smaller 3x3 submatrix depending on * which row and column to ignore. (used in the inverse function) * \param m A pointer to a float array to place the 3x3 submatrix (needs 9 elements) * \param colig The column to ignore * \param rowig The row to ignore */void CMatrix::split( float* m, int colig, int rowig) const{	int arr_count = 0;		// keep track of what element 					// in the array we're accessing	// split 'this' 4x4 into a 3x3	for(int i=0; i < 4; i++){		if( rowig == i )	// if we are ignoring this row			continue;	// skip back to the start of the loop		// traverse matrix column wise		for(int j=0; j < 4; j++){			if( colig == j )	// if we are ignoring this column				continue;	// skip back to start of the loop			// assign array value			m[ arr_count ] = (*this)(j,i);			arr_count++;	// only increment arr_count on element assignment		}// for j < 4	}// for i < 4}


Is it just that all the matrices I've tried actually don't have an inverse? I would hope not. I've tried 3-4 completely arbitrary ones and 2-3 from online. All of them have return 'false' from the 'setInverse' function.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Sneftel
Sneftel
Many matrices that you'd think of yourself (particularly those with lots of low integers) are singular. Try just generating 16 random floating point numbers between -1 and 1 and testing that matrix.

Also, have you stepped through with the debugger to make sure that split is doing the right thing?
Endar
Endar
Quote:
Original post by Sneftel
Many matrices that you'd think of yourself (particularly those with lots of low integers) are singular. Try just generating 16 random floating point numbers between -1 and 1 and testing that matrix.

Also, have you stepped through with the debugger to make sure that split is doing the right thing?


Thanks, I'll try the random numbers.

I haven't stepped through with a debugger, but before I wrote the body of the inverse function, I tested it on a matrix with 5 or so different column-row sets to ignore, including the edges. But, I'll take a little look-see at that again.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Endar
Endar
I'm guessing that these aren't normal values for a matrix (top) and its inverse (bottom).

 [  0.941343 0.938475 -0.151585 0.681570 ] [  -0.735374 -0.687185 0.858669 0.663289 ] [  -0.592578 0.374401 0.022279 -0.490646 ] [  -0.173345 0.390637 -0.856166 0.866726 ] [  17853140.000000 -1437558.375000 -12498008.000000 -3917574.750000 ] [  -17853140.000000 -1437558.375000 12498008.000000 -3917574.500000 ] [  -20696042.000000 -9722678.000000 -1299659.375000 -12273024.000000 ] [  -2842902.250000 -8285120.000000 -13797667.000000 -8355449.500000 ]


Although, when I just keep running it, every now and again it comes up with a "no inverse", so I guess that means something is working.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
etothex
etothex
The bottom is not the inverse of the top...matlab says the inverse of the top is:

[0.2397 -0.3242 -0.7909 -0.3881
0.7125 0.0742 1.0468 -0.0245
0.5595 0.5798 0.3670 -0.6760
0.2795 0.4745 -0.2674 0.4194]

I don't suggest random numbers until you get it at least sort of working. Instead, feed it matrices which are really simple, that you know the inverse of. For example, I. Plug the identity matrix in, and if it doesn't spit out the identity matrix, you know something's wrong.

Then move on to a simple reflection matrix, etc, where the result is known. The reason for all this is that with simple matrices like these, if you have an error (like you transposed a column or something) it would hopefully be evident from the (incorrect) inverse what the problem is. Like if you do I^-1 and get:

[1 0 0 0
0 0 1 0
0 0 1 0
0 0 0 1]

You know which part of the inverse function went wrong.

Off topic: this is an excellent place for some unit tests.
Zipster
Zipster
Spot checking your code revealed a few errors. Your calculation of a 2x2 determinant is incorrect, for a column-major matrix it should be (m[0]*m[3]) - (m[1]*m[2]). I also notice you mix the column-major and row-major conventions when indexing the matrix, for instance:

// block top and column 1, so (deter * (-1)^(1+1))a[0] = m[4];	a[1] = m[5];a[2] = m[7];	a[3] = m[8];d[0] = calcDeter(a,2); // block top and column 2, so (deter * (-1)^(2+1))a[0] = m[3];	// don't have to changea[2] = m[6];	// el 1 or el 3d[1] = -calcDeter(a,2);

The first minor expansion uses column-major convention, while the second expansion uses row-major convention. I highly suggest you add operators for row-column addressing, such as:

float& operator()(std::size_t i, std::size_t j){   assert(i < size && j < size);   return data[j*size + i];}const float& operator()(std::size_t i, std::size_t j) const{   assert(i < size && j < size);   return data[j*size + i];}

This way you can think purely in terms of rows and columns instead of having to worry about how you actually implement the matrix as a 1D array internally. The first value is the row, and the second value is the column. The 2x2 determinant would then be (m(0,0)*m(1,1)) - (m(1,0)*m(0,1)). I suspect this is what's causing a bunch of your problems, however I haven't taken a close look at the rest of the logic.
Endar
Endar
I thought that was wrong!!!



This is from the website I gave earlier.

I'm not really sure what you mean by I'm mixing conventions here:
// block top and column 1, so (deter * (-1)^(1+1))a[0] = m[4];	a[1] = m[5];a[2] = m[7];	a[3] = m[8];d[0] = calcDeter(a,2); // block top and column 2, so (deter * (-1)^(2+1))a[0] = m[3];	// don't have to changea[2] = m[6];	// el 1 or el 3d[1] = -calcDeter(a,2);


These are two of the parts where I'm blocking out the top row and a column of the 3x3 submatrix so I can calc the determinant of it. I'm accessing the elements directly, how does this relate to row-major or column-major conventions?

Also, I have the () operator defined for my 4x4 matrix, but I was hesitant to add it for anything else as I would have had to actually write a class for 2x2 and 3x3 matrices. Isn't that a little much considering I'm only using them to find the inverse of the 4x4 and nothing else?




Quote:
Original post by etothex
Plug the identity matrix in, and if it doesn't spit out the identity matrix, you know something's wrong.

...

Off topic: this is an excellent place for some unit tests.


Yeah, something is definatly wrong. I give it the identity matrix and I get "No determinant" back at me.

I'm a little fuzzy on unit tests. Is there a formal way of doing them? Or is it mostly just writing a bunch of tests (couple of general cases and special cases) and testing them each time you update the code?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
etothex
etothex
Quote:
Original post by Endar
Yeah, something is definatly wrong. I give it the identity matrix and I get "No determinant" back at me.

I'm a little fuzzy on unit tests. Is there a formal way of doing them? Or is it mostly just writing a bunch of tests (couple of general cases and special cases) and testing them each time you update the code?


Now step through with the debugger and you can trace the identity matrix through. It's a lot easier now to figure out which variable is wrong.

As with anything in life, people make a lot of fuss about nothing, going overboard with proper testing methodology, unit test frameworks, etc. Not necessary. Just make a new .exe where the main program takes a bunch of matrices and calcs the inverse, then checks if the answer is correct. Then, anytime you make a change to the class, run the exe again. It will verify that you have not added more bugs then you fixed.

And to the guy who posted about operator() - don't use asserts for bounds checking. Maybe if they were private class members, ok. But if operator() was public or protected, you need real runtime bounds checking, not asserts.
Endar
Endar
Okay. Determinant of an identity matrix. Is equal to 2, right?

split(m, 0, 0);temp[0] = calcDeter(m, 3);	// first deter bit * (-1)^((0+1)+1)split(m, 1, 0);temp[1] = -calcDeter(m, 3);	// second deter bit * (-1)^((1+1)+1)		split(m, 2, 0);temp[2] = calcDeter(m, 3);	// third deter bit * (-1)^((2+1)+1)split(m, 3, 0);temp[3] = -calcDeter(m, 3);	// last deter bit * (-1)^((3+1)+1)// calc matrix determinanatdeter = temp[0] + temp[1] + temp[2] + temp[3];


At temp[1], I get -1 instead of +1, and calcDeter returns +1.

The "(0+1)" part of "((0+1)+1)" is to move from a zero-indexed C array index to the real world of mathematics where matrices aren't zero-indexed. (it's so when I look back at the code, I can easily associated the '1' with column 1, and so forth)

I've verified that, at least with the identity matrix example, the calcDeter function works.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
etothex
etothex
Quote:
Original post by Endar
Okay. Determinant of an identity matrix. Is equal to 2, right?


Nope, always 1. It follows from the fact that det(AB) = det(A)*det(B). If I=A, then det(IB)=det(I)*det(B) --> det(B)=det(I)*det(B), therefore det(I) = 1

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.