doxygen.lib.txt 18 KB
 thomas.forbriger committed Oct 23, 2015 1 /*! \file libaff/lib/doxygen.lib.txt  thomas.forbriger committed Oct 23, 2015 2 3 4 5  * \brief Some more specific or more advanced topics * * ---------------------------------------------------------------------------- *  thomas.forbriger committed Oct 23, 2015 6  * $Id$  thomas.forbriger committed Oct 23, 2015 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  * * Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt) * * ---- * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * ---- * * Some more specific or more advanced topics * * This file contains documentation for * - namespace aff::util * - \ref page_representation * - \ref page_fortran * * REVISIONS and CHANGES * - 08/12/2002 V1.0 copied from libcontxx * - 20/12/2002 V1.1 (thof) * - complete revision of this file * - 27/12/2002 V1.2 (thof) * - completed Fortran considerations * - doxygen now reads Fortran and f2c generated code * - 28/12/2002 V1.3 (thof) * - new term for containers of const elements  thomas.forbriger committed Oct 23, 2015 42 43  * - 12/06/2013 V1.4 (thof) * - renamed file  thomas.forbriger committed Oct 23, 2015 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394  * * ============================================================================ */ namespace aff { /*! \brief Internal utilities * * In this namespace we collect modules that need not necessarily be exposed * to the user. */ namespace util { } // util } // aff /*======================================================================*/ /*! \page page_representation The concept of represented memory Contents of this page: - \ref sec_representation_sharedheap - \ref sec_representation_introduction \section sec_representation_introduction Introduction The array and iterator classes in this library should be insulated from the representation of the handled data in memory. Also they should be able to share references to the same memory area. Since returning an array from a function automatically invokes the copy constructor, this representation should have reference semantics. Using the same representation class (here aff::SharedHeap) as a basis for all containers (like aff::Array and aff::Series) and iterators, we may easily convert an aff::Series into an aff::Array without copying the data. Both objects just provide a different access interface to the data in memory. To use memory representations with reference semantics has some implications for the definition of the assignment operator. We have to decide between a deep copy (elementwise copy) and a shallow copy (copying the representation). \sa \ref sec_design_copy \section sec_representation_sharedheap Shared heap This type of memory access implements array handle semantics. On creation this class allocates memory on the free store (heap) to be used for the array elements. On a copy only a reference to the free store location is copied. Thus always a shallow copy is performed. The represenation itself takes care about the number of instances referencing the free store location. On destruction of the last of these instances, the free store location is freed. Additionally aff::SharedHeap offers a facility to take a global memory pointer on creation. In this case, memory management lies outside the representation class and the underlying aff::SHeap object will \em never call the delete operator in the destructor. This is usefull when interfacing arrays allocated through Fortran code subroutines. Creating an array projection may be done by copying the representation (reference to free store) with an array instance that only accesses a subset of the elements in the heap location. Thus projections may be created as true arrays (you don't have do distinguish between projections and true arrays in your code - like the sliced arrays in the STL must). However, changes applied to the array elements through the projection imediately affects the full array, in fact data of all array copies are affected by "write"-operations to the instances. This way of memory access allows easy and cheap copying of arrays. We may pass them freely to functions or receive them as return values. It doesn't matter where the array is actually created. Itself takes care about memory allocation. And it always does a shallow copy, with almost no overhead to passing a reference. By this mechanism, we may hold different projections to the same data, which are all full qualified arrays (even with possibly different dimensionality). For example, we may hold a complete set of earth model parameters. We may like to address them either in the sense of inversion parameters as a full set or in the sense of there physical meaning. In the latter case we may like to address the p-velocities as a subset. However, when any of the (anonymous) inversion parameters are changed, the change should immediatly be reflected by the projection that represents the physical parameters and vice versa. The same memory data may even be shared by objects of different class types. In this way an aff::Array may interface the same data in memory as a simultaneous aff::Series object. This is implemented by class aff::SharedHeap. It is presented in aff/lib/sharedheap.h \sa \ref sec_design_const */ /*======================================================================*/ /*! \page page_fortran Interfacing Fortran 77 Contents of this page: - \ref sec_fortran_general - \ref sec_fortran_call - \ref sec_fortran_common - \ref sec_fortran_links - \ref sec_fortran_source - \ref sec_fortran_f2c 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. \sa namespace f77interface \sa tests/f77interface.cc \sa tests/f77proto.h \sa \ref sec_fortran_f77procsf \sa \ref sec_fortran_f77commoninc \sa tests/Makefile \section sec_fortran_general Some general considerations \par Compiler There are two common Fortran 77 compilers available on Linux platforms: The GNU Fortran 77 (g77) from the GNU compiler collection ("http://www.gnu.org/software/gcc/gcc.html") and the Fortran to C compiler (f2c) published through netlib ("http://netlib.bell-labs.com/netlib/f2c/index.html"). \par When compiling the C++ part with the g++ from the GNU compiler collection it may seem natural to use g77 for the Fortran part. However, when interfacing the Fortran components, we have to know about the internals of the compiled Fortran code so that the linker will find the components, that we wish to access. g77 does not expose these internals, in particular it may operate in different modes (f2c compatible or not) and is subject to future changes. f2c on the other hand exposes the intermediate C code, which is then compiled by gcc from the GNU compiler collection and may easily be linked to C++ code. \par \b Decision: We use f2c and gcc in our examples of interoparting Fortran code and AFF. \par Prototypes Source code is usually separated into different compilation units (source files). These code fragmemts must be kept synchronous, i.e. all calls to a function must use the same (and correct) formal parameters, all access to global data (e.g. common blocks) must use the same declaration. \par While C offers a control mechanism to ensure snychronous code (through prototypes and header files), Fortran 77 does not. A common technique with Fortran is to read common block definitions from extra files (using the include statement), thus ensuring that every function and subroutine uses the same definition. How can we ensure that later changes applied to the Fortran code will be recognized in the interoperating C++ code? \par \b Decision: We make extensive use of header files and prototypes that can be generated with f2c. This makes interface code more complicated (i.e. splits it into more different compilation units) and introduces more header files (e.g. tests/f77common_com.P and tests/f77procs.P) but introduces more safety too. Aspects to consider: -# Passing pointers of Fortran type to pointer of C++ type (reinterpret_cast) -# Creating function call prototypes -# factoring out interfacing issues to seperate compilation unit and interface functions -# creating function call prototypes with extern "C" linkage -# creating common block declarations with extern linkage -# passing fixed array dimensions from Fortran to C++ -# passing variable array dimensions from Fortran common block to C++ -# how to satisfy linker with a MAIN__ function -# compiling f2c output with g++ (using -C++ option) \section sec_fortran_call Passing arrays through function calls 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 \code int f77interface::fill(const aff::Array& a) \endcode The Array is converted into an aff::FortranArray by \code aff::FortranArray fa(a); \endcode 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: - The corresponding Fortran subroutine in tests/f77procs.f is compiled by f2c and g++. Hence we pass the -C++ option to f2c. - We have to link against libf2c.a and libm.a or their dynamic companions. - We have to provide a MAIN__() function in our code to satisfy the linker (discovered by wolle). This function, however is never called. It must be declared with \c extern \c "C" linkage. - For calling the Fortran functionality we provide an extra C++ interface. This interface is presented in tests/f77proto.h and namespace f77interface. The definitions are coded in tests/f77interface.cc. - To ensure synchronous code between Fortran and the C++ interface, we use prototypes written by f2c. They are generated by \verbatim f2c -C++ -P -\!c tests/f77procs.f \endverbatim to file \ref sec_fortran_f77procsp - The prototypes are not declared with external C linkage. Therefore the correspnding include section in tests/f77interface.cc reads like \code extern "C" { #include "f77procs.P" } \endcode - Additionally we must include \c f2c.h in tests/f77interface.cc. - Within f77interface::fill type conversion must take place. The array shape is derived as C++ \c int values. They are converted to values of type \c integer (defined in f2c.h) with statements like \code integer n1=fa.last(0); \endcode and passed to the Fortran function as pointers of type \c integer* by \code fill_(pa, &l1, &n1, &l2, &n2, &l3, &n3) \endcode - The array values are access within the Fortran subroutine through a pointer to the first element. This pointer is of type \c integer*, which is defined as \c long \c int* in f2c.h. From the FortranArray object we receive a pointer of type \c int*. The only way I see to convert it is via \code integer* pa=reinterpret_cast(fa.pointer()); \endcode which is a totally unchecked conversion. Since the type size is known at compile-time, there should be a more elegant way. And there is: Have a look at aff::util::SizeCheckedCast. The more recent version of tests/f77test.cc uses the aff::FortranArray::castedpointer member template function, which again calls a compile-time size-check. \section sec_fortran_common Accessing arrays in common blocks 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: -# f77interface::fillarray takes two 1D aff::Array arguments and passes them to the Fotran subroutine fillarray which calculates the contents of a complex common block array from them. -# f77interface::sums takes the result of the Fortran subroutine sums, which calculates column-sums of the common block array, and returns them as an aff::Array. -# f77interface::viewcommon returns an aff::Array that offers direct read/write access to the Fortran common block. The interface functions are presented in tests/f77proto.h, are defined in tests/f77interface.cc and the underlying Fortran subroutines are defined in \ref sec_fortran_f77procsf. The common-block itself is defined in \ref sec_fortran_f77commoninc. 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 \ref sec_fortran_call we have to discuss the following: - f77interface::fillarray passes AFF arrays to Fortran code just in the way f77interface::fill discussed above. Since Fortran doesn't know of const-correctness it takes arguments of type \code const aff::Array& \endcode rather than \code const aff::ConstArray& \endcode (see also \ref sec_design_const). - f77interface::sums has to create an AFF array of appropriate size before passing a pointer to the underlying Fortran subroutine. Since the dimensions of fixed sized Fortran arrays are usually given by parameter constants that are defined in include files, these values are not accessible from the C++ code. We therefore introduced a Fortran subroutine \c comdim, which can be used to read the dimensions of the common-block array. - f77interface::viewcommon creates an AFF array, which is simply a reference to the common-block array and has appropriate shape. Shape and representation (i.e. SharedHeap) are craeted separately. The SharedHeap is intialized by \code aff::SharedHeap repr(p, shape.memory_size()); \endcode from a pointer \c p and a size in memory. Using this constructor ensures, that SharedHeap will never try to deallocate the memory block. - The common block definition is not visible from C++. To ensure synchronous code after changes being applied to the Fortran code, we must make use of automatic code generation by f2c. We use \verbatim f2c -C++ -f -u -ec tests/f77procs.f sed -e 's/^struct/extern struct/' tests/f77common_com.c > tests/f77common_com.P \endverbatim to create a common block definition in \ref sec_fortran_f77commoncomp. This definition is read via \code #include"f77common_com.P" \endcode in tests/f77interface.cc. The common block is then available as \code extern struct { ... } f77common_ \endcode with \c extern \c "C" linkage in the C++ code. - \b Notice: The access shape of the AFF array returned by f77interface::viewcommon is defined upon creation of the array. Changing the actual access shape in the common block later (i.e. the common block members \c na and \c 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++. \section sec_fortran_links Links to other helpful information - In the manual of the GNU Fortran 77 compiler you will find a section discussing "Interoperating with C and C++". - http://gcc.gnu.org/onlinedocs/g77/Interoperating-with-C-and-C--.html#Interoperating%20with%20C%20and%20C++ - http://gcc.gnu.org/onlinedocs/ - Burkhard D. Steinmacher-Burow provides cfortran.h for "Interfacing C or C++ and Fortran". - http://www-zeus.desy.de/~burow/cfortran/index.htm - http://www-zeus.desy.de/~burow/cfortran/cfortran.html - A very usefull tool for coding interfaces to Fortran 77 is the f2c compiler. Its documentation provides a lot of useful information about the way Fortran code objects may be accessed from C and C++. - http://netlib.bell-labs.com/netlib/f2c/index.html - Further discussions may be found at other places: - http://wwwinfo.cern.ch/asdcgi/listcernlibfaqs.pl/3 - http://home.online.no/~arnholm/cppf77.htm - http://www.llnl.gov/CASC/components/babel.html \section sec_fortran_source Fortran 77 Source code \subsection sec_fortran_f77commoninc tests/f77common.inc \verbinclude tests/f77common.inc \subsection sec_fortran_f77procsf tests/f77procs.f \verbinclude tests/f77procs.f \section sec_fortran_f2c Code generated by f2c \subsection sec_fortran_f77commoncomp tests/f77common_com.P \verbinclude tests/f77common_com.P \subsection sec_fortran_f77procsp tests/f77procs.P \verbinclude tests/f77procs.P */  thomas.forbriger committed Oct 23, 2015 395 // ----- END OF doxygen.lib.txt -----