cmatrixinverse

How to make a method return a two dimension array of type double in c


I have a method in c for computing the inverse of a three by three matrix, this method returns a 2 dimension vector of the type double,I declared a 2 dimension vector variable in my code and tried to assign but when i try to get the elements of the inverse 2 dimension vector, the code does not print anything

Code to compute the Inverse of a 3 by 3 matrix

#include <stdio.h>
#include <stdbool.h>
#include <conio.h>

double Determinant(double matrix[2][2]){
    double det=0;
    double a =matrix[0][0];
    double b=matrix[0][1];
    double c=matrix[1][0];
    double d=matrix[1][1];
    det=a*d-b*c;

    return det;
}
double** inverseMatrix(double matrix[3][3]){
    //define the entries for the matrix of minors
    double m1,m2,m3,m4,m5,m6,m7,m8,m9;
    //get the members of the matrix
    double a=matrix[0][0];
    double b=matrix[0][1];
    double c=matrix[0][2];

    double d=matrix[1][0];
    double e=matrix[1][1];
    double f=matrix[1][2];

    double g=matrix[2][0];
    double h=matrix[2][1];
    double i=matrix[2][2];

    //fill in the matrix of minors
    m1=(e*i)-(h*f);
    m2=d*i-g*f;
    m3=d*h-g*e;
    m4=b*i-h*c;
    m5=a*i-g*c;
    m6=a*h-g*b;
    m7=b*f-e*c;
    m8=a*f-d*c;
    m9=a*e-d*b;

    double minorArray[3][3];
    minorArray[0][0]=m1;
    minorArray[0][1]=m2;
    minorArray[0][2]=m3;
    minorArray[1][0]=m4;
    minorArray[1][1]=m5;
    minorArray[1][2]=m6;
    minorArray[2][0]=m7;
    minorArray[2][1]=m8;
    minorArray[2][2]=m9;


    //get the determinant //DEFINE THE MATRICES TO USE FOR THE DETERMINANT
    double A[2][2];
    A[0][0]=e;
    A[0][1]=f;
    A[1][0]=h;
    A[1][1]=i;

    double B[2][2];
    B[0][0]=d;
    B[0][1]=f;
    B[1][0]=g;
    B[1][1]=i;

    double C[2][2];
    C[0][0]=d;
    C[0][1]=e;
    C[1][0]=g;
    C[1][1]=h;

    double det=a*Determinant(A)-b*Determinant(B)+c*Determinant(C);
    int index=0;
    //get the matrix of co-factors
    for(int row=0;row<3;row++){
        for(int col=0;col<3;col++){
            index+=1;
            //check for entries at odd indices and negate them
            if(index%2!=0){
                minorArray[row][col]=-1*minorArray[row][col];
            }
        }
    }
    double answer[3][3];
    //divide everything by the determinant
    for(int row=0;row<3;row++){
        for(int col=0;col<3;col++){
            answer[row][col]=minorArray[row][col]/det;
        }
    }
    //determinant is given by a*DET(MA)-b*(DET(MB)+c*DET(MC
    double** ans= (double **) answer;
    return ans;
}

After that I try to assign the result of the method above to a variable I declared in the main, and then print out the elements of the inverse of the three by three matrix but my code outputs nothing

//assigning vaues to the matrix
 int kk=10;
    double test[3][3];
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            test[i][j]=kk;
            kk--;
        }
    }
//declare a 2d vector as pointer and assign the result of the method
 double** answer=inverseMatrix(test);
    //print out the elements of the function
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            printf("%.f  ",answer[i][j]);
        }
    }

Is it possible to do this in c and how do I get my code to successfully print out the members of the inverse matrix?


Solution

  • I suggest you wrap your matrix arrays into structs, different struct for different sizes. Here's one:

    struct Matrix3 {
        double m[3][3];
    };
    

    Let's also add some constants for convenience, a global (static or extern) variable:

    const struct Matrix3 ZeroMatrix3;  // globals are implicitly initialized to 0
    const struct Matrix3 IdentityMatrix3 = { { 
        { 1, 0, 0}, 
        { 0, 1, 0},
        { 0, 0, 1} } }
    

    Your inverse function might become:

    struct Matrix3 inverseMatrix3(const struct Matrix3 * restrict mp){
        struct Matrix3 result = ZeroMatrix3;
    
        // dummy code which does nothing:
        result = *mp;
    
        return result;
    }
    

    Example use:

    struct Matrix3 input = { { 
        { 1, 2, 3}, 
        { 4, 5, 6}, 
        { 0, 0, 0} } };
    struct Matrix3 inverse = inverseMatrix3(&input);
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            printf("%.f  ", inverse.m[i][j]);
        }
    }
    
    struct Matrix3 secondIdentity = inverseMatrix3(&IdentityMatrix3);
    
    // you probably want to add a compare function at some point...
    assert(compareMatrix3(&secondIdentity, &IdentityMatrix3)); // verify that inverse of identity works
    

    The point here is, define simple structs which holds your matrixes. You may want to add more structs, like struct Vector3 and struct Matrix3x1 and so on, what ever you need. Then you can return them from functions using values, and assign them with = directly, and so on.

    You could also pass them as values, but here they are passed as pointers to const struct, which is generally more efficient. That being said, 2x2 matrix is 32 bytes and 3x3 matrix is 72 bytes, and copying such small amount of bytes is very fast, so in general trying to optimize using pointers to heap allocated matrixes might even slow things down, and definitely add a lot of hassle. The use of restrict keyword here is a small optimization, you don't really need to care about it if you don't want to.