【问题标题】:MEX MATLAB/FORTRAN: Integer passing as a very high numberMEX MATLAB/FORTRAN:整数作为一个非常高的数字传递
【发布时间】: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


【解决方案1】:

当你输入时

n=5;
smmat(c,e,eps,n)

在 MATLAB 中,n 是一个双精度数,即使它具有一个整数值。在您的 MEX 文件中,您需要将其读取为双精度。您不能将mxArray 数据解释为任何方便的类型。在从中读取数据之前,请始终使用诸如mxIsDouble 之类的函数来验证数组的类型。

如果您期望一个整数值,您可能仍应将其读取为双精度值,然后转换为整数。

【讨论】:

  • 我实际上是自己得出这个结论的。我选择使用 idint(n) 将参数传递给整数。谢谢你!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多