AFF --- A container for numbers (array) by Friederich and Forbriger.
|
Contents of this page:
After switching to C++ many numerical routines coded in Fortran 77 will stay in use. Recoding them in C++ should not generally be considered. It involves a lot of extra work and potentially introduces new bugs and errors to code that was well tested before. Thus some of our C++ functions have to call underlying Fortran 77 code and must exchange data with this code, in particular. Exchanging data also involves passing arrays to and from Fortran.
The example tests/f77test.cc and its associates demonstrates how AFF data may be passed to Fortran and how Fortran arrays may be integrated into AFF.
Aspects to consider:
An example for passing AFF data to a Fortran function is given in f77interface::fill. The interface function is defined in tests/f77interface.cc and presented in tests/f77proto.h. It is declared
The Array is converted into an aff::FortranArray by
within the function. From this the function retrieves the appropriate Fortran layout of the array.
In case the Fortran code is modfified we only have to keep track within the interface module (i.e. tests/f77interface.cc and tests/f77proto.h).
Aspects that had to be considered:
extern
"C"
linkage.f2c -C++ -P -\!c tests/f77procs.fto file tests/f77procs.P
f2c.h
in tests/f77interface.cc.int
values. They are converted to values of type integer
(defined in f2c.h) with statements like integer*
by integer*
, which is defined as long
int*
in f2c.h. From the FortranArray object we receive a pointer of type int*
. The only way I see to convert it is via In many Fortran code modules essential array data is passed through global common blocks between subroutines. It is possible to make this data visible in form of an aff::Array object. However, this is slightly more complicated than passing a C++ array to an underlying Fortran subroutine.
An example for this technique is given by the following functions:
The interface functions are presented in tests/f77proto.h, are defined in tests/f77interface.cc and the underlying Fortran subroutines are defined in tests/f77procs.f. The common-block itself is defined in tests/f77common.inc. f77interface::viewcommon is the module that actually allows direct read/write acces to the common block. The other two provide means to access the same common block from tests/f77test.cc through calls to Fortran subroutines.
Addtionally to the considerations for Passing arrays through function calls we have to discuss the following:
comdim
, which can be used to read the dimensions of the common-block array.p
and a size in memory. Using this constructor ensures, that SharedHeap will never try to deallocate the memory block.f2c -C++ -f -u -ec tests/f77procs.f sed -e 's/^struct/extern struct/' tests/f77common_com.c > tests/f77common_com.Pto create a common block definition in tests/f77common_com.P. This definition is read via
extern
"C"
linkage in the C++ code.na
and nb
), e.g. by calling subroutine fillarray, is not reflected by the AFF array. This will first be noticed by the next call to f77interface::viewcommon. It is the responsibility of the programmer to avoid inconsistencies due to different access shapes in Fortran and C++.c this is <f77common.inc> c ---------------------------------------------------------------------------- c c Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt) c c common block for Fortran test c c ---- c This program is free software; you can redistribute it and/or modify c it under the terms of the GNU General Public License as published by c the Free Software Foundation; either version 2 of the License, or c (at your option) any later version. c c This program is distributed in the hope that it will be useful, c but WITHOUT ANY WARRANTY; without even the implied warranty of c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the c GNU General Public License for more details. c c You should have received a copy of the GNU General Public License c along with this program; if not, write to the Free Software c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA c ---- c c REVISIONS and CHANGES c 22/12/2002 V1.0 Thomas Forbriger c c ============================================================================ c c dimensions for arrays integer amax, bmax parameter(amax=10,bmax=20) c c used elements in each dimension integer na, nb c c complex array double complex array(amax,bmax) c c common block common /f77common/ array,na,nb c c ----- END OF f77common.inc -----
c this is <f77procs.f> c ---------------------------------------------------------------------------- c c Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt) c c Fortran 77 subroutines c c ---- c This program is free software; you can redistribute it and/or modify c it under the terms of the GNU General Public License as published by c the Free Software Foundation; either version 2 of the License, or c (at your option) any later version. c c This program is distributed in the hope that it will be useful, c but WITHOUT ANY WARRANTY; without even the implied warranty of c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the c GNU General Public License for more details. c c You should have received a copy of the GNU General Public License c along with this program; if not, write to the Free Software c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA c ---- c c REVISIONS and CHANGES c 22/12/2002 V1.0 Thomas Forbriger c c ============================================================================ c subroutine fillarray(vec1, vec2, n1, n2) c c writes to common block c include 'f77common.inc' c integer n1,n2 real vec1(n1),vec2(n2) c double complex ime parameter(ime=(0.d0,1.d0)) c integer i,j c if (n1.gt.amax) stop 'ERROR: first dimension is too large' if (n2.gt.bmax) stop 'ERROR: second dimension is too large' na=n1 nb=n2 do i=1,n1 do j=1,n2 array(i,j)=vec1(i)+ime*vec2(j) enddo enddo return end c c---------------------------------------------------------------------- c subroutine sums(vec,nmax,n) c c reads from common block c include 'f77common.inc' c complex vec(nmax) integer n,nmax c integer i,j c if (nb.gt.nmax) stop 'ERROR: vector too small' n=nb do i=1,nb vec(i)=(0.,0.) do j=1,na vec(i)=vec(i)+array(j,i) enddo enddo return end c c---------------------------------------------------------------------- c double complex function total(i) c c returns a value derived from common block c include 'f77common.inc' c integer i c double complex result integer j c if ((i.lt.1).or.(i.gt.na)) stop 'ERROR: illegal index' result=(0.d0,0.d0) do j=1,nb result=result+array(i,j) enddo total=result return end c c---------------------------------------------------------------------- c subroutine fill(a, ld1, n1, ld2, n2, ld3, n3) c c fill a three-domensional array that was passed to the subroutine c integer ld1,n1,ld2,n2,ld3,n3 integer a(ld1,ld2,ld3) c integer i,j,k c do i=1,n1 do j=1,n2 do k=1,n3 a(i,j,k)=i+10*j+100*k enddo enddo enddo c return end c c---------------------------------------------------------------------- c subroutine comdim(maxa, maxb) c c we have no access to the defined dimensions of the common block c this subroutines passes the values to the rest of the world c integer maxa,maxb c include 'f77common.inc' c maxa=amax maxb=bmax c return end c c ----- END OF f77procs.f -----
#include "f2c.h" #ifdef __cplusplus extern "C" { #endif extern struct { doublecomplex array[200] /* was [10][20] */; integer na, nb; } f77common_; #ifdef __cplusplus } #endif
extern int fillarray_(real *vec1, real *vec2, integer *n1, integer *n2); extern int sums_(complex *vec, integer *nmax, integer *n); extern Z_f total_(doublecomplex * ret_val, integer *i__); extern int fill_(integer *a, integer *ld1, integer *n1, integer *ld2, integer *n2, integer *ld3, integer *n3); extern int comdim_(integer *maxa, integer *maxb); /* comlen f77common_ 3208 */