From 079a6483618589a8caa9f2b49ee95b0e4ed3692c Mon Sep 17 00:00:00 2001 From: Houtan Bastani <houtan@dynare.org> Date: Fri, 14 Nov 2014 11:16:37 +0100 Subject: [PATCH] dmm: switch to mixed c/fortran for octave compilation --- mex/build/dmm.am | 1 + mex/sources/dmm/design.f90 | 68 +++++++++++-------------------- mex/sources/dmm/designInternal.cc | 46 +++++++++++++++++++++ mex/sources/dmm/mexinterface.f90 | 26 ++++++++---- mex/sources/dmm/mexprint.f90 | 9 ++-- 5 files changed, 91 insertions(+), 59 deletions(-) create mode 100644 mex/sources/dmm/designInternal.cc diff --git a/mex/build/dmm.am b/mex/build/dmm.am index 0838e408f1..82a9cac7c1 100644 --- a/mex/build/dmm.am +++ b/mex/build/dmm.am @@ -114,6 +114,7 @@ nodist_dmm_SOURCES = \ $(DMMDIR)/randlib/spofa.f \ $(DMMMEXSRCDIR)/design.f90 \ $(DMMMEXSRCDIR)/mexprint.f90 \ + $(DMMMEXSRCDIR)/designInternal.cc \ $(DMMMEXSRCDIR)/dmm.cc CLEANFILES = *.mod diff --git a/mex/sources/dmm/design.f90 b/mex/sources/dmm/design.f90 index 8b42659a64..95732d2854 100644 --- a/mex/sources/dmm/design.f90 +++ b/mex/sources/dmm/design.f90 @@ -20,66 +20,44 @@ #if defined(MATLAB_MEX_FILE) #include "fintrf.h" #endif + +#ifndef MWPOINTER +#define MWPOINTER integer(4) +#endif + +#ifndef mwPointer +#define mwPointer MWPOINTER +#endif + SUBROUTINE DESIGN(ny,nz,nx,nu,ns,nt,theta,c,H,G,a,F,R) USE MEXINTERFACE IMPLICIT NONE + ! INPUT - INTEGER ny,nz,nx,nu,ns(6),nt - DOUBLE PRECISION theta(nt), nsd(6) + INTEGER(C_INT), INTENT(IN) :: ny,nz,nx,nu,nt + INTEGER, DIMENSION(6), INTENT(IN) :: ns + DOUBLE PRECISION, DIMENSION(nt), INTENT(IN) :: theta ! OUTPUT - DOUBLE PRECISION c(ny,max(1,nz),ns(1)),H(ny,nx,ns(2)) - DOUBLE PRECISION G(ny,nu,ns(3)),a(nx,ns(4)) - DOUBLE PRECISION F(nx,nx,ns(5)),R(nx,nu,ns(6)) + DOUBLE PRECISION, DIMENSION(ny,max(1,nz),ns(1)), INTENT(OUT) :: c + DOUBLE PRECISION, DIMENSION(ny,nx,ns(2)), INTENT(OUT) :: H + DOUBLE PRECISION, DIMENSION(ny,nu,ns(3)), INTENT(OUT) :: G + DOUBLE PRECISION, DIMENSION(nx,ns(4)), INTENT(OUT) :: a + DOUBLE PRECISION, DIMENSION(nx,nx,ns(5)), INTENT(OUT) :: F + DOUBLE PRECISION, DIMENSION(nx,nu,ns(6)), INTENT(OUT) :: R ! COMMON CHARACTER*200 mfile COMMON /M/ mfile ! LOCAL - mwPointer INPUT(6), OUTPUT(6) - INTEGER STATUS, I - CHARACTER(len=200) :: toprint - integer*4, PARAMETER :: mxREAL = 0 - - ! Matlab mex/mx functions - INTEGER mexCallMATLAB - mwPointer mxGetPr, mxCreateDoubleScalar, mxCreateDoubleMatrix - EXTERNAL mxGetPr, mxCreateDoubleScalar, mxCreateDoubleMatrix, mxCopyPtrToReal8, mexCallMATLAB + INTEGER I + INTEGER(C_INT), DIMENSION(6) :: nsC DO I=1,6 - nsd(I) = ns(I) + nsC(I) = ns(I) END DO + CALL designInternal(ny,nz,nx,nu,nsC,nt,theta,TRIM(mfile)//C_NULL_CHAR,c,H,G,a,F,R) - ! Set input values - INPUT(1) = mxCreateDoubleScalar(ny*1.d0) - INPUT(2) = mxCreateDoubleScalar(nz*1.d0) - INPUT(3) = mxCreateDoubleScalar(nx*1.d0) - INPUT(4) = mxCreateDoubleScalar(nu*1.d0) - INPUT(5) = mxCreateDoubleMatrix(1, 6, mxREAL) - CALL mxCopyReal8ToPtr(nsd, mxGetPr(INPUT(5)), 6) - INPUT(6) = mxCreateDoubleMatrix(1, nt, mxREAL) - CALL mxCopyReal8ToPtr(theta, mxGetPr(INPUT(6)), nt) - - ! Call design .m function - STATUS = mexCallMATLAB(6, OUTPUT, 6, INPUT, mfile) - IF (STATUS .ne. 0) THEN - WRITE(toprint, '(A,A,A,I2,A)') '\nCall to ',mfile,' failed with code ',STATUS,'\n' - CALL mexErrMsgTxt(toprint) - ENDIF - - ! Copy Matlab output into Fortran - CALL mxCopyPtrToReal8(mxGetPr(OUTPUT(1)), c, ny*max(1,nz)*ns(1)) - CALL mxCopyPtrToReal8(mxGetPr(OUTPUT(2)), H, ny*nx*ns(2)) - CALL mxCopyPtrToReal8(mxGetPr(OUTPUT(3)), G, ny*nu*ns(3)) - CALL mxCopyPtrToReal8(mxGetPr(OUTPUT(4)), a, nx*ns(4)) - CALL mxCopyPtrToReal8(mxGetPr(OUTPUT(5)), F, nx*nx*ns(5)) - CALL mxCopyPtrToReal8(mxGetPr(OUTPUT(6)), R, nx*nu*ns(6)) - - ! Free memory - DO I = 1,6 - CALL mxDestroyArray(INPUT(I)) - CALL mxDestroyArray(OUTPUT(I)) - END DO END SUBROUTINE DESIGN #endif diff --git a/mex/sources/dmm/designInternal.cc b/mex/sources/dmm/designInternal.cc new file mode 100644 index 0000000000..e47b8fa0f2 --- /dev/null +++ b/mex/sources/dmm/designInternal.cc @@ -0,0 +1,46 @@ +#include <dynmex.h> +#include <algorithm> +using namespace std; + +extern "C" +void designInternal(int ny, int nz, int nx, int nu, int ns[6], int nt, + double *theta, char *mfile, + double *c, double *H, double *G, double *a, double *F, double *R) +{ + mxArray *lhs[6], *rhs[6]; + nz = max(1, nz); + const mwSize dimsC[] = {ny, nz, ns[0]}; + const mwSize dimsH[] = {ny, nx, ns[1]}; + const mwSize dimsG[] = {ny, nu, ns[2]}; + const mwSize dimsA[] = {nx, ns[3]}; + const mwSize dimsF[] = {nx, nx, ns[4]}; + const mwSize dimsR[] = {nx, nu, ns[5]}; + + lhs[0] = mxCreateNumericArray(3, dimsC, mxDOUBLE_CLASS, mxREAL); + lhs[1] = mxCreateNumericArray(3, dimsH, mxDOUBLE_CLASS, mxREAL); + lhs[2] = mxCreateNumericArray(3, dimsG, mxDOUBLE_CLASS, mxREAL); + lhs[3] = mxCreateNumericArray(2, dimsA, mxDOUBLE_CLASS, mxREAL); + lhs[4] = mxCreateNumericArray(3, dimsF, mxDOUBLE_CLASS, mxREAL); + lhs[5] = mxCreateNumericArray(3, dimsR, mxDOUBLE_CLASS, mxREAL); + + rhs[0] = mxCreateDoubleScalar(ny); + rhs[1] = mxCreateDoubleScalar(nz); + rhs[2] = mxCreateDoubleScalar(nx); + rhs[3] = mxCreateDoubleScalar(nu); + rhs[4] = mxCreateDoubleMatrix(1, 6, mxREAL); + rhs[5] = mxCreateDoubleMatrix(1, nt, mxREAL); + + double *passns = mxGetPr(rhs[4]); + for (int i = 0; i < 6; i++) + passns[i] = (double) ns[i]; + memcpy(mxGetPr(rhs[5]), theta, sizeof(double) * nt); + + mexCallMATLAB(6, lhs, 6, rhs, mfile); + + memcpy(c, mxGetPr(lhs[0]), sizeof(double) * mxGetNumberOfElements(lhs[0])); + memcpy(H, mxGetPr(lhs[1]), sizeof(double) * mxGetNumberOfElements(lhs[1])); + memcpy(G, mxGetPr(lhs[2]), sizeof(double) * mxGetNumberOfElements(lhs[2])); + memcpy(a, mxGetPr(lhs[3]), sizeof(double) * mxGetNumberOfElements(lhs[3])); + memcpy(F, mxGetPr(lhs[4]), sizeof(double) * mxGetNumberOfElements(lhs[4])); + memcpy(R, mxGetPr(lhs[5]), sizeof(double) * mxGetNumberOfElements(lhs[5])); +} diff --git a/mex/sources/dmm/mexinterface.f90 b/mex/sources/dmm/mexinterface.f90 index 365b80dbda..08cb7e92c0 100644 --- a/mex/sources/dmm/mexinterface.f90 +++ b/mex/sources/dmm/mexinterface.f90 @@ -23,17 +23,25 @@ MODULE MEXINTERFACE INTERFACE - INTEGER(4) FUNCTION mexPrintf(toprint) BIND(C, NAME="mexPrintf") - USE ISO_C_BINDING, ONLY : C_CHAR - IMPLICIT NONE - CHARACTER(KIND=C_CHAR), INTENT(IN) :: toprint(*) - END FUNCTION mexPrintf + SUBROUTINE mexPrintf(string) BIND(C, NAME="mexPrintf") + USE ISO_C_BINDING, ONLY: C_CHAR + CHARACTER(KIND=C_CHAR) :: string(*) + END SUBROUTINE mexPrintf - SUBROUTINE mexErrMsgTxt(toprint) BIND(C, NAME="mexErrMsgTxt") - USE ISO_C_BINDING, ONLY : C_CHAR - IMPLICIT NONE - CHARACTER(KIND=C_CHAR), INTENT(IN) :: toprint(*) + SUBROUTINE mexErrMsgTxt(string) BIND(C, NAME="mexErrMsgTxt") + USE ISO_C_BINDING, ONLY: C_CHAR + CHARACTER(KIND=C_CHAR) :: string(*) END SUBROUTINE mexErrMsgTxt + SUBROUTINE designInternal(ny,nz,nx,nu,ns,nt,theta,mfile,c,H,G,a,F,R) BIND(C, NAME="designInternal") + USE, INTRINSIC :: ISO_C_BINDING + IMPLICIT NONE + INTEGER(C_INT), VALUE, INTENT(IN) :: ny, nz, nx, nu, nt + INTEGER(C_INT), DIMENSION(*), INTENT(IN) :: ns + REAL(C_DOUBLE), DIMENSION(*), INTENT(IN) :: theta + CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: mfile + REAL(C_DOUBLE), DIMENSION(*), INTENT(OUT) :: c, H, G, a, F, R + END SUBROUTINE designInternal + END INTERFACE END MODULE MEXINTERFACE diff --git a/mex/sources/dmm/mexprint.f90 b/mex/sources/dmm/mexprint.f90 index 869cd3f558..03e920694f 100644 --- a/mex/sources/dmm/mexprint.f90 +++ b/mex/sources/dmm/mexprint.f90 @@ -17,13 +17,12 @@ ! along with Dynare. If not, see <http://www.gnu.org/licenses/>. ! -INTEGER(4) FUNCTION mexPrint(toprint) +SUBROUTINE mexPrint(string) USE MEXINTERFACE - USE ISO_C_BINDING IMPLICIT NONE - CHARACTER(len=200), INTENT(IN) :: toprint + CHARACTER(len=200), INTENT(IN) :: string - mexPrint = mexPrintf(TRIM(toprint)//NEW_LINE('A')//c_null_char) + CALL mexPrintf(TRIM(string)//NEW_LINE('A')//c_null_char) +END SUBROUTINE mexPrint -END FUNCTION mexPrint -- GitLab