在 C++ 程序中调用时,Fortran 子例程提供错误结果
Fortran subroutine delivers wrong result when called in C++ program
我必须编写一个返回逆矩阵的 Fortran 例程。如果我在 Fortran 程序中 运行 下面的代码逆矩阵是正确的,但是当我 运行 来自 C++ 代码的子例程时,我的第一个值是错误的值。似乎是数据类型或内存的问题。
我做错了什么?
子程序如下:
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
这是 C++ 代码中的声明:
extern "C"
{
void get_inverse_matrix( double *matrix, int *rows_matrix, int *cols_matrix, double *tmpMatrix, int *rows_tmpMatrix, int *cols_tmpMatrix);}
这是我的 C++ 程序的调用:
get_inverse_matrix(&lhs[0], &sz, &sz, &res[0], &sz, &sz);
我的程序只使用 3x3 矩阵。如果我传递单位矩阵,结果如下:
5.29981e-315 0 0
0 1 0
0 0 1
您将数组声明为类型 real
,类型为 c_double
,但您使用的 lapack 例程需要单精度输入(例如 c_float
)。要解决此问题,您应该将对 sgetrf
和 sgetri
的调用替换为 dgetrf
和 dgetri
.
正如 Vladimir F 在评论中指出的那样,如果您提供接口,这些问题会更容易被发现。
我必须编写一个返回逆矩阵的 Fortran 例程。如果我在 Fortran 程序中 运行 下面的代码逆矩阵是正确的,但是当我 运行 来自 C++ 代码的子例程时,我的第一个值是错误的值。似乎是数据类型或内存的问题。
我做错了什么?
子程序如下:
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
这是 C++ 代码中的声明:
extern "C"
{
void get_inverse_matrix( double *matrix, int *rows_matrix, int *cols_matrix, double *tmpMatrix, int *rows_tmpMatrix, int *cols_tmpMatrix);}
这是我的 C++ 程序的调用:
get_inverse_matrix(&lhs[0], &sz, &sz, &res[0], &sz, &sz);
我的程序只使用 3x3 矩阵。如果我传递单位矩阵,结果如下:
5.29981e-315 0 0
0 1 0
0 0 1
您将数组声明为类型 real
,类型为 c_double
,但您使用的 lapack 例程需要单精度输入(例如 c_float
)。要解决此问题,您应该将对 sgetrf
和 sgetri
的调用替换为 dgetrf
和 dgetri
.
正如 Vladimir F 在评论中指出的那样,如果您提供接口,这些问题会更容易被发现。