44

What's the easiest way to compute a 3x3 matrix inverse?

I'm just looking for a short code snippet that'll do the trick for non-singular matrices, possibly using Cramer's rule. It doesn't need to be highly optimized. I'd prefer simplicity over speed. I'd rather not link in additional libraries.

genpfault
  • 51,148
  • 11
  • 85
  • 139
batty
  • 7,528
  • 9
  • 31
  • 30

12 Answers12

60

Here's a version of batty's answer, but this computes the correct inverse. batty's version computes the transpose of the inverse.

// computes the inverse of a matrix m
double det = m(0, 0) * (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) -
             m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
             m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0));

double invdet = 1 / det;

Matrix33d minv; // inverse of matrix m
minv(0, 0) = (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) * invdet;
minv(0, 1) = (m(0, 2) * m(2, 1) - m(0, 1) * m(2, 2)) * invdet;
minv(0, 2) = (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * invdet;
minv(1, 0) = (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) * invdet;
minv(1, 1) = (m(0, 0) * m(2, 2) - m(0, 2) * m(2, 0)) * invdet;
minv(1, 2) = (m(1, 0) * m(0, 2) - m(0, 0) * m(1, 2)) * invdet;
minv(2, 0) = (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1)) * invdet;
minv(2, 1) = (m(2, 0) * m(0, 1) - m(0, 0) * m(2, 1)) * invdet;
minv(2, 2) = (m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1)) * invdet;
Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • 4
    This is the best answer imo, but it calculates some things 2 times, like m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2). Please store the 2nd part of the 3 determinant calculations in 3 temporary doubles. They're going to be used in the last part of the calculation again. If you flip m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0), you can even re-use it without the minus sign. – Luc Bloom Feb 23 '15 at 11:07
  • 2
    I wrote this primarily for clarity, not necessarily speed. But you're absolutely right that some operations are repeated and can be avoided by temporarily caching the result and reusing it. – Cornstalks Feb 23 '15 at 16:57
  • 6
    The compiler should be able to optimize that. No worries. – Hugo Maxwell Aug 16 '16 at 21:33
  • 1
    This is the simplest implementation of the algorithm. However, beware that the determinants of the minors might be affected by round-off errors. This site provides a good explanation of the problem, and a nice solution: https://pharr.org/matt/blog/2019/11/03/difference-of-floats.html – Maurizio Tomasi Oct 21 '20 at 07:41
  • The computations are correct, but result become unstable when determinant is close to 0. I found this by comparing it with with the numpy.linalg.inv method which provides much better result. Just multiply the inverted and the original matrices and compare it with the identity matrix. – Ivan Kovtun Jan 26 '22 at 03:55
33

This piece of code computes the transposed inverse of the matrix A:

double determinant =    +A(0,0)*(A(1,1)*A(2,2)-A(2,1)*A(1,2))
                        -A(0,1)*(A(1,0)*A(2,2)-A(1,2)*A(2,0))
                        +A(0,2)*(A(1,0)*A(2,1)-A(1,1)*A(2,0));
double invdet = 1/determinant;
result(0,0) =  (A(1,1)*A(2,2)-A(2,1)*A(1,2))*invdet;
result(1,0) = -(A(0,1)*A(2,2)-A(0,2)*A(2,1))*invdet;
result(2,0) =  (A(0,1)*A(1,2)-A(0,2)*A(1,1))*invdet;
result(0,1) = -(A(1,0)*A(2,2)-A(1,2)*A(2,0))*invdet;
result(1,1) =  (A(0,0)*A(2,2)-A(0,2)*A(2,0))*invdet;
result(2,1) = -(A(0,0)*A(1,2)-A(1,0)*A(0,2))*invdet;
result(0,2) =  (A(1,0)*A(2,1)-A(2,0)*A(1,1))*invdet;
result(1,2) = -(A(0,0)*A(2,1)-A(2,0)*A(0,1))*invdet;
result(2,2) =  (A(0,0)*A(1,1)-A(1,0)*A(0,1))*invdet;

Though the question stipulated non-singular matrices, you might still want to check if determinant equals zero (or very near zero) and flag it in some way to be safe.

brc-dd
  • 10,788
  • 3
  • 47
  • 67
batty
  • 7,528
  • 9
  • 31
  • 30
  • 2
    Don't forget to check if determinant is zero :) – Nick Dandoulakis Jun 11 '09 at 23:24
  • 1
    Now try doing that without so much... mess. :) (Ideally, without using any number other than "0" and "3" in the code.) – ShreevatsaR Jun 11 '09 at 23:24
  • 3
    This code actually gives you the TRANSPOSE of the inverse matrix. Check out the formula at the other answer – shoosh Nov 29 '09 at 13:10
  • 4
    Concise, elegant, and fast (even if it is the transpose) - nicely done! A more general solution that uses loops and multiple function calls is both overkill and needless overhead for such a fundamental operation. – AbePralle Feb 24 '12 at 07:32
