Hello all,
I've been thinking about this for quite some time now, and have finally decided
to pursue the idea of a modern FORTRAN Inline module. Given that soon I'll be
having some time available through to the end of this year, I'm confident that
I can make this work.
The name of the proposed module is Inline::F2003
The module will only work for compilers that are compliant with the FORTRAN
2003 standard and above. The reason for this is that FORTRAN 2003 introduced a
new feature named "C Interoperability". This feature, coupled with Inline::C,
are the core mechanisms that will make Inline::F2003 work.
For those who have an interest in programming using modern FORTRAN, below is an
example Perl program that illustrates how Inline::F2003 would be used. The
program performs multiplication of two matrices. Notice the two sections
__F2003__ and __C__
The __F2003__ section contains the FORTRAN subroutine that performs the actual
matrix multiplication. The subroutine utilises FORTRAN 2003's C
interoperability features to make it callable from C.
The __C__ section is the crucial part of an Inline::F2003 program, and must
always be present. It prepares any data from Perl that needs to be passed into
FORTRAN, and finally calls the FORTRAN subroutine with that data.
I am always interested to hear people's views. So, if you have any
comments/suggestions/questions, please post them or send me an e-mail.
Many thanks for reading this post and reviewing the example program below.
Cheers,
Ron.
#!/usr/local/ActivePerl/bin/perl
#
use strict;
use warnings;
use Inline F2003 => Config => (
SOURCE => "ModMatrixOps.f03",
LIBRARY => "libMatrixOps.so",
LIBTYPE => ".so",
DIRECTORY => "BLD_Linux.AMD64_nagfor",
FOR => "nagfor",
FORFLG => "-v -g90 -gline -otype=obj -f2003 -fpp"
);
use Inline C => Config => (
MYEXTLIB => "/u/BLD_Linux.AMD64_nagfor/libMatrixOps.so",
DIRECTORY => "BLD_Linux.AMD64_perl",
CCFLAGSEX => "-std=c99"
);
use Inline F2003 => "DATA";
use Inline C => "DATA";
MainFunction: {
my ($M1_rows, $M1_cols) = (3, 3);
my ($M2_rows, $M2_cols) = (3, 3);
my @M1_data = ( 2.4, 0.0, 0.0,
2.4, 3.8, 0.0,
0.0, 3.8, 0.0 );
my @M2_data = ( 2.4, 2.4, 0.0,
0.0, 3.8, 3.8,
1.25, 1.25, 1.25 );
MatrixMultiply( $M1_rows, $M1_cols, @M1_data,
$M2_rows, $M2_cols, @M2_data );
}
__DATA__
__F2003__
SUBROUTINE FOR_MatrixMultiply (M1_rows, M1_cols, C_M1_data, &
M2_rows, M2_cols, C_M2_data ) &
BIND(C, NAME="FOR_MatrixMultiply")
USE, INTRINSIC :: ISO_C_BINDING, &
ONLY : C_INT, C_DOUBLE, C_PTR, C_F_POINTER
USE ModMatrixOps
IMPLICIT NONE
INTEGER (KIND=C_INT), VALUE, INTENT(IN) :: M1_rows, M1_cols
INTEGER (KIND=C_INT), VALUE, INTENT(IN) :: M2_rows, M2_cols
REAL (KIND=C_DOUBLE), POINTER :: M1_data(:) => NULL()
REAL (KIND=C_DOUBLE), POINTER :: M2_data(:) => NULL()
TYPE (C_PTR), INTENT(IN) :: C_M1_data, C_M2_data
CALL C_F_POINTER (C_M1_data, M1_data, [M1_rows * M1_cols])
CALL C_F_POINTER (C_M2_data, M2_data, [M2_rows * M2_cols])
CALL MOD_SetMatrix (M1_rows, M1_cols, M1_data)
CALL MOD_SetMatrix (M2_rows, M2_cols, M2_data)
CALL MOD_MatrixMultiply()
IF (MOD_MatrixOp_OK()) THEN
CALL MOD_MatrixDisplay()
ELSE
PRINT "(A)", "FOR_MatrixMultiply: Error Condition Occurred."
END IF
CALL MOD_MatrixDestroy()
END SUBROUTINE FOR_MatrixMultiply
__C__
#define MAX_MATRIX_SZ 50
extern void FOR_MatrixMultiply(int, int, double *, int, int, double *);
void MatrixMultiply(SV* matrix_data, ...) {
double M1_data[MAX_MATRIX_SZ], M2_data[MAX_MATRIX_SZ];
int M1_rows, M1_cols, M2_rows, M2_cols;
int ix, arg_ix = 0;
Inline_Stack_Vars;
M1_rows = SvIV(Inline_Stack_Item(arg_ix++));
M1_cols = SvIV(Inline_Stack_Item(arg_ix++));
/*
* Fill values for Matrix 1
*/
for (ix=0; ix < M1_rows*M1_cols; ix++) {
M1_data[ix] = SvNV(Inline_Stack_Item(arg_ix++));
}
M2_rows = SvIV(Inline_Stack_Item(arg_ix++));
M2_cols = SvIV(Inline_Stack_Item(arg_ix++));
/*
* Fill values for Matrix 2
*/
for (ix=0; ix < M2_rows*M2_cols; ix++) {
M2_data[ix] = SvNV(Inline_Stack_Item(arg_ix++));
}
FOR_MatrixMultiply(M1_rows, M1_cols, M1_data,
M2_rows, M2_cols, M2_data );
Inline_Stack_Void;
}
________________________________________
Ron Grunwald
[email protected]
http://www.dvlcorner.org