在mex中使用LAPACK进行矩阵求逆的段错误

时间:2015-06-16 13:14:57

标签: matlab fortran mex lapack

我正在尝试在FORTRAN代码中进行矩阵求逆,这在MATLAB中调用。但是当我在调试模式下运行代码时,它可以调用并计算“dgetrf”而没有任何问题但是我在“dgetri”中得到了一个段错误。任何人都可以让我了解这种错误的任何可能原因吗?

这是我使用的测试功能的网关功能:

#include "fintrf.h"

!
SUBROUTINE MEXFUNCTION(NLHS, PLHS, NRHS, PRHS)
use mexf90
implicit none
integer*8, intent(in)   :: PRHS(*)      ! Pointers carrying the input data
integer*8, intent(out)  :: PLHS(*)      ! Pointers carrying the output data
integer*4, intent(in)   :: NLHS,NRHS    ! REMAINS THE SAME FOR 64BIT system
!-----------------------------------------------------------------------
integer*8               :: err, nA, mA
integer*8, pointer      :: matAR, AInvR
character(200)          :: errMsg
integer*4               :: txt, classId
integer*4, external     :: mexprintf

! THE PART BELOW SEPARATED WITH "!$$" IS FOR WINDOWS ONLY
! THIS RESETS THE FLOATING POINT EXCEPTION
! TO ALLOW DIVIDE BY ZERO,
! OVERFLOW AND INVALID 

!$$
!#if defined MSWIND
!        INTEGER(2) CONTROL
!        CALL GETCONTROLFPQQ(CONTROL)
!        CONTROL = CONTROL .OR. FPCW$ZERODIVIDE
!        CONTROL = CONTROL .OR. FPCW$INVALID
!        CONTROL = CONTROL .OR. FPCW$OVERFLOW
!        CALL SETCONTROLFPQQ(CONTROL)
!#endif
!$$

! ERROR CHECKING FOR INPUT
IF (NRHS .NE. 1) THEN
    CALL MEXERRMSGTXT('MultMexError: 1 INPUT ARGUMENT IS REQUIRED')
ENDIF

IF (NLHS .NE. 1) THEN
    CALL MEXERRMSGTXT('MultMexError: 1 OUTPUT ARGUMENT IS REQUIRED')
ENDIF

! ASSIGN POINTERS TO THE VARIOUS PARAMETERS
! Input matrix
matAR   =>MXGETPR(PRHS(1))
mA      = MXGETM(PRHS(1))
nA      = MXGETN(PRHS(1))
! Do something meaningful...
classId = mxClassIDFromClassName('double')
plhs(1) = mxCreateDoubleMatrix(mA,nA,0)
AInvR   =>mxGetPr(plhs(1))
call invTest(matAR,mA,nA,AInvR)
! Send the result to the return argument
!(For an alternative way of sending the results to the return arguments - see referenceF90.f90)
END SUBROUTINE MEXFUNCTION

我进行矩阵求逆的测试函数如下:

subroutine invTest(matAR,mA,nA,AInvR)
use mexf90
implicit none

interface
    function dinv(A) result(Ainv)
        use mexf90
        real*8, dimension(:,:), intent(in)      :: A
        real*8, dimension(size(A,1),size(A,2))  :: Ainv
        end function dinv
end interface

integer*4, intent(in)   :: mA, nA
real*8, intent(in)      :: matAR(mA,nA)
real*8, intent(out)     :: AInvR(mA,nA)

AInvR       = dinv(matAR)
end subroutine invTest

我在互联网上找到的用于矩阵求逆的子程序是:

function dinv(A) result(Ainv)
    use mexf90
    real*8, dimension(:,:), intent(in)      :: A
    real*8, dimension(size(A,1),size(A,2))  :: Ainv

    real*8, dimension(size(A,1)) :: work  ! work array for LAPACK
    integer, dimension(size(A,1)) :: ipiv   ! pivot indices
    integer :: n, info, ddd

    ! External procedures defined in LAPACK
    external DGETRF
    external DGETRI

    ! Store A in Ainv to prevent it from being overwritten by LAPACK
    Ainv = A
    n = size(A,1)

    ! DGETRF computes an LU factorization of a general M-by-N matrix A
    ! using partial pivoting with row interchanges.
    call DGETRF(n, n, Ainv, n, ipiv, info)
    if (info /= 0) then
     CALL MEXERRMSGTXT('Matrix is numerically singular!')
    end if

    ! DGETRI computes the inverse of a matrix using the LU factorization
    ! computed by DGETRF.
    call DGETRI(n, Ainv, n, ipiv, work, n, info)

    if (info /= 0) then
     CALL MEXERRMSGTXT('Matrix inversion failed!')
    end if
end function dinv

1 个答案:

答案 0 :(得分:1)

在调用invTest时,您的nA和mA类型不匹配。它们应该是整数* 4,但是你在MEXFUNCTION中将它们声明为整数* 8。

如果调用mxCreateDoubleMatrix需要整数* 8,那么只需要整数* 4副本或者可以尝试

调用invTest(matAR,int(mA),int(nA),AInvR)