27

Why don't you try to code it yourself? Take it as a challenge. :)

For a 3×3 matrix

alt text
(source: wolfram.com)

the matrix inverse is

alt text
(source: wolfram.com)

I'm assuming you know what the determinant of a matrix |A| is.

Images (c) Wolfram|Alpha and mathworld.wolfram (06-11-09, 22.06)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
SuPra
  • 8,488
  • 4
  • 37
  • 30
  • 2
    Nice typesetting as well. LaTeX? – duffymo Jun 11 '09 at 22:47
  • 7
    As big a fan as I am of LaTeX, no. They are JPEGs generated by Wolfram|Alpha. :) – SuPra Jun 11 '09 at 22:58
  • 1
    Uh, is this actually right? All the off-diagonal entries look wrong to me, but maybe I'm not aware of some interesting matrix identity. E.g., shouldn't the cofactor of a12 be -|a21 a23; a31 a33|? – ShreevatsaR Jun 11 '09 at 23:53
  • That is perfectly right. The way you're putting it will be right if the rows and columns are interchanged and the determinant sign is reversed. – SuPra Jun 12 '09 at 00:00
  • What Wolfram Alpha search did you use to get them? – sourcenouveau Jun 12 '09 at 02:39
  • 1
    It looks like the jpegs off the wolframe math site. Try google. Yes the matrix is correct. Inverse is 1/det * minor of the TRANSPOSED matrix. – Mr.Ree Jun 12 '09 at 10:38
  • "It is permitted to use and post individual, incidental results or small groups of results from Wolfram|Alpha on non-commercial websites and blogs, provided those results are properly credited to Wolfram|Alpha (see Attribution and Licensing below)." -- Where's the citation? – jmanning2k Dec 22 '09 at 15:43
  • I also have some advice that spares some unnecessary calculation. If you are also working with rotation matrices, their inverse is equal to their transpose. Rot^(-1) = Rot^t In such case the formula mentioned by @Suvesh Pratapa can be skipped, which adds a speed and memory boost if you deal with a huge amount of rotations (example: robotics). – rbaleksandar Dec 20 '12 at 14:36
  • I believe that this method is numerically unstable for some nearly singular matrices. – Michael Anderson Aug 08 '13 at 06:33
  • 4
    Nice if you have the time to take a challenge but frankly it doesn't answer the question: "I'm just looking for a short code snippet that'll do the trick for non-singular matrices" –  May 19 '14 at 07:42
  • A quite elegant way to do it, if the matrix's rows are 3d vectors `v[0]`,`v[1]`,`v[2]`, would be `invdet = 1/Sum(v[0]*cross(v[1],v[2]));` and `temp = transpose(mat3(cross(v[1],v[2]),cross(v[2],v[0]),cross(v[0],v[1])))` then the inverse matrix is `det*temp`. Where * is componentwise multiplication, `Sum(v) := v[0]+v[1]+v[2];`, cross is the cross product, mat3 is a constructor of a 3x3 matrix class that takes 3 3d vectors as arguments. – lightxbulb Dec 05 '16 at 17:15
  • 9
    I'm going to be that guy. Downvoted because this doesn't actually answer the question - the C++ code is not here. – Alan Wolfe Dec 21 '16 at 00:36
  • Hey, I can’t read those terms on the black background. – Константин Ван Feb 09 '21 at 04:08
10

With all due respect to our unknown (yahoo) poster, I look at code like that and just die a little inside. Alphabet soup is just so insanely difficult to debug. A single typo anywhere in there can really ruin your whole day. Sadly, this particular example lacked variables with underscores. It's so much more fun when we have a_b-c_d*e_f-g_h. Especially when using a font where _ and - have the same pixel length.

Taking up Suvesh Pratapa on his suggestion, I note:

Given 3x3 matrix:
       y0x0  y0x1  y0x2
       y1x0  y1x1  y1x2
       y2x0  y2x1  y2x2
Declared as double matrix [/*Y=*/3] [/*X=*/3];

(A) When taking a minor of a 3x3 array, we have 4 values of interest. The lower X/Y index is always 0 or 1. The higher X/Y index is always 1 or 2. Always! Therefore:

