Я играю с Matlab, Mex, Intel Fortran в Visual Studio и т. Д. Я скопировал подпрограмму из здесь , умножив матрицу на скаляр:
C Computational subroutine
subroutine xtimesy(x, y, z, m, n)
real*8 x, y(3,3), z(3,3)
integer m, n
do 20 i=1,m
do 10 j=1,n
z(i,j) = x*y(i,j)
10 continue
20 continue
return
end
исходный код переноса, который должен был генерировать файл mexw64 зависал на elseif (mxIsNumeric(prhs(2)) .ne. 1) then
, поэтому я адаптировал его следующим образом:
#include <fintrf.h>
C The gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
mwPointer mxGetM, mxGetN, mxIsNumeric
mwPointer mxCreateDoubleMatrix
mwPointer plhs(*), prhs(*)
integer x_pr, y_pr, z_pr
integer nlhs, nrhs
integer m, n, size
real*8 x, y(3,3), z(3,3)
C Check for proper number of arguments.
if (nrhs .ne. 2) then
call mexErrMsgTxt('Two inputs required.')
elseif (nlhs .ne. 1) then
call mexErrMsgTxt('One output required.')
endif
C Check to see both inputs are numeric.
if (mxIsNumeric(prhs(1)) .ne. 1) then
call mexErrMsgTxt('Input #1 is not a numeric.')
elseif (mxIsNumeric(prhs(2)) .ne. 1) then
call mexErrMsgTxt('Input #2 is not a numeric array.')
endif
C Check that input #1 is a scalar.
m = mxGetM(prhs(1))
n = mxGetN(prhs(1))
if(n .ne. 1 .or. m .ne. 1) then
call mexErrMsgTxt('Input #1 is not a scalar.')
endif
C Get the size of the input matrix.
m = mxGetM(prhs(2))
n = mxGetN(prhs(2))
size = m*n
C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(m, n, 0)
x_pr = mxGetPr(prhs(1))
y_pr = mxGetPr(prhs(2))
z_pr = mxGetPr(plhs(1))
C Load the data into Fortran arrays.
call mxCopyPtrToReal8(x_pr, x, 1)
call mxCopyPtrToReal8(y_pr, y, size)
C Call the computational subroutine.
call xtimesy(x, y, z, m, n)
C Load the output into a MATLAB array.
call mxCopyReal8ToPtr(z, z_pr, size)
return
end
При отладке в Visual Studio первый и второйвходные данные для моей функции имеют правильные размеры (соответственно 1x1 и 3x3), но prhs
странно.Точно, для этого ввода в Matlab:
![enter image description here](https://i.stack.imgur.com/3m6C9.png)
при отладке в Visual Studio я вижу:
![enter image description here](https://i.stack.imgur.com/KcEPT.png)
и я нахожу странным, что phrs
, который является массивом из двух указателей на массивы, содержит / points, имеет "тип" (1:1)
.Я пробежал строки до той, где установлена точка останова, строки с prhs(2)
, и на них не было ошибок.Также значения prhs(1)
и prhs(2)
странные.Я подозреваю, что где-то где-то я заполнил переменные значениями, которые можно привести к целым числам, которые слишком велики для типов задействованных переменных, но я не могу найти где.
Я аварийно завершаю работу, если выполняю утверждение точки остановастрока со следующим сообщением в matlab:
Error using doubleMatrixMultiplication
Requested 14757395255531667459x14757395255531667459 (17179869184.0GB) array exceeds maximum array size preference. Creation of
arrays greater than this limit may take a long time and cause MATLAB to become unresponsive. See array size limit or preference
panel for more information.
Подробности: у меня последнее обновление visual studio 2017, matlab 2018b, и я попробовал с intel visual fortran из параллельной студии xe 2018 обновление 5, а также обновление 2019 3.
Редактировать.(8 мая 2019 г.)
Наконец, правильный код для мекс-части:
#include <fintrf.h>
C The gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
mwPointer mxGetM, mxGetN, mxIsNumeric
mwPointer mxCreateDoubleMatrix
mwPointer plhs(*), prhs(*)
mwPointer x_pr, y_pr, z_pr
integer nlhs, nrhs
mwSize m, n, size
real*8 x, y(3,3), z(3,3)
C Check for proper number of arguments.
if (nrhs .ne. 2) then
call mexErrMsgTxt('Two inputs required.')
elseif (nlhs .ne. 1) then
call mexErrMsgTxt('One output required.')
endif
C Check to see both inputs are numeric.
if (mxIsNumeric(prhs(1)) .ne. 1) then
call mexErrMsgTxt('Input #1 is not a numeric.')
elseif (mxIsNumeric(prhs(2)) .ne. 1) then
call mexErrMsgTxt('Input #2 is not a numeric array.')
endif
C Check that input #1 is a scalar.
m = mxGetM(prhs(1))
n = mxGetN(prhs(1))
if(n .ne. 1 .or. m .ne. 1) then
call mexErrMsgTxt('Input #1 is not a scalar.')
endif
C Get the size of the input matrix.
m = mxGetM(prhs(2))
n = mxGetN(prhs(2))
size = m*n
C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(m, n, 0)
x_pr = mxGetPr(prhs(1))
y_pr = mxGetPr(prhs(2))
z_pr = mxGetPr(plhs(1))
C Load the data into Fortran arrays.
call mxCopyPtrToReal8(x_pr, x, 1)
call mxCopyPtrToReal8(y_pr, y, size)
C Call the computational subroutine.
call xtimesy(x, y, z, m, n)
C Load the output into a MATLAB array.
call mxCopyReal8ToPtr(z, z_pr, size)
return
end