/*! \file f77test.cc * \brief test interfacing Fortran code (implementation) * * ---------------------------------------------------------------------------- * * $Id: f77test.cc,v 1.8 2003-01-03 16:56:49 forbrig Exp $ * \author Thomas Forbriger * \date 22/12/2002 * * test interfacing Fortran code (implementation) * * \sa \ref page_fortran * * Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt) * * REVISIONS and CHANGES * - 22/12/2002 V1.0 Thomas Forbriger * - 29/12/2002 V1.1 (thof) * - new uses new function aff::subarray * - new uses new function aff::slice * - 03/01/2003 V1.2 (thof) * - test aff::util::SizeCheckedCast * * ============================================================================ */ /*! \example tests/f77test.cc * * Passing arrays to Fortran 77 code and retrieving array structures * from Fortran 77 common blocks. * * This test program gives an example of the usage of the following classes, * functions, and preprocessor macros: * - aff::FortranArray * - aff::FortranShape * - aff::Array * - aff::util::SizeCheckedCast * - #DUMP * - #CODE * * \sa tests/f77test.cc * \sa \ref page_fortran */ #define AFF_F77TEST_CC_VERSION \ "AFF_F77TEST_CC V1.2" #define AFF_F77TEST_CC_CVSID \ "$Id: f77test.cc,v 1.8 2003-01-03 16:56:49 forbrig Exp $" #include #include #include #include #include #include #include #include "f77proto.h" using std::cout; using std::endl; using namespace aff; /*----------------------------------------------------------------------*/ //! print headline void section(const char* s, const char l='-') { cout << endl << s << endl; const char* p=s; while (*p) { cout << l; ++p; } cout << endl; } /*======================================================================*/ /*! \brief test array interface to Fortran 77 * * \sa \ref page_fortran */ int main() { cout << AFF_F77TEST_CC_VERSION << endl; cout << AFF_F77TEST_CC_CVSID << endl; // First we test the shape class that should support passing arrays to // Fortran 77 functions section("FortranShape:", '='); { section("Full Layout"); // we create a test array with known Fortran layout CODE(Strided strided(Shaper(1,10,20)(1,5,10)(1,30)(20))); // dump this shape DUMP(strided); // create Fortran shape from this (should be identical to known) CODE(aff::util::FortranShape fs1(strided)); // and dump this DUMP(fs1.first()); DUMP(fs1.last()); DUMP(fs1.dimlast()); cout << "fs1.offset(): " << fs1.offset() << endl; section("Sliced Subshape"); // now take shape of a subarray CODE(Strided subshape(strided)); CODE(subshape.shrink(0,2).shrink(1,3,5).shrink(3,10,20)); CODE(subshape.collapse(2,15)); // create Fortran shape from this CODE(aff::util::FortranShape fs2(subshape)); // and dump this DUMP(fs2.first()); DUMP(fs2.last()); DUMP(fs2.dimlast()); cout << "fs2.offset(): " << fs2.offset() << endl; } /*----------------------------------------------------------------------*/ section("Pass array to Fortran via subroutine arguments:", '='); { // create an array and fill it CODE(Array A(Shaper(-3,3)(9)(-1,1))); CODE(A=-55); // create a subarray view and fill this through Fortran CODE(Array B=subarray(A)(-2,2)(3,7)(0)); CODE(f77interface::fill(B)); // dump the result CODE(dump_array(A)); // do it again for a slice CODE(f77interface::fill(slice(A)()(2))); CODE(dump_array(A)); } /*----------------------------------------------------------------------*/ section("Access to common block:", '='); { // prepare to vectors to pass to fillarray CODE(Array v1(5)); CODE(Array v2(3)); CODE(for(int i=v1.f(0); i<=v1.l(0); i++) { v1(i)=2.*i; }); CODE(for(int i=v2.f(0); i<=v2.l(0); i++) { v2(i)=.5*i; }); // fill common block through Fortran 77 subroutine CODE(f77interface::fillarray(v1, v2)); // get a view on the common block and dump it CODE(f77interface::Tzarray Z(f77interface::viewcommon())); CODE(dump_array(Z)); // call Fortran subroutine sum and dump result CODE(dump_array(f77interface::sums())); CODE(typedef f77interface::Tzarray::Tvalue Tzvalue); // write directly to common block through a subarray CODE(subarray(Z)(2,4)=Tzvalue(-10.)); // and dump the effect CODE(dump_array(Z)); CODE(dump_array(f77interface::sums())); } /*----------------------------------------------------------------------*/ section("Size-checked casts:", '='); { CODE(typedef std::complex Ticvalue); CODE(typedef std::complex Tcvalue); CODE(Array v1(1)); CODE(ConstArray v2(v1)); CODE(FortranArray > fv1(v1)); CODE(FortranArray > fv2(v2)); CODE(v1(1)=Ticvalue(3,7)); CODE(cout << v1(1) << ", " << v2(1) << endl); CODE(Ticvalue *icp=fv1.castedpointer()); CODE(*icp=Ticvalue(35,60)); CODE(cout << v1(1) << ", " << v2(1) << endl); CODE(const Ticvalue *cicp1=fv1.castedpointer()); CODE(const Ticvalue *cicp2=fv2.castedpointer()); CODE(cout << *cicp1 << ", " << *cicp2 << endl); section("That's dangerous:",' '); CODE(Tcvalue *cp=fv1.castedpointer()); CODE(*cp=Ticvalue(35,60)); CODE(cout << v1(1) << ", " << v2(1) << endl); CODE(double *dp=fv1.castedpointer()); CODE(*dp=35.e12); CODE(cout << v1(1) << ", " << v2(1) << endl); #ifdef ILLEGAL1 #warning intentionally compiling illegal code: #warning direct discard of const qualifier in conversion from non-const CODE(Ticvalue *ip1=fv1.castedpointer()); #endif #ifdef ILLEGAL2 #warning intentionally compiling illegal code: #warning direct discard of const qualifier in conversion from const array CODE(Ticvalue *ip2=fv2.castedpointer()); #endif #ifdef ILLEGAL3 #warning intentionally compiling illegal code: #warning discards const in conversion (reinterpret_cast) CODE(Ticvalue *ip3=fv2.castedpointer()); #endif #ifdef ILLEGAL4 #warning intentionally compiling illegal code: #warning direct type mismatch CODE(float *ip4=fv1.castedpointer()); #endif #ifdef ILLEGAL5 #warning intentionally compiling illegal code: #warning wrong type size in conversion through reinterpret_cast CODE(float *ip5=fv1.castedpointer()); #endif } } // main /* ----- END OF f77test.cc ----- */