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
ron...@yahoo.com.au
http://www.dvlcorner.org



Reply via email to