double determinantOfMinor( int          theRowHeightY,
                           int          theColumnWidthX,
                           const double theMatrix [/*Y=*/3] [/*X=*/3] )
{
  int x1 = theColumnWidthX == 0 ? 1 : 0;  /* always either 0 or 1 */
  int x2 = theColumnWidthX == 2 ? 1 : 2;  /* always either 1 or 2 */
  int y1 = theRowHeightY   == 0 ? 1 : 0;  /* always either 0 or 1 */
  int y2 = theRowHeightY   == 2 ? 1 : 2;  /* always either 1 or 2 */

  return ( theMatrix [y1] [x1]  *  theMatrix [y2] [x2] )
      -  ( theMatrix [y1] [x2]  *  theMatrix [y2] [x1] );
}

(B) Determinant is now: (Note the minus sign!)

double determinant( const double theMatrix [/*Y=*/3] [/*X=*/3] )
{
  return ( theMatrix [0] [0]  *  determinantOfMinor( 0, 0, theMatrix ) )
      -  ( theMatrix [0] [1]  *  determinantOfMinor( 0, 1, theMatrix ) )
      +  ( theMatrix [0] [2]  *  determinantOfMinor( 0, 2, theMatrix ) );
}

(C) And the inverse is now:

bool inverse( const double theMatrix [/*Y=*/3] [/*X=*/3],
                    double theOutput [/*Y=*/3] [/*X=*/3] )
{
  double det = determinant( theMatrix );

    /* Arbitrary for now.  This should be something nicer... */
  if ( ABS(det) < 1e-2 )
  {
    memset( theOutput, 0, sizeof theOutput );
    return false;
  }

  double oneOverDeterminant = 1.0 / det;

  for (   int y = 0;  y < 3;  y ++ )
    for ( int x = 0;  x < 3;  x ++   )
    {
        /* Rule is inverse = 1/det * minor of the TRANSPOSE matrix.  *
         * Note (y,x) becomes (x,y) INTENTIONALLY here!              */
      theOutput [y] [x]
        = determinantOfMinor( x, y, theMatrix ) * oneOverDeterminant;

        /* (y0,x1)  (y1,x0)  (y1,x2)  and (y2,x1)  all need to be negated. */
      if( 1 == ((x + y) % 2) )
        theOutput [y] [x] = - theOutput [y] [x];
    }

  return true;
}

And round it out with a little lower-quality testing code:

void printMatrix( const double theMatrix [/*Y=*/3] [/*X=*/3] )
{
  for ( int y = 0;  y < 3;  y ++ )
  {
    cout << "[  ";
    for ( int x = 0;  x < 3;  x ++   )
      cout << theMatrix [y] [x] << "  ";
    cout << "]" << endl;
  }
  cout << endl;
}

void matrixMultiply(  const double theMatrixA [/*Y=*/3] [/*X=*/3],
                      const double theMatrixB [/*Y=*/3] [/*X=*/3],
                            double theOutput  [/*Y=*/3] [/*X=*/3]  )
{
  for (   int y = 0;  y < 3;  y ++ )
    for ( int x = 0;  x < 3;  x ++   )
    {
      theOutput [y] [x] = 0;
      for ( int i = 0;  i < 3;  i ++ )
        theOutput [y] [x] +=  theMatrixA [y] [i] * theMatrixB [i] [x];
    }
}

int
main(int argc, char **argv)
{
  if ( argc > 1 )
    SRANDOM( atoi( argv[1] ) );

  double m[3][3] = { { RANDOM_D(0,1e3), RANDOM_D(0,1e3), RANDOM_D(0,1e3) },
                     { RANDOM_D(0,1e3), RANDOM_D(0,1e3), RANDOM_D(0,1e3) },
                     { RANDOM_D(0,1e3), RANDOM_D(0,1e3), RANDOM_D(0,1e3) } };
  double o[3][3], mm[3][3];

  if ( argc <= 2 )
    cout << fixed << setprecision(3);

  printMatrix(m);
  cout << endl << endl;

  SHOW( determinant(m) );
  cout << endl << endl;

  BOUT( inverse(m, o) );
  printMatrix(m);
  printMatrix(o);
  cout << endl << endl;

  matrixMultiply (m, o, mm );
  printMatrix(m);
  printMatrix(o);
  printMatrix(mm);  
  cout << endl << endl;
}

Afterthought:

You may also want to detect very large determinants as round-off errors will affect your accuracy!

Mr.Ree
  • 8,320
  • 27
  • 30
  • "With all due respect" my code is crap? Nice. ;-) Maybe you could do the forward error analysis to determine some bounds on the round-off error instead of just picking an arbitrary constant cutoff for the determinant? 1e-2 is probably rather too conservative of a cutoff. – batty Jun 12 '09 at 23:06
  • If the determinant is very large, 1/det (which we multiply by) is close to zero. If the determinant is very small, 1/det has divide by zero issues and becomes extremely large. Where to set the thresholds is somewhat application dependent, and perhaps best decided stochastically (probabilistically) depending on your data. Alternatively, you may want to consider libgmp/libgmpxx for improved precision. – Mr.Ree Jun 13 '09 at 01:24
  • 13
    The interesting thing here is that Mr Ree's code is a few more orders of magnitude more difficult to read and understand than the one given above. – Robinson Nov 11 '12 at 18:07
