Inverse of 4x4 matrix

Started by
13 comments, last by Steve132 13 years, 4 months ago
Quote:Original post by sooner123
Solving by using the cofactors is actually much harder and laborious than solving it directly.

Inverting a square matrix is the same as solving a system of four equations. This can be easily done by appending the identity matrix and converting the left half to reduced row echelon form.


The op didn't really specify whether this was for implementation or if he was to do it by hand. If doing by hand using an augmented matrix as you've shown is the easiest but trying to do the same with code isn't very practical.

Since this is under General Programming I'd assume he wants a method ideal for implementation.
- Blade -
Advertisement
Quote:Original post by bladerunner627
The op didn't really specify whether this was for implementation or if he was to do it by hand. If doing by hand using an augmented matrix as you've shown is the easiest but trying to do the same with code isn't very practical.

Since this is under General Programming I'd assume he wants a method ideal for implementation.


Going to have to disagree with you there.

I don't see anything impractical about treating the matrix as a straightforward system of four equations in four unknowns.

It seems to me that it would be much easier to code than dealing with cofactors and transposes.

But in terms of execution time, there's no question that the way I suggested is better than cofactors.

I can't really see a reason for using the cofactor approach other than learning a bit more deeply about linear algebra. Which, don't get me wrong, is a wonderful thing. It's just that the final implementation would be quicker to write and quicker to execute the other way.
I'll admit I've never implemented the routine you've mentioned but for the very same reason you make your suggestion over co-factors, it seems more difficult to implement.

Here's my implementation, I've never thoroughly benchmarked but it's sufficient for my needs.

i, j, k, and l are the matrix row vectors.

Vec4<T> i, j, k, l;T Determinant(){	T x = -l.x*(i.y*(j.z*k.w-j.w*k.z) - i.z*(j.y*k.w-j.w*k.y) + i.w*(j.y*k.z-j.z*k.y));	T y = l.y*(i.x*(j.z*k.w-j.w*k.z) - i.z*(j.x*k.w-j.w*k.x) + i.w*(j.x*k.z-j.z*k.x));	T z = -l.z*(i.x*(j.y*k.w-j.w*k.y) - i.y*(j.x*k.w-j.w*k.x) + i.w*(j.x*k.y-j.y*k.x));	T w = l.w*(i.x*(j.y*k.z-j.z*k.y) - i.y*(j.x*k.z-j.z*k.x) + i.z*(j.x*k.y-j.y*k.x));	return (x + y + z + w);}Mat4x4<T> Adjoint(){	Mat4x4<T> adj;	//	Transposed matrix of cofactors	//	First row	adj.i.x = (j.y*(k.z*l.w-k.w*l.z) - j.z*(k.y*l.w-k.w*l.y) + j.w*(k.y*l.z-k.z*l.y));	adj.i.y = -(i.y*(k.z*l.w-k.w*l.z) - i.z*(k.y*l.w-k.w*l.y) + i.w*(k.y*l.z-k.z*l.y));	adj.i.z = (i.y*(j.z*l.w-j.w*l.z) - i.z*(j.y*l.w-j.w*l.y) + i.w*(j.y*l.z-j.z*l.y));	adj.i.w = -(i.y*(j.z*k.w-j.w*k.z) - i.z*(j.y*k.w-j.w*k.y) + i.w*(j.y*k.z-j.z*k.y));				//	Second row	adj.j.x = -(j.x*(k.x*l.w-k.w*l.z) - j.z*(k.x*l.w-k.w*l.x) + j.w*(k.x*l.z-k.z*l.x));	adj.j.y = (i.x*(k.z*l.w-k.w*l.z) - i.z*(k.x*l.w-k.w*l.w) + i.w*(k.x*l.z-k.z*l.x));	adj.j.z = -(i.x*(j.z*l.w-j.w*l.z) - i.z*(j.x*l.w-j.w*l.x) + i.w*(j.x*l.z-j.z*l.x));	adj.j.w = (i.x*(j.z*k.w-j.w*k.z) - i.z*(j.x*k.w-j.w*k.x) + i.w*(j.x*k.z-j.z*k.x));	//	Third row	adj.k.x = (j.x*(k.y*l.w-k.w*l.y) - j.y*(k.x*l.w-k.w*l.x) + j.w*(k.x*l.y-k.y*l.x));	adj.k.y = -(i.x*(k.y*l.w-k.w*l.y) - i.y*(k.x*l.w-k.w*l.x) + i.w*(k.x*l.y-k.y*l.x));	adj.k.z = (i.x*(j.y*l.w-j.w*l.y) - i.y*(j.x*l.w-j.w*l.x) + i.w*(j.x*l.y-j.y*l.x));	adj.k.w = -(i.x*(j.y*k.w-j.w*k.y) - i.y*(j.x*k.w-j.w*k.x) + i.w*(j.x*k.y-j.y*k.x));	//	Fourth Row	adj.l.x = -(j.x*(k.y*l.z-k.z*l.y) - j.y*(k.x*l.z-k.z*l.x) + j.z*(k.x*l.y-k.y*l.x));	adj.l.y = (i.x*(k.y*l.z-k.z*l.y) - i.y*(k.x*l.z-k.z*l.x) + i.z*(k.x*l.y-k.y*l.x));	adj.l.z = -(i.x*(j.y*l.z-j.z*l.y) - i.y*(j.x*l.z-j.z*l.x) + i.z*(j.x*l.y-j.y*l.x));	adj.l.w = (i.x*(j.y*k.z-j.z*k.y) - i.y*(j.x*k.z-j.z*k.x) + i.z*(j.x*k.y-j.y*k.x));	return adj;}//	Inverse using Kramer's rule.Mat4x4<T> Invert(){	Mat4x4<T> adj = Adjoint();	T invdet = 1;				//	If the determinant is 0 there is no inverse.	//	1/0 == undefined.	if(Determinant() != 0)		invdet = 1/T(Determinant());				Mat4x4<T> inv;	inv.i = adj.i * invdet;	inv.j = adj.j * invdet;	inv.k = adj.k * invdet;	inv.l = adj.l * invdet;	return inv;}

There's a lot of room for optimization.

If the OP is going for speed/efficiency I'd recommend the looking into LU decomposition.
- Blade -
Quote:Original post by bladerunner627
I'll admit I've never implemented the routine you've mentioned but for the very same reason you make your suggestion over co-factors, it seems more difficult to implement.

Here's my implementation, I've never thoroughly benchmarked but it's sufficient for my needs.

i, j, k, and l are the matrix row vectors.

*** Source Snippet Removed ***
There's a lot of room for optimization.

If the OP is going for speed/efficiency I'd recommend the looking into LU decomposition.


Take a look at Dave Eberly's approach posted earlier. It is the same as yours, but allows you to reduce the number of operations a bit. As far as I know, it is the method with the fewest mathematical operations while maintaining precision and operating on a generic 4x4 matrix.
Quote:Original post by SteveDeFacto
Can someone show me how to do this? I tried to google it but I could not understand anything I read...


More importantly, is WHY are you doing this. If you are just frustrated because you read somewhere that you need to invert a matrix to do graphics, then stop worrying about how it works and use a library like Eigen. It is much less error prone and will work and work fast.

If you want to actually understand how matrix inversion is implemented so you can understand it better, go to your local library, get a textbook on linear algebra, read it and do the practice problems.

This topic is closed to new replies.

Advertisement