fx88
fx88

Reputation: 43

Fortran subroutine delivers wrong result when called in C++ program

I have to write a Fortran routine returning the inverse matrix. If I run the code below in a Fortran program the inverse matrix is correct, but when I run the subroutine from C++ code my first value is a wrong value. It seems like a problem with the data types or the memory.

What am I doing wrong?

Here is the subroutine:

    subroutine get_inverse_matrix( matrix, rows_matrix, cols_matrix, tmpMatrix, rows_tmpMatrix, cols_tmpMatrix) bind(c)
        use iso_c_binding
        integer :: m, n, lda, lwork, info, size_m
        integer(c_int) :: rows_matrix, cols_matrix, rows_tmpMatrix, cols_tmpMatrix
        real(c_double) :: matrix(rows_matrix, cols_matrix), tmpMatrix(rows_tmpMatrix, cols_tmpMatrix)
        integer, dimension( rows_matrix ) :: ipiv
        real, dimension( rows_matrix )  :: work
        size_m = rows_matrix
        m = size_m
        n = size_m
        lda = size_m
        lwork = size_m
        write(*,*) "Matrix: ", matrix
        !tmpMatrix = matrix
        write(*,*) "Temp matrix: ", tmpMatrix
        ! LU-Faktorisierung (Dreieckszerlegung) der Matrix
        call sgetrf( m, n, tmpMatrix, lda, ipiv, info )
        write(*,*) info
        ! Inverse der LU-faktorisierten Matrix
        call sgetri( n, tmpMatrix, lda, ipiv, work, lwork, info )
        write(*,*) info
        select case(info)
            case(0)
            write(*,*) "SUCCESS"
            case(:-1)
            write(*,*) "ILLEGAL VALUE"
            case(1:)
            write(*,*) "SINGULAR MATRIX"
        end select
    end subroutine get_inverse_matrix

Here is the declaration in the C++ code:

extern "C"
{
void get_inverse_matrix( double *matrix, int *rows_matrix, int *cols_matrix, double *tmpMatrix, int *rows_tmpMatrix, int *cols_tmpMatrix);}

Here is the call from my C++ program:

get_inverse_matrix(&lhs[0], &sz, &sz, &res[0], &sz, &sz);

My program only uses a 3x3 matrix. If I pass the identity matrix the result looks like:

5.29981e-315 0 0 
0 1 0 
0 0 1 

Upvotes: 0

Views: 246

Answers (1)

d_1999
d_1999

Reputation: 854

You are declaring your arrays as type real with kind c_double but you are using lapack routines that are expecting single precision inputs (e.g. c_float). To fix this you should replace the calls to sgetrf and sgetri with dgetrf and dgetri.

As noted by Vladimir F in the comments these issues can be more easily caught if you provide interfaces.

Upvotes: 4

Related Questions