4

Don't try to do this yourself if you're serious about getting edge cases right. So while they many naive/simple methods are theoretically exact, they can have nasty numerical behavior for nearly singular matrices. In particular you can get cancelation/round-off errors that cause you to get arbitrarily bad results.

A "correct" way is Gaussian elimination with row and column pivoting so that you're always dividing by the largest remaining numerical value. (This is also stable for NxN matrices.). Note that row pivoting alone doesn't catch all the bad cases.

However IMO implementing this right and fast is not worth your time - use a well tested library and there are a heap of header only ones.

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
3

A rather nice (I think) header file containing macros for most 2x2, 3x3 and 4x4 matrix operations has been available with most OpenGL toolkits. Not as standard but I've seen it at various places.

You can check it out here. At the end of it you will find both inverse of 2x2, 3x3 and 4x4.

vvector.h

HughA
  • 3
  • 2
epatel
  • 45,805
  • 17
  • 110
  • 144
3

I have just created a QMatrix class. It uses the built in vector > container. QMatrix.h It uses the Jordan-Gauss method to compute the inverse of a square matrix.

You can use it as follows:

#include "QMatrix.h"
#include <iostream>

int main(){
QMatrix<double> A(3,3,true);
QMatrix<double> Result = A.inverse()*A; //should give the idendity matrix

std::cout<<A.inverse()<<std::endl;
std::cout<<Result<<std::endl; // for checking
return 0;
}

The inverse function is implemented as follows:

Given a class with the following fields:

