Below is the code to calculate matrix inverse of a matrix of arbitrary size (order) by using analytic solution. This method is known to be slow for very large matrix because of the recursion. However, I used this mainly for calculating inverse of 4×4 matrices and it worked just fine. You can also use CalcDeterminant and GetMinor to calculate determinant of a matrix.
MatrixInversion: the main function to calculate the inverse matrix.
CalcDeterminant: calculate the determinant of a matrix.
GetMinor: Get minor matrix.
// matrix inversioon
// the result is put in Y
void MatrixInversion(float **A, int order, float **Y)
{
// get the determinant of a
double det = 1.0/CalcDeterminant(A,order);
// memory allocation
float *temp = new float[(order-1)*(order-1)];
float **minor = new float*[order-1];
for(int i=0;i<order-1;i++)
minor[i] = temp+(i*(order-1));
for(int j=0;j<order;j++)
{
for(int i=0;i<order;i++)
{
// get the co-factor (matrix) of A(j,i)
GetMinor(A,minor,j,i,order);
Y[i][j] = det*CalcDeterminant(minor,order-1);
if( (i+j)%2 == 1)
Y[i][j] = -Y[i][j];
}
}
// release memory
delete [] minor[0];
delete [] minor;
}
// calculate the cofactor of element (row,col)
int GetMinor(float **src, float **dest, int row, int col, int order)
{
// indicate which col and row is being copied to dest
int colCount=0,rowCount=0;
for(int i = 0; i < order; i++ )
{
if( i != row )
{
colCount = 0;
for(int j = 0; j < order; j++ )
{
// when j is not the element
if( j != col )
{
dest[rowCount][colCount] = src[i][j];
colCount++;
}
}
rowCount++;
}
}
return 1;
}
// Calculate the determinant recursively.
double CalcDeterminant( float **mat, int order)
{
// order must be >= 0
// stop the recursion when matrix is a single element
if( order == 1 )
return mat[0][0];
// the determinant value
float det = 0;
// allocate the cofactor matrix
float **minor;
minor = new float*[order-1];
for(int i=0;i<order-1;i++)
minor[i] = new float[order-1];
for(int i = 0; i < order; i++ )
{
// get minor of element (0,i)
GetMinor( mat, minor, 0, i , order);
// the recusion is here!
det += pow( -1.0, i ) * mat[0][i] * CalcDeterminant( minor,order-1 );
}
// release memory
for(int i=0;i<order-1;i++)
delete [] minor[i];
delete [] minor;
return det;
}
If you need to calculate matrix inverse frequently in your codes, you might want to optimize the code by declaring the matrix such as minor and temp as global variables and allocate memories for them only once.
implementation
matrix inversion in C++
July 28, 2008 at 12:57 pm |
Hi,
Found your webpage in google.
I think there is a little mistake in your source code l.47 :
dest[a][b] = src[i][j]; I don’t see any a or b but maybe is it i and j ?
July 28, 2008 at 6:08 pm |
Hi, Fab,
Thanks a lot for finding the bug. It should be dest[rowCount][colCount] instead of dest[a][b].
August 1, 2008 at 1:21 pm |
Hi,
I found your code for matrix inversion in google, too. But unfortunately I get a runtime error while trying to execute the code. I suppose the problem is conserned to dynamic memory allocation. Would you take a look at the main function, pls?
I use Dev C++ 4.9.9.1. Here is the code of the main function:
int main()
{ float cov[6][6]={ {228.585, 120.904, 147.073, 147.073, 228.585, 356.428},
{164.066, 85.4136, 104.528, 104.528, 164.066, 257.445},
{130.128, 66.7447, 82.1484, 82.1484, 130.128, 205.378},
{130.128, 66.7447, 82.1484, 82.1484, 130.128, 205.378},
{228.585, 120.904, 147.073, 147.073, 228.585, 356.428},
{286.483, 152.753, 185.253, 185.253, 286.483, 445.253}};
float **cov1 = new float *[6];
for(int p=0;p<6;p++)cov1[p]=new float [6];
for (int i=0; i<6; i++)
for (int j=0; j<6; j++) cov1[i][j]=cov[i][j];
for (int i=0; i<6; i++)
{for (int j=0; j<6; j++) cout<<cov1[i][j]<<” “;
cout<<endl;
}
float **res= new float *[6];
for(int p=0;p<6;p++)res[p]=new float [6];
MatrixInversion(cov1,6,res);
for (int i=0; i<6; i++)
{for (int j=0; j<6; j++) cout<<res[i][j]<<” “;
cout<<endl;
}
for(int i=0;i<6;i++)
delete [] cov1[i];
delete [] cov1;
for(int i=0;i<6;i++)
delete [] res[i];
delete [] res;
system (“pause”);
return 0;
}
August 29, 2008 at 6:17 am |
Quick question. I was trying to implement this, but I don’t know how to declare the initial matrix.
I tried:
float MyMatrix[14][14];
but after I fill it and stick it in the function, I get:
error: cannot convert ‘float (*)[14]‘ to ‘float**’ …
August 29, 2008 at 6:32 am |
Jason,
MyMatrix has to be dynamically allocated. For example,
float **MyMatrix;
MyMatrix = new float*[14];
for(int i=0;i<14;i++)
MyMatrix[i] = new float[14];
Hope this helps!
September 2, 2008 at 10:21 am |
Thanks, that did help. FYI though, your GetMinor( float **dest, float **src, int row, int col, int order) has the source and destination switched as compared to all the function calls.
e.g. GetMinor( mat, minor, 0, i , order); //where either the “mat” and “minor” should be switched, or the corresponding in the function itself.
Took me a while to figure out why I kept getting Segmentation faults.
September 2, 2008 at 5:55 pm |
Jason,
Thanks a lot for pointing out the bug.
January 8, 2009 at 9:04 pm |
Hi Dear Janson,
Thanks for your code.
I am beginner in C++ and I don’t know how can i put your code inside of the main function, how to call MatrixInversion and how to input matrix element values.
Really, pointer-to-pointer is somehow ambiguous and I can’t understand it.
Thanks.
January 8, 2009 at 9:09 pm |
Sorry for confusing the main code writer.
I also want to thank chi3×10 due to main contribution.
January 18, 2009 at 11:35 am |
I think your calculation of the determinant is possibly flawed. You’re calculation assumes that row and column indices in the range [0, n-1] where n is the size of the square matrix.
Generic expansion of a determinant at a row or column calls for row and column indices in the range [1, n], which means your summation should in fact be:
det += pow( -1.0, 2.0 + i ) * mat[0][i] * CalcDeterminant( minor,order-1 );
since you are expanding according to the first row of the matrix.
http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/determinant/
has a very good explanation of the theory and a C implementation
January 18, 2009 at 12:43 pm |
Sorry, my bad…just realized that squaring the square of negative one still produces the same answer. There is nothing wrong with your determinant calculation.
January 18, 2009 at 5:47 pm |
January 28, 2009 at 12:26 am |
Thanks very much for posting – this is very helpful!
January 28, 2009 at 12:32 pm |
chi3×10-
Thanks for posting this! I’m desperately trying to get my experiments under way and I’ve got enough to do without figuring this out!
One question: my compiler is setup strictly for C, no C++; I’ve translated the code most of the way (I think) but I’m sketchy on pointers. Can you direct me to anything like a C++ to C translation guide, or better yet post a C version? That’s asking a lot…
In any case, thank you!
January 28, 2009 at 1:38 pm |
Greg,
All you need to do is to modify memory allocation thing. Use malloc(…..) instead of new. Use free(…) instead of delete. It should work fine.
January 28, 2009 at 2:19 pm |
Thanks for the quick reply!
That’s what I thought (and what I did) but …
Ok, I just went back and found a bug in my translation, so now I’m not getting warnings, but I’m still segfaulting when I try to call the function.
To be clear, instead of (for example)
float *temp = new float[(order-1)*(order-1)];
float **minor = new float*[order-1];
I should use:
float *temp = malloc(sizeof(float)*((order-1)*(order-1)));
float **minor = malloc(sizeof(float)*(order-1));
Perhaps I’m having a problem initializing MyMatrix (as the above commenter).
Can I do direct assignment, i.e. (for 3×3 test case):
float **MyMatrix=malloc(sizeof(float)*3*3);
float **MyInverse=malloc(sizeof(float)*3*3);
MyMatrix[0][0]=1.2;
MyMatrix[0][1]=0.95;
//etc,etc
and then make the call as
MatrixInversion(MyMatrix, 3, MyInverse);
Thanks for your help!
March 29, 2009 at 5:31 pm |
Hello,
Thanks for sharing your code.
I am having a strange problem, the result being returned in Y is basically of type -1.#IND and 1.#QNAN.
I am using your code exactly as it is, and calling it as follows for a 4×4 matrix. Do you have any idea why? Thanks so much!
float **MyMatrix;
MyMatrix = new float*[4];
for(int i=0;i<4;i++)
MyMatrix[i] = new float[4];
float **Y;
Y = new float*[4];
for(int i=0;i<4;i++)
Y[i] = new float[4];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
MyMatrix[i][j] = i * 1.0;
cout<<endl;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
cout<<MyMatrix[i][j]<<” \n”;
MatrixInversion(MyMatrix, 4, Y);
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
cout<<Y[i][j]<<” \n”;
March 31, 2009 at 1:31 am |
Tom,
Maybe the problem is that your matrix is singular. You can check if a matrix is singular by calculating the determinant of the matrix first. If determinant of a matrix is zero, the matrix is invertible.
Hope this helps
April 26, 2009 at 9:39 pm |
why do I get an error GetMinor undefined and CalcDeterminant undefined. trying to establish matrix determinant (n less than =to 100)
October 16, 2009 at 5:49 am |
hey, can anyone post here your full source code? tnx..
October 18, 2009 at 9:22 am |
Hello… i used your code in my work… and it seemed to work fine.. thanks a lot…
November 2, 2009 at 3:17 am |
Hi Jason – great work
… so is it ok to incorporate your code into my GPL’d FOSS project?
November 2, 2009 at 3:31 am |
sure! but I hope you knows that this method would become really slow when the dimensionality of the matrix is high (like 10×10).