AnsweredAssumed Answered

FORTRAN ROUTINES

Question asked by VRFuser on Sep 25, 1997

Hello everybody,

Time ago I sent a question about how to use FORTRAN funtions/routines from VEE.

Greg helped me with the same message:

-----------------------------------------------------------------------------

[VEE] Building FORTRAN Functions For VEE

* It is possible to build FORTRAN functions for use with VEE, but you have to
configure them to resemble C functions as far as their interface to VEE is
concerned.

The following example is a FORTRAN function -- written into a file named
"add5.f" -- that accepts a floating-point array and an integer.  The function
adds the value 5 to each element in the array; the integer represents the
number of elements.

   integer*4 function add5(wave, size)

   real*8 wave
   dimension wave(1:*)
   integer*4 size

   integer*4 i
  
   do 10 i = 1, size
      wave(i) = wave(i) + 5
10 continue

   add5 = size

   return
   end

The function prototype is very similar to the equivalent C function.  We
declare the return type, followed by the function name and its parameters.
The parameter types are declared after the function declaration and before
the function body.

Notice the array declaration:

   real*8 wave
   dimension wave(1:*)

We declare a variable of type "real*8", which is a 64-bit floating-point
real, or the equivalent of a double.  We then dimension the variable to be an
"assumed size" array, using the "(1:8)" syntax.  In essence, this statement
says:  "Give me an array of reals, but don't tell it how many elements it has
in it."  FORTRAN, unless you tell it otherwise, assumes all array bounds
start at 1.  By also passing in the size of the array, we can use the
variable named "size" to check the bounds on our array subscript.

FORTRAN assumes all parameters passed to a function are passed by reference.
This means that the address of the variable, as opposed to the value that the
variable holds, is given to the called function.  This makes our coding
task easier, because we can declare variables without the need for pointer
dereferencing.

Here is the make file for the routine (named, say, "add5.mak"):

   add5.sl:   add5.o
              ld -b -o add5.sl add5.o
   add5.o:    add5.f
              f77 -c +z add5.f

You can then compile the function using the command:  "make +f add5.mak" --
and then you get a library file named "add5.sl".

To actually run the function, you need to create the VEE definition file
(named, say, "add5.vh") to tell VEE parameters the function uses:

   long add5 (double *wave, long *size)

A VEE program to run the library is as follows:

                   +---------------------------------------+
                   |             Import Library            |
                   +---------------------------------------+
                   | Library Type    [ Compiled Function ] |
                   | Library Name    [        fl         ] |
                   | File Name       [      add5.sl      ] |
                   | Definition File [      add5.vh      ] |
                   +-------------------+-------------------+
  +------------+                       |
  |    Real    |      +----------------+-----------------+   +-----------+
  +------------+      |           Call Function          |   |   Alpha   |
  | 0000: 1    |      +------+---------------------------+   +-----------+
  | 0000: 10   +----->| wave | Function Name | Ret Value |   | 0: 6      |
  | 0000: 100  |      |      |               |   wave    +-->| 1: 15     |
  | 0000: 1000 |  +-->| size | [  fl.add5  ] |   size    |   | 2: 105    |
  +------------+  |   +------+---------+-----+-----------+   | 3: 1O05   |
                  |                    |                     +-----------+
  +------------+  |        +-----------+-----------+
  |  Integer   |  |        |    Delete Library     |
  +------------+  |        +-----------------------+
  | 4          +--+        | Library Name [  fl  ] |
  +------------+           +-----------------------+

The library is loaded under the name "fl", which is arbitrary ... you should
set up the Import Library and then execute it before adding the other
objects, so when you add the Call Function, you can do a select function from
its object menu and install the function.

[<>]

--------------------------------------------------------------------------------

Well, first of all, the FORTRAN program had a little mistake:

   integer*4 function add5(wave, size)

   real*8 wave
   dimension wave(1:*)
   integer*4 size

   integer*4 i
  
   do 10 i = 1, size
      wave(i) = wave(i) + 5
10 continue

   add5 = size
C (This is the error that need to be replaced by line   add5 = wave)

   return
   end


In any case this is valid for FUNTIONS but not for ROUTINES, that is
procedures: in which you can perform several inputs in order to get several
outputs, even using the same variables:

Lets use an example of a dummy FORTRAN routine:

    subroutine test_vee (a,b)
    real*8 a(0:3), b

    b=b+1

    do i=1,4
      a(i)=a(i)*b+i
    enddo

    return
    end

This is a silly program. The only purpose is to show the calling mechanism.
First of all, we can see that in FORTRAN we can use an aray starting from 0
(the default is starting from 1) if we want. This routine is fixed for an
array of dimension 4 called 'a'. At the same time we can use the 'b'
variable as input/output.

We have to take into account that FORTRAN works normally with REAL*4 instead
of REAL*8 (as VEE) and we could have some problems if we try to use directly
old routines. Variables of all routines should be redeclared and converted
to intermediate variables of REAL*4 or use REAL*8 but maybe in this case it
is necessary to modify the old FORTRAN programs.

The way to compile and bild the shared library is the same than it has been
explained:

f77 -c +z test_vee.f

ld -b -o fortran_lib.sl test_vee.o file_1.o file_2.o....file_n.o

where  file_1, file_2... file_n are other routines already compiled to be
included in the shared library. (Each time we want to update the shared
library we have to do it with all the funtions/procedures).

The file fortran_lib.h should be the following:

void test_vee (double *a, double *b)
type file_1 (type *var1,... type *varm)
type file_2 (type *var1,... type *varm)
.......


Then VEE needs first to import the shared library according to
fortran_lib.sl and fortran_lib.h.

The only possibple problem is that in VEE 'a' and 'b' apperar always as
input values (output also) and they has to be excited with a dummy input.
The output can be choosen among the valid parameters (in this case both 'a'
and 'b'). This is becaus FORTRAN does not specify which parameters are
input, output or input/output.

I hope this help to FORTRAN people.
______________________________________________________

Juan Carlos Martin
E-mail     : jcmar@mdr.indra-espacio.es
Phone      : 34-1-3963995
Fax     : 34-1-3963912
Earth Stations Department
INDRA ESPACIO / MADRID /SPAIN


Outcomes