template<class T> class QMatrix{
public:
int rows, cols;
std::vector<std::vector<T> > A;

the inverse() function:

template<class T> 
QMatrix<T> QMatrix<T>:: inverse(){
Identity<T> Id(rows); //the Identity Matrix as a subclass of QMatrix.
QMatrix<T> Result = *this; // making a copy and transforming it to the Identity matrix
T epsilon = 0.000001;
for(int i=0;i<rows;++i){
    //check if Result(i,i)==0, if true, switch the row with another

    for(int j=i;j<rows;++j){
        if(std::abs(Result(j,j))<epsilon) { //uses Overloading()(int int) to extract element from Result Matrix
            Result.replace_rows(i,j+1); //switches rows i with j+1
        }
        else break;
    }
    // main part, making a triangular matrix
    Id(i)=Id(i)*(1.0/Result(i,i));
    Result(i)=Result(i)*(1.0/Result(i,i));  // Using overloading ()(int) to get a row form the matrix
    for(int j=i+1;j<rows;++j){
        T temp = Result(j,i);
        Result(j) = Result(j) - Result(i)*temp;
        Id(j) = Id(j) - Id(i)*temp; //doing the same operations to the identity matrix
        Result(j,i)=0; //not necessary, but looks nicer than 10^-15
    }
}

// solving a triangular matrix 
for(int i=rows-1;i>0;--i){
    for(int j=i-1;j>=0;--j){
        T temp = Result(j,i);
        Id(j) = Id(j) - temp*Id(i);
        Result(j)=Result(j)-temp*Result(i);
    }
}

return Id;
}
moldovean
  • 3,132
  • 33
  • 36
1

I would also recommend Ilmbase, which is part of OpenEXR. It's a good set of templated 2,3,4-vector and matrix routines.

Larry Gritz
  • 13,331
  • 5
  • 42
  • 42
  • This seems a very good choice to me - you can use `Matrix33::inverse` if you don't care about stability, and `Matrix33::gjInverse` if you do. – Michael Anderson Aug 08 '13 at 06:38
1
# include <conio.h>
# include<iostream.h>

const int size = 9;

int main()
{
    char ch;

    do
    {
        clrscr();
        int i, j, x, y, z, det, a[size], b[size];

        cout << "           **** MATRIX OF 3x3 ORDER ****"
             << endl
             << endl
             << endl;

        for (i = 0; i <= size; i++)
            a[i]=0;

        for (i = 0; i < size; i++)
        {
            cout << "Enter "
                 << i + 1
                 << " element of matrix=";

            cin >> a[i]; 

            cout << endl
                 <<endl;
        }

        clrscr();

        cout << "your entered matrix is "
             << endl
             <<endl;

        for (i = 0; i < size; i += 3)
            cout << a[i]
                 << "  "
                 << a[i+1]
                 << "  "
                 << a[i+2]
                 << endl
                 <<endl;

        cout << "Transpose of given matrix is"
             << endl
             << endl;

        for (i = 0; i < 3; i++)
            cout << a[i]
                 << "  "
                 << a[i+3]
                 << "  "
                 << a[i+6]
                 << endl
                 << endl;

        cout << "Determinent of given matrix is = ";

        x = a[0] * (a[4] * a[8] -a [5] * a[7]);
        y = a[1] * (a[3] * a[8] -a [5] * a[6]);
        z = a[2] * (a[3] * a[7] -a [4] * a[6]);
        det = x - y + z;

        cout << det 
             << endl
             << endl
             << endl
             << endl;

        if (det == 0)
        {
            cout << "As Determinent=0 so it is singular matrix and its inverse cannot exist"
                 << endl
                 << endl;

            goto quit;
        }

        b[0] = a[4] * a[8] - a[5] * a[7];
        b[1] = a[5] * a[6] - a[3] * a[8];
        b[2] = a[3] * a[7] - a[4] * a[6];
        b[3] = a[2] * a[7] - a[1] * a[8];
        b[4] = a[0] * a[8] - a[2] * a[6];
        b[5] = a[1] * a[6] - a[0] * a[7];
        b[6] = a[1] * a[5] - a[2] * a[4];
        b[7] = a[2] * a[3] - a[0] * a[5];
        b[8] = a[0] * a[4] - a[1] * a[3];

        cout << "Adjoint of given matrix is"
             << endl
             << endl;

        for (i = 0; i < 3; i++)
        {
            cout << b[i]
                 << "  "
                 << b[i+3]
                 << "  "
                 << b[i+6]
                 << endl
                 <<endl;
        }

        cout << endl
             <<endl;

        cout << "Inverse of given matrix is "
             << endl
             << endl
             << endl;

        for (i = 0; i < 3; i++)
        {
            cout << b[i]
                 << "/"
                 << det
                 << "  "
                 << b[i+3]
                 << "/" 
                 << det
                 << "  "
                 << b[i+6]
                 << "/" 
                 << det
                 << endl
                  <<endl;
        }

        quit:

        cout << endl
             << endl;

        cout << "Do You want to continue this again press (y/yes,n/no)";

        cin >> ch; 

        cout << endl
             << endl;
    } /* end do */

    while (ch == 'y');
    getch ();

    return 0;
}
rodrigo-silveira
  • 12,607
  • 11
  • 69
  • 123
aqeel
  • 11
  • 1
0
#include <iostream>
using namespace std;

int main()
{
    double A11, A12, A13;
    double A21, A22, A23;
    double A31, A32, A33;

    double B11, B12, B13;
    double B21, B22, B23;
    double B31, B32, B33;

    cout << "Enter all number from left to right, from top to bottom, and press enter after every number: ";
    cin  >> A11;
    cin  >> A12;
    cin  >> A13;
    cin  >> A21;
    cin  >> A22;
    cin  >> A23;
    cin  >> A31;
    cin  >> A32;
    cin  >> A33;

    B11 = 1 / ((A22 * A33) - (A23 * A32));
    B12 = 1 / ((A13 * A32) - (A12 * A33));
    B13 = 1 / ((A12 * A23) - (A13 * A22));
    B21 = 1 / ((A23 * A31) - (A21 * A33));
    B22 = 1 / ((A11 * A33) - (A13 * A31));
    B23 = 1 / ((A13 * A21) - (A11 * A23));
    B31 = 1 / ((A21 * A32) - (A22 * A31));
    B32 = 1 / ((A12 * A31) - (A11 * A32));
    B33 = 1 / ((A11 * A22) - (A12 * A21));

    cout << B11 << "\t" << B12 << "\t" << B13 << endl;
    cout << B21 << "\t" << B22 << "\t" << B23 << endl;
    cout << B31 << "\t" << B32 << "\t" << B33 << endl;

    return 0;
}
Ephemera
  • 8,672
  • 8
  • 44
  • 84
Matthew
  • 1
  • 1
  • 2
    This was my try... i guess it doesn't work right... sorry. lol. I didn't try it before hand. :/ – Matthew Feb 19 '13 at 02:45
  • 1
    It's bad mojo to have a code answer which is known to be defective. @Matthew, if you can't confirm that this works, can you remove the answer? – Kenn Sebesta Oct 08 '20 at 06:27
0
//Title: Matrix Header File
//Writer: Say OL
//This is a beginner code not an expert one
//No responsibilty for any errors
//Use for your own risk
using namespace std;
int row,col,Row,Col;
double Coefficient;
//Input Matrix
void Input(double Matrix[9][9],int Row,int Col)
{
    for(row=1;row<=Row;row++)
        for(col=1;col<=Col;col++)
        {
            cout<<"e["<<row<<"]["<<col<<"]=";
            cin>>Matrix[row][col];
        }
}
//Output Matrix
void Output(double Matrix[9][9],int Row,int Col)
{
    for(row=1;row<=Row;row++)
    {
        for(col=1;col<=Col;col++)
            cout<<Matrix[row][col]<<"\t";
        cout<<endl;
    }
}
//Copy Pointer to Matrix
void CopyPointer(double (*Pointer)[9],double Matrix[9][9],int Row,int Col)
{
    for(row=1;row<=Row;row++)
        for(col=1;col<=Col;col++)
            Matrix[row][col]=Pointer[row][col];
}
//Copy Matrix to Matrix
void CopyMatrix(double MatrixInput[9][9],double MatrixTarget[9][9],int Row,int Col)
{
    for(row=1;row<=Row;row++)
        for(col=1;col<=Col;col++)
            MatrixTarget[row][col]=MatrixInput[row][col];
}
//Transpose of Matrix
double MatrixTran[9][9];
double (*(Transpose)(double MatrixInput[9][9],int Row,int Col))[9]
{
    for(row=1;row<=Row;row++)
        for(col=1;col<=Col;col++)
            MatrixTran[col][row]=MatrixInput[row][col];
    return MatrixTran;
}
//Matrix Addition
double MatrixAdd[9][9];
double (*(Addition)(double MatrixA[9][9],double MatrixB[9][9],int Row,int Col))[9]
{
    for(row=1;row<=Row;row++)
        for(col=1;col<=Col;col++)
            MatrixAdd[row][col]=MatrixA[row][col]+MatrixB[row][col];
    return MatrixAdd;
}
//Matrix Subtraction
double MatrixSub[9][9];
double (*(Subtraction)(double MatrixA[9][9],double MatrixB[9][9],int Row,int Col))[9]
{
    for(row=1;row<=Row;row++)
        for(col=1;col<=Col;col++)
            MatrixSub[row][col]=MatrixA[row][col]-MatrixB[row][col];
    return MatrixSub;
}
//Matrix Multiplication
int mRow,nCol,pCol,kcol;
double MatrixMult[9][9];
double (*(Multiplication)(double MatrixA[9][9],double MatrixB[9][9],int mRow,int nCol,int pCol))[9]
{
    for(row=1;row<=mRow;row++)
        for(col=1;col<=pCol;col++)
        {
            MatrixMult[row][col]=0.0;
            for(kcol=1;kcol<=nCol;kcol++)
                MatrixMult[row][col]+=MatrixA[row][kcol]*MatrixB[kcol][col];
        }
    return MatrixMult;
}
//Interchange Two Rows
double RowTemp[9][9];
double MatrixInter[9][9];
double (*(InterchangeRow)(double MatrixInput[9][9],int Row,int Col,int iRow,int jRow))[9]
{
    CopyMatrix(MatrixInput,MatrixInter,Row,Col);
    for(col=1;col<=Col;col++)
    {
        RowTemp[iRow][col]=MatrixInter[iRow][col];
        MatrixInter[iRow][col]=MatrixInter[jRow][col];
        MatrixInter[jRow][col]=RowTemp[iRow][col];
    }
    return MatrixInter;
}
//Pivote Downward
double MatrixDown[9][9];
double (*(PivoteDown)(double MatrixInput[9][9],int Row,int Col,int tRow,int tCol))[9]
{
    CopyMatrix(MatrixInput,MatrixDown,Row,Col);
    Coefficient=MatrixDown[tRow][tCol];
    if(Coefficient!=1.0)
        for(col=1;col<=Col;col++)
            MatrixDown[tRow][col]/=Coefficient;
    if(tRow<Row)
        for(row=tRow+1;row<=Row;row++)
        {
            Coefficient=MatrixDown[row][tCol];
            for(col=1;col<=Col;col++)
                MatrixDown[row][col]-=Coefficient*MatrixDown[tRow][col];
        }
return MatrixDown;
}
//Pivote Upward
double MatrixUp[9][9];
double (*(PivoteUp)(double MatrixInput[9][9],int Row,int Col,int tRow,int tCol))[9]
{
    CopyMatrix(MatrixInput,MatrixUp,Row,Col);
    Coefficient=MatrixUp[tRow][tCol];
    if(Coefficient!=1.0)
        for(col=1;col<=Col;col++)
            MatrixUp[tRow][col]/=Coefficient;
    if(tRow>1)
        for(row=tRow-1;row>=1;row--)
        {
            Coefficient=MatrixUp[row][tCol];
            for(col=1;col<=Col;col++)
                MatrixUp[row][col]-=Coefficient*MatrixUp[tRow][col];
        }
    return MatrixUp;
}
//Pivote in Determinant
double MatrixPiv[9][9];
double (*(Pivote)(double MatrixInput[9][9],int Dim,int pTarget))[9]
{
    CopyMatrix(MatrixInput,MatrixPiv,Dim,Dim);
    for(row=pTarget+1;row<=Dim;row++)
    {
        Coefficient=MatrixPiv[row][pTarget]/MatrixPiv[pTarget][pTarget];
        for(col=1;col<=Dim;col++)
        {
            MatrixPiv[row][col]-=Coefficient*MatrixPiv[pTarget][col];
        }
    }
    return MatrixPiv;
}
//Determinant of Square Matrix
int dCounter,dRow;
double Det;
double MatrixDet[9][9];
double Determinant(double MatrixInput[9][9],int Dim)
{
    CopyMatrix(MatrixInput,MatrixDet,Dim,Dim);
    Det=1.0;
    if(Dim>1)
    {
        for(dRow=1;dRow<Dim;dRow++)
        {
            dCounter=dRow;
            while((MatrixDet[dRow][dRow]==0.0)&(dCounter<=Dim))
            {
                dCounter++;
                Det*=-1.0;
                CopyPointer(InterchangeRow(MatrixDet,Dim,Dim,dRow,dCounter),MatrixDet,Dim,Dim);
            }
            if(MatrixDet[dRow][dRow]==0)
            {
                Det=0.0;
                break;
            }
            else
            {
                Det*=MatrixDet[dRow][dRow];
                CopyPointer(Pivote(MatrixDet,Dim,dRow),MatrixDet,Dim,Dim);
            }
        }
        Det*=MatrixDet[Dim][Dim];
    }
    else Det=MatrixDet[1][1];
    return Det;
}
//Matrix Identity
double MatrixIdent[9][9];
double (*(Identity)(int Dim))[9]
{
    for(row=1;row<=Dim;row++)
        for(col=1;col<=Dim;col++)
            if(row==col)
                MatrixIdent[row][col]=1.0;
            else
                MatrixIdent[row][col]=0.0;
    return MatrixIdent;
}
//Join Matrix to be Augmented Matrix
double MatrixJoin[9][9];
double (*(JoinMatrix)(double MatrixA[9][9],double MatrixB[9][9],int Row,int ColA,int ColB))[9]
{
    Col=ColA+ColB;
    for(row=1;row<=Row;row++)
        for(col=1;col<=Col;col++)
            if(col<=ColA)
                MatrixJoin[row][col]=MatrixA[row][col];
            else
                MatrixJoin[row][col]=MatrixB[row][col-ColA];
    return MatrixJoin;
}
//Inverse of Matrix
double (*Pointer)[9];
double IdentMatrix[9][9];
int Counter;
double MatrixAug[9][9];
double MatrixInv[9][9];
double (*(Inverse)(double MatrixInput[9][9],int Dim))[9]
{
    Row=Dim;
    Col=Dim+Dim;
    Pointer=Identity(Dim);
    CopyPointer(Pointer,IdentMatrix,Dim,Dim);
    Pointer=JoinMatrix(MatrixInput,IdentMatrix,Dim,Dim,Dim);
    CopyPointer(Pointer,MatrixAug,Row,Col);
    for(Counter=1;Counter<=Dim;Counter++)   
    {
        Pointer=PivoteDown(MatrixAug,Row,Col,Counter,Counter);
        CopyPointer(Pointer,MatrixAug,Row,Col);
    }
    for(Counter=Dim;Counter>1;Counter--)
    {
        Pointer=PivoteUp(MatrixAug,Row,Col,Counter,Counter);
        CopyPointer(Pointer,MatrixAug,Row,Col);
    }
    for(row=1;row<=Dim;row++)
        for(col=1;col<=Dim;col++)
            MatrixInv[row][col]=MatrixAug[row][col+Dim];
    return MatrixInv;
}
//Gauss-Jordan Elemination
double MatrixGJ[9][9];
double VectorGJ[9][9];
double (*(GaussJordan)(double MatrixInput[9][9],double VectorInput[9][9],int Dim))[9]
{
    Row=Dim;
    Col=Dim+1;
    Pointer=JoinMatrix(MatrixInput,VectorInput,Dim,Dim,1);
    CopyPointer(Pointer,MatrixGJ,Row,Col);
    for(Counter=1;Counter<=Dim;Counter++)   
    {
        Pointer=PivoteDown(MatrixGJ,Row,Col,Counter,Counter);
        CopyPointer(Pointer,MatrixGJ,Row,Col);
    }
    for(Counter=Dim;Counter>1;Counter--)
    {
        Pointer=PivoteUp(MatrixGJ,Row,Col,Counter,Counter);
        CopyPointer(Pointer,MatrixGJ,Row,Col);
    }
    for(row=1;row<=Dim;row++)
        for(col=1;col<=1;col++)
            VectorGJ[row][col]=MatrixGJ[row][col+Dim];
    return VectorGJ;
}
//Generalized Gauss-Jordan Elemination
double MatrixGGJ[9][9];
double VectorGGJ[9][9];
double (*(GeneralizedGaussJordan)(double MatrixInput[9][9],double VectorInput[9][9],int Dim,int vCol))[9]
{
    Row=Dim;
    Col=Dim+vCol;
    Pointer=JoinMatrix(MatrixInput,VectorInput,Dim,Dim,vCol);
    CopyPointer(Pointer,MatrixGGJ,Row,Col);
    for(Counter=1;Counter<=Dim;Counter++)   
    {
        Pointer=PivoteDown(MatrixGGJ,Row,Col,Counter,Counter);
        CopyPointer(Pointer,MatrixGGJ,Row,Col);
    }
    for(Counter=Dim;Counter>1;Counter--)
    {
        Pointer=PivoteUp(MatrixGGJ,Row,Col,Counter,Counter);
        CopyPointer(Pointer,MatrixGGJ,Row,Col);
    }
    for(row=1;row<=Row;row++)
        for(col=1;col<=vCol;col++)
            VectorGGJ[row][col]=MatrixGGJ[row][col+Dim];
    return VectorGGJ;
}
//Matrix Sparse, Three Diagonal Non-Zero Elements
double MatrixSpa[9][9];
double (*(Sparse)(int Dimension,double FirstElement,double SecondElement,double ThirdElement))[9]
{
    MatrixSpa[1][1]=SecondElement;
    MatrixSpa[1][2]=ThirdElement;
    MatrixSpa[Dimension][Dimension-1]=FirstElement;
    MatrixSpa[Dimension][Dimension]=SecondElement;
    for(int Counter=2;Counter<Dimension;Counter++)
    {
        MatrixSpa[Counter][Counter-1]=FirstElement;
        MatrixSpa[Counter][Counter]=SecondElement;
        MatrixSpa[Counter][Counter+1]=ThirdElement;
    }
    return MatrixSpa;
}

Copy and save the above code as Matrix.h then try the following code:

#include<iostream>
#include<conio.h>
#include"Matrix.h"
int Dim;
double Matrix[9][9];
int main()
{
    cout<<"Enter your matrix dimension: ";
    cin>>Dim;
    Input(Matrix,Dim,Dim);
    cout<<"Your matrix:"<<endl;
    Output(Matrix,Dim,Dim);
    cout<<"The inverse:"<<endl;
    Output(Inverse(Matrix,Dim),Dim,Dim);
    getch();
}
Kijewski
  • 25,517
  • 12
  • 101
  • 143
Say OL
  • 1
  • 1
0
//Function for inverse of the input square matrix 'J' of dimension 'dim':

vector<vector<double > > inverseVec33(vector<vector<double > > J, int dim)
{
//Matrix of Minors
 vector<vector<double > > invJ(dim,vector<double > (dim));
for(int i=0; i<dim; i++)
{
    for(int j=0; j<dim; j++)
    {
        invJ[i][j] = (J[(i+1)%dim][(j+1)%dim]*J[(i+2)%dim][(j+2)%dim] -
                      J[(i+2)%dim][(j+1)%dim]*J[(i+1)%dim][(j+2)%dim]);
    }
}

//determinant of the matrix:
double detJ = 0.0;
for(int j=0; j<dim; j++)
{ detJ += J[0][j]*invJ[0][j];}

//Inverse of the given matrix.
 vector<vector<double > > invJT(dim,vector<double > (dim));
 for(int i=0; i<dim; i++)
{
    for(int j=0; j<dim; j++)
    {
        invJT[i][j] = invJ[j][i]/detJ;
    }
}

return invJT;
}

void main()
{
    //given matrix:
vector<vector<double > > Jac(3,vector<double > (3));
Jac[0][0] = 1; Jac[0][1] = 2;  Jac[0][2] = 6;
Jac[1][0] = -3; Jac[1][1] = 4;  Jac[1][2] = 3;
Jac[2][0] = 5; Jac[2][1] = 1;  Jac[2][2] = -4;`

//Inverse of the matrix Jac:
vector<vector<double > > JacI(3,vector<double > (3));
    //call function and store inverse of J as JacI:
JacI = inverseVec33(Jac,3);
}
RAhmed
  • 1