Search code examples
osx-lionlapackaccelerate-frameworkmatrix-inverse

How to perform matrix inverse operation using the accelerate framework?


I would like to find the inverse of a matrix.

I know this involves first LU factorisation then the inversion step but I cannot find the required function by searching apple's docs of 10.7!

This seems like a useful post Symmetric Matrix Inversion in C using CBLAS/LAPACK, pointing out that the sgetrf_ and sgetri_ functions should be used. However searching these terms I find nothing in Xcode docs.

Does anybody have boiler plate code for this matrix operation?


Solution

  • Apple does not document the LAPACK code at all, I guess because they just implement the standard interface from netlib.org. It's a shame that you cannot search the these function names from the built-in Xcode docs, however the solution is fairly straight forward: just specify the function name in the URL e.g. for dgetrf_() go to, http://www.netlib.org/clapack/what/double/dgetrf.c.

    To invert a matrix two LAPACK function are need: dgetrf_(), which performs LU factorisation, and dgetri_() which takes the output of the previous function and does the actual inversion.

    I created a standard Application Project using Xcode, added the Accelerate Framework, create two C files: matinv.h, matinv.c and edited the main.m file to remove Cocoa things:

    // main.m
    
    #import "matinv.h"
    
    int main(int argc, char *argv[])
    {
        int N = 3;
        double A[N*N];
        A[0] = 1; A[1] = 1; A[2] = 7;
        A[3] = 1; A[4] = 2; A[5] = 1;
        A[6] = 1; A[7] = 1; A[8] = 3;
        matrix_invert(N, A);
        //        [ -1.25  -1.0  3.25 ]
        // A^-1 = [  0.5       1.0  -1.5  ]
        //        [  0.25   0.0 -0.25 ] 
        return 0;
    }
    

    Now the header file,

    //  matinv.h
    
    int matrix_invert(int N, double *matrix);
    

    and then source file,

    int matrix_invert(int N, double *matrix) {
    
        int error=0;
        int *pivot = malloc(N*sizeof(int)); // LAPACK requires MIN(M,N), here M==N, so N will do fine.
        double *workspace = malloc(N*sizeof(double));
    
        /*  LU factorisation */
        dgetrf_(&N, &N, matrix, &N, pivot, &error);
    
        if (error != 0) {
            NSLog(@"Error 1");
            free(pivot);
            free(workspace);
            return error;
        }
    
        /*  matrix inversion */
        dgetri_(&N, matrix, &N, pivot, workspace, &N, &error);
    
        if (error != 0) {
            NSLog(@"Error 2");
            free(pivot);
            free(workspace);
            return error;
        }
    
        free(pivot);
        free(workspace);
        return error;
    }