【发布时间】:2018-08-04 15:36:13
【问题描述】:
我正在为 Matlab/Fortran 接口编写一个简单的 MEX 文件。代码正在编译,但是整数 n(例如 5)作为一个巨大的数字(O(14))传递。当 n 为整数 *4 时,它作为 0 传递。
用户运行编译后的mex文件为[z,w] = smmat(c,e,eps,n),其中c是一个大小为20xnl的复矩阵,e 是大小为 8xnl 的实矩阵,eps 是大小为 5xnl 的实矩阵,n 是整数标量。 z 是一个输出复数矩阵,w 应该是一个输出实数矩阵。
有人可以提供他们的专业知识吗?谢谢 :) 这是代码:
#include "fintrf.h"
C Gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
C Declarations
implicit none
C mexFunction arguments: plhs - left (output) pointers of unknown (*) size
C prhs - right (input) pointers of unknown (*) size
C nlhs - number (integer) of left (output) arguments
C nrhs - number (integer) of right (input) arguments
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
C Function declarations:
mwPointer mxGetPr, mxGetPi
mwPointer mxCreateDoubleMatrix
mwPointer mxGetM, mxGetN
integer mxIsComplex, mexEvalString
C Array information:
mwPointer mc, nc, me, ne, mep, nep, mn, nn, nz, nw, elc, ele, elep
integer*8 n
real*8 e(80), eps(50), w(5000000)
complex*16 c(200), z(5000000)
C-----------------------------------------------------------------------
C Check for proper number of arguments.
if (nrhs .ne. 4) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:nInput',
+ 'Four inputs required.')
elseif (nlhs .gt. 2) then
call mexErrMsgIdAndTxt ('MATLAB:convec:nOutput',
+ 'Too many output arguments.')
endif
C Validate inputs
mc = mxGetM(prhs(1))
nc = mxGetN(prhs(1))
me = mxGetM(prhs(2))
ne = mxGetN(prhs(2))
mep = mxGetM(prhs(3))
nep = mxGetN(prhs(3))
mn = mxGetM(prhs(4))
nn = mxGetN(prhs(4))
C Size of inputs
elc = mc*nc
ele = me*ne
elep = mep*nep
C Check number of lines of cij, eij, epsij
if(mc .ne. 20 .or. me .ne. 8 .or. mep .ne. 5) then
call mexErrMsgIdAndTxt ('Matlab:smmat:NotEnoConst',
+ 'Inputs must have correct number of constants.')
C Check that inputs are scalar.
elseif(mn .ne. 1 .or. nn .ne. 1) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:NonScalar',
+ 'Inputs must be a scalar.')
C Check size of the inputs.
elseif(elc .gt. 200 .or. ele .gt. 80 .or. elep .gt. 50) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:nLayer',
+ 'Maximum number of layers is 10.')
C Check if cij is complex.
elseif(mxIsComplex(prhs(1)) .ne. 1) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:NonComplex',
+ 'Cij must be complex.')
C Check if number of layers is correct for every constant.
elseif(nc .ne. ne .or. nc .ne. nep .or. ne .ne. nep) then
call mexErrMsgIdAndTxt ('MATLAB:smmat:nLayer',
+ 'Number of layers of constants must be equal.')
endif
C Create the output array.
nz = mc*me
nw = mc*mep
plhs(1) = mxCreateDoubleMatrix(mc, me, 1)
plhs(2) = mxCreateDoubleMatrix(mc, mep, 0)
C Load the data into Fortran arrays(native COMPLEX data).
call mxCopyPtrToComplex16(mxGetPr(prhs(1)),
+ mxGetPi(prhs(1)),c,elc)
call mxCopyPtrToReal8(mxGetPr(prhs(2)),e,ele)
call mxCopyPtrToReal8(mxGetPr(prhs(3)),eps,elep)
call mxCopyPtrToInteger4(mxGetPr(prhs(4)),n,1)
C Call the computational subroutine.
call smmat(c,e,eps,n,z,w,mc,me,mep,nc)
C Load the output into a MATLAB array.
call mxCopyComplex16ToPtr(z,mxGetPr(plhs(1)),
+ mxGetPi(plhs(1)),nz)
call mxCopyReal8ToPtr(w,mxGetPr(plhs(2)),nw)
return
end
C-----------------------------------------------------------------------
C Computational subroutine
subroutine smmat(c,e,eps,n,z,w,mc,me,mep)
implicit none
integer*8 n
real*8 e(8,*), eps(5,*), w(mc,mep)
complex*16 c(20,*), z(mc,me)
mwSize mc, nc, me, mep, i, j
C Determine size of stiff and mass matrices
C Initialize the output arrays
w = 0.0_8
do 20 i=1,mc
do 10 j=1,me
z(i,j) = (0.0,0.0)
10 continue
20 continue
do 40 i=1,mc
do 30 j=1,me
z(i,j) = z(i,j) + e(j,1) * c(i,1)
30 continue
40 continue
do 60 i=1,mc
do 50 j=1,mep
w(i,j) = w(i,j) + real(n)
50 continue
60 continue
return
end
C-----------------------------------------------------------------------
【问题讨论】:
-
从概念上讲,至少使用 Fortran 标准数据类型会更好。尽管如此,如果您将 INT64 传递给为默认 int 编译的函数,在低端平台上,适合 32 位的数字将全为零。如果您希望使用此组合,则需要向下转换您的整数,例如通过声明 INT32 变量并在调用之前进行赋值。
-
嗨!首先,感谢您的时间。其次,我已经尝试过 integer*4 类型,实际上解决方案全为零。使用整数 * 8,解决方案是 10 ^ 14 的常数倍。考虑到 real*8 并在需要时转换为整数,我使用了一种解决方法。
标签: matlab fortran integer mex