diff options
author | Pauli Virtanen <pav@iki.fi> | 2014-01-02 22:12:01 +0200 |
---|---|---|
committer | Pauli Virtanen <pav@iki.fi> | 2014-01-02 22:19:47 +0200 |
commit | 75c2d2fe3cc9daa6589707fb6b8512ffa48fc365 (patch) | |
tree | 32e729ca94dd28e06c7c2e10fd250f2ce4b91a2a /doc/f2py | |
parent | a32807e61b25205cc08d552127234b56709c6242 (diff) | |
download | numpy-75c2d2fe3cc9daa6589707fb6b8512ffa48fc365.tar.gz |
DOC: move f2py documentation under doc/ and link its user guide with Sphinx
Diffstat (limited to 'doc/f2py')
63 files changed, 9099 insertions, 0 deletions
diff --git a/doc/f2py/BUGS.txt b/doc/f2py/BUGS.txt new file mode 100644 index 000000000..ee08863bb --- /dev/null +++ b/doc/f2py/BUGS.txt @@ -0,0 +1,55 @@ +December 1, 2002: + +C FILE: STRING.F + SUBROUTINE FOO + END +C END OF FILE STRING.F +does not build with + f2py -c -m string string.f +Cause: string is mapped to string_bn +************************************************************************** +August 16, 2001: +1) re in Python 2.x is **three** times slower than the re in Python 1.5. +************************************************************************** +HP-UX B.10.20 A 9000/780: +Fortran function returning character*(*) (id=7) ... failed(core dump) +Fortran function returning logical*8 (id=21) ... expected .true. but got 0 +Callback function returning real (id=45) ... expected 34.56 but got 14087495680.0 +Callback function returning real*4 (id=46) ... expected 34.56 but got 14087495680.0 +Callback function returning logical*8 (id=55) ... expected .true. but got 0 + C compiler: gcc ('gcc 2.x.x' 2.95.2) (from .f2py_get_compiler_CC) + Fortran compiler: g77 ('g77 2.x.x' 2.95.2) (from .f2py_get_compiler_FC) + Linker: ld ('HP-UX ld' 92453-07 linker linker ld B.10.24 961204) (from .f2py_get_compiler_LD) +************************************************************************** +Linux 2.2.13-0.9 #1 Thu Dec 9 17:03:57 EST 1999 alpha unknown: +Fortran function returning character*(*) (id=7) ... expected 'abcdefgh' but got 'abcdefgh \201' (o?k) +Callback function returning complex (id=48) ... failed(core dump) + Trying with -DF2PY_CB_RETURNCOMPLEX ... failed(core dump) +Callback function returning complex*8 (id=49) ... failed(core dump) + Trying with -DF2PY_CB_RETURNCOMPLEX ... failed(core dump) +Callback function returning complex*16 (id=50) ... failed(core dump) + Trying with -DF2PY_CB_RETURNCOMPLEX ... failed(core dump) + C compiler: cc ('Compaq C' V6.2-002) (from .f2py_get_compiler_CC) + Fortran compiler: fort ('Compaq Fortran' V1.0-920) (from .f2py_get_compiler_FC) + Linker: fort ('Compaq Fortran' V1.0-920) (from .f2py_get_compiler_LD) +************************************************************************** +Linux 2.2.14-15mdk #1 Tue Jan 4 22:24:20 CET 2000 i686 unknown: +Callback function returning logical*8 (id=55) ... failed + C compiler: cc ('gcc 2.x.x' 2.95.2) + Fortran compiler: f90 ('Absoft F90' 3.0) + Linker: ld ('GNU ld' 2.9.5) +************************************************************************** +IRIX64 6.5 04151556 IP30: +Testing integer, intent(inout) ...failed # not f2py problem +Testing integer, intent(inout,out) ...failed +Testing integer*1, intent(inout) ...failed +Testing integer*1, intent(inout,out) ...failed +Testing integer*8, intent(inout) ...failed +Testing integer*8, intent(inout,out) ...failed +cc-1140 cc: WARNING File = genmodule.c, Line = 114 + A value of type "void *" cannot be used to initialize an entity of type + "void (*)()". + {"foo",-1,{-1},0,(char *)F_FUNC(foo,FOO),(void *)gen_foo,doc_gen_foo}, + C compiler: cc ('MIPSpro 7 Compilers' 7.30) + Fortran compiler: f77 ('MIPSpro 7 Compilers' 7.30) + Linker: ld ('Linker for MIPSpro 7 Compilers' 7.30.) diff --git a/doc/f2py/FAQ.txt b/doc/f2py/FAQ.txt new file mode 100644 index 000000000..2481b5b95 --- /dev/null +++ b/doc/f2py/FAQ.txt @@ -0,0 +1,603 @@ + +====================================================================== + F2PY Frequently Asked Questions +====================================================================== + +.. contents:: + +General information +=================== + +Q: How to get started? +---------------------- + +First, install__ F2PY. Then check that F2PY installation works +properly (see below__). Try out a `simple example`__. + +Read `F2PY Users Guide and Reference Manual`__. It contains lots +of complete examples. + +If you have any questions/problems when using F2PY, don't hesitate to +turn to `F2PY users mailing list`__ or directly to me. + +__ index.html#installation +__ #testing +__ index.html#usage +__ usersguide/index.html +__ index.html#mailing-list + +Q: When to report bugs? +----------------------- + +* If F2PY scanning fails on Fortran sources that otherwise compile + fine. + +* After checking that you have the latest version of F2PY from its + CVS. It is possible that a bug has been fixed already. See also the + log entries in the file `HISTORY.txt`_ (`HISTORY.txt in CVS`_). + +* After checking that your Python and Numerical Python installations + work correctly. + +* After checking that your C and Fortran compilers work correctly. + +Q: How to report bugs? +---------------------- + +F2PY is part of NumPy. Report bugs on the NumPy issue tracker at +__ https://github.com/numpy/numpy/issues +Please, include information about your platform (operating system, +version) and compilers/linkers, e.g. the output (both stdout/stderr) of +:: + + python -c 'import numpy.f2py.diagnose;numpy.f2py.diagnose.run()' + +Feel free to add any other relevant information. However, avoid +sending the output of F2PY generated ``.pyf`` files (unless they are +manually modified) or any binary files like shared libraries or object +codes. + +N.B. You may notice that other F2PY issues are tagged 'f2py'. Only the +admins can add tags to issues, don't waste time trying to work out how +to tag it yourself. + +While reporting bugs, you may find the following notes useful: + +* `How To Ask Questions The Smart Way`__ by E. S. Raymond and R. Moen. + +* `How to Report Bugs Effectively`__ by S. Tatham. + +__ http://www.catb.org/~esr/faqs/smart-questions.html +__ http://www.chiark.greenend.org.uk/~sgtatham/bugs.html + +Installation +============ + +Q: How to use F2PY with different Python versions? +-------------------------------------------------- + +Run the installation command using the corresponding Python +executable. For example, +:: + + python2.1 setup.py install + +installs the ``f2py`` script as ``f2py2.1``. + +See `Distutils User Documentation`__ for more information how to +install Python modules to non-standard locations. + +__ http://www.python.org/sigs/distutils-sig/doc/inst/inst.html + + +Q: Why F2PY is not working after upgrading? +------------------------------------------- + +If upgrading from F2PY version 2.3.321 or earlier then remove all f2py +specific files from ``/path/to/python/bin`` directory before +running installation command. + +Q: How to get/upgrade numpy and F2PY from git? +--------------------------------------------------------------- + +The numpy code repository is hosted on GitHub at +__ http://github.com/numpy/numpy + +You can check it out with +:: + git clone git://github.com/numpy/numpy.git numpy + +Installation information is at +__ http://www.scipy.org/scipylib/download.html + +Information for developers is at +__ http://www.scipy.org/scipylib/dev-zone.html + + +Testing +======= + +Q: How to test if F2PY is installed correctly? +---------------------------------------------- + +Run +:: + + f2py + +without arguments. If F2PY is installed correctly then it should print +the usage information for f2py. + +Q: How to test if F2PY is working correctly? +-------------------------------------------- + +For a quick test, try out an example problem from Usage__ +section in `README.txt`_. + +__ index.html#usage + +For running F2PY unit tests, see `TESTING.txt`_. + + +Compiler/Platform-specific issues +================================= + +Q: What are supported platforms and compilers? +---------------------------------------------- + +F2PY is developed on Linux system with a GCC compiler (versions +2.95.x, 3.x). Fortran 90 related hooks are tested against Intel +Fortran Compiler. F2PY should work under any platform where Python and +Numeric are installed and has supported Fortran compiler installed. + +To see a list of supported compilers, execute:: + + f2py -c --help-fcompiler + +Example output:: + + List of available Fortran compilers: + --fcompiler=gnu GNU Fortran Compiler (3.3.4) + --fcompiler=intel Intel Fortran Compiler for 32-bit apps (8.0) + List of unavailable Fortran compilers: + --fcompiler=absoft Absoft Corp Fortran Compiler + --fcompiler=compaq Compaq Fortran Compiler + --fcompiler=compaqv DIGITAL|Compaq Visual Fortran Compiler + --fcompiler=hpux HP Fortran 90 Compiler + --fcompiler=ibm IBM XL Fortran Compiler + --fcompiler=intele Intel Fortran Compiler for Itanium apps + --fcompiler=intelev Intel Visual Fortran Compiler for Itanium apps + --fcompiler=intelv Intel Visual Fortran Compiler for 32-bit apps + --fcompiler=lahey Lahey/Fujitsu Fortran 95 Compiler + --fcompiler=mips MIPSpro Fortran Compiler + --fcompiler=nag NAGWare Fortran 95 Compiler + --fcompiler=pg Portland Group Fortran Compiler + --fcompiler=sun Sun|Forte Fortran 95 Compiler + --fcompiler=vast Pacific-Sierra Research Fortran 90 Compiler + List of unimplemented Fortran compilers: + --fcompiler=f Fortran Company/NAG F Compiler + For compiler details, run 'config_fc --verbose' setup command. + + +Q: How to use the F compiler in F2PY? +------------------------------------- + +Read `f2py2e/doc/using_F_compiler.txt`__. It describes why the F +compiler cannot be used in a normal way (i.e. using ``-c`` switch) to +build F2PY generated modules. It also gives a workaround to this +problem. + +__ http://cens.ioc.ee/cgi-bin/viewcvs.cgi/python/f2py2e/doc/using_F_compiler.txt?rev=HEAD&content-type=text/vnd.viewcvs-markup + +Q: How to use F2PY under Windows? +--------------------------------- + +F2PY can be used both within Cygwin__ and MinGW__ environments under +Windows, F2PY can be used also in Windows native terminal. +See the section `Setting up environment`__ for Cygwin and MinGW. + +__ http://cygwin.com/ +__ http://www.mingw.org/ +__ http://cens.ioc.ee/~pearu/numpy/BUILD_WIN32.html#setting-up-environment + +Install numpy_distutils and F2PY. Win32 installers of these packages +are provided in `F2PY Download`__ section. + +__ http://cens.ioc.ee/projects/f2py2e/#download + +Use ``--compiler=`` and ``--fcompiler`` F2PY command line switches to +to specify which C and Fortran compilers F2PY should use, respectively. + +Under MinGW environment, ``mingw32`` is default for a C compiler. + +Supported and Unsupported Features +================================== + +Q: Does F2PY support ``ENTRY`` statements? +------------------------------------------ + +Yes, starting at F2PY version higher than 2.39.235_1706. + +Q: Does F2PY support derived types in F90 code? +----------------------------------------------- + +Not yet. However I do have plans to implement support for F90 TYPE +constructs in future. But note that the task in non-trivial and may +require the next edition of F2PY for which I don't have resources to +work with at the moment. + +Jeffrey Hagelberg from LLNL has made progress on adding +support for derived types to f2py. He writes: + + At this point, I have a version of f2py that supports derived types + for most simple cases. I have multidimensional arrays of derived + types and allocatable arrays of derived types working. I'm just now + starting to work on getting nested derived types to work. I also + haven't tried putting complex number in derived types yet. + +Hopefully he can contribute his changes to f2py soon. + +Q: Does F2PY support pointer data in F90 code? +----------------------------------------------- + +No. I have never needed it and I haven't studied if there are any +obstacles to add pointer data support to F2PY. + +Q: What if Fortran 90 code uses ``<type spec>(kind=KIND(..))``? +--------------------------------------------------------------- + +Currently, F2PY can handle only ``<type spec>(kind=<kindselector>)`` +declarations where ``<kindselector>`` is a numeric integer (e.g. 1, 2, +4,...) but not a function call ``KIND(..)`` or any other +expression. F2PY needs to know what would be the corresponding C type +and a general solution for that would be too complicated to implement. + +However, F2PY provides a hook to overcome this difficulty, namely, +users can define their own <Fortran type> to <C type> maps. For +example, if Fortran 90 code contains:: + + REAL(kind=KIND(0.0D0)) ... + +then create a file ``.f2py_f2cmap`` (into the working directory) +containing a Python dictionary:: + + {'real':{'KIND(0.0D0)':'double'}} + +for instance. + +Or more generally, the file ``.f2py_f2cmap`` must contain a dictionary +with items:: + + <Fortran typespec> : {<selector_expr>:<C type>} + +that defines mapping between Fortran type:: + + <Fortran typespec>([kind=]<selector_expr>) + +and the corresponding ``<C type>``. ``<C type>`` can be one of the +following:: + + char + signed_char + short + int + long_long + float + double + long_double + complex_float + complex_double + complex_long_double + string + +For more information, see ``f2py2e/capi_maps.py``. + +Related software +================ + +Q: How F2PY distinguishes from Pyfort? +-------------------------------------- + +F2PY and Pyfort have very similar aims and ideology of how they are +targeted. Both projects started to evolve in the same year 1999 +independently. When we discovered each others projects, a discussion +started to join the projects but that unfortunately failed for +various reasons, e.g. both projects had evolved too far that merging +the tools would have been impractical and giving up the efforts that +the developers of both projects have made was unacceptable to both +parties. And so, nowadays we have two tools for connecting Fortran +with Python and this fact will hardly change in near future. To decide +which one to choose is a matter of taste, I can only recommend to try +out both to make up your choice. + +At the moment F2PY can handle more wrapping tasks than Pyfort, +e.g. with F2PY one can wrap Fortran 77 common blocks, Fortran 90 +module routines, Fortran 90 module data (including allocatable +arrays), one can call Python from Fortran, etc etc. F2PY scans Fortran +codes to create signature (.pyf) files. F2PY is free from most of the +limitations listed in in `the corresponding section of Pyfort +Reference Manual`__. + +__ http://pyfortran.sourceforge.net/pyfort/pyfort_reference.htm#pgfId-296925 + +There is a conceptual difference on how F2PY and Pyfort handle the +issue of different data ordering in Fortran and C multi-dimensional +arrays. Pyfort generated wrapper functions have optional arguments +TRANSPOSE and MIRROR that can be used to control explicitly how the array +arguments and their dimensions are passed to Fortran routine in order +to deal with the C/Fortran data ordering issue. F2PY generated wrapper +functions hide the whole issue from an end-user so that translation +between Fortran and C/Python loops and array element access codes is +one-to-one. How the F2PY generated wrappers deal with the issue is +determined by a person who creates a signature file via using +attributes like ``intent(c)``, ``intent(copy|overwrite)``, +``intent(inout|in,out|inplace)`` etc. + +For example, let's consider a typical usage of both F2PY and Pyfort +when wrapping the following simple Fortran code: + +.. include:: simple.f + :literal: + +The comment lines starting with ``cf2py`` are read by F2PY (so that we +don't need to generate/handwrite an intermediate signature file in +this simple case) while for a Fortran compiler they are just comment +lines. + +And here is a Python version of the Fortran code: + +.. include:: pytest.py + :literal: + +To generate a wrapper for subroutine ``foo`` using F2PY, execute:: + + $ f2py -m f2pytest simple.f -c + +that will generate an extension module ``f2pytest`` into the current +directory. + +To generate a wrapper using Pyfort, create the following file + +.. include:: pyforttest.pyf + :literal: + +and execute:: + + $ pyfort pyforttest + +In Pyfort GUI add ``simple.f`` to the list of Fortran sources and +check that the signature file is in free format. And then copy +``pyforttest.so`` from the build directory to the current directory. + +Now, in Python + +.. include:: simple_session.dat + :literal: + +Q: Can Pyfort .pyf files used with F2PY and vice versa? +------------------------------------------------------- + +After some simple modifications, yes. You should take into account the +following differences in Pyfort and F2PY .pyf files. + ++ F2PY signature file contains ``python module`` and ``interface`` + blocks that are equivalent to Pyfort ``module`` block usage. + ++ F2PY attribute ``intent(inplace)`` is equivalent to Pyfort + ``intent(inout)``. F2PY ``intent(inout)`` is a strict (but safe) + version of ``intent(inplace)``, any mismatch in arguments with + expected type, size, or contiguouness will trigger an exception + while ``intent(inplace)`` (dangerously) modifies arguments + attributes in-place. + +Misc +==== + +Q: How to establish which Fortran compiler F2PY will use? +--------------------------------------------------------- + +This question may be releavant when using F2PY in Makefiles. Here +follows a script demonstrating how to determine which Fortran compiler +and flags F2PY will use:: + + # Using post-0.2.2 numpy_distutils + from numpy_distutils.fcompiler import new_fcompiler + compiler = new_fcompiler() # or new_fcompiler(compiler='intel') + compiler.dump_properties() + + # Using pre-0.2.2 numpy_distutils + import os + from numpy_distutils.command.build_flib import find_fortran_compiler + def main(): + fcompiler = os.environ.get('FC_VENDOR') + fcompiler_exec = os.environ.get('F77') + f90compiler_exec = os.environ.get('F90') + fc = find_fortran_compiler(fcompiler, + fcompiler_exec, + f90compiler_exec, + verbose = 0) + print 'FC=',fc.f77_compiler + print 'FFLAGS=',fc.f77_switches + print 'FOPT=',fc.f77_opt + if __name__ == "__main__": + main() + +Users feedback +============== + +Q: Where to find additional information on using F2PY? +------------------------------------------------------ + +There are several F2PY related tutorials, slides, papers, etc +available: + ++ `Fortran to Python Interface Generator with an Application to + Aerospace Engineering`__ by P. Peterson, J. R. R. A. Martins, and + J. J. Alonso in `In Proceedings of the 9th International Python + Conference`__, Long Beach, California, 2001. + +__ http://www.python9.org/p9-cdrom/07/index.htm +__ http://www.python9.org/ + ++ Section `Adding Fortran90 code`__ in the UG of `The Bolometer Data + Analysis Project`__. + +__ http://www.astro.rub.de/laboca/download/boa_master_doc/7_4Adding_Fortran90_code.html +__ http://www.openboa.de/ + ++ Powerpoint presentation `Python for Scientific Computing`__ by Eric + Jones in `The Ninth International Python Conference`__. + +__ http://www.python9.org/p9-jones.ppt +__ http://www.python9.org/ + ++ Paper `Scripting a Large Fortran Code with Python`__ by Alvaro Caceres + Calleja in `International Workshop on Software Engineering for High + Performance Computing System Applications`__. + +__ http://csdl.ics.hawaii.edu/se-hpcs/pdf/calleja.pdf +__ http://csdl.ics.hawaii.edu/se-hpcs/ + ++ Section `Automatic building of C/Fortran extension for Python`__ by + Simon Lacoste-Julien in `Summer 2002 Report about Hybrid Systems + Modelling`__. + +__ http://moncs.cs.mcgill.ca/people/slacoste/research/report/SummerReport.html#tth_sEc3.4 +__ http://moncs.cs.mcgill.ca/people/slacoste/research/report/SummerReport.html + ++ `Scripting for Computational Science`__ by Hans Petter Langtangen + (see the `Mixed language programming`__ and `NumPy array programming`__ + sections for examples on using F2PY). + +__ http://www.ifi.uio.no/~inf3330/lecsplit/ +__ http://www.ifi.uio.no/~inf3330/lecsplit/slide662.html +__ http://www.ifi.uio.no/~inf3330/lecsplit/slide718.html + ++ Chapters 5 and 9 of `Python Scripting for Computational Science`__ + by H. P. Langtangen for case studies on using F2PY. + +__ http://www.springeronline.com/3-540-43508-5 + ++ Section `Fortran Wrapping`__ in `Continuity`__, a computational tool + for continuum problems in bioengineering and physiology. + +__ http://www.continuity.ucsd.edu/cont6_html/docs_fram.html +__ http://www.continuity.ucsd.edu/ + ++ Presentation `PYFORT and F2PY: 2 ways to bind C and Fortran with Python`__ + by Reiner Vogelsang. + +__ http://www.prism.enes.org/WPs/WP4a/Slides/pyfort/pyfort.html + ++ Lecture slides of `Extending Python: speed it up`__. + +__ http://www.astro.uni-bonn.de/~heith/lecture_pdf/friedrich5.pdf + ++ Wiki topics on `Wrapping Tools`__ and `Wrapping Bemchmarks`__ for Climate + System Center at the University of Chicago. + +__ https://geodoc.uchicago.edu/climatewiki/DiscussWrappingTools +__ https://geodoc.uchicago.edu/climatewiki/WrappingBenchmarks + ++ `Performance Python with Weave`__ by Prabhu Ramachandran. + +__ http://www.numpy.org/documentation/weave/weaveperformance.html + ++ `How To Install py-f2py on Mac OSX`__ + +__ http://py-f2py.darwinports.com/ + +Please, let me know if there are any other sites that document F2PY +usage in one or another way. + +Q: What projects use F2PY? +-------------------------- + ++ `SciPy: Scientific tools for Python`__ + +__ http://www.numpy.org/ + ++ `The Bolometer Data Analysis Project`__ + +__ http://www.openboa.de/ + ++ `pywavelet`__ + +__ http://www.met.wau.nl/index.html?http://www.met.wau.nl/medewerkers/moenea/python/pywavelet.html + ++ `PyARTS: an ARTS related Python package`__. + +__ http://www.met.ed.ac.uk/~cory/PyARTS/ + ++ `Python interface to PSPLINE`__, a collection of Spline and + Hermite interpolation tools for 1D, 2D, and 3D datasets on + rectilinear grids. + +__ http://pypspline.sourceforge.net + ++ `Markovian Analysis Package for Python`__. + +__ http://pymc.sourceforge.net + ++ `Modular toolkit for Data Processing (MDP)`__ + +__ http://mdp-toolkit.sourceforge.net/ + + +Please, send me a note if you are using F2PY in your project. + +Q: What people think about F2PY? +-------------------------------- + +*F2PY is GOOD*: + +Here are some comments people have posted to f2py mailing list and c.l.py: + ++ Ryan Krauss: I really appreciate f2py. It seems weird to say, but I + am excited about relearning FORTRAN to compliment my python stuff. + ++ Fabien Wahl: f2py is great, and is used extensively over here... + ++ Fernando Perez: Anyway, many many thanks for this amazing tool. + + I haven't used pyfort, but I can definitely vouch for the amazing quality of + f2py. And since f2py is actively used by numpy, it won't go unmaintained. + It's quite impressive, and very easy to use. + ++ Kevin Mueller: First off, thanks to those responsible for F2PY; + its been an integral tool of my research for years now. + ++ David Linke: Best regards and thanks for the great tool! + ++ Perrin Meyer: F2Py is really useful! + ++ Hans Petter Langtangen: First of all, thank you for developing + F2py. This is a very important contribution to the scientific + computing community. We are using F2py a lot and are very happy with + it. + ++ Berthold Höllmann: Thank's alot. It seems it is also working in my + 'real' application :-) + ++ John Hunter: At first I wrapped them with f2py (unbelievably easy!)... + ++ Cameron Laird: Among many other features, Python boasts a mature + f2py, which makes it particularly rewarding to yoke Fortran- and + Python-coded modules into finished applications. + ++ Ryan Gutenkunst: f2py is sweet magic. + +*F2PY is BAD*: + ++ `Is it worth using on a large scale python drivers for Fortran + subroutines, interfaced with f2py?`__ + +__ http://sepwww.stanford.edu/internal/computing/python.html + +Additional comments on F2PY, good or bad, are welcome! + +.. References: +.. _README.txt: index.html +.. _HISTORY.txt: HISTORY.html +.. _HISTORY.txt in CVS: http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt?rev=HEAD&content-type=text/x-cvsweb-markup +.. _TESTING.txt: TESTING.html diff --git a/doc/f2py/HISTORY.txt b/doc/f2py/HISTORY.txt new file mode 100644 index 000000000..4326e4852 --- /dev/null +++ b/doc/f2py/HISTORY.txt @@ -0,0 +1,1043 @@ +.. -*- rest -*- + +========================= + F2PY History +========================= + +:Author: Pearu Peterson <pearu@cens.ioc.ee> +:Web-site: http://cens.ioc.ee/projects/f2py2e/ +:Date: $Date: 2005/09/16 08:36:45 $ +:Revision: $Revision: 1.191 $ + +.. Contents:: + +Release 2.46.243 +===================== + +* common_rules.py + + - Fixed compiler warnings. + +* fortranobject.c + + - Fixed another dims calculation bug. + - Fixed dims calculation bug and added the corresponding check. + - Accept higher dimensional arrays if their effective rank matches. + Effective rank is multiplication of non-unit dimensions. + +* f2py2e.py + + - Added support for numpy.distutils version 0.4.0. + +* Documentation + + - Added example about ``intent(callback,hide)`` usage. Updates. + - Updated FAQ. + +* cb_rules.py + + - Fixed missing need kw error. + - Fixed getting callback non-existing extra arguments. + - External callback functions and extra_args can be set via + ext.module namespace. + - Avoid crash when external callback function is not set. + +* rules.py + + - Enabled ``intent(out)`` for ``intent(aux)`` non-complex scalars. + - Fixed splitting lines in F90 fixed form mode. + - Fixed FORTRANAME typo, relevant when wrapping scalar functions with + ``--no-wrap-functions``. + - Improved failure handling for callback functions. + - Fixed bug in writting F90 wrapper functions when a line length + is exactly 66. + +* cfuncs.py + + - Fixed dependency issue with typedefs. + - Introduced ``-DUNDERSCORE_G77`` that cause extra underscore to be + used for external names that contain an underscore. + +* capi_maps.py + + - Fixed typos. + - Fixed using complex cb functions. + +* crackfortran.py + + - Introduced parent_block key. Get ``use`` statements recursively + from parent blocks. + - Apply parameter values to kindselectors. + - Fixed bug evaluating ``selected_int_kind`` function. + - Ignore Name and Syntax errors when evaluating scalars. + - Treat ``<int>_intType`` as ``<int>`` in get_parameters. + - Added support for F90 line continuation in fix format mode. + - Include optional attribute of external to signature file. + - Add ``entry`` arguments to variable lists. + - Treat \xa0 character as space. + - Fixed bug where __user__ callback subroutine was added to its + argument list. + - In strict 77 mode read only the first 72 columns. + - Fixed parsing ``v(i) = func(r)``. + - Fixed parsing ``integer*4::``. + - Fixed parsing ``1.d-8`` when used as a parameter value. + +Release 2.45.241_1926 +===================== + +* diagnose.py + + - Clean up output. + +* cb_rules.py + + - Fixed ``_cpointer`` usage for subroutines. + - Fortran function ``_cpointer`` can be used for callbacks. + +* func2subr.py + + - Use result name when wrapping functions with subroutines. + +* f2py2e.py + + - Fixed ``--help-link`` switch. + - Fixed ``--[no-]lower`` usage with ``-c`` option. + - Added support for ``.pyf.src`` template files. + +* __init__.py + + - Using ``exec_command`` in ``compile()``. + +* setup.py + + - Clean up. + - Disabled ``need_numpy_distutils`` function. From now on it is assumed + that proper version of ``numpy_distutils`` is already installed. + +* capi_maps.py + + - Added support for wrapping unsigned integers. In a .pyf file + ``integer(-1)``, ``integer(-2)``, ``integer(-4)`` correspond to + ``unsigned char``, ``unsigned short``, ``unsigned`` C types, + respectively. + +* tests/c/return_real.py + + - Added tests to wrap C functions returning float/double. + +* fortranobject.c + + - Added ``_cpointer`` attribute to wrapped objects. + +* rules.py + + - ``_cpointer`` feature for wrapped module functions is not + functional at the moment. + - Introduced ``intent(aux)`` attribute. Useful to save a value + of a parameter to auxiliary C variable. Note that ``intent(aux)`` + implies ``intent(c)``. + - Added ``usercode`` section. When ``usercode`` is used in ``python + module`` block twise then the contents of the second multi-line + block is inserted after the definition of external routines. + - Call-back function arguments can be CObjects. + +* cfuncs.py + + - Allow call-back function arguments to be fortran objects. + - Allow call-back function arguments to be built-in functions. + +* crackfortran.py + + - Fixed detection of a function signature from usage example. + - Cleaned up -h output for intent(callback) variables. + - Repair malformed argument list (missing argument name). + - Warn on the usage of multiple attributes without type specification. + - Evaluate only scalars ``<initexpr>`` (e.g. not of strings). + - Evaluate ``<initexpr>`` using parameters name space. + - Fixed resolving `<name>(<args>)[result(<result>)]` pattern. + - ``usercode`` can be used more than once in the same context. + +Release 2.43.239_1831 +===================== + +* auxfuncs.py + + - Made ``intent(in,inplace)`` to mean ``intent(inplace)``. + +* f2py2e.py + + - Intoduced ``--help-link`` and ``--link-<resource>`` + switches to link generated extension module with system + ``<resource>`` as defined by numpy_distutils/system_info.py. + +* fortranobject.c + + - Patch to make PyArray_CanCastSafely safe on 64-bit machines. + Fixes incorrect results when passing ``array('l')`` to + ``real*8 intent(in,out,overwrite)`` arguments. + +* rules.py + + - Avoid empty continuation lines in Fortran wrappers. + +* cfuncs.py + + - Adding ``\0`` at the end of a space-padded string, fixes tests + on 64-bit Gentoo. + +* crackfortran.py + + - Fixed splitting lines with string parameters. + +Release 2.43.239_1806 +===================== + +* Tests + + - Fixed test site that failed after padding strings with spaces + instead of zeros. + +* Documentation + + - Documented ``intent(inplace)`` attribute. + - Documented ``intent(callback)`` attribute. + - Updated FAQ, added Users Feedback section. + +* cfuncs.py + + - Padding longer (than provided from Python side) strings with spaces + (that is Fortran behavior) instead of nulls (that is C strncpy behavior). + +* f90mod_rules.py + + - Undoing rmbadnames in Python and Fortran layers. + +* common_rules.py + + - Renaming common block items that have names identical to C keywords. + - Fixed wrapping blank common blocks. + +* fortranobject.h + + - Updated numarray (0.9, 1.0, 1.1) support (patch by Todd Miller). + +* fortranobject.c + + - Introduced ``intent(inplace)`` feature. + - Fix numarray reference counts (patch by Todd). + - Updated numarray (0.9, 1.0, 1.1) support (patch by Todd Miller). + - Enabled F2PY_REPORT_ON_ARRAY_COPY for Numarray. + +* capi_maps.py + + - Always normalize .f2py_f2cmap keys to lower case. + +* rules.py + + - Disabled ``index`` macro as it conflicts with the one defined + in string.h. + - Moved ``externroutines`` up to make it visible to ``usercode``. + - Fixed bug in f90 code generation: no empty line continuation is + allowed. + - Fixed undefined symbols failure when ``fortranname`` is used + to rename a wrapped function. + - Support for ``entry`` statement. + +* auxfuncs.py + + - Made is* functions more robust with respect to parameters that + have no typespec specified. + - Using ``size_t`` instead of ``int`` as the type of string + length. Fixes issues on 64-bit platforms. + +* setup.py + + - Fixed bug of installing ``f2py`` script as ``.exe`` file. + +* f2py2e.py + + - ``--compiler=`` and ``--fcompiler=`` can be specified at the same time. + +* crackfortran.py + + - Fixed dependency detection for non-intent(in|inout|inplace) arguments. + They must depend on their dimensions, not vice-versa. + - Don't match ``!!f2py`` as a start of f2py directive. + - Only effective intent attributes will be output to ``-h`` target. + - Introduced ``intent(callback)`` to build interface between Python + functions and Fortran external routines. + - Avoid including external arguments to __user__ modules. + - Initial hooks to evaluate ``kind`` and ``selected_int_kind``. + - Evaluating parameters in {char,kind}selectors and applying rmbadname. + - Evaluating parameters using also module parameters. Fixed the order + of parameter evaluation. + - Fixed silly bug: when block name was not lower cased, it was not + recognized correctly. + - Applying mapping '.false.'->'False', '.true.'->'True' to logical + parameters. TODO: Support for logical expressions is needed. + - Added support for multiple statements in one line (separated with semicolon). + - Impl. get_useparameters function for using parameter values from + other f90 modules. + - Applied Bertholds patch to fix bug in evaluating expressions + like ``1.d0/dvar``. + - Fixed bug in reading string parameters. + - Evaluating parameters in charselector. Code cleanup. + - Using F90 module parameters to resolve kindselectors. + - Made the evaluation of module data init-expression more robust. + - Support for ``entry`` statement. + - Fixed ``determineexprtype`` that in the case of parameters + returned non-dictionary objects. + - Use ``-*- fix -*-`` to specify that a file is in fixed format. + +Release 2.39.235_1693 +===================== + +* fortranobject.{h,c} + + - Support for allocatable string arrays. + +* cfuncs.py + + - Call-back arguments can now be also instances that have ``__call__`` method + as well as instance methods. + +* f2py2e.py + + - Introduced ``--include_paths <path1>:<path2>:..`` command line + option. + - Added ``--compiler=`` support to change the C/C++ compiler from + f2py command line. + +* capi_maps.py + + - Handle ``XDY`` parameter constants. + +* crackfortran.py + + - Handle ``XDY`` parameter constants. + + - Introduced formatpattern to workaround a corner case where reserved + keywords are used in format statement. Other than that, format pattern + has no use. + + - Parameters are now fully evaluated. + +* More splitting of documentation strings. + +* func2subr.py - fixed bug for function names that f77 compiler + would set ``integer`` type. + +Release 2.39.235_1660 +===================== + +* f2py2e.py + + - Fixed bug in using --f90flags=.. + +* f90mod_rules.py + + - Splitted generated documentation strings (to avoid MSVC issue when + string length>2k) + + - Ignore ``private`` module data. + +Release 2.39.235_1644 +===================== + +:Date:24 February 2004 + +* Character arrays: + + - Finished complete support for character arrays and arrays of strings. + - ``character*n a(m)`` is treated like ``character a(m,n)`` with ``intent(c)``. + - Character arrays are now considered as ordinary arrays (not as arrays + of strings which actually didn't work). + +* docs + + - Initial f2py manpage file f2py.1. + - Updated usersguide and other docs when using numpy_distutils 0.2.2 + and up. + +* capi_maps.py + + - Try harder to use .f2py_f2cmap mappings when kind is used. + +* crackfortran.py + + - Included files are first search in the current directory and + then from the source file directory. + - Ignoring dimension and character selector changes. + - Fixed bug in Fortran 90 comments of fixed format. + - Warn when .pyf signatures contain undefined symbols. + - Better detection of source code formats. Using ``-*- fortran -*-`` + or ``-*- f90 -*-`` in the first line of a Fortran source file is + recommended to help f2py detect the format, fixed or free, + respectively, correctly. + +* cfuncs.py + + - Fixed intent(inout) scalars when typecode=='l'. + - Fixed intent(inout) scalars when not using numarray. + - Fixed intent(inout) scalars when using numarray. + +* diagnose.py + + - Updated for numpy_distutils 0.2.2 and up. + - Added numarray support to diagnose. + +* fortranobject.c + + - Fixed nasty bug with intent(in,copy) complex slice arrays. + - Applied Todd's patch to support numarray's byteswapped or + misaligned arrays, requires numarray-0.8 or higher. + +* f2py2e.py + + - Applying new hooks for numpy_distutils 0.2.2 and up, keeping + backward compatibility with depreciation messages. + - Using always os.system on non-posix platforms in f2py2e.compile + function. + +* rules.py + + - Changed the order of buildcallback and usercode junks. + +* setup.cfg + + - Added so that docs/ and tests/ directories are included to RPMs. + +* setup.py + + - Installing f2py.py instead of f2py.bat under NT. + - Introduced ``--with-numpy_distutils`` that is useful when making + f2py tar-ball with numpy_distutils included. + +Release 2.37.233-1545 +===================== + +:Date: 11 September 2003 + +* rules.py + + - Introduced ``interface_usercode`` replacement. When ``usercode`` + statement is used inside the first interface block, its contents + will be inserted at the end of initialization function of a F2PY + generated extension module (feature request: Berthold Höllmann). + - Introduced auxiliary function ``as_column_major_storage`` that + converts input array to an array with column major storage order + (feature request: Hans Petter Langtangen). + +* crackfortran.py + + - Introduced ``pymethoddef`` statement. + +* cfuncs.py + + - Fixed "#ifdef in #define TRYPYARRAYTEMPLATE" bug (patch thanks + to Bernhard Gschaider) + +* auxfuncs.py + + - Introduced ``getpymethod`` function. + - Enabled multi-line blocks in ``callprotoargument`` statement. + +* f90mod_rules.py + + - Undone "Fixed Warning 43 emitted by Intel Fortran compiler" that + causes (curios) segfaults. + +* fortranobject.c + + - Fixed segfaults (that were introduced with recent memory leak + fixes) when using allocatable arrays. + - Introduced F2PY_REPORT_ON_ARRAY_COPY CPP macro int-variable. If defined + then a message is printed to stderr whenever a copy of an array is + made and arrays size is larger than F2PY_REPORT_ON_ARRAY_COPY. + +Release 2.35.229-1505 +===================== + +:Date: 5 August 2003 + +* General + + - Introduced ``usercode`` statement (dropped ``c_code`` hooks). + +* setup.py + + - Updated the CVS location of numpy_distutils. + +* auxfuncs.py + + - Introduced ``isint1array(var)`` for fixing ``integer*1 intent(out)`` + support. + +* tests/f77/callback.py + + Introduced some basic tests. + +* src/fortranobject.{c,h} + + - Fixed memory leaks when getting/setting allocatable arrays. + (Bug report by Bernhard Gschaider) + + - Initial support for numarray (Todd Miller's patch). Use -DNUMARRAY + on the f2py command line to enable numarray support. Note that + there is no character arrays support and these hooks are not + tested with F90 compilers yet. + +* cfuncs.py + + - Fixed reference counting bug that appeared when constructing extra + argument list to callback functions. + - Added ``NPY_LONG != NPY_INT`` test. + +* f2py2e.py + + Undocumented ``--f90compiler``. + +* crackfortran.py + + - Introduced ``usercode`` statement. + - Fixed newlines when outputting multi-line blocks. + - Optimized ``getlincoef`` loop and ``analyzevars`` for cases where + len(vars) is large. + - Fixed callback string argument detection. + - Fixed evaluating expressions: only int|float expressions are + evaluated succesfully. + +* docs + + Documented -DF2PY_REPORT_ATEXIT feature. + +* diagnose.py + + Added CPU information and sys.prefix printout. + +* tests/run_all.py + + Added cwd to PYTHONPATH. + +* tests/f??/return_{real,complex}.py + + Pass "infinity" check in SunOS. + +* rules.py + + - Fixed ``integer*1 intent(out)`` support + - Fixed free format continuation of f2py generated F90 files. + +* tests/mixed/ + + Introduced tests for mixing Fortran 77, Fortran 90 fixed and free + format codes in one module. + +* f90mod_rules.py + + - Fixed non-prototype warnings. + - Fixed Warning 43 emitted by Intel Fortran compiler. + - Avoid long lines in Fortran codes to reduce possible problems with + continuations of lines. + +Public Release 2.32.225-1419 +============================ + +:Date: 8 December 2002 + +* docs/usersguide/ + + Complete revision of F2PY Users Guide + +* tests/run_all.py + + - New file. A Python script to run all f2py unit tests. + +* Removed files: buildmakefile.py, buildsetup.py. + +* tests/f77/ + + - Added intent(out) scalar tests. + +* f2py_testing.py + + - Introduced. It contains jiffies, memusage, run, cmdline functions + useful for f2py unit tests site. + +* setup.py + + - Install numpy_distutils only if it is missing or is too old + for f2py. + +* f90modrules.py + + - Fixed wrapping f90 module data. + - Fixed wrapping f90 module subroutines. + - Fixed f90 compiler warnings for wrapped functions by using interface + instead of external stmt for functions. + +* tests/f90/ + + - Introduced return_*.py tests. + +* func2subr.py + + - Added optional signature argument to createfuncwrapper. + - In f2pywrappers routines, declare external, scalar, remaining + arguments in that order. Fixes compiler error 'Invalid declaration' + for:: + + real function foo(a,b) + integer b + real a(b) + end + +* crackfortran.py + + - Removed first-line comment information support. + - Introduced multiline block. Currently usable only for + ``callstatement`` statement. + - Improved array length calculation in getarrlen(..). + - "From sky" program group is created only if ``groupcounter<1``. + See TODO.txt. + - Added support for ``dimension(n:*)``, ``dimension(*:n)``. They are + treated as ``dimesnion(*)`` by f2py. + - Fixed parameter substitution (this fixes TODO item by Patrick + LeGresley, 22 Aug 2001). + +* f2py2e.py + + - Disabled all makefile, setup, manifest file generation hooks. + - Disabled --[no]-external-modroutines option. All F90 module + subroutines will have Fortran/C interface hooks. + - --build-dir can be used with -c option. + - only/skip modes can be used with -c option. + - Fixed and documented `-h stdout` feature. + - Documented extra options. + - Introduced --quiet and --verbose flags. + +* cb_rules.py + + - Fixed debugcapi hooks for intent(c) scalar call-back arguments + (bug report: Pierre Schnizer). + - Fixed intent(c) for scalar call-back arguments. + - Improved failure reports. + +* capi_maps.py + + - Fixed complex(kind=..) to C type mapping bug. The following hold + complex==complex(kind=4)==complex*8, complex(kind=8)==complex*16 + - Using signed_char for integer*1 (bug report: Steve M. Robbins). + - Fixed logical*8 function bug: changed its C correspondence to + long_long. + - Fixed memory leak when returning complex scalar. + +* __init__.py + + - Introduced a new function (for f2py test site, but could be useful + in general) ``compile(source[,modulename,extra_args])`` for + compiling fortran source codes directly from Python. + +* src/fortranobject.c + + - Multi-dimensional common block members and allocatable arrays + are returned as Fortran-contiguous arrays. + - Fixed NULL return to Python without exception. + - Fixed memory leak in getattr(<fortranobj>,'__doc__'). + - <fortranobj>.__doc__ is saved to <fortranobj>.__dict__ (previously + it was generated each time when requested). + - Fixed a nasty typo from the previous item that caused data + corruption and occasional SEGFAULTs. + - array_from_pyobj accepts arbitrary rank arrays if the last dimension + is undefined. E.g. dimension(3,*) accepts a(3,4,5) and the result is + array with dimension(3,20). + - Fixed (void*) casts to make g++ happy (bug report: eric). + - Changed the interface of ARR_IS_NULL macro to avoid "``NULL used in + arithmetics``" warnings from g++. + +* src/fortranobject.h + + - Undone previous item. Defining NO_IMPORT_ARRAY for + src/fortranobject.c (bug report: travis) + - Ensured that PY_ARRAY_UNIQUE_SYMBOL is defined only for + src/fortranobject.c (bug report: eric). + +* rules.py + + - Introduced dummy routine feature. + - F77 and F90 wrapper subroutines (if any) as saved to different + files, <modulename>-f2pywrappers.f and <modulename>-f2pywrappers2.f90, + respectively. Therefore, wrapping F90 requires numpy_distutils >= + 0.2.0_alpha_2.229. + - Fixed compiler warnings about meaningless ``const void (*f2py_func)(..)``. + - Improved error messages for ``*_from_pyobj``. + - Changed __CPLUSPLUS__ macros to __cplusplus (bug report: eric). + - Changed (void*) casts to (f2py_init_func) (bug report: eric). + - Removed unnecessary (void*) cast for f2py_has_column_major_storage + in f2py_module_methods definition (bug report: eric). + - Changed the interface of f2py_has_column_major_storage function: + removed const from the 1st argument. + +* cfuncs.py + + - Introduced -DPREPEND_FORTRAN. + - Fixed bus error on SGI by using PyFloat_AsDouble when ``__sgi`` is defined. + This seems to be `know bug`__ with Python 2.1 and SGI. + - string_from_pyobj accepts only arrays whos elements size==sizeof(char). + - logical scalars (intent(in),function) are normalized to 0 or 1. + - Removed NUMFROMARROBJ macro. + - (char|short)_from_pyobj now use int_from_pyobj. + - (float|long_double)_from_pyobj now use double_from_pyobj. + - complex_(float|long_double)_from_pyobj now use complex_double_from_pyobj. + - Rewrote ``*_from_pyobj`` to be more robust. This fixes segfaults if + getting * from a string. Note that int_from_pyobj differs + from PyNumber_Int in that it accepts also complex arguments + (takes the real part) and sequences (takes the 1st element). + - Removed unnecessary void* casts in NUMFROMARROBJ. + - Fixed casts in ``*_from_pyobj`` functions. + - Replaced CNUMFROMARROBJ with NUMFROMARROBJ. + +.. __: http://sourceforge.net/tracker/index.php?func=detail&aid=435026&group_id=5470&atid=105470 + +* auxfuncs.py + + - Introduced isdummyroutine(). + - Fixed islong_* functions. + - Fixed isintent_in for intent(c) arguments (bug report: Pierre Schnizer). + - Introduced F2PYError and throw_error. Using throw_error, f2py + rejects illegal .pyf file constructs that otherwise would cause + compilation failures or python crashes. + - Fixed islong_long(logical*8)->True. + - Introduced islogical() and islogicalfunction(). + - Fixed prototype string argument (bug report: eric). + +* Updated README.txt and doc strings. Starting to use docutils. + +* Speed up for ``*_from_pyobj`` functions if obj is a sequence. + +* Fixed SegFault (reported by M.Braun) due to invalid ``Py_DECREF`` + in ``GETSCALARFROMPYTUPLE``. + +Older Releases +============== + +:: + + *** Fixed missing includes when wrapping F90 module data. + *** Fixed typos in docs of build_flib options. + *** Implemented prototype calculator if no callstatement or + callprotoargument statements are used. A warning is issued if + callstatement is used without callprotoargument. + *** Fixed transposing issue with array arguments in callback functions. + *** Removed -pyinc command line option. + *** Complete tests for Fortran 77 functions returning scalars. + *** Fixed returning character bug if --no-wrap-functions. + *** Described how to wrap F compiled Fortran F90 module procedures + with F2PY. See doc/using_F_compiler.txt. + *** Fixed the order of build_flib options when using --fcompiler=... + *** Recognize .f95 and .F95 files as Fortran sources with free format. + *** Cleaned up the output of 'f2py -h': removed obsolete items, + added build_flib options section. + *** Added --help-compiler option: it lists available Fortran compilers + as detected by numpy_distutils/command/build_flib.py. This option + is available only with -c option. + + +:Release: 2.13.175-1250 +:Date: 4 April 2002 + +:: + + *** Fixed copying of non-contigious 1-dimensional arrays bug. + (Thanks to Travis O.). + + +:Release: 2.13.175-1242 +:Date: 26 March 2002 + +:: + + *** Fixed ignoring type declarations. + *** Turned F2PY_REPORT_ATEXIT off by default. + *** Made MAX,MIN macros available by default so that they can be + always used in signature files. + *** Disabled F2PY_REPORT_ATEXIT for FreeBSD. + + +:Release: 2.13.175-1233 +:Date: 13 March 2002 + +:: + + *** Fixed Win32 port when using f2py.bat. (Thanks to Erik Wilsher). + *** F2PY_REPORT_ATEXIT is disabled for MACs. + *** Fixed incomplete dependency calculator. + + +:Release: 2.13.175-1222 +:Date: 3 March 2002 + +:: + + *** Plugged a memory leak for intent(out) arrays with overwrite=0. + *** Introduced CDOUBLE_to_CDOUBLE,.. functions for copy_ND_array. + These cast functions probably work incorrectly in Numeric. + + +:Release: 2.13.175-1212 +:Date: 23 February 2002 + +:: + + *** Updated f2py for the latest numpy_distutils. + *** A nasty bug with multi-dimensional Fortran arrays is fixed + (intent(out) arrays had wrong shapes). (Thanks to Eric for + pointing out this bug). + *** F2PY_REPORT_ATEXIT is disabled by default for __WIN32__. + + +:Release: 2.11.174-1161 +:Date: 14 February 2002 + +:: + + *** Updated f2py for the latest numpy_distutils. + *** Fixed raise error when f2py missed -m flag. + *** Script name `f2py' now depends on the name of python executable. + For example, `python2.2 setup.py install' will create a f2py + script with a name `f2py2.2'. + *** Introduced 'callprotoargument' statement so that proper prototypes + can be declared. This is crucial when wrapping C functions as it + will fix segmentation faults when these wrappers use non-pointer + arguments (thanks to R. Clint Whaley for explaining this to me). + Note that in f2py generated wrapper, the prototypes have + the following forms: + extern #rtype# #fortranname#(#callprotoargument#); + or + extern #rtype# F_FUNC(#fortranname#,#FORTRANNAME#)(#callprotoargument#); + *** Cosmetic fixes to F2PY_REPORT_ATEXIT feature. + + +:Release: 2.11.174-1146 +:Date: 3 February 2002 + +:: + + *** Reviewed reference counting in call-back mechanism. Fixed few bugs. + *** Enabled callstatement for complex functions. + *** Fixed bug with initializing capi_overwrite_<varname> + *** Introduced intent(overwrite) that is similar to intent(copy) but + has opposite effect. Renamed copy_<name>=1 to overwrite_<name>=0. + intent(overwrite) will make default overwrite_<name>=1. + *** Introduced intent(in|inout,out,out=<name>) attribute that renames + arguments name when returned. This renaming has effect only in + documentation strings. + *** Introduced 'callstatement' statement to pyf file syntax. With this + one can specify explicitly how wrapped function should be called + from the f2py generated module. WARNING: this is a dangerous feature + and should be used with care. It is introduced to provide a hack + to construct wrappers that may have very different signature + pattern from the wrapped function. Currently 'callstatement' can + be used only inside a subroutine or function block (it should be enough + though) and must be only in one continuous line. The syntax of the + statement is: callstatement <C-expression>; + + +:Release: 2.11.174 +:Date: 18 January 2002 + +:: + + *** Fixed memory-leak for PyFortranObject. + *** Introduced extra keyword argument copy_<varname> for intent(copy) + variables. It defaults to 1 and forces to make a copy for + intent(in) variables when passing on to wrapped functions (in case + they undesirably change the variable in-situ). + *** Introduced has_column_major_storage member function for all f2py + generated extension modules. It is equivalent to Python call + 'transpose(obj).iscontiguous()' but very efficient. + *** Introduced -DF2PY_REPORT_ATEXIT. If this is used when compiling, + a report is printed to stderr as python exits. The report includes + the following timings: + 1) time spent in all wrapped function calls; + 2) time spent in f2py generated interface around the wrapped + functions. This gives a hint whether one should worry + about storing data in proper order (C or Fortran). + 3) time spent in Python functions called by wrapped functions + through call-back interface. + 4) time spent in f2py generated call-back interface. + For now, -DF2PY_REPORT_ATEXIT is enabled by default. Use + -DF2PY_REPORT_ATEXIT_DISABLE to disable it (I am not sure if + Windows has needed tools, let me know). + Also, I appreciate if you could send me the output of 'F2PY + performance report' (with CPU and platform information) so that I + could optimize f2py generated interfaces for future releases. + *** Extension modules can be linked with dmalloc library. Use + -DDMALLOC when compiling. + *** Moved array_from_pyobj to fortranobject.c. + *** Usage of intent(inout) arguments is made more strict -- only + with proper type contiguous arrays are accepted. In general, + you should avoid using intent(inout) attribute as it makes + wrappers of C and Fortran functions asymmetric. I recommend using + intent(in,out) instead. + *** intent(..) has new keywords: copy,cache. + intent(copy,in) - forces a copy of an input argument; this + may be useful for cases where the wrapped function changes + the argument in situ and this may not be desired side effect. + Otherwise, it is safe to not use intent(copy) for the sake + of a better performance. + intent(cache,hide|optional) - just creates a junk of memory. + It does not care about proper storage order. Can be also + intent(in) but then the corresponding argument must be a + contiguous array with a proper elsize. + *** intent(c) can be used also for subroutine names so that + -DNO_APPEND_FORTRAN can be avoided for C functions. + + *** IMPORTANT BREAKING GOOD ... NEWS!!!: + + From now on you don't have to worry about the proper storage order + in multi-dimensional arrays that was earlier a real headache when + wrapping Fortran functions. Now f2py generated modules take care + of the proper conversations when needed. I have carefully designed + and optimized this interface to avoid any unnecessary memory usage + or copying of data. However, it is wise to use input arrays that + has proper storage order: for C arguments it is row-major and for + Fortran arguments it is column-major. But you don't need to worry + about that when developing your programs. The optimization of + initializing the program with proper data for possibly better + memory usage can be safely postponed until the program is working. + + This change also affects the signatures in .pyf files. If you have + created wrappers that take multi-dimensional arrays in arguments, + it is better to let f2py re-generate these files. Or you have to + manually do the following changes: reverse the axes indices in all + 'shape' macros. For example, if you have defined an array A(n,m) + and n=shape(A,1), m=shape(A,0) then you must change the last + statements to n=shape(A,0), m=shape(A,1). + + +:Release: 2.8.172 +:Date: 13 January 2002 + +:: + + *** Fixed -c process. Removed pyf_extensions function and pyf_file class. + *** Reorganized setup.py. It generates f2py or f2py.bat scripts + depending on the OS and the location of the python executable. + *** Started to use update_version from numpy_distutils that makes + f2py startup faster. As a side effect, the version number system + changed. + *** Introduced test-site/test_f2py2e.py script that runs all + tests. + *** Fixed global variables initialization problem in crackfortran + when run_main is called several times. + *** Added 'import Numeric' to C/API init<module> function. + *** Fixed f2py.bat in setup.py. + *** Switched over to numpy_distutils and dropped fortran_support. + *** On Windows create f2py.bat file. + *** Introduced -c option: read fortran or pyf files, construct extension + modules, build, and save them to current directory. + In one word: do-it-all-in-one-call. + *** Introduced pyf_extensions(sources,f2py_opts) function. It simplifies + the extension building process considerably. Only for internal use. + *** Converted tests to use numpy_distutils in order to improve portability: + a,b,c + *** f2py2e.run_main() returns a pyf_file class instance containing + information about f2py generated files. + *** Introduced `--build-dir <dirname>' command line option. + *** Fixed setup.py for bdist_rpm command. + *** Added --numpy-setup command line option. + *** Fixed crackfortran that did not recognized capitalized type + specification with --no-lower flag. + *** `-h stdout' writes signature to stdout. + *** Fixed incorrect message for check() with empty name list. + + +:Release: 2.4.366 +:Date: 17 December 2001 + +:: + + *** Added command line option --[no-]manifest. + *** `make test' should run on Windows, but the results are not truthful. + *** Reorganized f2py2e.py a bit. Introduced run_main(comline_list) function + that can be useful when running f2py from another Python module. + *** Removed command line options -f77,-fix,-f90 as the file format + is determined from the extension of the fortran file + or from its header (first line starting with `!%' and containing keywords + free, fix, or f77). The later overrides the former one. + *** Introduced command line options --[no-]makefile,--[no-]latex-doc. + Users must explicitly use --makefile,--latex-doc if Makefile-<modulename>, + <modulename>module.tex is desired. --setup is default. Use --no-setup + to disable setup_<modulename>.py generation. --overwrite-makefile + will set --makefile. + *** Added `f2py_rout_' to #capiname# in rules.py. + *** intent(...) statement with empty namelist forces intent(...) attribute for + all arguments. + *** Dropped DL_IMPORT and DL_EXPORT in fortranobject.h. + *** Added missing PyFortran_Type.ob_type initialization. + *** Added gcc-3.0 support. + *** Raising non-existing/broken Numeric as a FatalError exception. + *** Fixed Python 2.x specific += construct in fortran_support.py. + *** Fixed copy_ND_array for 1-rank arrays that used to call calloc(0,..) + and caused core dump with a non-gcc compiler (Thanks to Pierre Schnizer + for reporting this bug). + *** Fixed "warning: variable `..' might be clobbered by `longjmp' or `vfork'": + - Reorganized the structure of wrapper functions to get rid of + `goto capi_fail' statements that caused the above warning. + + +:Release: 2.3.343 +:Date: 12 December 2001 + +:: + + *** Issues with the Win32 support (thanks to Eric Jones and Tiffany Kamm): + - Using DL_EXPORT macro for init#modulename#. + - Changed PyObject_HEAD_INIT(&PyType_Type) to PyObject_HEAD_INIT(0). + - Initializing #name#_capi=NULL instead of Py_None in cb hooks. + *** Fixed some 'warning: function declaration isn't a prototype', mainly + in fortranobject.{c,h}. + *** Fixed 'warning: missing braces around initializer'. + *** Fixed reading a line containing only a label. + *** Fixed nonportable 'cp -fv' to shutil.copy in f2py2e.py. + *** Replaced PyEval_CallObject with PyObject_CallObject in cb_rules. + *** Replaced Py_DECREF with Py_XDECREF when freeing hidden arguments. + (Reason: Py_DECREF caused segfault when an error was raised) + *** Impl. support for `include "file"' (in addition to `include 'file'') + *** Fixed bugs (buildsetup.py missing in Makefile, in generated MANIFEST.in) + + +:Release: 2.3.327 +:Date: 4 December 2001 + +:: + + *** Sending out the third public release of f2py. + *** Support for Intel(R) Fortran Compiler (thanks to Patrick LeGresley). + *** Introduced `threadsafe' statement to pyf-files (or to be used with + the 'f2py' directive in fortran codes) to force + Py_BEGIN|END_ALLOW_THREADS block around the Fortran subroutine + calling statement in Python C/API. `threadsafe' statement has + an effect only inside a subroutine block. + *** Introduced `fortranname <name>' statement to be used only within + pyf-files. This is useful when the wrapper (Python C/API) function + has different name from the wrapped (Fortran) function. + *** Introduced `intent(c)' directive and statement. It is useful when + wrapping C functions. Use intent(c) for arguments that are + scalars (not pointers) or arrays (with row-ordering of elements). + + +:Release: 2.3.321 +:Date: 3 December 2001 + +:: + + *** f2py2e can be installed using distutils (run `python setup.py install'). + *** f2py builds setup_<modulename>.py. Use --[no-]setup to control this + feature. setup_<modulename>.py uses fortran_support module (from SciPy), + but for your convenience it is included also with f2py as an additional + package. Note that it has not as many compilers supported as with + using Makefile-<modulename>, but new compilers should be added to + fortran_support module, not to f2py2e package. + *** Fixed some compiler warnings about else statements. diff --git a/doc/f2py/Makefile b/doc/f2py/Makefile new file mode 100644 index 000000000..2f241da0a --- /dev/null +++ b/doc/f2py/Makefile @@ -0,0 +1,76 @@ +# Makefile for compiling f2py2e documentation (dvi, ps, html) +# Pearu Peterson <pearu@ioc.ee> + +REL=4 +TOP = usersguide +LATEXSRC = bugs.tex commands.tex f2py2e.tex intro.tex notes.tex signaturefile.tex +MAINLATEX = f2py2e + +LATEX = latex +PDFLATEX = pdflatex + +COLLECTINPUT = ./collectinput.py +INSTALLDATA = install -m 644 -c + +TTH = tth +TTHFILTER = sed -e "s/{{}\\\verb@/\\\texttt{/g" | sed -e "s/@{}}/}/g" | $(TTH) -L$(MAINLATEX) -i +TTHFILTER2 = sed -e "s/{{}\\\verb@/\\\texttt{/g" | sed -e "s/@{}}/}/g" | $(TTH) -Lpython9 -i +TTHFILTER3 = sed -e "s/{{}\\\verb@/\\\texttt{/g" | sed -e "s/@{}}/}/g" | $(TTH) -Lfortranobject -i +TTHMISSING = "\ +***************************************************************\n\ +Warning: Could not find tth (a TeX to HTML translator) \n\ + or an error arised was by tth\n\ +You can download tth from http://hutchinson.belmont.ma.us/tth/ \n\ +or\n\ +use your favorite LaTeX to HTML translator on file tmp_main.tex\n\ +***************************************************************\ +" + +all: dvi ps html clean +$(MAINLATEX).dvi: $(LATEXSRC) + $(LATEX) $(MAINLATEX).tex + $(LATEX) $(MAINLATEX).tex + $(LATEX) $(MAINLATEX).tex + $(PDFLATEX) $(MAINLATEX).tex +$(TOP).dvi: $(MAINLATEX).dvi + cp -f $(MAINLATEX).dvi $(TOP).dvi + mv -f $(MAINLATEX).pdf $(TOP).pdf +$(TOP).ps: $(TOP).dvi + dvips $(TOP).dvi -o +$(TOP).html: $(LATEXSRC) + $(COLLECTINPUT) < $(MAINLATEX).tex > tmp_$(MAINLATEX).tex + @test `which $(TTH)` && cat tmp_$(MAINLATEX).tex | $(TTHFILTER) > $(TOP).html\ + || echo -e $(TTHMISSING) +dvi: $(TOP).dvi +ps: $(TOP).ps + gzip -f $(TOP).ps +html: $(TOP).html + +python9: + cp -f python9.tex f2python9-final/src/ + cd f2python9-final && mk_html.sh + cd f2python9-final && mk_ps.sh + cd f2python9-final && mk_pdf.sh +pyfobj: + $(LATEX) fortranobject.tex + $(LATEX) fortranobject.tex + $(LATEX) fortranobject.tex + @test `which $(TTH)` && cat fortranobject.tex | $(TTHFILTER3) > pyfobj.html\ + || echo -e $(TTHMISSING) + dvips fortranobject.dvi -o pyfobj.ps + gzip -f pyfobj.ps + pdflatex fortranobject.tex + mv fortranobject.pdf pyfobj.pdf + +WWWDIR=/net/cens/home/www/unsecure/projects/f2py2e/ +wwwpage: all + $(INSTALLDATA) index.html $(TOP).html $(TOP).ps.gz $(TOP).dvi $(TOP).pdf \ + Release-$(REL).x.txt ../NEWS.txt win32_notes.txt $(WWWDIR) + $(INSTALLDATA) pyfobj.{ps.gz,pdf,html} $(WWWDIR) + $(INSTALLDATA) f2python9-final/f2python9.{ps.gz,pdf,html} f2python9-final/{flow,structure,aerostructure}.jpg $(WWWDIR) +clean: + rm -f tmp_$(MAINLATEX).* $(MAINLATEX).{aux,dvi,log,toc} +distclean: + rm -f tmp_$(MAINLATEX).* $(MAINLATEX).{aux,dvi,log,toc} + rm -f $(TOP).{ps,dvi,html,pdf,ps.gz} + rm -f *~ diff --git a/doc/f2py/OLDNEWS.txt b/doc/f2py/OLDNEWS.txt new file mode 100644 index 000000000..7b094951c --- /dev/null +++ b/doc/f2py/OLDNEWS.txt @@ -0,0 +1,93 @@ + +.. topic:: Old F2PY NEWS + + January 30, 2005 + + Latest F2PY release (version 2.45.241_1926). + New features: wrapping unsigned integers, support for ``.pyf.src`` template files, + callback arguments can now be CObjects, fortran objects, built-in functions. + Introduced ``intent(aux)`` attribute. Wrapped objects have ``_cpointer`` + attribute holding C pointer to wrapped functions or variables. + Many bug fixes and improvements, updated documentation. + `Differences with the previous release (version 2.43.239_1831)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.163&r2=1.137&f=h + + October 4, 2004 + F2PY bug fix release (version 2.43.239_1831). + Better support for 64-bit platforms. + Introduced ``--help-link`` and ``--link-<resource>`` options. + Bug fixes. + `Differences with the previous release (version 2.43.239_1806)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.137&r2=1.131&f=h + + September 25, 2004 + Latest F2PY release (version 2.43.239_1806). + Support for ``ENTRY`` statement. New attributes: + ``intent(inplace)``, ``intent(callback)``. Supports Numarray 1.1. + Introduced ``-*- fix -*-`` header content. Improved ``PARAMETER`` support. + Documentation updates. `Differences with the previous release + (version 2.39.235-1693)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.131&r2=1.98&f=h + + March 30, 2004 + F2PY bug fix release (version 2.39.235-1693). Two new command line switches: + ``--compiler`` and ``--include_paths``. Support for allocatable string arrays. + Callback arguments may now be arbitrary callable objects. Win32 installers + for F2PY and Scipy_core are provided. + `Differences with the previous release (version 2.37.235-1660)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.98&r2=1.87&f=h + + March 9, 2004 + F2PY bug fix release (version 2.39.235-1660). + `Differences with the previous release (version 2.37.235-1644)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.87&r2=1.83&f=h + + February 24, 2004 + Latest F2PY release (version 2.39.235-1644). + Support for numpy_distutils 0.2.2 and up (e.g. compiler flags can be + changed via f2py command line options). Implemented support for + character arrays and arrays of strings (e.g. ``character*(*) a(m,..)``). + *Important bug fixes regarding complex arguments, upgrading is + highly recommended*. Documentation updates. + `Differences with the previous release (version 2.37.233-1545)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.83&r2=1.58&f=h + + September 11, 2003 + Latest F2PY release (version 2.37.233-1545). + New statements: ``pymethoddef`` and ``usercode`` in interface blocks. + New function: ``as_column_major_storage``. + New CPP macro: ``F2PY_REPORT_ON_ARRAY_COPY``. + Bug fixes. + `Differences with the previous release (version 2.35.229-1505)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.58&r2=1.49&f=h + + August 2, 2003 + Latest F2PY release (version 2.35.229-1505). + `Differences with the previous release (version 2.32.225-1419)`__. + + __ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt.diff?r1=1.49&r2=1.28&f=h + + April 2, 2003 + Initial support for Numarray_ (thanks to Todd Miller). + + December 8, 2002 + Sixth public release of F2PY (version 2.32.225-1419). Comes with + revised `F2PY Users Guide`__, `new testing site`__, lots of fixes + and other improvements, see `HISTORY.txt`_ for details. + + __ usersguide/index.html + __ TESTING.txt_ + +.. References + ========== + +.. _HISTORY.txt: HISTORY.html +.. _Numarray: http://www.stsci.edu/resources/software_hardware/numarray +.. _TESTING.txt: TESTING.html diff --git a/doc/f2py/README.txt b/doc/f2py/README.txt new file mode 100644 index 000000000..971183bb0 --- /dev/null +++ b/doc/f2py/README.txt @@ -0,0 +1,415 @@ +.. -*- rest -*- + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + F2PY: Fortran to Python interface generator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:Author: Pearu Peterson <pearu@cens.ioc.ee> +:License: NumPy License +:Web-site: http://cens.ioc.ee/projects/f2py2e/ +:Discussions to: `f2py-users mailing list`_ +:Documentation: `User's Guide`__, FAQ__ +:Platforms: All +:Date: $Date: 2005/01/30 18:54:53 $ + +.. _f2py-users mailing list: http://cens.ioc.ee/mailman/listinfo/f2py-users/ +__ usersguide/index.html +__ FAQ.html + +.. Contents:: + +============== + Introduction +============== + +The purpose of the F2PY --*Fortran to Python interface generator*-- +project is to provide connection between Python_ and Fortran +languages. F2PY is a Python extension tool for creating Python C/API +modules from (handwritten or F2PY generated) signature files (or +directly from Fortran sources). The generated extension modules +facilitate: + +* Calling Fortran 77/90/95, Fortran 90/95 module, and C functions from + Python. + +* Accessing Fortran 77 ``COMMON`` blocks and Fortran 90/95 module + data (including allocatable arrays) from Python. + +* Calling Python functions from Fortran or C (call-backs). + +* Automatically handling the difference in the data storage order of + multi-dimensional Fortran and Numerical Python (i.e. C) arrays. + +In addition, F2PY can build the generated extension modules to shared +libraries with one command. F2PY uses the ``numpy_distutils`` module +from SciPy_ that supports number of major Fortran compilers. + +.. + (see `COMPILERS.txt`_ for more information). + +F2PY generated extension modules depend on NumPy_ package that +provides fast multi-dimensional array language facility to Python. + + +--------------- + Main features +--------------- + +Here follows a more detailed list of F2PY features: + +* F2PY scans real Fortran codes to produce the so-called signature + files (.pyf files). The signature files contain all the information + (function names, arguments and their types, etc.) that is needed to + construct Python bindings to Fortran (or C) functions. + + The syntax of signature files is borrowed from the + Fortran 90/95 language specification and has some F2PY specific + extensions. The signature files can be modified to dictate how + Fortran (or C) programs are called from Python: + + + F2PY solves dependencies between arguments (this is relevant for + the order of initializing variables in extension modules). + + + Arguments can be specified to be optional or hidden that + simplifies calling Fortran programs from Python considerably. + + + In principle, one can design any Python signature for a given + Fortran function, e.g. change the order arguments, introduce + auxiliary arguments, hide the arguments, process the arguments + before passing to Fortran, return arguments as output of F2PY + generated functions, etc. + +* F2PY automatically generates __doc__ strings (and optionally LaTeX + documentation) for extension modules. + +* F2PY generated functions accept arbitrary (but sensible) Python + objects as arguments. The F2PY interface automatically takes care of + type-casting and handling of non-contiguous arrays. + +* The following Fortran constructs are recognized by F2PY: + + + All basic Fortran types:: + + integer[ | *1 | *2 | *4 | *8 ], logical[ | *1 | *2 | *4 | *8 ] + integer*([ -1 | -2 | -4 | -8 ]) + character[ | *(*) | *1 | *2 | *3 | ... ] + real[ | *4 | *8 | *16 ], double precision + complex[ | *8 | *16 | *32 ] + + Negative ``integer`` kinds are used to wrap unsigned integers. + + + Multi-dimensional arrays of all basic types with the following + dimension specifications:: + + <dim> | <start>:<end> | * | : + + + Attributes and statements:: + + intent([ in | inout | out | hide | in,out | inout,out | c | + copy | cache | callback | inplace | aux ]) + dimension(<dimspec>) + common, parameter + allocatable + optional, required, external + depend([<names>]) + check([<C-booleanexpr>]) + note(<LaTeX text>) + usercode, callstatement, callprotoargument, threadsafe, fortranname + pymethoddef + entry + +* Because there are only little (and easily handleable) differences + between calling C and Fortran functions from F2PY generated + extension modules, then F2PY is also well suited for wrapping C + libraries to Python. + +* Practice has shown that F2PY generated interfaces (to C or Fortran + functions) are less error prone and even more efficient than + handwritten extension modules. The F2PY generated interfaces are + easy to maintain and any future optimization of F2PY generated + interfaces transparently apply to extension modules by just + regenerating them with the latest version of F2PY. + +* `F2PY Users Guide and Reference Manual`_ + + +=============== + Prerequisites +=============== + +F2PY requires the following software installed: + +* Python_ (versions 1.5.2 or later; 2.1 and up are recommended). + You must have python-dev package installed. +* NumPy_ (versions 13 or later; 20.x, 21.x, 22.x, 23.x are recommended) +* Numarray_ (version 0.9 and up), optional, partial support. +* Scipy_distutils (version 0.2.2 and up are recommended) from SciPy_ + project. Get it from Scipy CVS or download it below. + +Python 1.x users also need distutils_. + +Of course, to build extension modules, you'll need also working C +and/or Fortran compilers installed. + +========== + Download +========== + +You can download the sources for the latest F2PY and numpy_distutils +releases as: + +* `2.x`__/`F2PY-2-latest.tar.gz`__ +* `2.x`__/`numpy_distutils-latest.tar.gz`__ + +Windows users might be interested in Win32 installer for F2PY and +Scipy_distutils (these installers are built using Python 2.3): + +* `2.x`__/`F2PY-2-latest.win32.exe`__ +* `2.x`__/`numpy_distutils-latest.win32.exe`__ + +Older releases are also available in the directories +`rel-0.x`__, `rel-1.x`__, `rel-2.x`__, `rel-3.x`__, `rel-4.x`__, `rel-5.x`__, +if you need them. + +.. __: 2.x/ +.. __: 2.x/F2PY-2-latest.tar.gz +.. __: 2.x/ +.. __: 2.x/numpy_distutils-latest.tar.gz +.. __: 2.x/ +.. __: 2.x/F2PY-2-latest.win32.exe +.. __: 2.x/ +.. __: 2.x/numpy_distutils-latest.win32.exe +.. __: rel-0.x +.. __: rel-1.x +.. __: rel-2.x +.. __: rel-3.x +.. __: rel-4.x +.. __: rel-5.x + +Development version of F2PY from CVS is available as `f2py2e.tar.gz`__. + +__ http://cens.ioc.ee/cgi-bin/viewcvs.cgi/python/f2py2e/f2py2e.tar.gz?tarball=1 + +Debian Sid users can simply install ``python-f2py`` package. + +============== + Installation +============== + +Unpack the source file, change to directrory ``F2PY-?-???/`` and run +(you may need to become a root):: + + python setup.py install + +The F2PY installation installs a Python package ``f2py2e`` to your +Python ``site-packages`` directory and a script ``f2py`` to your +Python executable path. + +See also Installation__ section in `F2PY FAQ`_. + +.. __: FAQ.html#installation + +Similarly, to install ``numpy_distutils``, unpack its tar-ball and run:: + + python setup.py install + +======= + Usage +======= + +To check if F2PY is installed correctly, run +:: + + f2py + +without any arguments. This should print out the usage information of +the ``f2py`` program. + +Next, try out the following three steps: + +1) Create a Fortran file `hello.f`__ that contains:: + + C File hello.f + subroutine foo (a) + integer a + print*, "Hello from Fortran!" + print*, "a=",a + end + +__ hello.f + +2) Run + + :: + + f2py -c -m hello hello.f + + This will build an extension module ``hello.so`` (or ``hello.sl``, + or ``hello.pyd``, etc. depending on your platform) into the current + directory. + +3) Now in Python try:: + + >>> import hello + >>> print hello.__doc__ + >>> print hello.foo.__doc__ + >>> hello.foo(4) + Hello from Fortran! + a= 4 + >>> + +If the above works, then you can try out more thorough +`F2PY unit tests`__ and read the `F2PY Users Guide and Reference Manual`_. + +__ FAQ.html#q-how-to-test-if-f2py-is-working-correctly + +=============== + Documentation +=============== + +The documentation of the F2PY project is collected in ``f2py2e/docs/`` +directory. It contains the following documents: + +`README.txt`_ (on GitHub__) + The first thing to read about F2PY -- this document. + +__ https://github.com/numpy/numpy/blob/master/numpy/f2py/docs/README.txt + +`usersguide/index.txt`_, `usersguide/f2py_usersguide.pdf`_ + F2PY Users Guide and Reference Manual. Contains lots of examples. + +`FAQ.txt`_ (on GitHub__) + F2PY Frequently Asked Questions. + +__ https://github.com/numpy/numpy/blob/master/numpy/f2py/docs/FAQ.txt + +`TESTING.txt`_ (on GitHub__) + About F2PY testing site. What tests are available and how to run them. + +__ https://github.com/numpy/numpy/blob/master/numpy/f2py/docs/TESTING.txt + +`HISTORY.txt`_ (on GitHub__) + A list of latest changes in F2PY. This is the most up-to-date + document on F2PY. + +__ https://github.com/numpy/numpy/blob/master/numpy/f2py/docs/HISTORY.txt + +`THANKS.txt`_ + Acknowledgments. + +.. + `COMPILERS.txt`_ + Compiler and platform specific notes. + +=============== + Mailing list +=============== + +A mailing list f2py-users@cens.ioc.ee is open for F2PY releated +discussion/questions/etc. + +* `Subscribe..`__ +* `Archives..`__ + +__ http://cens.ioc.ee/mailman/listinfo/f2py-users +__ http://cens.ioc.ee/pipermail/f2py-users + + +===== + CVS +===== + +F2PY is being developed under CVS_. The CVS version of F2PY can be +obtained as follows: + +1) First you need to login (the password is ``guest``):: + + cvs -d :pserver:anonymous@cens.ioc.ee:/home/cvs login + +2) and then do the checkout:: + + cvs -z6 -d :pserver:anonymous@cens.ioc.ee:/home/cvs checkout f2py2e + +3) You can update your local F2PY tree ``f2py2e/`` by executing:: + + cvs -z6 update -P -d + +You can browse the `F2PY CVS`_ repository. + +=============== + Contributions +=============== + +* `A short introduction to F2PY`__ by Pierre Schnizer. + +* `F2PY notes`__ by Fernando Perez. + +* `Debian packages of F2PY`__ by José Fonseca. [OBSOLETE, Debian Sid + ships python-f2py package] + +__ http://fubphpc.tu-graz.ac.at/~pierre/f2py_tutorial.tar.gz +__ http://cens.ioc.ee/pipermail/f2py-users/2003-April/000472.html +__ http://jrfonseca.dyndns.org/debian/ + + +=============== + Related sites +=============== + +* `Numerical Python`_ -- adds a fast array facility to the Python language. +* Pyfort_ -- A Python-Fortran connection tool. +* SciPy_ -- An open source library of scientific tools for Python. +* `Scientific Python`_ -- A collection of Python modules that are + useful for scientific computing. +* `The Fortran Company`_ -- A place to find products, services, and general + information related to the Fortran programming language. +* `American National Standard Programming Language FORTRAN ANSI(R) X3.9-1978`__ +* `J3`_ -- The US Fortran standards committee. +* SWIG_ -- A software development tool that connects programs written + in C and C++ with a variety of high-level programming languages. +* `Mathtools.net`_ -- A technical computing portal for all scientific + and engineering needs. + +.. __: http://www.fortran.com/fortran/F77_std/rjcnf.html + +.. References + ========== + + +.. _F2PY Users Guide and Reference Manual: usersguide/index.html +.. _usersguide/index.txt: usersguide/index.html +.. _usersguide/f2py_usersguide.pdf: usersguide/f2py_usersguide.pdf +.. _README.txt: README.html +.. _COMPILERS.txt: COMPILERS.html +.. _F2PY FAQ: +.. _FAQ.txt: FAQ.html +.. _HISTORY.txt: HISTORY.html +.. _HISTORY.txt from CVS: http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt?rev=HEAD&content-type=text/x-cvsweb-markup +.. _THANKS.txt: THANKS.html +.. _TESTING.txt: TESTING.html +.. _F2PY CVS2: http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/ +.. _F2PY CVS: http://cens.ioc.ee/cgi-bin/viewcvs.cgi/python/f2py2e/ + +.. _CVS: http://www.cvshome.org/ +.. _Python: http://www.python.org/ +.. _SciPy: http://www.numpy.org/ +.. _NumPy: http://www.numpy.org/ +.. _Numarray: http://www.stsci.edu/resources/software_hardware/numarray +.. _docutils: http://docutils.sourceforge.net/ +.. _distutils: http://www.python.org/sigs/distutils-sig/ +.. _Numerical Python: http://www.numpy.org/ +.. _Pyfort: http://pyfortran.sourceforge.net/ +.. _Scientific Python: + http://starship.python.net/crew/hinsen/scientific.html +.. _The Fortran Company: http://www.fortran.com/fortran/ +.. _J3: http://www.j3-fortran.org/ +.. _Mathtools.net: http://www.mathtools.net/ +.. _SWIG: http://www.swig.org/ + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + End: diff --git a/doc/f2py/Release-1.x.txt b/doc/f2py/Release-1.x.txt new file mode 100644 index 000000000..46d6fbf09 --- /dev/null +++ b/doc/f2py/Release-1.x.txt @@ -0,0 +1,27 @@ + +I am pleased to announce the first public release of f2py 1.116: + +Writing Python C/API wrappers for Fortran routines can be a very +tedious task, especially if a Fortran routine takes more than 20 +arguments but only few of them are relevant for the problems that they +solve. + +The Fortran to Python Interface Generator, or FPIG for short, is a +command line tool (f2py) for generating Python C/API modules for +wrapping Fortran 77 routines, accessing common blocks from Python, and +calling Python functions from Fortran (call-backs). + +The tool can be downloaded from + + http://cens.ioc.ee/projects/f2py2e/ + +where you can find also information about f2py features and its User's +Guide. + +f2py is released under the LGPL license. + +With regards, + Pearu Peterson <pearu@ioc.ee> + +<P><A HREF="http://cens.ioc.ee/projects/f2py2e/">f2py 1.116</A> - The +Fortran to Python Interface Generator (25-Jan-00) diff --git a/doc/f2py/Release-2.x.txt b/doc/f2py/Release-2.x.txt new file mode 100644 index 000000000..2085cb1be --- /dev/null +++ b/doc/f2py/Release-2.x.txt @@ -0,0 +1,77 @@ + +FPIG - Fortran to Python Interface Generator + +I am pleased to announce the second public release of f2py +(version 2.264): + + http://cens.ioc.ee/projects/f2py2e/ + +f2py is a command line tool for binding Python and Fortran codes. It +scans Fortran 77/90/95 codes and generates a Python C/API module that +makes it possible to call Fortran routines from Python. No Fortran or +C expertise is required for using this tool. + +Features include: + + *** All basic Fortran types are supported: + integer[ | *1 | *2 | *4 | *8 ], logical[ | *1 | *2 | *4 | *8 ], + character[ | *(*) | *1 | *2 | *3 | ... ] + real[ | *4 | *8 | *16 ], double precision, + complex[ | *8 | *16 | *32 ] + + *** Multi-dimensional arrays of (almost) all basic types. + Dimension specifications: + <dim> | <start>:<end> | * | : + + *** Supported attributes: + intent([ in | inout | out | hide | in,out | inout,out ]) + dimension(<dimspec>) + depend([<names>]) + check([<C-booleanexpr>]) + note(<LaTeX text>) + optional, required, external + + *** Calling Fortran 77/90/95 subroutines and functions. Also + Fortran 90/95 module routines. Internal initialization of + optional arguments. + + *** Accessing COMMON blocks from Python. Accessing Fortran 90/95 + module data coming soon. + + *** Call-back functions: calling Python functions from Fortran with + very flexible hooks. + + *** In Python, arguments of the interfaced functions may be of + different type - necessary type conversations are done + internally in C level. + + *** Automatically generates documentation (__doc__,LaTeX) for + interface functions. + + *** Automatically generates signature files --- user has full + control over the interface constructions. Automatically + detects the signatures of call-back functions, solves argument + dependencies, etc. + + *** Automatically generates Makefile for compiling Fortran and C + codes and linking them to a shared module. Many compilers are + supported: gcc, Compaq Fortran, VAST/f90 Fortran, Absoft + F77/F90, MIPSpro 7 Compilers, etc. Platforms: Intel/Alpha + Linux, HP-UX, IRIX64. + + *** Complete User's Guide in various formats (html,ps,pdf,dvi). + + *** f2py users list is available for support, feedback, etc. + +More information about f2py, see + + http://cens.ioc.ee/projects/f2py2e/ + +f2py is released under the LGPL license. + +Sincerely, + Pearu Peterson <pearu@ioc.ee> + September 12, 2000 + +<P><A HREF="http://cens.ioc.ee/projects/f2py2e/">f2py 2.264</A> - The +Fortran to Python Interface Generator (12-Sep-00) diff --git a/doc/f2py/Release-3.x.txt b/doc/f2py/Release-3.x.txt new file mode 100644 index 000000000..ddb93b9fd --- /dev/null +++ b/doc/f2py/Release-3.x.txt @@ -0,0 +1,87 @@ + +F2PY - Fortran to Python Interface Generator + +I am pleased to announce the third public release of f2py +(version 2.3.321): + + http://cens.ioc.ee/projects/f2py2e/ + +f2py is a command line tool for binding Python and Fortran codes. It +scans Fortran 77/90/95 codes and generates a Python C/API module that +makes it possible to call Fortran subroutines from Python. No Fortran or +C expertise is required for using this tool. + +Features include: + + *** All basic Fortran types are supported: + integer[ | *1 | *2 | *4 | *8 ], logical[ | *1 | *2 | *4 | *8 ], + character[ | *(*) | *1 | *2 | *3 | ... ] + real[ | *4 | *8 | *16 ], double precision, + complex[ | *8 | *16 | *32 ] + + *** Multi-dimensional arrays of (almost) all basic types. + Dimension specifications: + <dim> | <start>:<end> | * | : + + *** Supported attributes and statements: + intent([ in | inout | out | hide | in,out | inout,out ]) + dimension(<dimspec>) + depend([<names>]) + check([<C-booleanexpr>]) + note(<LaTeX text>) + optional, required, external +NEW: intent(c), threadsafe, fortranname + + *** Calling Fortran 77/90/95 subroutines and functions. Also + Fortran 90/95 module subroutines are supported. Internal + initialization of optional arguments. + + *** Accessing COMMON blocks from Python. +NEW: Accessing Fortran 90/95 module data. + + *** Call-back functions: calling Python functions from Fortran with + very flexible hooks. + + *** In Python, arguments of the interfaced functions may be of + different type - necessary type conversations are done + internally in C level. + + *** Automatically generates documentation (__doc__,LaTeX) for + interfaced functions. + + *** Automatically generates signature files --- user has full + control over the interface constructions. Automatically + detects the signatures of call-back functions, solves argument + dependencies, etc. + +NEW: * Automatically generates setup_<modulename>.py for building + extension modules using tools from distutils and + fortran_support module (SciPy). + + *** Automatically generates Makefile for compiling Fortran and C + codes and linking them to a shared module. Many compilers are + supported: gcc, Compaq Fortran, VAST/f90 Fortran, Absoft + F77/F90, MIPSpro 7 Compilers, etc. Platforms: Intel/Alpha + Linux, HP-UX, IRIX64. + + *** Complete User's Guide in various formats (html,ps,pdf,dvi). + + *** f2py users list is available for support, feedback, etc. + +NEW: * Installation with distutils. + + *** And finally, many bugs are fixed. + +More information about f2py, see + + http://cens.ioc.ee/projects/f2py2e/ + +LICENSE: + f2py is released under the LGPL. + +Sincerely, + Pearu Peterson <pearu@cens.ioc.ee> + December 4, 2001 + +<P><A HREF="http://cens.ioc.ee/projects/f2py2e/">f2py 2.3.321</A> - The +Fortran to Python Interface Generator (04-Dec-01) diff --git a/doc/f2py/Release-4.x.txt b/doc/f2py/Release-4.x.txt new file mode 100644 index 000000000..d490dcb7a --- /dev/null +++ b/doc/f2py/Release-4.x.txt @@ -0,0 +1,91 @@ + +F2PY - Fortran to Python Interface Generator + +I am pleased to announce the fourth public release of f2py +(version 2.4.366): + + http://cens.ioc.ee/projects/f2py2e/ + +f2py is a command line tool for binding Python and Fortran codes. It +scans Fortran 77/90/95 codes and generates a Python C/API module that +makes it possible to call Fortran subroutines from Python. No Fortran or +C expertise is required for using this tool. + +New features: + *** Win32 support. + *** Better Python C/API generated code (-Wall is much less verbose). + +Features include: + + *** All basic Fortran types are supported: + integer[ | *1 | *2 | *4 | *8 ], logical[ | *1 | *2 | *4 | *8 ], + character[ | *(*) | *1 | *2 | *3 | ... ] + real[ | *4 | *8 | *16 ], double precision, + complex[ | *8 | *16 | *32 ] + + *** Multi-dimensional arrays of (almost) all basic types. + Dimension specifications: + <dim> | <start>:<end> | * | : + + *** Supported attributes and statements: + intent([ in | inout | out | hide | in,out | inout,out ]) + dimension(<dimspec>) + depend([<names>]) + check([<C-booleanexpr>]) + note(<LaTeX text>) + optional, required, external + intent(c), threadsafe, fortranname + + *** Calling Fortran 77/90/95 subroutines and functions. Also + Fortran 90/95 module subroutines are supported. Internal + initialization of optional arguments. + + *** Accessing COMMON blocks from Python. + Accessing Fortran 90/95 module data. + + *** Call-back functions: calling Python functions from Fortran with + very flexible hooks. + + *** In Python, arguments of the interfaced functions may be of + different type - necessary type conversations are done + internally in C level. + + *** Automatically generates documentation (__doc__,LaTeX) for + interfaced functions. + + *** Automatically generates signature files --- user has full + control over the interface constructions. Automatically + detects the signatures of call-back functions, solves argument + dependencies, etc. + + *** Automatically generates setup_<modulename>.py for building + extension modules using tools from distutils and + fortran_support module (SciPy). + + *** Automatically generates Makefile for compiling Fortran and C + codes and linking them to a shared module. Many compilers are + supported: gcc, Compaq Fortran, VAST/f90 Fortran, Absoft + F77/F90, MIPSpro 7 Compilers, etc. Platforms: Intel/Alpha + Linux, HP-UX, IRIX64. + + *** Complete User's Guide in various formats (html,ps,pdf,dvi). + + *** f2py users list is available for support, feedback, etc. + + *** Installation with distutils. + + *** And finally, many bugs are fixed. + +More information about f2py, see + + http://cens.ioc.ee/projects/f2py2e/ + +LICENSE: + f2py is released under the LGPL. + +Sincerely, + Pearu Peterson <pearu@cens.ioc.ee> + December 17, 2001 + +<P><A HREF="http://cens.ioc.ee/projects/f2py2e/">f2py 2.4.366</A> - The +Fortran to Python Interface Generator (17-Dec-01) diff --git a/doc/f2py/TESTING.txt b/doc/f2py/TESTING.txt new file mode 100644 index 000000000..a6df92c48 --- /dev/null +++ b/doc/f2py/TESTING.txt @@ -0,0 +1,108 @@ + +======================================================= + F2PY unit testing site +======================================================= + +.. Contents:: + +Tests +----- + +* To run all F2PY unit tests in one command:: + + cd tests + python run_all.py [<options>] + + For example:: + + localhost:~/src_cvs/f2py2e/tests$ python2.2 run_all.py 100 --quiet + ********************************************** + Running '/usr/bin/python2.2 f77/return_integer.py 100 --quiet' + run 1000 tests in 1.87 seconds + initial virtual memory size: 3952640 bytes + current virtual memory size: 3952640 bytes + ok + ********************************************** + Running '/usr/bin/python2.2 f77/return_logical.py 100 --quiet' + run 1000 tests in 1.47 seconds + initial virtual memory size: 3952640 bytes + current virtual memory size: 3952640 bytes + ok + ... + + If some tests fail, try to run the failing tests separately (without + the ``--quiet`` option) as described below to get more information + about the failure. + +* Test intent(in), intent(out) scalar arguments, + scalars returned by F77 functions + and F90 module functions:: + + tests/f77/return_integer.py + tests/f77/return_real.py + tests/f77/return_logical.py + tests/f77/return_complex.py + tests/f77/return_character.py + tests/f90/return_integer.py + tests/f90/return_real.py + tests/f90/return_logical.py + tests/f90/return_complex.py + tests/f90/return_character.py + + Change to tests/ directory and run:: + + python f77/return_<type>.py [<options>] + python f90/return_<type>.py [<options>] + + where ``<type>`` is integer, real, logical, complex, or character. + Test scripts options are described below. + + A test is considered succesful if the last printed line is "ok". + + If you get import errors like:: + + ImportError: No module named f77_ext_return_integer + + but ``f77_ext_return_integer.so`` exists in the current directory then + it means that the current directory is not included in to `sys.path` + in your Python installation. As a fix, prepend ``.`` to ``PYTHONPATH`` + environment variable and rerun the tests. For example:: + + PYTHONPATH=. python f77/return_integer.py + +* Test mixing Fortran 77, Fortran 90 fixed and free format codes:: + + tests/mixed/run.py + +* Test basic callback hooks:: + + tests/f77/callback.py + +Options +------- + +You may want to use the following options when running the test +scripts: + +``<integer>`` + Run tests ``<integer>`` times. Useful for detecting memory leaks. Under + Linux tests scripts output virtual memory size state of the process + before and after calling the wrapped functions. + +``--quiet`` + Suppress all messages. On success only "ok" should be displayed. + +``--fcompiler=<Gnu|Intel|...>`` + Use:: + + f2py -c --help-fcompiler + + to find out what compilers are available (or more precisely, which + ones are recognized by ``numpy_distutils``). + +Reporting failures +------------------ + +XXX: (1) make sure that failures are due to f2py and (2) send full +stdout/stderr messages to me. Also add compiler,python,platform +information. diff --git a/doc/f2py/THANKS.txt b/doc/f2py/THANKS.txt new file mode 100644 index 000000000..636540687 --- /dev/null +++ b/doc/f2py/THANKS.txt @@ -0,0 +1,63 @@ + +================= + Acknowledgments +================= + +F2PY__ is an open source Python package and command line tool developed and +maintained by Pearu Peterson (me__). + +.. __: http://cens.ioc.ee/projects/f2py2e/ +.. __: http://cens.ioc.ee/~pearu/ + +Many people have contributed to the F2PY project in terms of interest, +encouragement, suggestions, criticism, bug reports, code +contributions, and keeping me busy with developing F2PY. For all that +I thank + + James Amundson, John Barnard, David Beazley, Frank Bertoldi, Roman + Bertle, James Boyle, Moritz Braun, Rolv Erlend Bredesen, John + Chaffer, Fred Clare, Adam Collard, Ben Cornett, Jose L Gomez Dans, + Jaime D. Perea Duarte, Paul F Dubois, Thilo Ernst, Bonilla Fabian, + Martin Gelfand, Eduardo A. Gonzalez, Siegfried Gonzi, Bernhard + Gschaider, Charles Doutriaux, Jeff Hagelberg, Janko Hauser, Thomas + Hauser, Heiko Henkelmann, William Henney, Yueqiang Huang, Asim + Hussain, Berthold Höllmann, Vladimir Janku, Henk Jansen, Curtis + Jensen, Eric Jones, Tiffany Kamm, Andrey Khavryuchenko, Greg + Kochanski, Jochen Küpper, Simon Lacoste-Julien, Tim Lahey, Hans + Petter Langtangen, Jeff Layton, Matthew Lewis, Patrick LeGresley, + Joaquim R R A Martins, Paul Magwene Lionel Maziere, Craig McNeile, + Todd Miller, David C. Morrill, Dirk Muders, Kevin Mueller, Andrew + Mullhaupt, Vijayendra Munikoti, Travis Oliphant, Kevin O'Mara, Arno + Paehler, Fernando Perez, Didrik Pinte, Todd Alan Pitts, Prabhu + Ramachandran, Brad Reisfeld, Steve M. Robbins, Theresa Robinson, + Pedro Rodrigues, Les Schaffer, Christoph Scheurer, Herb Schilling, + Pierre Schnizer, Kevin Smith, Paulo Teotonio Sobrinho, José Rui + Faustino de Sousa, Andrew Swan, Dustin Tang, Charlie Taylor, Paul le + Texier, Michael Tiller, Semen Trygubenko, Ravi C Venkatesan, Peter + Verveer, Nils Wagner, R. Clint Whaley, Erik Wilsher, Martin + Wiechert, Gilles Zerah, SungPil Yoon. + +(This list may not be complete. Please forgive me if I have left you +out and let me know, I'll add your name.) + +Special thanks are due to ... + +Eric Jones - he and Travis O. are responsible for starting the +numpy_distutils project that allowed to move most of the platform and +compiler specific codes out from F2PY. This simplified maintaining the +F2PY project considerably. + +Joaquim R R A Martins - he made possible for me to test F2PY on IRIX64 +platform. He also presented our paper about F2PY in the 9th Python +Conference that I planned to attend but had to cancel in very last +minutes. + +Travis Oliphant - his knowledge and experience on Numerical Python +C/API has been invaluable in early development of the F2PY program. +His major contributions are call-back mechanism and copying N-D arrays +of arbitrary types. + +Todd Miller - he is responsible for Numarray support in F2PY. + +Thanks! + Pearu diff --git a/doc/f2py/TODO.txt b/doc/f2py/TODO.txt new file mode 100644 index 000000000..a883f75d0 --- /dev/null +++ b/doc/f2py/TODO.txt @@ -0,0 +1,67 @@ +Determine fixed/free format Fortran 90 dialect from the +contents of Fortran files. See numpy_distutils/command/build_flib.py. + +[DONE] +======================================================================== +Wrapping F90 code as follows: + +subroutine foo +print*,"In foo" +end subroutine foo +subroutine bar(func) + interface aa ! bug: this interface block is ignored + subroutine foo + end subroutine foo + end interface + !external foo + external func + call func(foo) +end subroutine bar +subroutine gun(a) + external a + call a() +end subroutine gun +subroutine fun + call bar(gun) +end subroutine fun + +========================================================================= +Users Guide needs major revision. + +[DONE] +========================================================================= +On Thu, 27 Sep 2001, José Luis Gómez Dans wrote: + +> Hi, +> just one question: does f2py supporte derived types in F90 code? +> Stuff like something%or and things like that. + +Not yet. + +========================================================================= +Date: Tue, 28 Aug 2001 22:23:04 -0700 +From: Patrick LeGresley <plegresl@ape.stanford.edu> +To: f2py-users@cens.ioc.ee +Subject: [f2py] Strange initialization of allocatable arrays + +I've noticed an odd behavior when setting an allocatable, multidimensional +array in a module. If the rank of the array is odd, the initialization is +fine. However, if the rank is even only the first element of the array is +set properly. See the attached sample code for example. + +========================================================================= +On Wed, 22 Aug 2001, Patrick LeGresley wrote: + +> I've noticed that if a parameter is defined in terms of another parameter, +> that the parameter is replaced not by a number but by another parameter +> (try the attached subroutine for example). Is there any way to have f2py +> automatically recognize the dependencies and generate a signature file +> without parameter variables ? + +It is certainly possible. In fact, f2py has only a basic support for +PARAMETER statements and it fails in your 'advanced' example to produce a +robust signature file. +I am sorry but you have to wait until I'll get back from my travel tour +(somewhere in the middle of September) and get a chance to work on it. + +[DONE] diff --git a/doc/f2py/apps.tex b/doc/f2py/apps.tex new file mode 100644 index 000000000..513c048bd --- /dev/null +++ b/doc/f2py/apps.tex @@ -0,0 +1,71 @@ + +\section{Applications} +\label{sec:apps} + + +\subsection{Example: wrapping C library \texttt{fftw}} +\label{sec:wrapfftw} + +Here follows a simple example how to use \fpy to generate a wrapper +for C functions. Let us create a FFT code using the functions in FFTW +library. I'll assume that the library \texttt{fftw} is configured with +\texttt{-{}-enable-shared} option. + +Here is the wrapper for the typical usage of FFTW: +\begin{verbatim} +/* File: wrap_dfftw.c */ +#include <dfftw.h> + +extern void dfftw_one(fftw_complex *in,fftw_complex *out,int *n) { + fftw_plan p; + p = fftw_create_plan(*n,FFTW_FORWARD,FFTW_ESTIMATE); + fftw_one(p,in,out); + fftw_destroy_plan(p); +} +\end{verbatim} +and here follows the corresponding siganture file (created manually): +\begin{verbatim} +!%f90 +! File: fftw.f90 +module fftw + interface + subroutine dfftw_one(in,out,n) + integer n + complex*16 in(n),out(n) + intent(out) out + intent(hide) n + end subroutine dfftw_one + end interface +end module fftw +\end{verbatim} + +Now let us generate the Python C/API module with \fpy: +\begin{verbatim} +f2py fftw.f90 +\end{verbatim} +and compile it +\begin{verbatim} +gcc -shared -I/numeric/include -I`f2py -I` -L/numeric/lib -ldfftw \ + -o fftwmodule.so -DNO_APPEND_FORTRAN fftwmodule.c wrap_dfftw.c +\end{verbatim} + +In Python: +\begin{verbatim} +>>> from Numeric import * +>>> from fftw import * +>>> print dfftw_one.__doc__ +Function signature: + out = dfftw_one(in) +Required arguments: + in : input rank-1 array('D') with bounds (n) +Return objects: + out : rank-1 array('D') with bounds (n) +>>> print dfftw_one([1,2,3,4]) +[ 10.+0.j -2.+2.j -2.+0.j -2.-2.j] +>>> +\end{verbatim} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "f2py2e" +%%% End: diff --git a/doc/f2py/bugs.tex b/doc/f2py/bugs.tex new file mode 100644 index 000000000..699ecf530 --- /dev/null +++ b/doc/f2py/bugs.tex @@ -0,0 +1,109 @@ + +\section{Bugs, Plans, and Feedback} +\label{sec:bugs} + +Currently no bugs have found that I was not able to fix. I will be +happy to receive bug reports from you (so that I could fix them and +keep the first sentence of this paragraph as true as possible ;-). +Note that \fpy is developed to work properly with gcc/g77 +compilers. +\begin{description} +\item[NOTE:] Wrapping callback functions returning \texttt{COMPLEX} + may fail on some systems. Workaround: avoid it by using callback + subroutines. +\end{description} + +Here follows a list of things that I plan to implement in (near) future: +\begin{enumerate} +\item recognize file types by their extension (signatures: + \texttt{*.pyf}, Fortran 77, Fortran 90 fixed: \texttt{*.f, *.for, *.F, *.FOR}, + Fortran 90 free: \texttt{*.F90, *.f90, *.m, *.f95, *.F95}); [DONE] +\item installation using \texttt{distutils} (when it will be stable); +\item put out to the web examples of \fpy usages in real situations: + wrapping \texttt{vode}, for example; +\item implement support for \texttt{PARAMETER} statement; [DONE] +\item rewrite test-site; +\item ... +\end{enumerate} +and here are things that I plan to do in future: +\begin{enumerate} +\item implement \texttt{intent(cache)} attribute for an optional work + arrays with a feature of allocating additional memory if needed; +\item use \fpy for wrapping Fortran 90/95 codes. \fpy should scan + Fortran 90/95 codes with no problems, what needs to be done is find + out how to call a Fortran 90/95 function (from a module) from + C. Anybody there willing to test \fpy with Fortran 90/95 modules? [DONE] +\item implement support for Fortran 90/95 module data; [DONE] +\item implement support for \texttt{BLOCK DATA} blocks (if needed); +\item test/document \fpy for \texttt{CHARACTER} arrays; +\item decide whether internal transposition of multi-dimensional + arrays is reasonable (need efficient code then), even if this is + controlled by the user trough some additional keyword; need + consistent and safe policy here; +\item use \fpy for generating wrapper functions also for C programs (a + kind of SWIG, only between Python and C). For that \fpy needs a + command line switch to inform itself that C scalars are passed in by + their value, not by their reference, for instance; +\item introduce a counter that counts the number of inefficient usages + of wrapper functions (copying caused by type-casting, non-contiguous + arrays); +\item if needed, make \texttt{DATA} statement to work properly for + arrays; +\item rewrite \texttt{COMMON} wrapper; [DONE] +\item ... +\end{enumerate} +I'll appreciate any feedback that will improve \fpy (bug reports, +suggestions, etc). If you find a correct Fortran code that fails with +\fpy, try to send me a minimal version of it so that I could track +down the cause of the failure. Note also that there is no sense to +send me files that are auto-generated with \fpy (I can generate them +myself); the version of \fpy that you are using (run \texttt{\fpy\ + -v}), and the relevant fortran codes or modified signature files +should be enough information to fix the bugs. Also add some +information on compilers and linkers that you use to the bug report. + + +\section{History of \fpy} +\label{sec:history} + +\begin{enumerate} +\item I was driven to start developing a tool such as \fpy after I had + wrote several Python C/API modules for interfacing various Fortran + routines from the Netlib. This work was tedious (some of functions + had more than 20 arguments, only few of them made sense for the + problems that they solved). I realized that most of the writing + could be done automatically. +\item On 9th of July, 1999, the first lines of the tool was written. A + prototype of the tool was ready to use in only three weeks. During + this time Travis Oliphant joined to the project and shared his + valuable knowledge and experience; the call-back mechanism is his + major contribution. Then I gave the tool to public under the name + FPIG --- \emph{Fortran to Python Interface Generator}. The tool contained + only one file \texttt{f2py.py}. +\item By autumn, it was clear that a better implementation was needed + as the debugging process became very tedious. So, I reserved some + time and rewrote the tool from scratch. The most important result of + this rewriting was the code that reads real Fortran codes and + determines the signatures of the Fortran routines. The main + attention was payed in particular to this part so that the tool + could read arbitrary Fortran~77/90/95 codes. As a result, the other + side of the tools task, that is, generating Python C/API functions, + was not so great. In public, this version of the tool was called + \texttt{f2py2e} --- \emph{Fortran to Python C/API generator, the + Second Edition}. +\item So, a month before The New Year 2000, I started the third + iteration of the \fpy development. Now the main attention was to + have a good C/API module constructing code. By 21st of January, + 2000, the tool of generating wrapper functions for Fortran routines + was ready. It had many new features and was more robust than ever. +\item In 25th of January, 2000, the first public release of \fpy was + announced (version 1.116). +\item In 12th of September, 2000, the second public release of \fpy was + announced (version 2.264). It now has among other changes a support + for Fortran 90/95 module routines. +\end{enumerate} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "f2py2e" +%%% End: diff --git a/doc/f2py/collectinput.py b/doc/f2py/collectinput.py new file mode 100755 index 000000000..2585dae49 --- /dev/null +++ b/doc/f2py/collectinput.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +""" +collectinput - Collects all files that are included to a main Latex document + with \input or \include commands. These commands must be + in separate lines. + +Copyright 1999 Pearu Peterson all rights reserved, +Pearu Peterson <pearu@ioc.ee> +Permission to use, modify, and distribute this software is given under the +terms of the NumPy License + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + +Pearu Peterson + +Usage: + collectinput <infile> <outfile> + collectinput <infile> # <outfile>=inputless_<infile> + collectinput # in and out are stdin and stdout + +""" +from __future__ import division, absolute_import, print_function + +__version__ = "0.0" + +stdoutflag=0 +import sys +import fileinput +import re + +if sys.version_info[0] >= 3: + from subprocess import getoutput +else: + from commands import getoutput + +try: fn=sys.argv[2] +except: + try: fn='inputless_'+sys.argv[1] + except: stdoutflag=1 +try: fi=sys.argv[1] +except: fi=() +if not stdoutflag: + sys.stdout=open(fn, 'w') + +nonverb=r'[\w\s\\&=\^\*\.\{\(\)\[\?\+\$/]*(?!\\verb.)' +input=re.compile(nonverb+r'\\(input|include)\*?\s*\{?.*}?') +comment=re.compile(r'[^%]*%') + +for l in fileinput.input(fi): + l=l[:-1] + l1='' + if comment.match(l): + m=comment.match(l) + l1=l[m.end()-1:] + l=l[:m.end()-1] + m=input.match(l) + if m: + l=l.strip() + if l[-1]=='}': l=l[:-1] + i=m.end()-2 + sys.stderr.write('>>>>>>') + while i>-1 and (l[i] not in [' ', '{']): i=i-1 + if i>-1: + fn=l[i+1:] + try: f=open(fn, 'r'); flag=1; f.close() + except: + try: f=open(fn+'.tex', 'r'); flag=1;fn=fn+'.tex'; f.close() + except: flag=0 + if flag==0: + sys.stderr.write('Could not open a file: '+fn+'\n') + print(l+l1) + continue + elif flag==1: + sys.stderr.write(fn+'\n') + print('%%%%% Begin of '+fn) + print(getoutput(sys.argv[0]+' < '+fn)) + print('%%%%% End of '+fn) + else: + sys.stderr.write('Could not extract a file name from: '+l) + print(l+l1) + else: + print(l+l1) +sys.stdout.close() diff --git a/doc/f2py/commands.tex b/doc/f2py/commands.tex new file mode 100644 index 000000000..5101a9ff5 --- /dev/null +++ b/doc/f2py/commands.tex @@ -0,0 +1,20 @@ +\usepackage{xspace} +\usepackage{verbatim} + +%%tth:\newcommand{\xspace}{ } + +\newcommand{\fpy}{\texttt{f2py}\xspace} + +\newcommand{\bs}{\symbol{`\\}} +% need bs here: +%%tth:\newcommand{\bs}{\texttt{<backslash>}} + +\newcommand{\shell}[1]{\hspace*{1em}\texttt{sh> \begin{minipage}[t]{0.8\textwidth}#1\end{minipage}}} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "f2py2e" +%%% End: + + diff --git a/doc/f2py/default.css b/doc/f2py/default.css new file mode 100644 index 000000000..9289e2826 --- /dev/null +++ b/doc/f2py/default.css @@ -0,0 +1,180 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date: 2002/08/01 20:52:44 $ +:version: $Revision: 1.1 $ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +body { + background: #FFFFFF ; + color: #000000 +} + +a.footnote-reference { + font-size: smaller ; + vertical-align: super } + +a.target { + color: blue } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.first { + margin-top: 0 } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.field-argument { + font-style: italic } + +span.interpreted { + font-family: sans-serif } + +span.option-argument { + font-style: italic } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: baseline } + +td.docinfo-name { + font-weight: bold ; + text-align: right } + +td.field-name { + font-weight: bold } diff --git a/doc/f2py/docutils.conf b/doc/f2py/docutils.conf new file mode 100644 index 000000000..4e5a8425b --- /dev/null +++ b/doc/f2py/docutils.conf @@ -0,0 +1,16 @@ +[general] + +# These entries affect all processing: +#source-link: 1 +datestamp: %Y-%m-%d %H:%M UTC +generator: 1 + +# These entries affect HTML output: +#stylesheet-path: pearu_style.css +output-encoding: latin-1 + +# These entries affect reStructuredText-style PEPs: +#pep-template: pep-html-template +#pep-stylesheet-path: stylesheets/pep.css +#python-home: http://www.python.org +#no-random: 1 diff --git a/doc/f2py/ex1/arr.f b/doc/f2py/ex1/arr.f new file mode 100644 index 000000000..c4e49988f --- /dev/null +++ b/doc/f2py/ex1/arr.f @@ -0,0 +1,4 @@ + subroutine arr(l,m,n,a) + integer l,m,n + real*8 a(l,m,n) + end diff --git a/doc/f2py/ex1/bar.f b/doc/f2py/ex1/bar.f new file mode 100644 index 000000000..c723b5af1 --- /dev/null +++ b/doc/f2py/ex1/bar.f @@ -0,0 +1,4 @@ + function bar(a,b) + integer a,b,bar + bar = a + b + end diff --git a/doc/f2py/ex1/foo.f b/doc/f2py/ex1/foo.f new file mode 100644 index 000000000..cdcac4103 --- /dev/null +++ b/doc/f2py/ex1/foo.f @@ -0,0 +1,5 @@ + subroutine foo(a) + integer a +cf2py intent(in,out) :: a + a = a + 5 + end diff --git a/doc/f2py/ex1/foobar-smart.f90 b/doc/f2py/ex1/foobar-smart.f90 new file mode 100644 index 000000000..61385a685 --- /dev/null +++ b/doc/f2py/ex1/foobar-smart.f90 @@ -0,0 +1,24 @@ +!%f90 +module foobar ! in + note(This module contains two examples that are used in & + \texttt{f2py} documentation.) foobar + interface ! in :foobar + subroutine foo(a) ! in :foobar:foo.f + note(Example of a wrapper function of a Fortran subroutine.) foo + integer intent(inout),& + note(5 is added to the variable {{}\verb@a@{}} ``in place''.) :: a + end subroutine foo + function bar(a,b) result (ab) ! in :foobar:bar.f + integer :: a + integer :: b + integer :: ab + note(The first value.) a + note(The second value.) b + note(Add two values.) bar + note(The result.) ab + end function bar + end interface +end module foobar + +! This file was auto-generated with f2py (version:0.95). +! See http://cens.ioc.ee/projects/f2py2e/ diff --git a/doc/f2py/ex1/foobar.f90 b/doc/f2py/ex1/foobar.f90 new file mode 100644 index 000000000..53ac5b506 --- /dev/null +++ b/doc/f2py/ex1/foobar.f90 @@ -0,0 +1,16 @@ +!%f90 +module foobar ! in + interface ! in :foobar + subroutine foo(a) ! in :foobar:foo.f + integer intent(inout) :: a + end subroutine foo + function bar(a,b) ! in :foobar:bar.f + integer :: a + integer :: b + integer :: bar + end function bar + end interface +end module foobar + +! This file was auto-generated with f2py (version:0.95). +! See http://cens.ioc.ee/projects/f2py2e/ diff --git a/doc/f2py/ex1/foobarmodule.tex b/doc/f2py/ex1/foobarmodule.tex new file mode 100644 index 000000000..32411ec03 --- /dev/null +++ b/doc/f2py/ex1/foobarmodule.tex @@ -0,0 +1,36 @@ +% This file is auto-generated with f2py (version:2.266) +\section{Module \texttt{foobar}} + +This module contains two examples that are used in \texttt{f2py} documentation. + +\subsection{Wrapper function \texttt{foo}} + + +\noindent{{}\verb@foo@{}}\texttt{(a)} +--- Example of a wrapper function of a Fortran subroutine. + +\noindent Required arguments: +\begin{description} +\item[]{{}\verb@a : in/output rank-0 array(int,'i')@{}} +--- 5 is added to the variable {{}\verb@a@{}} ``in place''. +\end{description} + +\subsection{Wrapper function \texttt{bar}} + + +\noindent{{}\verb@bar = bar@{}}\texttt{(a, b)} +--- Add two values. + +\noindent Required arguments: +\begin{description} +\item[]{{}\verb@a : input int@{}} +--- The first value. +\item[]{{}\verb@b : input int@{}} +--- The second value. +\end{description} +\noindent Return objects: +\begin{description} +\item[]{{}\verb@bar : int@{}} +--- See elsewhere. +\end{description} + diff --git a/doc/f2py/ex1/runme b/doc/f2py/ex1/runme new file mode 100755 index 000000000..2aac6158e --- /dev/null +++ b/doc/f2py/ex1/runme @@ -0,0 +1,18 @@ +#!/bin/sh + +f2py2e='python ../../f2py2e.py' +PYINC=`$f2py2e -pyinc` +$f2py2e foobar-smart.pyf --short-latex --overwrite-makefile -makefile foo.f bar.f +gmake -f Makefile-foobar +#gcc -O3 -I$PYINC -I$PYINC/Numeric -shared -o foobarmodule.so foobarmodule.c foo.f bar.f +python -c ' +import foobar +print foobar.__doc__ +print foobar.bar(2,3) +from Numeric import * +a=array(3) +print a,foobar.foo(a),a +print foobar.foo.__doc__ +print foobar.bar.__doc__ +print "ok" +' diff --git a/doc/f2py/f2py.1 b/doc/f2py/f2py.1 new file mode 100644 index 000000000..279647424 --- /dev/null +++ b/doc/f2py/f2py.1 @@ -0,0 +1,209 @@ +.TH "F2PY" 1 +.SH NAME +f2py \- Fortran to Python interface generator +.SH SYNOPSIS +(1) To construct extension module sources: + +.B f2py +[<options>] <fortran files> [[[only:]||[skip:]] <fortran functions> ] [: <fortran files> ...] + +(2) To compile fortran files and build extension modules: + +.B f2py +\-c [<options>, <config_fc options>, <extra options>] <fortran files> + +(3) To generate signature files: + +.B f2py +\-h <filename.pyf> ...< same options as in (1) > +.SH DESCRIPTION +This program generates a Python C/API file (<modulename>module.c) +that contains wrappers for given Fortran or C functions so that they +can be called from Python. +With the \-c option the corresponding +extension modules are built. +.SH OPTIONS +.TP +.B \-h <filename> +Write signatures of the fortran routines to file <filename> and +exit. You can then edit <filename> and use it instead of <fortran +files>. If <filename>==stdout then the signatures are printed to +stdout. +.TP +.B <fortran functions> +Names of fortran routines for which Python C/API functions will be +generated. Default is all that are found in <fortran files>. +.TP +.B skip: +Ignore fortran functions that follow until `:'. +.TP +.B only: +Use only fortran functions that follow until `:'. +.TP +.B : +Get back to <fortran files> mode. +.TP +.B \-m <modulename> +Name of the module; f2py generates a Python/C API file +<modulename>module.c or extension module <modulename>. Default is +\'untitled\'. +.TP +.B \-\-[no\-]lower +Do [not] lower the cases in <fortran files>. By default, \-\-lower is +assumed with \-h key, and \-\-no\-lower without \-h key. +.TP +.B \-\-build\-dir <dirname> +All f2py generated files are created in <dirname>. Default is tempfile.mktemp(). +.TP +.B \-\-overwrite\-signature +Overwrite existing signature file. +.TP +.B \-\-[no\-]latex\-doc +Create (or not) <modulename>module.tex. Default is \-\-no\-latex\-doc. +.TP +.B \-\-short\-latex +Create 'incomplete' LaTeX document (without commands \\documentclass, +\\tableofcontents, and \\begin{document}, \\end{document}). +.TP +.B \-\-[no\-]rest\-doc +Create (or not) <modulename>module.rst. Default is \-\-no\-rest\-doc. +.TP +.B \-\-debug\-capi +Create C/API code that reports the state of the wrappers during +runtime. Useful for debugging. +.TP +.B \-include\'<includefile>\' +Add CPP #include statement to the C/API code. <includefile> should be +in the format of either `"filename.ext"' or `<filename.ext>'. As a +result <includefile> will be included just before wrapper functions +part in the C/API code. The option is depreciated, use `usercode` +statement in signature files instead. +.TP +.B \-\-[no\-]wrap\-functions +Create Fortran subroutine wrappers to Fortran 77 +functions. \-\-wrap\-functions is default because it ensures maximum +portability/compiler independence. +.TP +.B \-\-help\-link [..] +List system resources found by system_info.py. [..] may contain +a list of resources names. See also \-\-link\-<resource> switch below. +.TP +.B \-\-quiet +Run quietly. +.TP +.B \-\-verbose +Run with extra verbosity. +.TP +.B \-v +Print f2py version ID and exit. +.TP +.B \-\-include_paths path1:path2:... +Search include files (that f2py will scan) from the given directories. +.SH "CONFIG_FC OPTIONS" +The following options are effective only when \-c switch is used. +.TP +.B \-\-help-compiler +List available Fortran compilers [DEPRECIATED]. +.TP +.B \-\-fcompiler=<name> +Specify Fortran compiler type by vendor. +.TP +.B \-\-compiler=<name> +Specify C compiler type (as defined by distutils) +.TP +.B \-\-fcompiler-exec=<path> +Specify the path to F77 compiler [DEPRECIATED]. +.TP +.B \-\-f90compiler\-exec=<path> +Specify the path to F90 compiler [DEPRECIATED]. +.TP +.B \-\-help\-fcompiler +List available Fortran compilers and exit. +.TP +.B \-\-f77exec=<path> +Specify the path to F77 compiler. +.TP +.B \-\-f90exec=<path> +Specify the path to F90 compiler. +.TP +.B \-\-f77flags="..." +Specify F77 compiler flags. +.TP +.B \-\-f90flags="..." +Specify F90 compiler flags. +.TP +.B \-\-opt="..." +Specify optimization flags. +.TP +.B \-\-arch="..." +Specify architecture specific optimization flags. +.TP +.B \-\-noopt +Compile without optimization. +.TP +.B \-\-noarch +Compile without arch-dependent optimization. +.TP +.B \-\-debug +Compile with debugging information. +.SH "EXTRA OPTIONS" +The following options are effective only when \-c switch is used. +.TP +.B \-\-link-<resource> +Link extension module with <resource> as defined by +numpy_distutils/system_info.py. E.g. to link with optimized LAPACK +libraries (vecLib on MacOSX, ATLAS elsewhere), use +\-\-link\-lapack_opt. See also \-\-help\-link switch. + +.TP +.B -L/path/to/lib/ -l<libname> +.TP +.B -D<define> -U<name> -I/path/to/include/ +.TP +.B <filename>.o <filename>.so <filename>.a + +.TP +.B -DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN -DUNDERSCORE_G77 +Macros that might be required with non-gcc Fortran compilers. + +.TP +.B -DF2PY_REPORT_ATEXIT +To print out a performance report of F2PY interface when python +exits. Available for Linux. + +.TP +.B -DF2PY_REPORT_ON_ARRAY_COPY=<int> +To send a message to stderr whenever F2PY interface makes a copy of an +array. Integer <int> sets the threshold for array sizes when a message +should be shown. + +.SH REQUIREMENTS +Python 1.5.2 or higher (2.x is supported). + +Numerical Python 13 or higher (20.x,21.x,22.x,23.x are supported). + +Optional Numarray 0.9 or higher partially supported. + +numpy_distutils from Scipy (can be downloaded from F2PY homepage) +.SH "SEE ALSO" +python(1) +.SH BUGS +For instructions on reporting bugs, see + + http://cens.ioc.ee/projects/f2py2e/FAQ.html +.SH AUTHOR +Pearu Peterson <pearu@cens.ioc.ee> +.SH "INTERNET RESOURCES" +Main website: http://cens.ioc.ee/projects/f2py2e/ + +User's Guide: http://cens.ioc.ee/projects/f2py2e/usersguide/ + +Mailing list: http://cens.ioc.ee/mailman/listinfo/f2py-users/ + +Scipy website: http://www.numpy.org +.SH COPYRIGHT +Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Pearu Peterson +.SH LICENSE +NumPy License +.SH VERSION +2.45.241 diff --git a/doc/f2py/f2py2e.tex b/doc/f2py/f2py2e.tex new file mode 100644 index 000000000..6e3e9d68c --- /dev/null +++ b/doc/f2py/f2py2e.tex @@ -0,0 +1,50 @@ +\documentclass{article} +\usepackage{a4wide} + +\input commands + +\title{\fpy\\Fortran to Python Interface Generator\\{\large Second Edition}} +\author{Pearu Peterson \texttt{<pearu@ioc.ee>}} +\date{$Revision: 1.16 $\\\today} +\begin{document} +\special{html: <font size=-1>If equations does not show Greek letters or large + brackets correctly, then your browser configuration needs some + adjustment. Read the notes for <A + href=http://hutchinson.belmont.ma.us/tth/Xfonts.html>Enabling Symbol + Fonts in Netscape under X </A>. In addition, the browser must be set + to use document fonts. </font> +} + +\maketitle +\begin{abstract} + \fpy is a Python program that generates Python C/API modules for + wrapping Fortran~77/90/95 codes to Python. The user can influence the + process by modifying the signature files that \fpy generates when + scanning the Fortran codes. This document describes the syntax of + the signature files and the ways how the user can dictate the tool + to produce wrapper functions with desired Python signatures. Also + how to call the wrapper functions from Python is discussed. + + See \texttt{http://cens.ioc.ee/projects/f2py2e/} for updates of this + document and the tool. +\end{abstract} + +\tableofcontents + +\input intro +\input signaturefile +\input notes +\input options +\input bugs + +\appendix +\input ex1/foobarmodule +\input apps +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: + + diff --git a/doc/f2py/f2python9-final/README.txt b/doc/f2py/f2python9-final/README.txt new file mode 100644 index 000000000..2ce8e393a --- /dev/null +++ b/doc/f2py/f2python9-final/README.txt @@ -0,0 +1,38 @@ + +This directory contains the source of the paper + + "Fortran to Python Interface Generator with an Application + to Aerospace Engineering" + +by + Pearu Peterson <pearu@cens.ioc.ee> (the corresponding author) + Joaquim R. R. A. Martins <joaquim.martins@stanford.edu> + Juan J. Alonso <jjalonso@stanford.edu> + +for The 9th International Python Conference, March 5-8, 2001, Long Beach, California. + +The paper is provided here is in the HTML format: + + f2python9.html (size=48151 bytes) + +Note that this file includes the following JPG images + + flow.jpg (size=13266) + structure.jpg (size=17860) + aerostructure.jpg (size=72247) + +PS: +The HTML file f2python9.html is generated using TTH (http://hutchinson.belmont.ma.us/tth/) +from the LaTeX source file `python9.tex'. The source can be found in the + src/ +directory. This directory contains also the following EPS files + flow.eps + structure.eps + aerostructure.eps +and the text files + examples/{exp1.f,exp1mess.txt,exp1session.txt,foo.pyf,foom.pyf} +that are used by the LaTeX source python9.tex. + +Regards, + Pearu +January 15, 2001 diff --git a/doc/f2py/f2python9-final/aerostructure.jpg b/doc/f2py/f2python9-final/aerostructure.jpg Binary files differnew file mode 100644 index 000000000..896ad6e12 --- /dev/null +++ b/doc/f2py/f2python9-final/aerostructure.jpg diff --git a/doc/f2py/f2python9-final/flow.jpg b/doc/f2py/f2python9-final/flow.jpg Binary files differnew file mode 100644 index 000000000..cfe0f85f3 --- /dev/null +++ b/doc/f2py/f2python9-final/flow.jpg diff --git a/doc/f2py/f2python9-final/mk_html.sh b/doc/f2py/f2python9-final/mk_html.sh new file mode 100755 index 000000000..944110e93 --- /dev/null +++ b/doc/f2py/f2python9-final/mk_html.sh @@ -0,0 +1,13 @@ +#!/bin/sh +cd src + +test -f aerostructure.eps || convert ../aerostructure.jpg aerostructure.eps +test -f flow.eps || convert ../flow.jpg flow.eps +test -f structure.eps || convert ../structure.jpg structure.eps + +latex python9.tex +latex python9.tex +latex python9.tex + +test `which tth` && cat python9.tex | sed -e "s/{{}\\\verb@/\\\texttt{/g" | sed -e "s/@{}}/}/g" | tth -Lpython9 -i > ../f2python9.html +cd .. diff --git a/doc/f2py/f2python9-final/mk_pdf.sh b/doc/f2py/f2python9-final/mk_pdf.sh new file mode 100755 index 000000000..b773028b7 --- /dev/null +++ b/doc/f2py/f2python9-final/mk_pdf.sh @@ -0,0 +1,13 @@ +#!/bin/sh +cd src + +test -f aerostructure.pdf || convert ../aerostructure.jpg aerostructure.pdf +test -f flow.pdf || convert ../flow.jpg flow.pdf +test -f structure.pdf || convert ../structure.jpg structure.pdf + +cat python9.tex | sed -e "s/eps,/pdf,/g" > python9pdf.tex +pdflatex python9pdf.tex +pdflatex python9pdf.tex +pdflatex python9pdf.tex + +mv python9pdf.pdf ../f2python9.pdf
\ No newline at end of file diff --git a/doc/f2py/f2python9-final/mk_ps.sh b/doc/f2py/f2python9-final/mk_ps.sh new file mode 100755 index 000000000..4b0863fcd --- /dev/null +++ b/doc/f2py/f2python9-final/mk_ps.sh @@ -0,0 +1,14 @@ +#!/bin/sh +cd src + +test -f aerostructure.eps || convert ../aerostructure.jpg aerostructure.eps +test -f flow.eps || convert ../flow.jpg flow.eps +test -f structure.eps || convert ../structure.jpg structure.eps + +latex python9.tex +latex python9.tex +latex python9.tex + +dvips python9.dvi -o ../f2python9.ps +cd .. +gzip -f f2python9.ps diff --git a/doc/f2py/f2python9-final/src/examples/exp1.f b/doc/f2py/f2python9-final/src/examples/exp1.f new file mode 100644 index 000000000..36bee50b0 --- /dev/null +++ b/doc/f2py/f2python9-final/src/examples/exp1.f @@ -0,0 +1,26 @@ + subroutine exp1(l,u,n) +C Input: n is number of iterations +C Output: l,u are such that +C l(1)/l(2) < exp(1) < u(1)/u(2) +C +Cf2py integer*4 :: n = 1 +Cf2py intent(out) l,u + integer*4 n,i + real*8 l(2),u(2),t,t1,t2,t3,t4 + l(2) = 1 + l(1) = 0 + u(2) = 0 + u(1) = 1 + do 10 i=0,n + t1 = 4 + 32*(1+i)*i + t2 = 11 + (40+32*i)*i + t3 = 3 + (24+32*i)*i + t4 = 8 + 32*(1+i)*i + t = u(1) + u(1) = l(1)*t1 + t*t2 + l(1) = l(1)*t3 + t*t4 + t = u(2) + u(2) = l(2)*t1 + t*t2 + l(2) = l(2)*t3 + t*t4 + 10 continue + end diff --git a/doc/f2py/f2python9-final/src/examples/exp1mess.txt b/doc/f2py/f2python9-final/src/examples/exp1mess.txt new file mode 100644 index 000000000..d4188a91b --- /dev/null +++ b/doc/f2py/f2python9-final/src/examples/exp1mess.txt @@ -0,0 +1,17 @@ +Reading fortran codes... + Reading file 'exp1.f' +Post-processing... + Block: foo + Block: exp1 +Creating 'Makefile-foo'... + Linker: ld ('GNU ld' 2.9.5) + Fortran compiler: f77 ('g77 2.x.x' 2.95.2) + C compiler: cc ('gcc 2.x.x' 2.95.2) +Building modules... + Building module "foo"... + Constructing wrapper function "exp1"... + l,u = exp1([n]) + Wrote C/API module "foo" to file "foomodule.c" + Documentation is saved to file "foomodule.tex" +Run GNU make to build shared modules: + gmake -f Makefile-<modulename> [test] diff --git a/doc/f2py/f2python9-final/src/examples/exp1session.txt b/doc/f2py/f2python9-final/src/examples/exp1session.txt new file mode 100644 index 000000000..5ae75ebd1 --- /dev/null +++ b/doc/f2py/f2python9-final/src/examples/exp1session.txt @@ -0,0 +1,20 @@ +>>> import foo,Numeric +>>> print foo.exp1.__doc__ +exp1 - Function signature: + l,u = exp1([n]) +Optional arguments: + n := 1 input int +Return objects: + l : rank-1 array('d') with bounds (2) + u : rank-1 array('d') with bounds (2) + +>>> l,u = foo.exp1() +>>> print l,u +[ 1264. 465.] [ 1457. 536.] +>>> print l[0]/l[1], u[0]/u[1]-l[0]/l[1] +2.71827956989 2.25856657199e-06 +>>> l,u = foo.exp1(2) +>>> print l,u +[ 517656. 190435.] [ 566827. 208524.] +>>> print l[0]/l[1], u[0]/u[1]-l[0]/l[1] +2.71828182845 1.36437527942e-11 diff --git a/doc/f2py/f2python9-final/src/examples/foo.pyf b/doc/f2py/f2python9-final/src/examples/foo.pyf new file mode 100644 index 000000000..516bb292f --- /dev/null +++ b/doc/f2py/f2python9-final/src/examples/foo.pyf @@ -0,0 +1,13 @@ +!%f90 -*- f90 -*- +python module foo + interface + subroutine exp1(l,u,n) + real*8 dimension(2) :: l + real*8 dimension(2) :: u + integer*4 :: n + end subroutine exp1 + end interface +end python module foo +! This file was auto-generated with f2py +! (version:2.298). +! See http://cens.ioc.ee/projects/f2py2e/ diff --git a/doc/f2py/f2python9-final/src/examples/foom.pyf b/doc/f2py/f2python9-final/src/examples/foom.pyf new file mode 100644 index 000000000..6392ebc95 --- /dev/null +++ b/doc/f2py/f2python9-final/src/examples/foom.pyf @@ -0,0 +1,14 @@ +!%f90 -*- f90 -*- +python module foo + interface + subroutine exp1(l,u,n) + real*8 dimension(2) :: l + real*8 dimension(2) :: u + intent(out) l,u + integer*4 optional :: n = 1 + end subroutine exp1 + end interface +end python module foo +! This file was auto-generated with f2py +! (version:2.298) and modified by pearu. +! See http://cens.ioc.ee/projects/f2py2e/ diff --git a/doc/f2py/f2python9-final/structure.jpg b/doc/f2py/f2python9-final/structure.jpg Binary files differnew file mode 100644 index 000000000..9aa691339 --- /dev/null +++ b/doc/f2py/f2python9-final/structure.jpg diff --git a/doc/f2py/fortranobject.tex b/doc/f2py/fortranobject.tex new file mode 100644 index 000000000..88a56835e --- /dev/null +++ b/doc/f2py/fortranobject.tex @@ -0,0 +1,574 @@ +\documentclass{article} + +\headsep=0pt +\topmargin=0pt +\headheight=0pt +\oddsidemargin=0pt +\textwidth=6.5in +\textheight=9in + +\usepackage{xspace} +\usepackage{verbatim} +\newcommand{\fpy}{\texttt{f2py}\xspace} +\newcommand{\bs}{\symbol{`\\}} +\newcommand{\email}[1]{\special{html:<A href="mailto:#1">}\texttt{<#1>}\special{html:</A>}} +\title{\texttt{PyFortranObject} --- example usages} +\author{ +\large Pearu Peterson\\ +\small \email{pearu@cens.ioc.ee} +} + +\begin{document} + +\maketitle + +\special{html: Other formats of this document: +<A href=pyfobj.ps.gz>Gzipped PS</A>, +<A href=pyfobj.pdf>PDF</A> +} + +\tableofcontents + +\section{Introduction} +\label{sec:intro} + +Fortran language defines the following concepts that we would like to +access from Python: functions, subroutines, data in \texttt{COMMON} blocks, +F90 module functions and subroutines, F90 module data (both static and +allocatable arrays). + +In the following we shall assume that we know the signatures (full +specifications of routine arguments and variables) of these concepts +from their Fortran source codes. Now, in order to call or use them +from C, one needs to have pointers to the corresponding objects. The +pointers to Fortran 77 objects (routines, data in \texttt{COMMON} +blocks) are readily available to C codes (there are various sources +available about mixing Fortran 77 and C codes). On the other hand, F90 +module specifications are highly compiler dependent and sometimes it +is not even possible to access F90 module objects from C (at least, +not directly, see remark about MIPSPro 7 Compilers). But using some +tricks (described below), the pointers to F90 module objects can be +determined in runtime providing a compiler independent solution. + +To use Fortran objects from Python in unified manner, \fpy introduces +\texttt{PyFortranObject} to hold pointers of the Fortran objects and +the corresponing wrapper functions. In fact, \texttt{PyFortranObject} +does much more: it generates documentation strings in run-time (for +items in \texttt{COMMON} blocks and data in F90 modules), provides +methods for accessing Fortran data and for calling Fortran routines, +etc. + +\section{\texttt{PyFortranObject}} +\label{sec:pyfortobj} + +\texttt{PyFortranObject} is defined as follows +\begin{verbatim} +typedef struct { + PyObject_HEAD + int len; /* Number of attributes */ + FortranDataDef *defs; /* An array of FortranDataDef's */ + PyObject *dict; /* Fortran object attribute dictionary */ +} PyFortranObject; +\end{verbatim} +where \texttt{FortranDataDef} is +\begin{verbatim} +typedef struct { + char *name; /* attribute (array||routine) name */ + int rank; /* array rank, 0 for scalar, max is F2PY_MAX_DIMS, + || rank=-1 for Fortran routine */ + struct {int d[F2PY_MAX_DIMS];} dims; /* dimensions of the array, || not used */ + int type; /* NPY_<type> || not used */ + char *data; /* pointer to array || Fortran routine */ + void (*func)(); /* initialization function for + allocatable arrays: + func(&rank,dims,set_ptr_func,name,len(name)) + || C/API wrapper for Fortran routine */ + char *doc; /* documentation string; only recommended + for routines. */ +} FortranDataDef; +\end{verbatim} +In the following we demonstrate typical usages of +\texttt{PyFortranObject}. Just relevant code fragments will be given. + + +\section{Fortran 77 subroutine} +\label{sec:f77subrout} + +Consider Fortran 77 subroutine +\begin{verbatim} +subroutine bar() +end +\end{verbatim} +The corresponding \texttt{PyFortranObject} is defined in C as follows: +\begin{verbatim} +static char doc_bar[] = "bar()"; +static PyObject *c_bar(PyObject *self, PyObject *args, + PyObject *keywds, void (*f2py_func)()) { + static char *capi_kwlist[] = {NULL}; + if (!PyArg_ParseTupleAndKeywords(args,keywds,"|:bar",capi_kwlist)) + return NULL; + (*f2py_func)(); + return Py_BuildValue(""); +} +extern void F_FUNC(bar,BAR)(); +static FortranDataDef f2py_routines_def[] = { + {"bar",-1, {-1}, 0, (char *)F_FUNC(bar,BAR),(void*)c_bar,doc_bar}, + {NULL} +}; +void initfoo() { + <snip> + d = PyModule_GetDict(m); + PyDict_SetItemString(d, f2py_routines_def[0].name, + PyFortranObject_NewAsAttr(&f2py_routines_def[0])); +} +\end{verbatim} +where CPP macro \texttt{F\_FUNC} defines how Fortran 77 routines are +seen in C. +In Python, Fortran subroutine \texttt{bar} is called as follows +\begin{verbatim} +>>> import foo +>>> foo.bar() +\end{verbatim} + +\section{Fortran 77 function} +\label{sec:f77func} +Consider Fortran 77 function +\begin{verbatim} +function bar() +complex bar +end +\end{verbatim} +The corresponding \texttt{PyFortranObject} is defined in C as in +previous example but with the following changes: +\begin{verbatim} +static char doc_bar[] = "bar = bar()"; +static PyObject *c_bar(PyObject *self, PyObject *args, + PyObject *keywds, void (*f2py_func)()) { + complex_float bar; + static char *capi_kwlist[] = {NULL}; + if (!PyArg_ParseTupleAndKeywords(args,keywds,"|:bar",capi_kwlist)) + return NULL; + (*f2py_func)(&bar); + return Py_BuildValue("O",pyobj_from_complex_float1(bar)); +} +extern void F_WRAPPEDFUNC(bar,BAR)(); +static FortranDataDef f2py_routines_def[] = { + {"bar",-1,{-1},0,(char *)F_WRAPPEDFUNC(bar,BAR),(void *)c_bar,doc_bar}, + {NULL} +}; +\end{verbatim} +where CPP macro \texttt{F\_WRAPPEDFUNC} gives the pointer to the following +Fortran 77 subroutine: +\begin{verbatim} +subroutine f2pywrapbar (barf2pywrap) +external bar +complex bar, barf2pywrap +barf2pywrap = bar() +end +\end{verbatim} +With these hooks, calling Fortran functions returning composed types +becomes platform/compiler independent. + + +\section{\texttt{COMMON} block data} +\label{sec:commondata} + +Consider Fortran 77 \texttt{COMMON} block +\begin{verbatim} +integer i +COMMON /bar/ i +\end{verbatim} +In order to access the variable \texttt{i} from Python, +\texttt{PyFortranObject} is defined as follows: +\begin{verbatim} +static FortranDataDef f2py_bar_def[] = { + {"i",0,{-1},NPY_INT}, + {NULL} +}; +static void f2py_setup_bar(char *i) { + f2py_bar_def[0].data = i; +} +extern void F_FUNC(f2pyinitbar,F2PYINITBAR)(); +static void f2py_init_bar() { + F_FUNC(f2pyinitbar,F2PYINITBAR)(f2py_setup_bar); +} +void initfoo() { + <snip> + PyDict_SetItemString(d, "bar", PyFortranObject_New(f2py_bar_def,f2py_init_bar)); +} +\end{verbatim} +where auxiliary Fortran function \texttt{f2pyinitbar} is defined as follows +\begin{verbatim} +subroutine f2pyinitbar(setupfunc) +external setupfunc +integer i +common /bar/ i +call setupfunc(i) +end +\end{verbatim} +and it is called in \texttt{PyFortranObject\_New}. + + +\section{Fortran 90 module subroutine} +\label{sec:f90modsubrout} + +Consider +\begin{verbatim} +module fun + subroutine bar() + end subroutine bar +end module fun +\end{verbatim} +\texttt{PyFortranObject} is defined as follows +\begin{verbatim} +static char doc_fun_bar[] = "fun.bar()"; +static PyObject *c_fun_bar(PyObject *self, PyObject *args, + PyObject *keywds, void (*f2py_func)()) { + static char *kwlist[] = {NULL}; + if (!PyArg_ParseTupleAndKeywords(args,keywds,"",kwlist)) + return NULL; + (*f2py_func)(); + return Py_BuildValue(""); +} +static FortranDataDef f2py_fun_def[] = { + {"bar",-1,{-1},0,NULL,(void *)c_fun_bar,doc_fun_bar}, + {NULL} +}; +static void f2py_setup_fun(char *bar) { + f2py_fun_def[0].data = bar; +} +extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); +static void f2py_init_fun() { + F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); +} +void initfoo () { + <snip> + PyDict_SetItemString(d, "fun", PyFortranObject_New(f2py_fun_def,f2py_init_fun)); +} +\end{verbatim} +where auxiliary Fortran function \texttt{f2pyinitfun} is defined as +follows +\begin{verbatim} +subroutine f2pyinitfun(f2pysetupfunc) +use fun +external f2pysetupfunc +call f2pysetupfunc(bar) +end subroutine f2pyinitfun +\end{verbatim} +The following Python session demonstrates how to call Fortran 90 +module function \texttt{bar}: +\begin{verbatim} +>>> import foo +>>> foo.fun.bar() +\end{verbatim} + +\section{Fortran 90 module function} +\label{sec:f90modfunc} + +Consider +\begin{verbatim} +module fun + function bar() + complex bar + end subroutine bar +end module fun +\end{verbatim} +\texttt{PyFortranObject} is defined as follows +\begin{verbatim} +static char doc_fun_bar[] = "bar = fun.bar()"; +static PyObject *c_fun_bar(PyObject *self, PyObject *args, + PyObject *keywds, void (*f2py_func)()) { + complex_float bar; + static char *kwlist[] = {NULL}; + if (!PyArg_ParseTupleAndKeywords(args,keywds,"",kwlist)) + return NULL; + (*f2py_func)(&bar); + return Py_BuildValue("O",pyobj_from_complex_float1(bar)); +} +static FortranDataDef f2py_fun_def[] = { + {"bar",-1,{-1},0,NULL,(void *)c_fun_bar,doc_fun_bar}, + {NULL} +}; +static void f2py_setup_fun(char *bar) { + f2py_fun_def[0].data = bar; +} +extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); +static void f2py_init_fun() { + F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); +} +void initfoo() { + <snip> + PyDict_SetItemString(d, "fun", PyFortranObject_New(f2py_fun_def,f2py_init_fun)); +} +\end{verbatim} +where +\begin{verbatim} +subroutine f2pywrap_fun_bar (barf2pywrap) +use fun +complex barf2pywrap +barf2pywrap = bar() +end + +subroutine f2pyinitfun(f2pysetupfunc) +external f2pysetupfunc,f2pywrap_fun_bar +call f2pysetupfunc(f2pywrap_fun_bar) +end +\end{verbatim} + + +\section{Fortran 90 module data} +\label{sec:f90moddata} + +Consider +\begin{verbatim} +module fun + integer i +end module fun +\end{verbatim} +Then +\begin{verbatim} +static FortranDataDef f2py_fun_def[] = { + {"i",0,{-1},NPY_INT}, + {NULL} +}; +static void f2py_setup_fun(char *i) { + f2py_fun_def[0].data = i; +} +extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); +static void f2py_init_fun() { + F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); +} +void initfoo () { + <snip> + PyDict_SetItemString(d, "fun", + PyFortranObject_New(f2py_fun_def,f2py_init_fun)); +} +\end{verbatim} +where +\begin{verbatim} +subroutine f2pyinitfun(f2pysetupfunc) +use fun +external f2pysetupfunc +call f2pysetupfunc(i) +end subroutine f2pyinitfun +\end{verbatim} +Example usage in Python: +\begin{verbatim} +>>> import foo +>>> foo.fun.i = 4 +\end{verbatim} + +\section{Fortran 90 module allocatable array} +\label{sec:f90modallocarr} + +Consider +\begin{verbatim} +module fun + real, allocatable :: r(:) +end module fun +\end{verbatim} +Then +\begin{verbatim} +static FortranDataDef f2py_fun_def[] = { + {"r",1,{-1},NPY_FLOAT}, + {NULL} +}; +static void f2py_setup_fun(void (*r)()) { + f2py_fun_def[0].func = r; +} +extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); +static void f2py_init_fun() { + F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); +} +void initfoo () { + <snip> + PyDict_SetItemString(d, "fun", PyFortranObject_New(f2py_fun_def,f2py_init_fun)); +} +\end{verbatim} +where +\begin{verbatim} +subroutine f2py_fun_getdims_r(r,s,f2pysetdata) +use fun, only: d => r +external f2pysetdata +logical ns +integer s(*),r,i,j +ns = .FALSE. +if (allocated(d)) then + do i=1,r + if ((size(d,r-i+1).ne.s(i)).and.(s(i).ge.0)) then + ns = .TRUE. + end if + end do + if (ns) then + deallocate(d) + end if +end if +if ((.not.allocated(d)).and.(s(1).ge.1)) then + allocate(d(s(1))) +end if +if (allocated(d)) then + do i=1,r + s(i) = size(d,r-i+1) + end do +end if +call f2pysetdata(d,allocated(d)) +end subroutine f2py_fun_getdims_r + +subroutine f2pyinitfun(f2pysetupfunc) +use fun +external f2pysetupfunc,f2py_fun_getdims_r +call f2pysetupfunc(f2py_fun_getdims_r) +end subroutine f2pyinitfun +\end{verbatim} +Usage in Python: +\begin{verbatim} +>>> import foo +>>> foo.fun.r = [1,2,3,4] +\end{verbatim} + +\section{Callback subroutine} +\label{sec:cbsubr} + +Thanks to Travis Oliphant for working out the basic idea of the +following callback mechanism. + +Consider +\begin{verbatim} +subroutine fun(bar) +external bar +call bar(1) +end +\end{verbatim} +Then +\begin{verbatim} +static char doc_foo8_fun[] = " +Function signature: + fun(bar,[bar_extra_args]) +Required arguments: + bar : call-back function +Optional arguments: + bar_extra_args := () input tuple +Call-back functions: + def bar(e_1_e): return + Required arguments: + e_1_e : input int"; +static PyObject *foo8_fun(PyObject *capi_self, PyObject *capi_args, + PyObject *capi_keywds, void (*f2py_func)()) { + PyObject *capi_buildvalue = NULL; + PyObject *bar_capi = Py_None; + PyTupleObject *bar_xa_capi = NULL; + PyTupleObject *bar_args_capi = NULL; + jmp_buf bar_jmpbuf; + int bar_jmpbuf_flag = 0; + int bar_nofargs_capi = 0; + static char *capi_kwlist[] = {"bar","bar_extra_args",NULL}; + + if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\ + "O!|O!:foo8.fun",\ + capi_kwlist,&PyFunction_Type,&bar_capi,&PyTuple_Type,&bar_xa_capi)) + goto capi_fail; + + bar_nofargs_capi = cb_bar_in_fun__user__routines_nofargs; + if (create_cb_arglist(bar_capi,bar_xa_capi,1,0, + &cb_bar_in_fun__user__routines_nofargs,&bar_args_capi)) { + if ((PyErr_Occurred())==NULL) + PyErr_SetString(foo8_error,"failed in processing argument list for call-back bar." ); + goto capi_fail; + } + + SWAP(bar_capi,cb_bar_in_fun__user__routines_capi,PyObject); + SWAP(bar_args_capi,cb_bar_in_fun__user__routines_args_capi,PyTupleObject); + memcpy(&bar_jmpbuf,&cb_bar_in_fun__user__routines_jmpbuf,sizeof(jmp_buf)); + bar_jmpbuf_flag = 1; + + if ((setjmp(cb_bar_in_fun__user__routines_jmpbuf))) { + if ((PyErr_Occurred())==NULL) + PyErr_SetString(foo8_error,"Failure of a callback function"); + goto capi_fail; + } else + (*f2py_func)(cb_bar_in_fun__user__routines); + + capi_buildvalue = Py_BuildValue(""); +capi_fail: + + if (bar_jmpbuf_flag) { + cb_bar_in_fun__user__routines_capi = bar_capi; + Py_DECREF(cb_bar_in_fun__user__routines_args_capi); + cb_bar_in_fun__user__routines_args_capi = bar_args_capi; + cb_bar_in_fun__user__routines_nofargs = bar_nofargs_capi; + memcpy(&cb_bar_in_fun__user__routines_jmpbuf,&bar_jmpbuf,sizeof(jmp_buf)); + bar_jmpbuf_flag = 0; + } + return capi_buildvalue; +} +extern void F_FUNC(fun,FUN)(); +static FortranDataDef f2py_routine_defs[] = { + {"fun",-1,{-1},0,(char *)F_FUNC(fun,FUN),(void *)foo8_fun,doc_foo8_fun}, + {NULL} +}; +void initfoo8 () { + <snip> + PyDict_SetItemString(d, f2py_routine_defs[0].name, + PyFortranObject_NewAsAttr(&f2py_routine_defs[0])); +} +\end{verbatim} +where +\begin{verbatim} +PyObject *cb_bar_in_fun__user__routines_capi = Py_None; +PyTupleObject *cb_bar_in_fun__user__routines_args_capi = NULL; +int cb_bar_in_fun__user__routines_nofargs = 0; +jmp_buf cb_bar_in_fun__user__routines_jmpbuf; +static void cb_bar_in_fun__user__routines (int *e_1_e_cb_capi) { + PyTupleObject *capi_arglist = cb_bar_in_fun__user__routines_args_capi; + PyObject *capi_return = NULL; + PyObject *capi_tmp = NULL; + int capi_j,capi_i = 0; + + int e_1_e=(*e_1_e_cb_capi); + if (capi_arglist == NULL) + goto capi_fail; + if (cb_bar_in_fun__user__routines_nofargs>capi_i) + if (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyobj_from_int1(e_1_e))) + goto capi_fail; + + capi_return = PyEval_CallObject(cb_bar_in_fun__user__routines_capi, + (PyObject *)capi_arglist); + + if (capi_return == NULL) + goto capi_fail; + if (capi_return == Py_None) { + Py_DECREF(capi_return); + capi_return = Py_BuildValue("()"); + } + else if (!PyTuple_Check(capi_return)) { + capi_tmp = capi_return; + capi_return = Py_BuildValue("(O)",capi_tmp); + Py_DECREF(capi_tmp); + } + capi_j = PyTuple_Size(capi_return); + capi_i = 0; + goto capi_return_pt; +capi_fail: + fprintf(stderr,"Call-back cb_bar_in_fun__user__routines failed.\n"); + Py_XDECREF(capi_return); + longjmp(cb_bar_in_fun__user__routines_jmpbuf,-1); +capi_return_pt: + ; +} +\end{verbatim} +Usage in Python: +\begin{verbatim} +>>> import foo8 as foo +>>> def bar(i): print 'In bar i=',i +... +>>> foo.fun(bar) +In bar i= 1 +\end{verbatim} + +\end{document} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/doc/f2py/hello.f b/doc/f2py/hello.f new file mode 100644 index 000000000..3e0dc6d21 --- /dev/null +++ b/doc/f2py/hello.f @@ -0,0 +1,7 @@ +C File hello.f + subroutine foo (a) + integer a + print*, "Hello from Fortran!" + print*, "a=",a + end + diff --git a/doc/f2py/index.html b/doc/f2py/index.html new file mode 100644 index 000000000..e162ed41a --- /dev/null +++ b/doc/f2py/index.html @@ -0,0 +1,264 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> +<HTML> +<HEAD> +<META name="Author" content="Pearu Peterson"> +<!-- You may add here some keywords (comma separeted list) --> +<META name="Keywords" content="fortran,python,interface,f2py,f2py2e,wrapper,fpig"> +<TITLE>F2PY - Fortran to Python Interface Generator</TITLE> +<LINK rel="stylesheet" type="text/css" href="/styles/userstyle.css"> +</HEAD> + +<BODY> +<!-- Begin of user text --> +<H1>F2PY ­ Fortran to Python Interface Generator</H1> +by <em>Pearu Peterson</em> + +<h2>What's new?</h2> + +See <a href="NEWS.txt">NEWS.txt</a> for the latest changes in <code>f2py</code>. +<dl> + <dt> July ??, 2002 + <dd> Implemented prototype calculator, complete tests for scalar F77 + functions, --help-compiler option. Fixed number of bugs and + removed obsolete features. + <dt> April 4, 2002 + <dd> Fixed a nasty bug of copying one-dimensional non-contiguous arrays. + (Thanks to Travis O. for pointing this out). + <dt> March 26, 2002 + <dd> Bug fixes, turned off F2PY_REPORT_ATEXIT by default. + <dt> March 13, 2002 + <dd> MAC support, fixed incomplete dependency calculator, minor bug fixes. + <dt> March 3, 2002 + <dd> Fixed memory leak and copying of multi-dimensional complex arrays. + <dt> <a href="oldnews.html">Old news</a>. +</dl> + +<h2>Introduction</h2> + +Writing Python C/API wrappers for Fortran routines can be a very +tedious task, especially if a Fortran routine takes more than 20 +arguments but only few of them are relevant for the problems that they +solve. So, I have developed a tool that generates the C/API modules +containing wrapper functions of Fortran routines. I call this +tool as <em>F2PY ­ Fortran to Python Interface Generator</em>. +It is completely written in <a href="http://www.python.org">Python</a> +language and can be called from the command line as <code>f2py</code>. +<em>F2PY</em> (in NumPy) is released under the terms of the NumPy License. + + +<h2><code>f2py</code>, Second Edition</h2> + +The development of <code>f2py</code> started in summer of 1999. +For now (January, 2000) it has reached to stage of being a +complete tool: it scans real Fortran code, creates signature file +that the user can modify, constructs C/API module that can be +complied and imported to Python, and it creates LaTeX documentation +for wrapper functions. Below is a bit longer list of +<code>f2py</code> features: +<ol> + <li> <code>f2py</code> scans real Fortran codes and produces the signature files. + The syntax of the signature files is borrowed from the Fortran 90/95 + language specification with some extensions. + <li> <code>f2py</code> generates a GNU Makefile that can be used + for building shared modules (see below for a list of supported + platforms/compilers). Starting from the third release, + <code>f2py</code> generates <code>setup_modulename.py</code> for + building extension modules using <code>distutils</code> tools. + <li> <code>f2py</code> uses the signature files to produce the wrappers for + Fortran 77 routines and their <code>COMMON</code> blocks. + <li> For <code>external</code> arguments <code>f2py</code> constructs a very flexible + call-back mechanism so that Python functions can be called from + Fortran. + <li> You can pass in almost arbitrary Python objects to wrapper + functions. If needed, <code>f2py</code> takes care of type-casting and + non-contiguous arrays. + <li> You can modify the signature files so that <code>f2py</code> will generate + wrapper functions with desired signatures. <code>depend()</code> + attribute is introduced to control the initialization order of the + variables. <code>f2py</code> introduces <code>intent(hide)</code> + attribute to remove + the particular argument from the argument list of the wrapper + function and <code>intent(c)</code> that is useful for wrapping C +libraries. In addition, <code>optional</code> and +<code>required</code> + attributes are introduced and employed. + <li> <code>f2py</code> supports almost all standard Fortran 77/90/95 constructs + and understands all basic Fortran types, including + (multi-dimensional, complex) arrays and character strings with + adjustable and assumed sizes/lengths. + <li> <code>f2py</code> generates a LaTeX document containing the + documentations of the wrapped functions (argument types, dimensions, + etc). The user can easily add some human readable text to the + documentation by inserting <code>note(<LaTeX text>)</code> attribute to + the definition of routine signatures. + <li> With <code>f2py</code> one can access also Fortran 90/95 + module subroutines from Python. +</ol> + +For more information, see the <a href="usersguide.html">User's +Guide</a> of the tool. Windows users should also take a look at +<a href="win32_notes.txt">f2py HOWTO for Win32</a> (its latest version +can be found <a +href="http://www.numpy.org/Members/eric/f2py_win32">here</a>). + +<h3>Requirements</h3> +<ol> + <li> You'll need <a + href="http://www.python.org/download/">Python</a> + (1.5.2 or later, 2.2 is recommended) to run <code>f2py</code> + (because it uses exchanged module <code>re</code>). + To build generated extension modules with distutils setup script, + you'll need Python 2.x. + <li> You'll need <a + href="http://sourceforge.net/project/?group_id=1369">Numerical + Python</a> + (version 13 or later, 20.3 is recommended) to compile + C/API modules (because they use function + <code>PyArray_FromDimsAndDataAndDescr</code>) +</ol> + +<h3>Download</h3> + +<dl> + <dt> User's Guide: + <dd> <a href="usersguide.html">usersguide.html</a>, + <a href="usersguide.pdf">usersguide.pdf</a>, + <a href="usersguide.ps.gz">usersguide.ps.gz</a>, + <a href="usersguide.dvi">usersguide.dvi</a>. + <dt> Snapshots of the fifth public release: + <dd> <a href="2.x">2.x</a>/<a href="2.x/F2PY-2-latest.tar.gz">F2PY-2-latest.tar.gz</a> + <dt> Snapshots of earlier releases: + <dd> <a href="rel-5.x">rel-5.x</a>, <a href="rel-4.x">rel-4.x</a>, + <a href="rel-3.x">rel-3.x</a>, + <a href="rel-2.x">rel-2.x</a>,<a href="rel-1.x">rel-1.x</a>, + <a href="rel-0.x">rel-0.x</a> +</dl> + +<h3>Installation</h3> + +Unpack the source file, change to directory <code>f2py-?-???</code> +and run <code>python setup.py install</code>. That's it! + +<h3>Platform/Compiler Related Notes</h3> + +<code>f2py</code> has been successfully tested on +<ul> + <li> Intel Linux (MD7.0,RH6.1,RH4.2,Debian woody), Athlon Linux (RH6.1), Alpha Linux (RH5.2,RH6.1) with <a +href="http://gcc.gnu.org/">gcc</a> (versions egcs-2.91.60,egcs-2.91.66, and 2.95.2). + <li> Intel Linux (MD7.0) with <a + href="http://www.psrv.com/index.html">Pacific-Sierra + Research</a> <a href="http://www.psrv.com/lnxf90.html">Personal + Linux VAST/f90 Fortran 90 compiler</a> (version V3.4N5). + <li> Intel Linux (RH6.1) with <a href="http://www.absoft.com/">Absoft F77/F90</a> compilers for Linux. + <li> IRIX64 with <a href="http://gcc.gnu.org/">gcc</a> (2.95.2) and <a +href="http://www.sgi.com/developers/devtools/languages/mipspro.html">MIPSpro +7 Compilers</a> (f77,f90,cc versions 7.30). + <li> Alpha Linux (RH5.2,RH6.1) with <a href="http://www.digital.com/fortran/linux/">Compaq Fortran </a> compiler (version V1.0-920). + <li> Linux with <a href="http://www.nag.co.uk/">NAGWare</a> Fortran + 95 compiler. + <li> <a href="http://developer.intel.com/software/products/compilers/f50/linux/"> + Intel(R) Fortran Compiler for Linux</a> + <li> Windows 2000 with <a href="http://www.mingw.org">mingw32</a>. +</ul> +<code>f2py</code> will probably run on other UN*X systems as +well. Additions to the list of platforms/compilers where +<code>f2py</code> has been successfully used are most welcome. +<P> +<em>Note:</em> +Using Compaq Fortran +compiler on Alpha Linux is succesful unless when +wrapping Fortran callback functions returning +<code>COMPLEX</code>. This applies also for IRIX64. +<P> +<em>Note:</em> +Fortran 90/95 module support is currently tested with Absoft F90, VAST/f90, Intel F90 compilers on Linux (MD7.0,Debian woody). + + +<h3><a name="f2py-users">Mailing list</a></h3> + +There is a mailing list <a +href="http://cens.ioc.ee/pipermail/f2py-users/">f2py-users</a> +available for the users of the <code>f2py</code> +program and it is open for discussion, questions, and answers. You can subscribe +the list <a href="http://cens.ioc.ee/mailman/listinfo/f2py-users">here</a>. + +<h3><a href="http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/">CVS Repository</a></h3> + +<code>f2py</code> is being developed under <a href="http://www.sourcegear.com/CVS">CVS</a> and those who are +interested in the really latest version of <code>f2py</code> (possibly +unstable) can get it from the repository as follows: +<ol> + <li> First you need to login (the password is <code>guest</code>): +<pre> +> cvs -d :pserver:anonymous@cens.ioc.ee:/home/cvs login +</pre> + <li> and then do the checkout: +<pre> +> cvs -z6 -d :pserver:anonymous@cens.ioc.ee:/home/cvs checkout f2py2e +</pre> + <li> In the directory <code>f2py2e</code> you can get the updates by hitting +<pre> +> cvs -z6 update -P -d +</pre> +</ol> +You can browse <code>f2py</code> CVS repository <a href="http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/">here</a>. + +<h2>Related sites</h2> + +<ol> + <li> <a href="http://pfdubois.com/numpy/" target="_top">Numerical Python</a>. + <li> <a href="http://pyfortran.sourceforge.net/" target="_top">Pyfort</a> -- The Python-Fortran connection tool. + <li> <a href="http://starship.python.net/crew/hinsen/scientific.html" target="_top">Scientific Python</a>. + <li> <a href="http://numpy.org/" target="_top">SciPy</a> -- Scientific tools for Python (includes Multipack). + <li> <a href="http://www.fortran.com/fortran/" target="_top">The Fortran Company</a>. + <li> <a href="http://www.j3-fortran.org/" target="_top">Fortran Standards</a>. + + <li> <a href="http://www.fortran.com/fortran/F77_std/rjcnf.html">American National Standard Programming Language FORTRAN ANSI(R) X3.9-1978</a> + <li> <a href="http://www.mathtools.net" target="_top">Mathtools.net</a> -- A technical computing portal for all scientific and engineering needs. + +</ol> + +<!-- End of user text --> +<HR> +<ADDRESS> +<A href="http://validator.w3.org/"><IMG border=0 align=right src="/icons/vh40.gif" alt="Valid HTML 4.0!" height=31 width=88></A> +<A href="http://cens.ioc.ee/~pearu/" target="_top">Pearu Peterson</A> +<A href="mailto:pearu(at)ioc.ee"><pearu(at)ioc.ee></A><BR> +<!-- hhmts start --> +Last modified: Fri Jan 20 14:55:12 MST 2006 +<!-- hhmts end --> +</ADDRESS> +<!-- You may want to comment the following line out when the document is final--> +<!-- Check that the reference is right --> +<!--A href="http://validator.w3.org/check?uri=http://cens.ioc.ee/projects/f2py2e/index.html;ss"> Submit this page for validation</A--> + +<p> +<center> +This <a href="http://www.ctv.es/USERS/irmina/pythonring.html">Python +ring</a> site owned by <a href="mailto:pearu(at)ioc.ee">Pearu Peterson</a>. +<br> +[ + <a href="http://nav.webring.org/cgi-bin/navcgi?ring=python_ring;id=12;prev5">Previous 5 Sites</a> +| + <a href="http://nav.webring.org/cgi-bin/navcgi?ring=python_ring;id=12;prev">Previous</a> +| + <a href="http://nav.webring.org/cgi-bin/navcgi?ring=python_ring;id=12;next">Next</a> +| + <a href="http://nav.webring.org/cgi-bin/navcgi?ring=python_ring;id=12;next5">Next 5 Sites</a> +| + <a href="http://nav.webring.org/cgi-bin/navcgi?ring=python_ring;random">Random Site</a> +| + <a href="http://nav.webring.org/cgi-bin/navcgi?ring=python_ring;list">List Sites</a> +] +</center> +<p> + + + +</BODY> + + +</HTML> + + + diff --git a/doc/f2py/intro.tex b/doc/f2py/intro.tex new file mode 100644 index 000000000..d9625b09c --- /dev/null +++ b/doc/f2py/intro.tex @@ -0,0 +1,158 @@ + +\section{Introduction} +\label{sec:intro} + +\fpy is a command line tool that generates Python C/API modules for +interfacing Fortran~77/90/95 codes and Fortran~90/95 modules from +Python. In general, using \fpy an +interface is produced in three steps: +\begin{itemize} +\item[(i)] \fpy scans Fortran sources and creates the so-called + \emph{signature} file; the signature file contains the signatures of + Fortran routines; the signatures are given in the free format of the + Fortran~90/95 language specification. Latest version of \fpy + generates also a make file for building shared module. + About currently supported compilers see the \fpy home page +\item[(ii)] Optionally, the signature files can be modified manually + in order to dictate how the Fortran routines should be called or + seemed from the Python environment. +\item[(iii)] \fpy reads the signature files and generates Python C/API + modules that can be compiled and imported to Python code. In + addition, a LaTeX document is generated that contains the + documentation of wrapped functions. +\end{itemize} +(Note that if you are satisfied with the default signature that \fpy +generates in step (i), all three steps can be covered with just +one call to \fpy --- by not specifying `\texttt{-h}' flag). +Latest versions of \fpy support so-called \fpy directive that allows +inserting various information about wrapping directly to Fortran +source code as comments (\texttt{<comment char>f2py <signature statement>}). + +The following diagram illustrates the usage of the tool: +\begin{verbatim} +! Fortran file foo.f: + subroutine foo(a) + integer a + a = a + 5 + end +\end{verbatim} +\begin{verbatim} +! Fortran file bar.f: + function bar(a,b) + integer a,b,bar + bar = a + b + end +\end{verbatim} +\begin{itemize} +\item[(i)] \shell{\fpy foo.f bar.f -m foobar -h foobar.pyf} +\end{itemize} +\begin{verbatim} +!%f90 +! Signature file: foobar.pyf +python module foobar ! in + interface ! in :foobar + subroutine foo(a) ! in :foobar:foo.f + integer intent(inout) :: a + end subroutine foo + function bar(a,b) ! in :foobar:bar.f + integer :: a + integer :: b + integer :: bar + end function bar + end interface +end python module foobar +\end{verbatim} +\begin{itemize} +\item[(ii)] Edit the signature file (here I made \texttt{foo}s + argument \texttt{a} to be \texttt{intent(inout)}, see + Sec.~\ref{sec:attributes}). +\item[(iii)] \shell{\fpy foobar.pyf} +\end{itemize} +\begin{verbatim} +/* Python C/API module: foobarmodule.c */ +... +\end{verbatim} +\begin{itemize} +\item[(iv)] \shell{make -f Makefile-foobar} +%\shell{gcc -shared -I/usr/include/python1.5/ foobarmodule.c\bs\\ +%foo.f bar.f -o foobarmodule.so} +\end{itemize} +\begin{verbatim} +Python shared module: foobarmodule.so +\end{verbatim} +\begin{itemize} +\item[(v)] Usage in Python: +\end{itemize} +\vspace*{-4ex} +\begin{verbatim} +>>> import foobar +>>> print foobar.__doc__ +This module 'foobar' is auto-generated with f2py (version:1.174). +The following functions are available: + foo(a) + bar = bar(a,b) +. +>>> print foobar.bar(2,3) +5 +>>> from Numeric import * +>>> a = array(3) +>>> print a,foobar.foo(a),a +3 None 8 +\end{verbatim} +Information about how to call \fpy (steps (i) and (iii)) can be +obtained by executing\\ +\shell{\fpy}\\ +This will print the usage instructions. + Step (iv) is system dependent +(compiler and the locations of the header files \texttt{Python.h} and +\texttt{arrayobject.h}), and so you must know how to compile a shared +module for Python in you system. + +The next Section describes the step (ii) in more detail in order to +explain how you can influence to the process of interface generation +so that the users can enjoy more writing Python programs using your +wrappers that call Fortran routines. Step (v) is covered in +Sec.~\ref{sec:notes}. + + +\subsection{Features} +\label{sec:features} + +\fpy has the following features: +\begin{enumerate} +\item \fpy scans real Fortran codes and produces the signature files. + The syntax of the signature files is borrowed from the Fortran~90/95 + language specification with some extensions. +\item \fpy uses the signature files to produce the wrappers for + Fortran~77 routines and their \texttt{COMMON} blocks. +\item For \texttt{external} arguments \fpy constructs a very flexible + call-back mechanism so that Python functions can be called from + Fortran. +\item You can pass in almost arbitrary Python objects to wrapper + functions. If needed, \fpy takes care of type-casting and + non-contiguous arrays. +\item You can modify the signature files so that \fpy will generate + wrapper functions with desired signatures. \texttt{depend()} + attribute is introduced to control the initialization order of the + variables. \fpy introduces \texttt{intent(hide)} attribute to remove + the particular argument from the argument list of the wrapper + function. In addition, \texttt{optional} and \texttt{required} + attributes are introduced and employed. +\item \fpy supports almost all standard Fortran~77/90/95 constructs + and understands all basic Fortran types, including + (multi-dimensional, complex) arrays and character strings with + adjustable and assumed sizes/lengths. +\item \fpy generates a LaTeX document containing the + documentations of the wrapped functions (argument types, dimensions, + etc). The user can easily add some human readable text to the + documentation by inserting \texttt{note(<LaTeX text>)} attribute to + the definition of routine signatures. +\item \fpy generates a GNU make file that can be used for building + shared modules calling Fortran functions. +\item \fpy supports wrapping Fortran 90/95 module routines. +\end{enumerate} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "f2py2e" +%%% End: diff --git a/doc/f2py/multiarray/array_from_pyobj.c b/doc/f2py/multiarray/array_from_pyobj.c new file mode 100644 index 000000000..237d16dbc --- /dev/null +++ b/doc/f2py/multiarray/array_from_pyobj.c @@ -0,0 +1,323 @@ +/* + * File: array_from_pyobj.c + * + * Description: + * ------------ + * Provides array_from_pyobj function that returns a contigious array + * object with the given dimensions and required storage order, either + * in row-major (C) or column-major (Fortran) order. The function + * array_from_pyobj is very flexible about its Python object argument + * that can be any number, list, tuple, or array. + * + * array_from_pyobj is used in f2py generated Python extension + * modules. + * + * Author: Pearu Peterson <pearu@cens.ioc.ee> + * Created: 13-16 January 2002 + * $Id: array_from_pyobj.c,v 1.1 2002/01/16 18:57:33 pearu Exp $ + */ + + +#define ARR_IS_NULL(arr,mess) \ +if (arr==NULL) { \ + fprintf(stderr,"array_from_pyobj:" mess); \ + return NULL; \ +} + +#define CHECK_DIMS_DEFINED(rank,dims,mess) \ +if (count_nonpos(rank,dims)) { \ + fprintf(stderr,"array_from_pyobj:" mess); \ + return NULL; \ +} + +#define HAS_PROPER_ELSIZE(arr,type_num) \ + ((PyArray_DescrFromType(type_num)->elsize) == (arr)->descr->elsize) + +/* static */ +/* void f2py_show_args(const int type_num, */ +/* const int *dims, */ +/* const int rank, */ +/* const int intent) { */ +/* int i; */ +/* fprintf(stderr,"array_from_pyobj:\n\ttype_num=%d\n\trank=%d\n\tintent=%d\n",\ */ +/* type_num,rank,intent); */ +/* for (i=0;i<rank;++i) */ +/* fprintf(stderr,"\tdims[%d]=%d\n",i,dims[i]); */ +/* } */ + +static +int count_nonpos(const int rank, + const int *dims) { + int i=0,r=0; + while (i<rank) { + if (dims[i] <= 0) ++r; + ++i; + } + return r; +} + +static void lazy_transpose(PyArrayObject* arr); +static int check_and_fix_dimensions(const PyArrayObject* arr, + const int rank, + int *dims); +static +int array_has_column_major_storage(const PyArrayObject *ap); + +static +PyArrayObject* array_from_pyobj(const int type_num, + int *dims, + const int rank, + const int intent, + PyObject *obj) { + /* Note about reference counting + ----------------------------- + If the caller returns the array to Python, it must be done with + Py_BuildValue("N",arr). + Otherwise, if obj!=arr then the caller must call Py_DECREF(arr). + */ + +/* f2py_show_args(type_num,dims,rank,intent); */ + + if (intent & F2PY_INTENT_CACHE) { + /* Don't expect correct storage order or anything reasonable when + returning cache array. */ + if ((intent & F2PY_INTENT_HIDE) + || (obj==Py_None)) { + PyArrayObject *arr = NULL; + CHECK_DIMS_DEFINED(rank,dims,"optional,intent(cache) must" + " have defined dimensions.\n"); + arr = (PyArrayObject *)PyArray_FromDims(rank,dims,type_num); + ARR_IS_NULL(arr,"FromDims failed: optional,intent(cache)\n"); + if (intent & F2PY_INTENT_OUT) + Py_INCREF(arr); + return arr; + } + if (PyArray_Check(obj) + && ISCONTIGUOUS((PyArrayObject *)obj) + && HAS_PROPER_ELSIZE((PyArrayObject *)obj,type_num) + ) { + if (check_and_fix_dimensions((PyArrayObject *)obj,rank,dims)) + return NULL; /*XXX: set exception */ + if (intent & F2PY_INTENT_OUT) + Py_INCREF(obj); + return (PyArrayObject *)obj; + } + ARR_IS_NULL(NULL,"intent(cache) must be contiguous array with a proper elsize.\n"); + } + + if (intent & F2PY_INTENT_HIDE) { + PyArrayObject *arr = NULL; + CHECK_DIMS_DEFINED(rank,dims,"intent(hide) must have defined dimensions.\n"); + arr = (PyArrayObject *)PyArray_FromDims(rank,dims,type_num); + ARR_IS_NULL(arr,"FromDims failed: intent(hide)\n"); + if (intent & F2PY_INTENT_OUT) { + if ((!(intent & F2PY_INTENT_C)) && (rank>1)) { + lazy_transpose(arr); + arr->flags &= ~NPY_CONTIGUOUS; + } + Py_INCREF(arr); + } + return arr; + } + + if (PyArray_Check(obj)) { /* here we have always intent(in) or + intent(inout) */ + + PyArrayObject *arr = (PyArrayObject *)obj; + int is_cont = (intent & F2PY_INTENT_C) ? + (ISCONTIGUOUS(arr)) : (array_has_column_major_storage(arr)); + + if (check_and_fix_dimensions(arr,rank,dims)) + return NULL; /*XXX: set exception */ + + if ((intent & F2PY_INTENT_COPY) + || (! (is_cont + && HAS_PROPER_ELSIZE(arr,type_num) + && PyArray_CanCastSafely(arr->descr->type_num,type_num)))) { + PyArrayObject *tmp_arr = NULL; + if (intent & F2PY_INTENT_INOUT) { + ARR_IS_NULL(NULL,"intent(inout) array must be contiguous and" + " with a proper type and size.\n") + } + if ((rank>1) && (! (intent & F2PY_INTENT_C))) + lazy_transpose(arr); + if (PyArray_CanCastSafely(arr->descr->type_num,type_num)) { + tmp_arr = (PyArrayObject *)PyArray_CopyFromObject(obj,type_num,0,0); + ARR_IS_NULL(arr,"CopyFromObject failed: array.\n"); + } else { + tmp_arr = (PyArrayObject *)PyArray_FromDims(arr->nd, + arr->dimensions, + type_num); + ARR_IS_NULL(tmp_arr,"FromDims failed: array with unsafe cast.\n"); + if (copy_ND_array(arr,tmp_arr)) + ARR_IS_NULL(NULL,"copy_ND_array failed: array with unsafe cast.\n"); + } + if ((rank>1) && (! (intent & F2PY_INTENT_C))) { + lazy_transpose(arr); + lazy_transpose(tmp_arr); + tmp_arr->flags &= ~NPY_CONTIGUOUS; + } + arr = tmp_arr; + } + if (intent & F2PY_INTENT_OUT) + Py_INCREF(arr); + return arr; + } + + if ((obj==Py_None) && (intent & F2PY_OPTIONAL)) { + PyArrayObject *arr = NULL; + CHECK_DIMS_DEFINED(rank,dims,"optional must have defined dimensions.\n"); + arr = (PyArrayObject *)PyArray_FromDims(rank,dims,type_num); + ARR_IS_NULL(arr,"FromDims failed: optional.\n"); + if (intent & F2PY_INTENT_OUT) { + if ((!(intent & F2PY_INTENT_C)) && (rank>1)) { + lazy_transpose(arr); + arr->flags &= ~NPY_CONTIGUOUS; + } + Py_INCREF(arr); + } + return arr; + } + + if (intent & F2PY_INTENT_INOUT) { + ARR_IS_NULL(NULL,"intent(inout) argument must be an array.\n"); + } + + { + PyArrayObject *arr = (PyArrayObject *) \ + PyArray_ContiguousFromObject(obj,type_num,0,0); + ARR_IS_NULL(arr,"ContiguousFromObject failed: not a sequence.\n"); + if (check_and_fix_dimensions(arr,rank,dims)) + return NULL; /*XXX: set exception */ + if ((rank>1) && (! (intent & F2PY_INTENT_C))) { + PyArrayObject *tmp_arr = NULL; + lazy_transpose(arr); + arr->flags &= ~NPY_CONTIGUOUS; + tmp_arr = (PyArrayObject *) PyArray_CopyFromObject((PyObject *)arr,type_num,0,0); + Py_DECREF(arr); + arr = tmp_arr; + ARR_IS_NULL(arr,"CopyFromObject(Array) failed: intent(fortran)\n"); + lazy_transpose(arr); + arr->flags &= ~NPY_CONTIGUOUS; + } + if (intent & F2PY_INTENT_OUT) + Py_INCREF(arr); + return arr; + } + +} + + /*****************************************/ + /* Helper functions for array_from_pyobj */ + /*****************************************/ + +static +int array_has_column_major_storage(const PyArrayObject *ap) { + /* array_has_column_major_storage(a) is equivalent to + transpose(a).iscontiguous() but more efficient. + + This function can be used in order to decide whether to use a + Fortran or C version of a wrapped function. This is relevant, for + example, in choosing a clapack or flapack function depending on + the storage order of array arguments. + */ + int sd; + int i; + sd = ap->descr->elsize; + for (i=0;i<ap->nd;++i) { + if (ap->dimensions[i] == 0) return 1; + if (ap->strides[i] != sd) return 0; + sd *= ap->dimensions[i]; + } + return 1; +} + +static +void lazy_transpose(PyArrayObject* arr) { + /* + Changes the order of array strides and dimensions. This + corresponds to the lazy transpose of a Numeric array in-situ. + Note that this function is assumed to be used even times for a + given array. Otherwise, the caller should set flags &= ~NPY_CONTIGUOUS. + */ + int rank,i,s,j; + rank = arr->nd; + if (rank < 2) return; + + for(i=0,j=rank-1;i<rank/2;++i,--j) { + s = arr->strides[i]; + arr->strides[i] = arr->strides[j]; + arr->strides[j] = s; + s = arr->dimensions[i]; + arr->dimensions[i] = arr->dimensions[j]; + arr->dimensions[j] = s; + } +} + +static +int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,int *dims) { + /* + This function fills in blanks (that are -1's) in dims list using + the dimensions from arr. It also checks that non-blank dims will + match with the corresponding values in arr dimensions. + */ + const int arr_size = (arr->nd)?PyArray_Size((PyObject *)arr):1; + + if (rank > arr->nd) { /* [1,2] -> [[1],[2]]; 1 -> [[1]] */ + int new_size = 1; + int free_axe = -1; + int i; + /* Fill dims where -1 or 0; check dimensions; calc new_size; */ + for(i=0;i<arr->nd;++i) { + if (dims[i] >= 0) { + if (dims[i]!=arr->dimensions[i]) { + fprintf(stderr,"%d-th dimension must be fixed to %d but got %d\n", + i,dims[i],arr->dimensions[i]); + return 1; + } + if (!dims[i]) dims[i] = 1; + } else { + dims[i] = arr->dimensions[i] ? arr->dimensions[i] : 1; + } + new_size *= dims[i]; + } + for(i=arr->nd;i<rank;++i) + if (dims[i]>1) { + fprintf(stderr,"%d-th dimension must be %d but got 0 (not defined).\n", + i,dims[i]); + return 1; + } else if (free_axe<0) + free_axe = i; + else + dims[i] = 1; + if (free_axe>=0) { + dims[free_axe] = arr_size/new_size; + new_size *= dims[free_axe]; + } + if (new_size != arr_size) { + fprintf(stderr,"confused: new_size=%d, arr_size=%d (maybe too many free" + " indices)\n",new_size,arr_size); + return 1; + } + } else { + int i; + for (i=rank;i<arr->nd;++i) + if (arr->dimensions[i]>1) { + fprintf(stderr,"too many axes: %d, expected rank=%d\n",arr->nd,rank); + return 1; + } + for (i=0;i<rank;++i) + if (dims[i]>=0) { + if (arr->dimensions[i]!=dims[i]) { + fprintf(stderr,"%d-th dimension must be fixed to %d but got %d\n", + i,dims[i],arr->dimensions[i]); + return 1; + } + if (!dims[i]) dims[i] = 1; + } else + dims[i] = arr->dimensions[i]; + } + return 0; +} + +/* End of file: array_from_pyobj.c */ diff --git a/doc/f2py/multiarray/bar.c b/doc/f2py/multiarray/bar.c new file mode 100644 index 000000000..350636ea6 --- /dev/null +++ b/doc/f2py/multiarray/bar.c @@ -0,0 +1,15 @@ + +#include <stdio.h> + +void bar(int *a,int m,int n) { + int i,j; + printf("C:"); + printf("m=%d, n=%d\n",m,n); + for (i=0;i<m;++i) { + printf("Row %d:\n",i+1); + for (j=0;j<n;++j) + printf("a(i=%d,j=%d)=%d\n",i,j,a[n*i+j]); + } + if (m*n) + a[0] = 7777; +} diff --git a/doc/f2py/multiarray/foo.f b/doc/f2py/multiarray/foo.f new file mode 100644 index 000000000..f8c39c4d1 --- /dev/null +++ b/doc/f2py/multiarray/foo.f @@ -0,0 +1,13 @@ + subroutine foo(a,m,n) + integer a(m,n), m,n,i,j + print*, "F77:" + print*, "m=",m,", n=",n + do 100,i=1,m + print*, "Row ",i,":" + do 50,j=1,n + print*, "a(i=",i,",j=",j,") = ",a(i,j) + 50 continue + 100 continue + if (m*n.gt.0) a(1,1) = 77777 + end + diff --git a/doc/f2py/multiarray/fortran_array_from_pyobj.txt b/doc/f2py/multiarray/fortran_array_from_pyobj.txt new file mode 100644 index 000000000..e351e8e89 --- /dev/null +++ b/doc/f2py/multiarray/fortran_array_from_pyobj.txt @@ -0,0 +1,284 @@ + + _____________________________________________________________ + / Proposed internal structure for f2py generated extension \ + < modules regarding the issues with different storage-orders > + \ of multi-dimensional matrices in Fortran and C. / + ============================================================= + +Author: Pearu Peterson +Date: 14 January, 2001 + +Definitions: +============ + +In the following I will use the following definitions: + +1) A matrix is a mathematical object that represents a collection of + objects (elements), usually visualized in a table form, and one can + define a set of various (algebraic,etc) operations for matrices. + One can think of a matrix as a defintion of a certain mapping: + (i) |--> A(i) + where i belongs to the set of indices (an index itself can be a + sequence of objects, for example, a sequence of integers) and A(i) + is an element from a specified set, for example, a set of fruits. + Symbol A then denotes a matrix of fruits. + +2) An array is a storage object that represents a collection of + objects stored in a certain systematic way, for example, as an + ordered sequence in computer memory. + +In order to manipulate matrices using computers, one must store matrix +elements in computer memory. In the following, I will assume that the +elements of a matrix is stored as an array. There is no unique way in +which order one should save matrix elements in the array. However, in +C and Fortran programming languages, two, unfortunately different, +conventions are used. + +Aim: +==== + +The purpose of this writing is to work out an interface for Python +language so that C and Fortran routines can be called without +bothering about how multi-dimensional matrices are stored in memory. +For example, accessing a matrix element A[i,j] in Python will be +equivalent to accessing the same matrix in C, using A[i][j], or in +Fortran, using A(i,j). + +External conditions: +==================== + +In C programming language, it is custom to think that matrices are +stored in the so-called row-major order, that is, a matrix is stored +row by row, each row is as a contiguous array in computer memory. + +In Fortran programming language, matrices are stored in the +column-major order: each column is a contiguous array in computer +memory. + +In Python programming language, matrices can be stored using Python +Numeric array() function that uses internally C approach, that is, +elements of matrices are stored in row-major order. For example, +A = array([[1,2,3],[4,5,6]]) represents a 2-by-3 matrix + + / 1 2 3 \ + | | + \ 4 5 6 / + +and its elements are stored in computer memory as the following array: + + 1 2 3 4 5 6 + +The same matrix, if used in Fortran, would be stored in computer +memory as the following array: + + 1 4 2 5 3 6 + +Problem and solution: +===================== + +A problem arises if one wants to use the same matrix both in C and in +Fortran functions. Then the difference in storage order of a matrix +elements must be taken into account. This technical detail can be very +confusing even for an experienced programmer. This is because when +passing a matrix to a Fortran subroutine, you must (mentally or +programmically) transpose the matrix and when the subroutine returns, +you must transpose it back. + +As will be discussed below, there is a way to overcome these +difficulties in Python by creating an interface between Python and +Fortran code layers that takes care of this transition internally. So +that if you will read the manual pages of the Fortran codes, then you +need not to think about how matrices are actually stored, the storage +order will be the same, seemingly. + +Python / C / Fortran interface: +=============================== + +The interface between Python and Fortran codes will use the following +Python Numeric feature: transposing a Numeric array does not involve +copying of its data but just permuting the dimensions and strides of +the array (the so-called lazy transpose). + +However, when passing a Numeric array data pointer to Fortran or C +function, the data must be contiguous in memory. If it is not, then +data is rearranged inplace. I don't think that it can be avoided. +This is certainly a penalty hit to performance. However, one can +easily avoid it by creating a Numeric array with the right storage +order, so that after transposing, the array data will be contiguous in +memory and the data pointer can safely passed on to the Fortran +subroutine. This lazy-transpose operation will be done within the +interface and users need not to bother about this detail anymore (that +is, after they initialize Numeric array with matrix elements using the +proper order. Of course, the proper order depends on the target +function: C or Fortran). The interface should be smart enough to +minimize the need of real-transpose operations and the need to +additional memory storage as well. + +Statement of the problem: +========================= + +Consider a M-by-N matrix A of integers, where M and N are the number A +rows and columns, respectively. + +In Fortran language, the storing array of this matrix can be defined +as follows: + + integer A(M,N) + +in C: + + int A[M][N]; + +and in Python: + + A = Numeric.zeros((M,N),'i') + +Consider also the corresponding Fortran and C functions that +that use matrix arguments: + +Fortran: + subroutine FUN(A,M,N) + integer A(M,N) + ... + end +C: + void cun(int *a,int m,int n) { + ... + } + +and the corresponding Python interface signatures: + + def py_fun(a): + ... + def py_cun(a): + ... + +Main goal: +========== + +Our goal is to generate Python C/API functions py_fun and py_cun such +that their usage in Python would be identical. The cruical part of +their implementation are in functions that take a PyObject and +return a PyArrayObject such that it is contiguous and its data pointer +is suitable for passing on to the arguments of C or Fortran functions. +The prototypes of these functions are: + +PyArrayObject* fortran_array_from_pyobj( + int typecode, + int *dims, + int rank, + int intent, + PyObject *obj); + +and + +PyArrayObject* c_array_from_pyobj( + int typecode, + int *dims, + int rank, + int intent, + PyObject *obj); + +for wrapping Fortran and C functions, respectively. + +Pseudo-code for fortran_array_from_pyobj: +========================================= + +if type(obj) is ArrayType: + #raise not check(len(ravel(obj)) >= dims[0]*dims[1]*...*dims[rank-1]) + if obj.typecode is typecode: + if is_contiguous(obj): + transpose_data_inplace(obj) # real-transpose + set_transpose_strides(obj) # lazy-transpose + Py_INCREF(obj); + return obj + set_transpose_strides(obj) + if is_contiguous(obj): + set_transpose_strides(obj) + Py_INCREF(obj); + return obj + else: + tmp_obj = PyArray_ContiguousFromObject(obj,typecode,0,0) + swap_datapointer_and_typeinfo(obj,tmp_obj) + Py_DECREF(tmp_obj); + set_transpose_strides(obj) + Py_INCREF(obj); + return obj + else: + tmp_obj = PyArray_FromDims(rank,dims,typecode) + set_transpose_strides(tmp_obj) + if intent in [in,inout]: + copy_ND_array(obj,tmp_obj) + swap_datapointer_and_typeinfo(obj,tmp_obj) + Py_DECREF(tmp_obj); + Py_INCREF(obj); + return obj +elif obj is None: # happens when only intent is 'hide' + tmp_obj = PyArray_FromDims(rank,dims,typecode) + if intent is out: + set_transpose_strides(tmp_obj) + # otherwise tmp_obj->data is used as a work array + Py_INCREF(tmp_obj) + return tmp_obj +else: + tmp_obj = PyArray_ContiguousFromObject(obj,typecode,0,0) + #raise not check(len(ravel(obj)) >= dims[0]*dims[1]*...*dims[rank-1]) + set_transpose_strides(tmp_obj) + transpose_data_inplace(tmp_obj) + Py_INCREF(tmp_obj) + return tmp_obj + +Notes: + 1) CPU expensive tasks are in transpose_data_inplace and + copy_ND_array, PyArray_ContiguousFromObject. + 2) Memory expensive tasks are in PyArray_FromDims, + PyArray_ContiguousFromObject + 3) Side-effects are expected when set_transpose_strides and + transpose_data_inplace are used. For example: + >>> a = Numeric([[1,2,3],[4,5,6]],'d') + >>> a.is_contiguous() + 1 + >>> py_fun(a) + >>> a.typecode() + 'i' + >>> a.is_contiguous() + 0 + >>> transpose(a).is_contiguous() + 1 + +Pseudo-code for c_array_from_pyobj: +=================================== + +if type(obj) is ArrayType: + #raise not check(len(ravel(obj)) >= dims[0]*dims[1]*...*dims[rank-1]) + if obj.typecode is typecode: + if is_contiguous(obj): + Py_INCREF(obj); + return obj + else: + tmp_obj = PyArray_ContiguousFromObject(obj,typecode,0,0) + swap_datapointer_and_typeinfo(obj,tmp_obj) + Py_DECREF(tmp_obj); + Py_INCREF(obj); + return obj + else: + tmp_obj = PyArray_FromDims(rank,dims,typecode) + if intent in [in,inout]: + copy_ND_array(obj,tmp_obj) + swap_datapointer_and_typeinfo(obj,tmp_obj) + Py_DECREF(tmp_obj); + Py_INCREF(obj); + return obj +elif obj is None: # happens when only intent is 'hide' + tmp_obj = PyArray_FromDims(rank,dims,typecode) + Py_INCREF(tmp_obj) + return tmp_obj +else: + tmp_obj = PyArray_ContiguousFromObject(obj,typecode,0,0) + #raise not check(len(ravel(obj)) >= dims[0]*dims[1]*...*dims[rank-1]) + Py_INCREF(tmp_obj) + return tmp_obj + + +14 January, 2002 +Pearu Peterson <pearu@cens.ioc.ee> diff --git a/doc/f2py/multiarray/fun.pyf b/doc/f2py/multiarray/fun.pyf new file mode 100644 index 000000000..ed5d1923f --- /dev/null +++ b/doc/f2py/multiarray/fun.pyf @@ -0,0 +1,89 @@ +!%f90 -*- f90 -*- + +! Example: +! Using f2py for wrapping multi-dimensional Fortran and C arrays +! [NEW APPROACH, use it with f2py higher than 2.8.x] +! $Id: fun.pyf,v 1.3 2002/01/18 10:06:50 pearu Exp $ + +! Usage (with gcc compiler): +! f2py -c fun.pyf foo.f bar.c + +python module fun ! in + interface ! in :fun + +! >>> from Numeric import * +! >>> import fun +! >>> a=array([[1,2,3],[4,5,6]]) + + subroutine foo(a,m,n) ! in :fun:foo.f + integer dimension(m,n) :: a + intent(in,out,copy) :: a + integer optional,check(shape(a,0)==m),depend(a) :: m=shape(a,0) + integer optional,check(shape(a,1)==n),depend(a) :: n=shape(a,1) + end subroutine foo + +! >>> print fun.foo.__doc__ +! foo - Function signature: +! a = foo(a,[m,n]) +! Required arguments: +! a : input rank-2 array('i') with bounds (m,n) +! Optional arguments: +! m := shape(a,0) input int +! n := shape(a,1) input int +! Return objects: +! a : rank-2 array('i') with bounds (m,n) + +! >>> print fun.foo(a) +! F77: +! m= 2, n= 3 +! Row 1: +! a(i= 1,j= 1) = 1 +! a(i= 1,j= 2) = 2 +! a(i= 1,j= 3) = 3 +! Row 2: +! a(i= 2,j= 1) = 4 +! a(i= 2,j= 2) = 5 +! a(i= 2,j= 3) = 6 +! [[77777 2 3] +! [ 4 5 6]] + + + subroutine bar(a,m,n) + intent(c) + intent(c) bar + integer dimension(m,n) :: a + intent(in,out) :: a + integer optional,check(shape(a,0)==m),depend(a) :: m=shape(a,0) + integer optional,check(shape(a,1)==n),depend(a) :: n=shape(a,1) + intent(in) m,n + end subroutine bar + +! >>> print fun.bar.__doc__ +! bar - Function signature: +! a = bar(a,[m,n]) +! Required arguments: +! a : input rank-2 array('i') with bounds (m,n) +! Optional arguments: +! m := shape(a,0) input int +! n := shape(a,1) input int +! Return objects: +! a : rank-2 array('i') with bounds (m,n) + +! >>> print fun.bar(a) +! C:m=2, n=3 +! Row 1: +! a(i=0,j=0)=1 +! a(i=0,j=1)=2 +! a(i=0,j=2)=3 +! Row 2: +! a(i=1,j=0)=4 +! a(i=1,j=1)=5 +! a(i=1,j=2)=6 +! [[7777 2 3] +! [ 4 5 6]] + + end interface +end python module fun + +! This file was auto-generated with f2py (version:2.9.166). +! See http://cens.ioc.ee/projects/f2py2e/ diff --git a/doc/f2py/multiarray/run.pyf b/doc/f2py/multiarray/run.pyf new file mode 100644 index 000000000..bb12a439b --- /dev/null +++ b/doc/f2py/multiarray/run.pyf @@ -0,0 +1,91 @@ +!%f90 -*- f90 -*- + +! Example: +! Using f2py for wrapping multi-dimensional Fortran and C arrays +! [OLD APPROACH, do not use it with f2py higher than 2.8.x] +! $Id: run.pyf,v 1.1 2002/01/14 15:49:46 pearu Exp $ + +! Usage (with gcc compiler): +! f2py -c run.pyf foo.f bar.c -DNO_APPEND_FORTRAN + +python module run ! in + interface ! in :run + +! >>> from Numeric import * +! >>> import run +! >>> a=array([[1,2,3],[4,5,6]],'i') + + subroutine foo(a,m,n) + fortranname foo_ + integer dimension(m,n) :: a + integer optional,check(shape(a,1)==m),depend(a) :: m=shape(a,1) + integer optional,check(shape(a,0)==n),depend(a) :: n=shape(a,0) + end subroutine foo + +! >>> print run.foo.__doc__ +! foo - Function signature: +! foo(a,[m,n]) +! Required arguments: +! a : input rank-2 array('i') with bounds (n,m) +! Optional arguments: +! m := shape(a,1) input int +! n := shape(a,0) input int + +! >>> run.foo(a) +! F77: +! m= 3, n= 2 +! Row 1: +! a(i= 1,j= 1) = 1 +! a(i= 1,j= 2) = 4 +! Row 2: +! a(i= 2,j= 1) = 2 +! a(i= 2,j= 2) = 5 +! Row 3: +! a(i= 3,j= 1) = 3 +! a(i= 3,j= 2) = 6 + +! >>> run.foo(transpose(a)) +! F77: +! m= 2, n= 3 +! Row 1: +! a(i= 1,j= 1) = 1 +! a(i= 1,j= 2) = 2 +! a(i= 1,j= 3) = 3 +! Row 2: +! a(i= 2,j= 1) = 4 +! a(i= 2,j= 2) = 5 +! a(i= 2,j= 3) = 6 + + subroutine bar(a,m,n) + intent(c) + integer dimension(m,n) :: a + integer optional,check(shape(a,0)==m),depend(a) :: m=shape(a,0) + integer optional,check(shape(a,1)==n),depend(a) :: n=shape(a,1) + end subroutine bar + +! >>> print run.bar.__doc__ +! bar - Function signature: +! bar(a,[m,n]) +! Required arguments: +! a : rank-2 array('i') with bounds (m,n) +! Optional arguments: +! m := shape(a,0) int +! n := shape(a,1) int + +! >>> run.bar(a) +! C:m=2, n=3 +! Row 1: +! a(i=0,j=0)=1 +! a(i=0,j=1)=2 +! a(i=0,j=2)=3 +! Row 2: +! a(i=1,j=0)=4 +! a(i=1,j=1)=5 +! a(i=1,j=2)=6 + + + end interface +end python module run + +! This file was auto-generated with f2py (version:2.8.172). +! See http://cens.ioc.ee/projects/f2py2e/ diff --git a/doc/f2py/multiarray/transpose.txt b/doc/f2py/multiarray/transpose.txt new file mode 100644 index 000000000..925e7a399 --- /dev/null +++ b/doc/f2py/multiarray/transpose.txt @@ -0,0 +1,1126 @@ +From: Phil Garner (garner@signal.dra.hmg.gb) + Subject: In place matrix transpose + Newsgroups: sci.math.num-analysis + Date: 1993-08-05 06:35:06 PST + + +Someone was talking about matrix transposes earlier on. It's a +curious subject. I found that an in-place transpose is about 12 times +slower than the trivial copying method. + +Here's somthing I nicked from netlib and translated into C to do the +in-place one for those that are interested: (matrix must be in one +block) + + +typedef float scalar; /* float -> double for double precision */ + +/* + * In Place Matrix Transpose + * From: Algorithm 380 collected algorithms from ACM. + * Converted to C by Phil Garner + * + * Algorithm appeared in comm. ACM, vol. 13, no. 05, + * p. 324. + */ +int trans(scalar *a, unsigned m, unsigned n, int *move, int iwrk) +{ + scalar b; + int i, j, k, i1, i2, ia, ib, ncount, kmi, Max, mn; + + /* + * a is a one-dimensional array of length mn=m*n, which + * contains the m by n matrix to be transposed. + * move is a one-dimensional array of length iwrk + * used to store information to speed up the process. the + * value iwrk=(m+n)/2 is recommended. Return val indicates the + * success or failure of the routine. + * normal return = 0 + * errors + * -2, iwrk negative or zero. + * ret > 0, (should never occur). in this case + * we set ret equal to the final value of i when the search + * is completed but some loops have not been moved. + * check arguments and initialise + */ + + /* Function Body */ + if (n < 2 || m < 2) + return 0; + if (iwrk < 1) + return -2; + + /* If matrix is square, exchange elements a(i,j) and a(j,i). */ + if (n == m) + { + for (i = 0; i < m - 1; ++i) + for (j = i + 1; j < m; ++j) + { + i1 = i + j * m; + i2 = j + i * m; + b = a[i1]; + a[i1] = a[i2]; + a[i2] = b; + } return 0; + } + + /* Non square matrix */ + ncount = 2; + for (i = 0; i < iwrk; ++i) + move[i] = 0; + + if (n > 2) + /* Count number,ncount, of single points. */ + for (ia = 1; ia < n - 1; ++ia) + { + ib = ia * (m - 1) / (n - 1); + if (ia * (m - 1) != ib * (n - 1)) + continue; + ++ncount; + i = ia * m + ib; + if (i > iwrk) + continue; + move[i] = 1; + } + + /* Set initial values for search. */ + mn = m * n; + k = mn - 1; + kmi = k - 1; + Max = mn; + i = 1; + + while (1) + { + /* Rearrange elements of a loop. */ + /* At least one loop must be re-arranged. */ + i1 = i; + while (1) + { + b = a[i1]; + while (1) + { + i2 = n * i1 - k * (i1 / m); + if (i1 <= iwrk) + move[i1 - 1] = 2; + ++ncount; + if (i2 == i || i2 >= kmi) + { + if (Max == kmi || i2 == i) + break; + Max = kmi; + } + a[i1] = a[i2]; + i1 = i2; + } + + /* Test for symmetric pair of loops. */ + a[i1] = b; + if (ncount >= mn) + return 0; + if (i2 == Max || Max == kmi) + break; + Max = kmi; + i1 = Max; + } + + /* Search for loops to be rearranged. */ + while (1) + { + Max = k - i; + ++i; + kmi = k - i; + if (i > Max) + return i; + if (i <= iwrk) + { + if (move[i-1] < 1) + break; + continue; + } + if (i == n * i - k * (i / m)) + continue; + i1 = i; + while (1) + { + i2 = n * i1 - k * (i1 / m); + if (i2 <= i || i2 >= Max) + break; + i1 = i2; + } + if (i2 == i) + break; + } + } /* End never reached */ +} + +-- + ,----------------------------- ______ + ____ | Phil Garner. \___| |/ \ \ ____ +/__/ `--, _L__L\_ | garner@signal.dra.hmg.gb | _|`---' \_/__/ `--, +`-0---0-' `-0--0-' `--OO-------------------O-----' `---0---' `-0---0-' + + From: Murray Dow (mld900@anusf.anu.edu.au) + Subject: Re: In place matrix transpose + Newsgroups: sci.math.num-analysis + Date: 1993-08-09 19:45:57 PST + + +In article <23qmp3INN3gl@mentor.dra.hmg.gb>, garner@signal.dra.hmg.gb (Phil Garner) writes: +|> Someone was talking about matrix transposes earlier on. It's a +|> curious subject. I found that an in-place transpose is about 12 times +|> slower than the trivial copying method. +|> + +Algorithm 380 from CACM is sloweer than ALG 467. Here are my times +from a VP2200 vector computer. Note that the CACM algorithms are scalar. +Times are in seconds, for a 900*904 matrix: + +380 NAG 467 disc copy +1.03 1.14 .391 .177 + +Compare two vector algortihms, one I wrote and the second a matrix +copy: + +My Alg Matrix copy +.0095 .0097 + +Conclusions: dont use Alg 380 from Netlib. If you have the available memory, +do a matrix copy. If you don't have the memory, I will send you my algorithm +when I have published it. +-- +Murray Dow GPO Box 4 Canberra ACT 2601 Australia +Supercomputer Facility Phone: +61 6 2495028 +Australian National University Fax: +61 6 2473425 +mld900@anusf.anu.edu.au + +============================================================================= + +From: Mark Smotherman (mark@hubcap.clemson.edu) + Subject: Matrix transpose benchmark [was Re: MIPS R8000 == TFP?] + Newsgroups: comp.arch, comp.benchmarks, comp.sys.super + Date: 1994-07-01 06:35:51 PST + + +mccalpin@perelandra.cms.udel.edu (John D. McCalpin) writes: + +> +>Of course, these results are all for the naive algorithm. I would be +>interested to see what an efficient blocked algorithm looks like. +>Anyone care to offer one? There is clearly a lot of performance +>to be gained by the effort.... + +Here is a matrix transpose benchmark generator. Enter something like + + 10d10eij; + +and you get a benchmark program with tiles of size 10 for the i and j +inner loops. Please email code improvements and flames. + +Enjoy! + + +/*--------------------------------------------------------------------------- + + Matrix Transpose Generator + + Copyright 1993, Dept. of Computer Science, Clemson University + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appears in all copies. + + Clemson University and its Dept. of Computer Science make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied warranty. + + Original author: Mark Smotherman + + -------------------------------------------------------------------------*/ + + +/* tpgen.c version 1.0 + * + * generate a matrix transpose loop nest, with tiling and unrolling + * (timing code using getrusage is included in the generated program) + * + * mark smotherman + * mark@cs.clemson.edu + * clemson university + * 9 july 1993 + * + * a loop nest can be described by the order of its loop indices, so + * this program takes as input a simple language describing these indices: + * <number>d ==> generate tiling loop for index i with step size of <number> + * <number>e ==> generate tiling loop for index j with step size of <number> + * <number>i ==> generate loop for index i with unrolling factor of <number> + * <number>j ==> generate loop for index j with unrolling factor of <number> + * ; ==> input terminator (required) + * rules are: + * i,j tokens must appear + * if d appears, it must appear before i + * if e appears, it must appear before j + * ; must appear + * matrix size is controlled by #define N in this program. + * + * this code was adapted from mmgen.c v1.2 and extended to generate pre- + * condition loops for unrolling factors that do not evenly divide the + * matrix size (or the tiling step size for loop nests with a tiling loop). + * note that this program only provides a preconditioning loop for the + * innermost loop. unrolling factors for non-innermost loops that do not + * evenly divide the matrix size (or step size) are not supported. + * + * my interest in this program generator is to hook it to a sentence + * generator and a minimum execution time finder, that is + * while((sentence=sgen())!=NULL){ + * genprogram=tpgen(sentence); + * system("cc -O4 genprogram.c"); + * system("a.out >> tpresults"); + * } + * findmintime(tpresults); + * this will find the optimum algorithm for the host system via an + * exhaustive search. + * + * please report bugs and suggestions for enhancements to me. + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#define N 500 + +#define ALLOC1 temp1=(struct line *)malloc(sizeof(struct line));\ +temp1->indentcnt=indentcnt; + +#define LINK1 temp1->next=insertbefore;\ +insertafter->next=temp1;\ +insertafter=temp1; + +#define INSERT1 temp1->next=start;\ +start=temp1; + +#define ALLOC2 temp1=(struct line *)malloc(sizeof(struct line));\ +temp2=(struct line *)malloc(sizeof(struct line));\ +temp1->indentcnt=indentcnt;\ +temp2->indentcnt=indentcnt++; + +#define LINK2 temp1->next=temp2;\ +temp2->next=insertbefore;\ +insertafter->next=temp1;\ +insertafter=temp1;\ +insertbefore=temp2; + +struct line{ int indentcnt; char line[256]; struct line *next; }; + +int indentcnt; +int iflag,jflag; +int ijflag,jiflag; +int dflag,eflag; +int counter; +int iistep,jjstep; +int iunroll,junroll; +int precond; + +char c; +int i,ttp,nt; +char *p0; +char tptype[80]; +char number[10]; + +struct line *start,*head,*insertafter,*insertbefore,*temp1,*temp2; + +void processloop(); +void processstmt(); + +main(){ + + indentcnt=0; + iflag=jflag=0; + ijflag=jiflag=0; + dflag=eflag=0; + iunroll=junroll=0; + counter=1; + precond=0; + ttp=0; + + start=NULL; + ALLOC2 + sprintf(temp1->line,"/* begin */\nt_start=second();\n"); + sprintf(temp2->line,"/* end */\nt_end = second();\n"); + head=temp1; temp1->next=temp2; temp2->next=NULL; + insertafter=temp1; insertbefore=temp2; + + while((c=getchar())!=';'){ + tptype[ttp++]=c; + if(isdigit(c)){ + nt=0; + while(isdigit(c)){ + number[nt++]=c; + c=getchar(); + if(c==';'){ fprintf(stderr,"unexpected ;!\n"); exit(1); } + tptype[ttp++]=c; + } + number[nt]='\0'; + sscanf(number,"%d",&counter); + } + switch(c){ + case 'd': + if(iflag){ fprintf(stderr,"d cannot appear after i!\n"); exit(1); } + dflag++; + ALLOC1 + sprintf(temp1->line,"#define IISTEP %d\n",counter); + INSERT1 + iistep=counter; + counter=1; + ALLOC2 + sprintf(temp1->line,"for(ii=0;ii<%d;ii+=IISTEP){\n",N); + sprintf(temp2->line,"}\n",N); + LINK2 + ALLOC1 + sprintf(temp1->line,"it=min(ii+IISTEP,%d);\n",N); + LINK1 + break; + case 'e': + if(jflag){ fprintf(stderr,"e cannot appear after j!\n"); exit(1); } + eflag++; + ALLOC1 + sprintf(temp1->line,"#define JJSTEP %d\n",counter); + INSERT1 + jjstep=counter; + counter=1; + ALLOC2 + sprintf(temp1->line,"for(jj=0;jj<%d;jj+=JJSTEP){\n",N); + sprintf(temp2->line,"}\n",N); + LINK2 + ALLOC1 + sprintf(temp1->line,"jt=min(jj+JJSTEP,%d);\n",N); + LINK1 + break; + case 'i': + iunroll=counter; + counter=1; + iflag++; if(jflag) jiflag++; + if(dflag) precond=iistep%iunroll; else precond=N%iunroll; + if(precond&&(jiflag==0)){ + fprintf(stderr,"unrolling factor for outer loop i\n"); + fprintf(stderr," does not evenly divide matrix/step size!\n"); + exit(1); + } + if(dflag&&(iunroll>1)&&(N%iistep)){ + fprintf(stderr,"with unrolling of i, step size for tiled loop ii\n"); + fprintf(stderr," does not evenly divide matrix size!\n"); + exit(1); + } + processloop('i',dflag,iunroll,precond,junroll); + break; + case 'j': + junroll=counter; + counter=1; + jflag++; if(iflag) ijflag++; + if(eflag) precond=jjstep%junroll; else precond=N%junroll; + if(precond&&(ijflag==0)){ + fprintf(stderr,"unrolling factor for outer loop j\n"); + fprintf(stderr," does not evenly divide matrix/step size!\n"); + exit(1); + } + if(eflag&&(junroll>1)&&(N%jjstep)){ + fprintf(stderr,"with unrolling of j, step size for tiled loop jj\n"); + fprintf(stderr," does not evenly divide matrix size!\n"); + exit(1); + } + processloop('j',eflag,junroll,precond,iunroll); + break; + default: break; + } + } + processstmt(); + + tptype[ttp++]=c; + + if((iflag==0)||(jflag==0)){ + fprintf(stderr, + "one of the loops (i,j) was not specified!\n"); + exit(1); + } + + temp1=start; + while(temp1!=NULL){ + printf("%s",temp1->line); + temp1=temp1->next; + } + printf("#include <stdio.h>\n"); + printf("#include <sys/time.h>\n"); + printf("#include <sys/resource.h>\n"); + if(dflag|eflag) printf("#define min(a,b) ((a)<=(b)?(a):(b))\n"); + printf("double second();\n"); + printf("double t_start,t_end,t_total;\n"); + printf("int times;\n"); + printf("\ndouble b[%d][%d],dummy[10000],bt[%d][%d];\n\nmain(){\n" + ,N,N,N,N); + if(precond) printf(" int i,j,n;\n"); else printf(" int i,j;\n"); + if(dflag) printf(" int ii,it;\n"); + if(eflag) printf(" int jj,jt;\n"); + printf("/* set coefficients so that result matrix should have \n"); + printf(" * column entries equal to column index\n"); + printf(" */\n"); + printf(" for (i=0;i<%d;i++){\n",N); + printf(" for (j=0;j<%d;j++){\n",N); + printf(" b[i][j] = (double) i;\n"); + printf(" }\n"); + printf(" }\n"); + printf("\n t_total=0.0;\n for(times=0;times<10;times++){\n\n",N); + printf("/* try to flush cache */\n"); + printf(" for(i=0;i<10000;i++){\n",N); + printf(" dummy[i] = 0.0;\n"); + printf(" }\n"); + printf("%s",head->line); + temp1=head->next; + while(temp1!=NULL){ + for(i=0;i<temp1->indentcnt;i++) printf(" "); + while((p0=strstr(temp1->line,"+0"))!=NULL){ + *p0++=' '; *p0=' '; + } + printf("%s",temp1->line); + temp1=temp1->next; + } + printf("\n t_total+=t_end-t_start;\n }\n"); + printf("/* check result */\n"); + printf(" for (j=0;j<%d;j++){\n",N); + printf(" for (i=0;i<%d;i++){\n",N); + printf(" if (bt[i][j]!=((double)j)){\n"); + printf(" fprintf(stderr,\"error in bt[%cd][%cd]",'%','%'); + printf("\\n\",i,j);\n"); + printf(" fprintf(stderr,\" for %s\\n\");\n",tptype); + printf(" exit(1);\n"); + printf(" }\n"); + printf(" }\n"); + printf(" }\n"); + tptype[ttp]='\0'; + printf(" printf(\"%c10.2f secs\",t_total);\n",'%'); + printf(" printf(\" for 10 runs of %s\\n\");\n",tptype); + printf("}\n"); + printf("double second(){\n"); + printf(" void getrusage();\n"); + printf(" struct rusage ru;\n"); + printf(" double t;\n"); + printf(" getrusage(RUSAGE_SELF,&ru);\n"); + printf(" t = ((double)ru.ru_utime.tv_sec) +\n"); + printf(" ((double)ru.ru_utime.tv_usec)/1.0e6;\n"); + printf(" return t;\n"); + printf("}\n"); + +} + +void processloop(index,flag,unroll,precond,unroll2) +char index; +int flag,unroll,precond,unroll2; +{ + char build[80],temp[40]; + int n; + if(precond){ + ALLOC1 + sprintf(temp1->line,"/* preconditioning loop for unrolling factor */\n"); + LINK1 + if(unroll2==1){ + build[0]='\0'; + if(flag){ + if(index='i') + sprintf(temp,"n=IISTEP%c%d; ",'%',unroll); + else + sprintf(temp,"n=JJSTEP%c%d; ",'%',unroll); + strcat(build,temp); + sprintf(temp,"for(%c=%c%c;%c<%c%c+n;%c++) ",index,index,index, + index,index,index,index); + strcat(build,temp); + }else{ + sprintf(temp,"n=%d%c%d; ",N,'%',unroll); + strcat(build,temp); + sprintf(temp,"for(%c=0;%c<n;%c++) ",index,index,index); + strcat(build,temp); + } + sprintf(temp,"bt[i][j]=b[j][i];\n"); + strcat(build,temp); + ALLOC1 + sprintf(temp1->line,"%s\n",build); + LINK1 + }else{ + if(flag){ + ALLOC1 + if(index=='i') + sprintf(temp1->line,"n=IISTEP%c%d;\n",'%',unroll); + else + sprintf(temp1->line,"n=JJSTEP%c%d;\n",'%',unroll); + LINK1 + ALLOC1 + sprintf(temp1->line,"for(%c=%c%c;%c<%c%c+n;%c++){\n",index,index,index, + index,index,index,index); + LINK1 + }else{ + ALLOC1 + sprintf(temp1->line,"n=%d%c%d;\n",N,'%',unroll); + LINK1 + ALLOC1 + sprintf(temp1->line,"for(%c=0;%c<n;%c++){\n",index,index,index); + LINK1 + } + if(index=='i'){ + for(n=0;n<unroll2;n++){ + ALLOC1 + sprintf(temp1->line," bt[i][j+%d]=b[j+%d][i];\n",n,n); + LINK1 + } + }else{ + for(n=0;n<unroll2;n++){ + ALLOC1 + sprintf(temp1->line," bt[i+%d][j]=b[j][i+%d];\n",n,n); + LINK1 + } + } + ALLOC1 + sprintf(temp1->line,"}\n"); + LINK1 + } + ALLOC2 + if(flag){ + sprintf(temp1->line,"for(%c=%c%c+n;%c<%ct;%c+=%d){\n",index,index,index, + index,index,index,unroll); + }else{ + sprintf(temp1->line,"for(%c=n;%c<%d;%c+=%d){\n",index,index,N,index, + unroll); + } + sprintf(temp2->line,"}\n",N); + LINK2 + }else{ + ALLOC2 + if(unroll==1){ + if(flag){ + sprintf(temp1->line,"for(%c=%c%c;%c<%ct;%c++){\n",index,index,index, + index,index,index); + }else{ + sprintf(temp1->line,"for(%c=0;%c<%d;%c++){\n",index,index,N,index); + } + }else{ + if(flag){ + sprintf(temp1->line,"for(%c=%c%c;%c<%ct;%c+=%d){\n",index,index,index, + index,index,index,unroll); + }else{ + sprintf(temp1->line,"for(%c=0;%c<%d;%c+=%d){\n",index,index,N,index, + unroll); + } + } + sprintf(temp2->line,"}\n",N); + LINK2 + } +} + +void processstmt() +{ + int i,j; + for(i=0;i<iunroll;i++){ + for(j=0;j<junroll;j++){ + ALLOC1 + sprintf(temp1->line,"bt[i+%d][j+%d]=b[j+%d][i+%d];\n",i,j,j,i); + LINK1 + } + } +} +-- +Mark Smotherman, Computer Science Dept., Clemson University, Clemson, SC + +======================================================================= +From: has (h.genceli@bre.com) + Subject: transpose of a nxm matrix stored in a vector !!! + Newsgroups: sci.math.num-analysis + Date: 2000/07/25 + + +If I have a matrix nrows x ncols, I can store it in a vector. +so A(i,j) is really a[i*ncols+j]. So really TRANS of A +(say B) is really is also a vector B where + +0<=i b[j*nrows+i] <nrows, 0<=j<ncols +b[j*nrows+i] = a[i*ncols+j]. + +Fine but I want to use only one array a to do this transformation. + +i.e a[j*nrows+i] = a[i*ncols+j]. this will itself +erase some elements so each time a swap is necessary in a loop. + +temp = a[j*nrows+i] +a[j*nrows+i] = a[i*ncols+j] +a[i*ncols+j] = temp + +but still this will lose some info as it is, so indexing +should have more intelligence in it ???? anybody +can give me a lead here, thanks. + +Has + + From: wei-choon ng (wng@ux8.cso.uiuc.edu) + Subject: Re: transpose of a nxm matrix stored in a vector !!! + Newsgroups: sci.math.num-analysis + Date: 2000/07/25 + + +has <h.genceli@bre.com> wrote: +> If I have a matrix nrows x ncols, I can store it in a vector. +> so A(i,j) is really a[i*ncols+j]. So really TRANS of A +> (say B) is really is also a vector B where + +[snip] + +Hey, if you just want to do a transpose-matrix vector multiply, there is +no need to explicitly store the transpose matrix in another array and +doubling the storage! + +W.C. +-- + + From: Robin Becker (robin@jessikat.fsnet.co.uk) + Subject: Re: transpose of a nxm matrix stored in a vector !!! + Newsgroups: sci.math.num-analysis + Date: 2000/07/25 + + +In article <snr532fo3j1180@corp.supernews.com>, has <h.genceli@bre.com> +writes +>If I have a matrix nrows x ncols, I can store it in a vector. +>so A(i,j) is really a[i*ncols+j]. So really TRANS of A +>(say B) is really is also a vector B where +> +>0<=i b[j*nrows+i] <nrows, 0<=j<ncols +>b[j*nrows+i] = a[i*ncols+j]. +> +>Fine but I want to use only one array a to do this transformation. +> +>i.e a[j*nrows+i] = a[i*ncols+j]. this will itself +>erase some elements so each time a swap is necessary in a loop. +> +>temp = a[j*nrows+i] +>a[j*nrows+i] = a[i*ncols+j] +>a[i*ncols+j] = temp +> +>but still this will lose some info as it is, so indexing +>should have more intelligence in it ???? anybody +>can give me a lead here, thanks. +> +>Has +> +> +> + +void dmx_transpose(unsigned n, unsigned m, double* a, double* b) +{ + unsigned size = m*n; + if(b!=a){ + real *bmn, *aij, *anm; + bmn = b + size; /*b+n*m*/ + anm = a + size; + while(b<bmn) for(aij=a++;aij<anm; aij+=n ) *b++ = *aij; + } + else if(size>3){ + unsigned i,row,column,current; + for(i=1, size -= 2;i<size;i++){ + current = i; + do { + /*current = row+n*column*/ + column = current/m; + row = current%m; + current = n*row + column; + } while(current < i); + + if (current >i) { + real temp = a[i]; + a[i] = a[current]; + a[current] = temp; + } + } + } +} +-- +Robin Becker + + From: E. Robert Tisdale (edwin@netwood.net) + Subject: Re: transpose of a nxm matrix stored in a vector !!! + Newsgroups: sci.math.num-analysis + Date: 2000/07/25 + + +Take a look at +The C++ Scalar, Vector, Matrix and Tensor class library + + http://www.netwood.net/~edwin/svmt/ + +<Type><System>SubVector& + <Type><System>SubVector::transpose(Extent p, Extent q) { + <Type><System>SubVector& + v = *this; + if (1 < p && 1 < q) { + // A vector v of extent n = qp is viewed as a q by p matrix U and + // a p by q matrix V where U_{ij} = v_{p*i+j} and V_{ij} = v_{q*i+j}. + // The vector v is modified in-place so that V is the transpose of U. + // The algorithm searches for every sequence k_s of S indices + // such that a circular shift of elements v_{k_s} <-- v_{k_{s+1}} + // and v_{k_{S-1}} <-- v_{k_0} effects an in-place transpose. + Extent n = q*p; + Extent m = 0; // count up to n-2 + Offset l = 0; // 1 <= l <= n-2 + while (++l < n-1 && m < n-2) { + Offset k = l; + Offset j = k; + while (l < (k = (j%p)*q + j/p)) { // Search backward for k < l. + j = k; + } + // If a sequence of indices beginning with l has any index k < l, + // it has already been transposed. The sequence length S = 1 + // and diagonal element v_k is its own transpose if k = j. + // Skip every index sequence that has already been transposed. + if (k == l) { // a new sequence + if (k < j) { // with 1 < S + TYPE x = v[k]; // save v_{k_0} + do { + v[k] = v[j]; // v_{k_{s}} <-- v_{k_{s+1}} + k = j; + ++m; + } while (l < (j = (k%q)*p + k/q)); + v[k] = x; // v_{k_{S-1}} <-- v_{k_0} + } + ++m; + } + } + } return v; + } + + + +<Type><System>SubVector& + +Read the rest of this message... (50 more lines) + + From: Victor Eijkhout (eijkhout@disco.cs.utk.edu) + Subject: Re: transpose of a nxm matrix stored in a vector !!! + Newsgroups: sci.math.num-analysis + Date: 2000/07/25 + + +"Alan Miller" <amiller @ vic.bigpond.net.au> writes: + +> The attached routine does an in situ transpose. +> begin 666 Dtip.f90 +> M4U5"4D]55$E.12!D=&EP("AA+"!N,2P@;C(L(&YD:6TI#0HA("TM+2TM+2TM + +Hm. F90? You're not silently allocating a temporary I hope? + +(Why did you have to encode this? Now I have to save, this decode, ... +and all for plain ascii?) + +-- +Victor Eijkhout +"When I was coming up, [..] we knew exactly who the they were. It was us +versus them, and it was clear who the them was were. Today, we are not +so sure who the they are, but we know they're there." [G.W. Bush] + + From: Alan Miller (amiller_@_vic.bigpond.net.au) + Subject: Re: transpose of a nxm matrix stored in a vector !!! + Newsgroups: sci.math.num-analysis + Date: 2000/07/25 + + +Victor Eijkhout wrote in message ... +>"Alan Miller" <amiller @ vic.bigpond.net.au> writes: +> +>> The attached routine does an in situ transpose. +>> begin 666 Dtip.f90 +>> M4U5"4D]55$E.12!D=&EP("AA+"!N,2P@;C(L(&YD:6TI#0HA("TM+2TM+2TM +> +>Hm. F90? You're not silently allocating a temporary I hope? +> +>(Why did you have to encode this? Now I have to save, this decode, ... +>and all for plain ascii?) +> + +I know the problem. +I sometimes use a Unix system, and have to use decode64 to read +attachments. On the other hand, Windows wraps lines around, +formats then and generally makes the code unreadable. + +The straight code for dtip (double transpose in place) is attached +this time. + +>-- +>Victor Eijkhout + + +-- +Alan Miller, Retired Scientist (Statistician) +CSIRO Mathematical & Information Sciences +Alan.Miller -at- vic.cmis.csiro.au +http://www.ozemail.com.au/~milleraj +http://users.bigpond.net.au/amiller/ + + +================================================================= + +From: Darran Edmundson (dedmunds@sfu.ca) + Subject: array reordering algorithm? + Newsgroups: sci.math.num-analysis + Date: 1995/04/30 + + +A code I've written refers to a complex array as two separate real arrays. +However, I have a canned subroutine which expects a single array where the +real and imaginary values alternate. Essentially I have a case of mismatched +data structures, yet for reasons that I'd rather not go into, I'm stuck with them. + +Assuming that the two real arrays A and B are sequential in memory, and +that the single array of alternating real/imaginary values C shares the same +space, what I need is a porting subroutine that remaps the data from one format +to the other - using as little space as possible. + +I think of the problem as follows. Imagine an array of dimension 10 containing +the values 1,3,5,7,9,2,4,6,8,10 in this order. + + A(1) / 1 \ C(1) + A(2) | 3 | C(2) + A(3) | 5 | C(3) + A(4) | 7 | C(4) + A(5) \ 9 | C(5) + | + B(1) / 2 | C(6) + B(2) | 4 | C(7) + B(3) | 6 | C(8) + B(4) | 8 | C(9) + B(5) \ 10 / C(10) + +Given that I know this initial pattern, I want to sort the array C in-place *without +making comparisons*. That is, the algorithm can only depend on the initial +knowledge of the pattern. Do you see what a sort is going to do? It will +make the A and B arrays alternate, i.e. C(1)=A(1), C(2)=B(1), C(3)=A(2), +C(4)=B(2), etc. It's not a real sort though because I can't actually refer to the +values above (i.e. no comparisons) because A and B will be holding real data, +not this contrived pattern. The pattern above exists though - it's the +natural ordering in memory of A and B. + +Either pair swapping only or a small amount of workspace can be used. The +in-place is important - imagine scaling this problem up to an +array of 32 or 64 million double precision values and you can easily see how +duplicating the array is not a feasible solution. + +Any ideas? I've been stumped on this for a day and a half now. + +Darran Edmundson +dedmunds@sfu.ca + + From: Roger Critchlow (rec@elf115.elf.org) + Subject: Re: array reordering algorithm? + Newsgroups: sci.math.num-analysis + Date: 1995/04/30 + + + Any ideas? I've been stumped on this for a day and a half now. + +Here's some code for in situ permutations of arrays that I wrote +a few years ago. It all started from the in situ transposition +algorithms in the Collected Algorithms of the ACM, the references +for which always get lost during the decryption from fortran. + +This is the minimum space algorithm. All you need to supply is +a function which computes the new order array index from the old +order array index. + +If you can spare n*m bits to record the indexes of elements which +have been permuted, then you can speed things up. + +-- rec -- + +------------------------------------------------------------------------ +/* +** Arbitrary in situ permutations of an m by n array of base type TYPE. +** Copyright 1995 by Roger E Critchlow Jr, rec@elf.org, San Francisco, CA. +** Fair use permitted, caveat emptor. +*/ +typedef int TYPE; + +int transposition(int ij, int m, int n) /* transposition about diagonal from upper left to lower right */ +{ return ((ij%m)*n+ (ij/m)); } + +int countertrans(int ij, int m, int n) /* transposition about diagonal from upper right to lower left */ +{ return ((m-1-(ij%m))*n+ (n-1-(ij/m))); } + +int rotate90cw(int ij, int m, int n) /* 90 degree clockwise rotation */ +{ return ((m-1-(ij%m))*n+ (ij/m)); } + +int rotate90ccw(int ij, int m, int n) /* 90 degree counter clockwise rotation */ +{ return ((ij%m)*n+ (n-1-(ij/m))); } + +int rotate180(int ij, int m, int n) /* 180 degree rotation */ +{ return ((m-1-(ij/n))*n+ (n-1-(ij%n))); } + +int reflecth(int ij, int m, int n) /* reflection across horizontal plane */ +{ return ((m-1-(ij/n))*n+ (ij%n)); } + +int reflectv(int ij, int m, int n) /* reflection across vertical plane */ +{ return ((ij/n)*n+ (n-1-(ij%n))); } + +int in_situ_permutation(TYPE a[], int m, int n, int (*origination)(int ij, int m, int n)) +{ + int ij, oij, dij, n_to_do; + TYPE b; + n_to_do = m*n; + for (ij = 0; ij < m*n && n_to_do > 0; ij += 1) { + /* Test for previously permuted */ + for (oij = origination(ij,m,n); oij > ij; oij = origination(oij,m,n)) + ; + if (oij < ij) + continue; + /* Chase the cycle */ + dij = ij; + b = a[ij]; + for (oij = origination(dij,m,n); oij != ij; oij = origination(dij,m,n)) { + a[dij] = a[oij]; + dij = oij; + n_to_do -= 1; + } + a[dij] = b; + n_to_do -= 1; + } return 0; +} + +#define TESTING 1 +#if TESTING + +/* fill a matrix with sequential numbers, row major ordering */ +void fill_matrix_rows(a, m, n) TYPE *a; int m, n; +{ + int i, j; + for (i = 0; i < m; i += 1) + for (j = 0; j < n; j += 1) + a[i*n+j] = i*n+j; +} + +/* fill a matrix with sequential numbers, column major ordering */ +void fill_matrix_cols(a, m, n) TYPE *a; int m, n; +{ + int i, j; + for (i = 0; i < m; i += 1) + for (j = 0; j < n; j += 1) + a[i*n+j] = j*m+i; +} + +/* test a matrix for sequential numbers, row major ordering */ +int test_matrix_rows(a, m, n) TYPE *a; int m, n; +{ + int i, j, o; + for (o = i = 0; i < m; i += 1) + for (j = 0; j < n; j += 1) + o += a[i*n+j] != i*n+j; + return o; +} + +/* test a matrix for sequential numbers, column major ordering */ +int test_matrix_cols(a, m, n) TYPE *a; int m, n; +{ + int i, j, o; + for (o = i = 0; i < m; i += 1) + for (j = 0; j < n; j += 1) + o += a[i*n+j] != j*m+i; + return o; +} + +/* print a matrix */ +void print_matrix(a, m, n) TYPE *a; int m, n; +{ + char *format; + int i, j; + if (m*n < 10) format = "%2d"; + if (m*n < 100) format = "%3d"; + if (m*n < 1000) format = "%4d"; + if (m*n < 10000) format = "%5d"; + for (i = 0; i < m; i += 1) { + for (j = 0; j < n; j += 1) + printf(format, a[i*n+j]); + printf("\n"); + } +} + +#if TEST_TRANSPOSE +#define MAXSIZE 1000 + +main() +{ + int i, j, m, n, o; + TYPE a[MAXSIZE]; + for (m = 1; m < sizeof(a)/sizeof(a[0]); m += 1) + for (n = 1; m*n < sizeof(a)/sizeof(a[0]); n += 1) { + fill_matrix_rows(a, m, n); /* {0 1} {2 3} */ + if (o = transpose(a, m, n)) + printf(">> transpose returned %d for a[%d][%d], row major\n", o, m, n); + if ((o = test_matrix_cols(a, n, m)) != 0) /* {0 2} {1 3} */ + printf(">> transpose made %d mistakes for a[%d][%d], row major\n", o, m, n); + /* column major */ + fill_matrix_rows(a, m, n); + if (o = transpose(a, m, n)) + printf(">> transpose returned %d for a[%d][%d], column major\n", o, m, n); + if ((o = test_matrix_cols(a, n, m)) != 0) + printf(">> transpose made %d mistakes for a[%d][%d], column major\n", o, m, n); + } return 0; +} +#endif /* TEST_TRANSPOSE */ + + +#define TEST_DISPLAY 1 +#if TEST_DISPLAY +main(argc, argv) int argc; char *argv[]; +{ + TYPE *a; + int m = 5, n = 5; + extern void *malloc(); + if (argc > 1) { + m = atoi(argv[1]); + if (argc > 2) + n = atoi(argv[2]); + } + a = malloc(m*n*sizeof(TYPE)); + + printf("matrix\n"); + fill_matrix_rows(a, m, n); + print_matrix(a, m, n); + printf("transposition\n"); + in_situ_permutation(a, m, n, transposition); + print_matrix(a, n, m); + + printf("counter transposition\n"); + fill_matrix_rows(a, m, n); + in_situ_permutation(a, m, n, countertrans); + print_matrix(a, n, m); + + printf("rotate 90 degrees clockwise\n"); + fill_matrix_rows(a, m, n); + in_situ_permutation(a, m, n, rotate90cw); + print_matrix(a, n, m); + + printf("rotate 90 degrees counterclockwise\n"); + fill_matrix_rows(a, m, n); + in_situ_permutation(a, m, n, rotate90ccw); + print_matrix(a, n, m); + + printf("rotate 180 degrees\n"); + fill_matrix_rows(a, m, n); + in_situ_permutation(a, m, n, rotate180); + print_matrix(a, m, n); + + printf("reflect across horizontal\n"); + fill_matrix_rows(a, m, n); + in_situ_permutation(a, m, n, reflecth); + print_matrix(a, m, n); + + printf("reflect across vertical\n"); + fill_matrix_rows(a, m, n); + in_situ_permutation(a, m, n, reflectv); + print_matrix(a, m, n); + + return 0; +} + +#endif +#endif diff --git a/doc/f2py/multiarrays.txt b/doc/f2py/multiarrays.txt new file mode 100644 index 000000000..75aeaab9a --- /dev/null +++ b/doc/f2py/multiarrays.txt @@ -0,0 +1,119 @@ +From pearu@ioc.ee Thu Dec 30 09:58:01 1999 +Date: Fri, 26 Nov 1999 12:02:42 +0200 (EET) +From: Pearu Peterson <pearu@ioc.ee> +To: Users of f2py2e -- Curtis Jensen <cjensen@be-research.ucsd.edu>, + Vladimir Janku <vjanku@kvet.sk>, + Travis Oliphant <Oliphant.Travis@mayo.edu> +Subject: Multidimensional arrays in f2py2e + + +Hi! + +Below I will describe how f2py2e wraps Fortran multidimensional arrays as +it constantly causes confusion. As for example, consider Fortran code + + subroutine foo(l,m,n,a) + integer l,m,n + real*8 a(l,m,n) + .. + end +Running f2py2e with -h flag, it generates the following signature + +subroutine foo(l,m,n,a) + integer optional,check(shape(a,2)==l),depend(a) :: l=shape(a,2) + integer optional,check(shape(a,1)==m),depend(a) :: m=shape(a,1) + integer optional,check(shape(a,0)==n),depend(a) :: n=shape(a,0) + real*8 dimension(l,m,n),check(rank(a)==3) :: a +end subroutine foo + +where parameters l,m,n are considered optional and they are initialized in +Python C/API code using the array a. Note that a can be also a proper +list, that is, asarray(a) should result in a rank-3 array. But then there +is an automatic restriction that elements of a (in Python) are not +changeable (in place) even if Fortran subroutine changes the array a (in +C,Fortran). + +Hint: you can attribute the array a with 'intent(out)' which causes foo to +return the array a (in Python) if you are to lazy to define a=asarray(a) +before the call to foo (in Python). + +Calling f2py2e without the switch -h, a Python C/API module will be +generated. After compiling it and importing it to Python +>>> print foo.__doc__ +shows +None = foo(a,l=shape(a,2),m=shape(a,1),n=shape(a,0)) + +You will notice that f2py2e has changed the order of arguments putting the +optional ones at the end of the argument list. +Now, you have to be careful when specifying the parameters l,m,n (though +situations where you need this should be rare). A proper definition +of the array a should be, say + + a = zeros(n,m,l) + +Note that the dimensions l,m,n are in reverse, that is, the array a should +be transposed when feeding it to the wrapper. + +Hint (and a performance hit): To be always consistent with fortran +arrays, you can define, for example + a = zeros(l,m,n) +and call from Python + foo(transpose(a),l,m,n) +which is equivalent with the given Fortran call + call foo(l,m,n,a) + +Another hint (not recommended, though): If you don't like optional +arguments feature at all and want to be strictly consistent with Fortran +signature, that is, you want to call foo from Python as + foo(l,m,n,a) +then you should edit the signature to +subroutine foo(l,m,n,a) + integer :: l + integer :: m + integer :: n + real*8 dimension(l,m,n),check(rank(a)==3),depend(l,m,n), & + check(shape(a,2)==l,shape(a,1)==m,shape(a,0)==n):: a +end +Important! Note that now the array a should depend on l,m,n +so that the checks can be performed in the proper order. +(you cannot check, say, shape(a,2)==l before initializing a or l) +(There are other ways to edit the signature in order to get the same +effect but they are not so safe and I will not discuss about them here). + +Hint: If the array a should be a work array (as used frequently in +Fortran) and you a too lazy (its good lazyness;) to provide it (in Python) +then you can define it as optional by ediding the signature: +subroutine foo(l,m,n,a) + integer :: l + integer :: m + integer :: n + real*8 dimension(l,m,n),check(rank(a)==3),depend(l,m,n), & + check(shape(a,2)==l,shape(a,1)==m,shape(a,0)==n):: a + optional a +end +Note again that the array a must depend on l,m,n. Then the array a will be +allocated in the Python C/API module. Not also that +>>> print foo.__doc__ +shows then +None = foo(l,m,n,a=) +Performance hint: If you call the given foo lots of times from Python then +you don't want to allocate/deallocate the memory in each call. So, it is +then recommended to define a temporary array in Python, for instance +>>> tmp = zeros(n,m,l) +>>> for i in ...: +>>> foo(l,m,n,a=tmp) + +Important! It is not good at all to define + >>> tmp = transpose(zeros(l,m,n)) +because tmp will be then a noncontiguous array and there will be a +huge performance hit as in Python C/API a new array will be allocated and +also a copying of arrays will be performed elementwise! +But + >>> tmp = asarray(transpose(zeros(l,m,n))) +is still ok. + +I hope that the above answers lots of your (possible) questions about +wrapping Fortran multidimensional arrays with f2py2e. + +Regards, + Pearu diff --git a/doc/f2py/notes.tex b/doc/f2py/notes.tex new file mode 100644 index 000000000..2746b049d --- /dev/null +++ b/doc/f2py/notes.tex @@ -0,0 +1,310 @@ + +\section{Calling wrapper functions from Python} +\label{sec:notes} + +\subsection{Scalar arguments} +\label{sec:scalars} + +In general, for scalar argument you can pass in in +addition to ordinary Python scalars (like integers, floats, complex +values) also arbitrary sequence objects (lists, arrays, strings) --- +then the first element of a sequence is passed in to the Fortran routine. + +It is recommended that you always pass in scalars of required type. This +ensures the correctness as no type-casting is needed. +However, no exception is raised if type-casting would produce +inaccurate or incorrect results! For example, in place of an expected +complex value you can give an integer, or vice-versa (in the latter case only +a rounded real part of the complex value will be used). + +If the argument is \texttt{intent(inout)} then Fortran routine can change the +value ``in place'' only if you pass in a sequence object, for +instance, rank-0 array. Also make sure that the type of an array is of +correct type. Otherwise type-casting will be performed and you may +get inaccurate or incorrect results. The following example illustrates this +\begin{verbatim} +>>> a = array(0) +>>> calculate_pi(a) +>>> print a +3 +\end{verbatim} + +If you pass in an ordinary Python scalar in place of +\texttt{intent(inout)} variable, it will be used as an input argument +since +Python +scalars cannot not be changed ``in place'' (all Python scalars +are immutable objects). + +\subsection{String arguments} +\label{sec:strings} + +You can pass in strings of arbitrary length. If the length is greater than +required, only a required part of the string is used. If the length +is smaller than required, additional memory is allocated and fulfilled +with `\texttt{\bs0}'s. + +Because Python strings are immutable, \texttt{intent(inout)} argument +expects an array version of a string --- an array of chars: +\texttt{array("<string>")}. +Otherwise, the change ``in place'' has no effect. + + +\subsection{Array arguments} +\label{sec:arrays} + +If the size of an array is relatively large, it is \emph{highly + recommended} that you pass in arrays of required type. Otherwise, +type-casting will be performed which includes the creation of new +arrays and their copying. If the argument is also +\texttt{intent(inout)}, the wasted time is doubled. So, pass in arrays +of required type! + +On the other hand, there are situations where it is perfectly all +right to ignore this recommendation: if the size of an array is +relatively small or the actual time spent in Fortran routine takes +much longer than copying an array. Anyway, if you want to optimize +your Python code, start using arrays of required types. + +Another source of performance hit is when you use non-contiguous +arrays. The performance hit will be exactly the same as when using +incorrect array types. This is because a contiguous copy is created +to be passed in to the Fortran routine. + +\fpy provides a feature such that the ranks of array arguments need +not to match --- only the correct total size matters. For example, if +the wrapper function expects a rank-1 array \texttt{array([...])}, +then it is correct to pass in rank-2 (or higher) arrays +\texttt{array([[...],...,[...]])} assuming that the sizes will match. +This is especially useful when the arrays should contain only one +element (size is 1). Then you can pass in arrays \texttt{array(0)}, +\texttt{array([0])}, \texttt{array([[0]])}, etc and all cases are +handled correctly. In this case it is correct to pass in a Python +scalar in place of an array (but then ``change in place'' is ignored, +of course). + +\subsubsection{Multidimensional arrays} + +If you are using rank-2 or higher rank arrays, you must always +remember that indexing in Fortran starts from the lowest dimension +while in Python (and in C) the indexing starts from the highest +dimension (though some compilers have switches to change this). As a +result, if you pass in a 2-dimensional array then the Fortran routine +sees it as the transposed version of the array (in multi-dimensional +case the indexes are reversed). + +You must take this matter into account also when modifying the +signature file and interpreting the generated Python signatures: + +\begin{itemize} +\item First, when initializing an array using \texttt{init\_expr}, the index +vector \texttt{\_i[]} changes accordingly to Fortran convention. +\item Second, the result of CPP-macro \texttt{shape(<array>,0)} + corresponds to the last dimension of the Fortran array, etc. +\end{itemize} +Let me illustrate this with the following example:\\ +\begin{verbatim} +! Fortran file: arr.f + subroutine arr(l,m,n,a) + integer l,m,n + real*8 a(l,m,n) + ... + end +\end{verbatim} +\fpy will generate the following signature file:\\ +\begin{verbatim} +!%f90 +! Signature file: arr.f90 +python module arr ! in + interface ! in :arr + subroutine arr(l,m,n,a) ! in :arr:arr.f + integer optional,check(shape(a,2)==l),depend(a) :: l=shape(a,2) + integer optional,check(shape(a,1)==m),depend(a) :: m=shape(a,1) + integer optional,check(shape(a,0)==n),depend(a) :: n=shape(a,0) + real*8 dimension(l,m,n) :: a + end subroutine arr + end interface +end python module arr +\end{verbatim} +and the following wrapper function will be produced +\begin{verbatim} +None = arr(a,l=shape(a,2),m=shape(a,1),n=shape(a,0)) +\end{verbatim} + +In general, I would suggest not to specify the given optional +variables \texttt{l,m,n} when calling the wrapper function --- let the +interface find the values of the variables \texttt{l,m,n}. But there +are occasions when you need to specify the dimensions in Python. + +So, in Python a proper way to create an array from the given +dimensions is +\begin{verbatim} +>>> a = zeros(n,m,l,'d') +\end{verbatim} +(note that the dimensions are reversed and correct type is specified), +and then a complete call to \texttt{arr} is +\begin{verbatim} +>>> arr(a,l,m,n) +\end{verbatim} + +From the performance point of view, always be consistent with Fortran +indexing convention, that is, use transposed arrays. But if you do the +following +\begin{verbatim} +>>> a = transpose(zeros(l,m,n,'d')) +>>> arr(a) +\end{verbatim} +then you will get a performance hit! The reason is that here the +transposition is not actually performed. Instead, the array \texttt{a} +will be non-contiguous which means that before calling a Fortran +routine, internally a contiguous array is created which +includes memory allocation and copying. In addition, if +the argument array is also \texttt{intent(inout)}, the results are +copied back to the initial array which doubles the +performance hit! + +So, to improve the performance: always pass in +arrays that are contiguous. + +\subsubsection{Work arrays} + +Often Fortran routines use the so-called work arrays. The +corresponding arguments can be declared as optional arguments, but be +sure that all dimensions are specified (bounded) and defined before +the initialization (dependence relations). + +On the other hand, if you call the Fortran routine many times then you +don't want to allocate/deallocate the memory of the work arrays on +every call. In this case it is recommended that you create temporary +arrays with proper sizes in Python and use them as work arrays. But be +careful when specifying the required type and be sure that the +temporary arrays are contiguous. Otherwise the performance hit would +be even harder than the hit when not using the temporary arrays from +Python! + + + +\subsection{Call-back arguments} +\label{sec:cbargs} + +\fpy builds a very flexible call-back mechanisms for call-back +arguments. If the wrapper function expects a call-back function \texttt{fun} +with the following Python signature to be passed in +\begin{verbatim} +def fun(a_1,...,a_n): + ... + return x_1,...,x_k +\end{verbatim} +but the user passes in a function \texttt{gun} with the signature +\begin{verbatim} +def gun(b_1,...,b_m): + ... + return y_1,...,y_l +\end{verbatim} +and the following extra arguments (specified as additional optional +argument for the wrapper function): +\begin{verbatim} +fun_extra_args = (e_1,...,e_p) +\end{verbatim} +then the actual call-back is constructed accordingly to the following rules: +\begin{itemize} +\item if \texttt{p==0} then \texttt{gun(a\_1,...,a\_q)}, where + \texttt{q=min(m,n)}; +\item if \texttt{n+p<=m} then \texttt{gun(a\_1,...,a\_n,e\_1,...,e\_p)}; +\item if \texttt{p<=m<n+p} then \texttt{gun(a\_1,...,a\_q,e\_1,...,e\_p)}, + where \texttt{q=m-p}; +\item if \texttt{p>m} then \texttt{gun(e\_1,...,e\_m)}; +\item if \texttt{n+p} is less than the number of required arguments + of the function \texttt{gun}, an exception is raised. +\end{itemize} + +A call-back function \texttt{gun} may return any number of objects as a tuple: +if \texttt{k<l}, then objects \texttt{y\_k+1,...,y\_l} are ignored; +if \texttt{k>l}, then only objects \texttt{x\_1,...,x\_l} are set. + + +\subsection{Obtaining information on wrapper functions} +\label{sec:info} + +From the previous sections we learned that it is useful for the +performance to pass in arguments of expected type, if possible. To +know what are the expected types, \fpy generates a complete +documentation strings for all wrapper functions. You can read them +from Python by printing out \texttt{\_\_doc\_\_} attributes of the +wrapper functions. For the example in Sec.~\ref{sec:intro}: +\begin{verbatim} +>>> print foobar.foo.__doc__ +Function signature: + foo(a) +Required arguments: + a : in/output rank-0 array(int,'i') +>>> print foobar.bar.__doc__ +Function signature: + bar = bar(a,b) +Required arguments: + a : input int + b : input int +Return objects: + bar : int +\end{verbatim} + +In addition, \fpy generates a LaTeX document +(\texttt{<modulename>module.tex}) containing a bit more information on +the wrapper functions. See for example Appendix that contains a result +of the documentation generation for the example module +\texttt{foobar}. Here the file \texttt{foobar-smart.f90} (modified +version of \texttt{foobar.f90}) is used --- it contains +\texttt{note(<LaTeX text>)} attributes for specifying some additional +information. + +\subsection{Wrappers for common blocks} +\label{sec:wrapcomblock} + +[See examples \texttt{test-site/e/runme*}] + +What follows is obsolute for \fpy version higher that 2.264. + +\fpy generates wrapper functions for common blocks. For every common +block with a name \texttt{<commonname>} a function +\texttt{get\_<commonname>()} is constructed that takes no arguments +and returns a dictionary. The dictionary represents maps between the +names of common block fields and the arrays containing the common +block fields (multi-dimensional arrays are transposed). So, in order +to access to the common block fields, you must first obtain the +references +\begin{verbatim} +commonblock = get_<commonname>() +\end{verbatim} +and then the fields are available through the arrays +\texttt{commonblock["<fieldname>"]}. +To change the values of common block fields, you can use for scalars +\begin{verbatim} +commonblock["<fieldname>"][0] = <new value> +\end{verbatim} +and for arrays +\begin{verbatim} +commonblock["<fieldname>"][:] = <new array> +\end{verbatim} +for example. + +For more information on the particular common block wrapping, see +\texttt{get\_<commonname>.\_\_doc\_\_}. + +\subsection{Wrappers for F90/95 module data and routines} +\label{sec:wrapf90modules} + +[See example \texttt{test-site/mod/runme\_mod}] + +\subsection{Examples} +\label{sec:examples} + +Examples on various aspects of wrapping Fortran routines to Python can +be found in directories \texttt{test-site/d/} and +\texttt{test-site/e/}: study the shell scripts \texttt{runme\_*}. See +also files in \texttt{doc/ex1/}. + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "f2py2e" +%%% End: diff --git a/doc/f2py/oldnews.html b/doc/f2py/oldnews.html new file mode 100644 index 000000000..0e09c032f --- /dev/null +++ b/doc/f2py/oldnews.html @@ -0,0 +1,121 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> +<HTML> +<HEAD> +<META name="Author" content="Pearu Peterson"> +<!-- You may add here some keywords (comma separeted list) --> +<META name="Keywords" content="fortran,python,interface,f2py,f2py2e,wrapper,fpig"> +<TITLE>F2PY - Fortran to Python Interface Generator</TITLE> +<LINK rel="stylesheet" type="text/css" href="/styles/userstyle.css"> +</HEAD> + +<body> +<h2><a href="http://cens.ioc.ee/projects/f2py2e">F2PY</a> old news.</h2> + +<dl> + <dt> February 23, 2002 + <dd> Fixed a bug of incorrect shapes of multi-dimensional arrays + when returning from Fortran routine (thanks to Eric for pointing + this out). + <code>F2PY_REPORT_ATEXIT</code> is disabled by default under Win32. + <dt> February 14, 2002 + <dd> Introduced <code>callprotoargument</code> statement so that + proper prototypes can be specified (this fixes SEGFAULTs when + wrapping C functions with <code>f2py</code>, see <a + href="NEWS.txt">NEWS.txt</a> for more details). Updated for the + latest <code>numpy_distutils</code>. Fixed few bugs. + <dt> February 3, 2002 + <dd> Introduced <code>intent(overwrite),intent(out=name)</code> + attributes, <code>callstatement C-expr;</code> statement, and + reviewed reference counting in callback mechanism. Fixed bugs. + <dt> January 18, 2002 + <dd> Introduced extra keyword argument <code>copy_#varname#=1</code> + for <code>intent(copy)</code> variables, + <code>-DF2PY_REPORT_ATEXIT</code> for reporting <code>f2py</code> + performance, + <code>has_column_major_storage</code> member function for generated + modules, and <a href="http://dmalloc.com/">dmalloc</a> support. + <dt> January 16, 2002 + <dd> BREAKING NEWS! Solved long lasted dilemma of wrapping + multi-dimensional arrays where different + storage orders in C and Fortran come into account. From now on + this difference is dealt automatically by the f2py generated + module and in a very efficient way. For example, the corresponding + element A(i,j) of a Fortran array can be accessed in Python as + A[i,j]. + <dt> January 13, 2002 + <dd> Fifth Public Release is coming soon..., a snapshot is available + for download, now with updates. + <dt> December 17, 2001 + <dd> <a href="Release-4.x.txt">Fourth Public Release</a>: Win32 support. + <dd> Making <code>f2py2e</code> a module. Currently it has only one + member function <code>run_main(comline_list)</code>. + <dd> Removed command line arguments <code>-fix,-f90,-f77</code> + and introduced many new ones. See <a href="NEWS.txt">NEWS.txt</a>. + <dd> <code>intent(..)</code> statement with empty name list defines + default <code>intent(..)</code> attribute for all routine arguments. + <dd> Refinements in Win32 support. Eric Jones has provided a f2py + HOWTO for Windows users. See <a href="win32_notes.txt">win32_notes.txt</a>. + <dd> Major rewrote of the code generator to achieve + a higher quality of generated C/API modules (-Wall messages are + considerably reduced, especially for callback functions). + <dd> Many bugs were fixed. + <dt> December 12, 2001 + <dd> Win32 support (thanks to Eric Jones and Tiffany Kamm). Minor + cleanups and fixes. + <dt> December 4, 2001 + <dd> <a href="Release-3.x.txt">Third Public Release</a>: <code>f2py</code> supports <code>distutils</code>. It can be + installed with one and it generates <code>setup_modulename.py</code> + to be used for building Python extension modules. + <dd> Introduced <code>threadsafe</code>, <code>fortranname</code>, + and <code>intent(c)</code> statements. + <dt> August 13, 2001 + <dd> Changed the name FPIG to F2PY for avoiding confusion with project names. + <dd> Updated <code>f2py</code> for use with Numeric version 20.x. + <dt> January 12, 2001 + <dd> Example usages of <a href="pyfobj.html"><code>PyFortranObject</code></a>. + Fixed bugs. Updated the + <a href="f2python9.html">Python 9 Conference paper</a> (F2PY paper). + <dt> December 9, 2000 + <dd> Implemented support for <code>PARAMETER</code> statement. + <dt> November 6, 2000 + <dd> Submitted a paper for 9th Python Conference (accepted). It is available in <a + href="f2python9.html">html</a>, <a href="f2python9.pdf">PDF</a>, + and <a href="f2python9.ps.gz">Gzipped PS</a> formats. + <dt> September 17, 2000 + <dd> Support for F90/95 module data and routines. COMMON block + wrapping is rewritten. New signature file syntax: + <code>pythonmodule</code>. Signature files generated with + f2py-2.264 or earlier, are incompatible (need replacement + <code>module</code> with + <code>pythonmodule</code>). + <dt> September 12, 2000 + <dd> The second public release of <code>f2py</code> is out. See <a + href="Release-2.x.txt">Release notes</a>. + <dt> September 11, 2000 + <dd> Now <code>f2py</code> supports wrapping Fortran 90/95 module routines + (support for F90/95 module data coming soon) + <dt> June 12, 2000 + <dd> Now <code>f2py</code> has a mailing list <a +href="#f2py-users">f2py-users</a> open for discussion. + +</dl> + + +<!-- End of user text --> +<HR> +<ADDRESS> +<A href="http://validator.w3.org/"><IMG border=0 align=right src="/icons/vh40.gif" alt="Valid HTML 4.0!" height=31 width=88></A> +<A href="http://cens.ioc.ee/~pearu/" target="_top">Pearu Peterson</A> +<A href="mailto:pearu (at) ioc.ee"><pearu(at)ioc.ee></A><BR> +<!-- hhmts start --> +Last modified: Mon Dec 3 19:40:26 EET 2001 +<!-- hhmts end --> +</ADDRESS> +<!-- You may want to comment the following line out when the document is final--> +<!-- Check that the reference is right --> +<!--A href="http://validator.w3.org/check?uri=http://cens.ioc.ee/projects/f2py2e/index.html;ss"> Submit this page for validation</A--> + +</BODY> + + +</HTML> diff --git a/doc/f2py/options.tex b/doc/f2py/options.tex new file mode 100644 index 000000000..84d9410f8 --- /dev/null +++ b/doc/f2py/options.tex @@ -0,0 +1,63 @@ + +\section{\fpy command line options} +\label{sec:opts} + +\fpy has the following command line syntax (run \fpy without arguments +to get up to date options!!!): +\begin{verbatim} +f2py [<options>] <fortran files> [[[only:]||[skip:]] <fortran functions> ]\ + [: <fortran files> ...] +\end{verbatim} +where +\begin{description} +\item[\texttt{<options>}] --- the following options are available: + \begin{description} + \item[\texttt{-f77}] --- \texttt{<fortran files>} are in Fortran~77 + fixed format (default). + \item[\texttt{-f90}] --- \texttt{<fortran files>} are in + Fortran~90/95 free format (default for signature files). + \item[\texttt{-fix}] --- \texttt{<fortran files>} are in + Fortran~90/95 fixed format. + \item[\texttt{-h <filename>}] --- after scanning the + \texttt{<fortran files>} write the signatures of Fortran routines + to file \texttt{<filename>} and exit. If \texttt{<filename>} + exists, \fpy quits without overwriting the file. Use + \texttt{-{}-overwrite-signature} to overwrite. + \item[\texttt{-m <modulename>}] --- specify the name of the module + when scanning Fortran~77 codes for the first time. \fpy will + generate Python C/API module source \texttt{<modulename>module.c}. + \item[\texttt{-{}-lower/-{}-no-lower}] --- lower/do not lower the cases + when scanning the \texttt{<fortran files>}. Default when + \texttt{-h} flag is specified/unspecified (that is for Fortran~77 + codes/signature files). + \item[\texttt{-{}-short-latex}] --- use this flag when you want to + include the generated LaTeX document to another LaTeX document. + \item[\texttt{-{}-debug-capi}] --- create a very verbose C/API + code. Useful for debbuging. +% \item[\texttt{-{}-h-force}] --- if \texttt{-h <filename>} is used then +% overwrite the file \texttt{<filename>} (if it exists) and continue +% with constructing the C/API module source. + \item[\texttt{-makefile <options>}] --- run \fpy without arguments + for more information. + \item[\texttt{-{}-use-libs}] --- see \texttt{-makefile}. + \item[\texttt{-{}-overwrite-makefile}] --- overwrite existing + \texttt{Makefile-<modulename>}. + \item[\texttt{-v}] --- print \fpy version number and exit. + \item[\texttt{-pyinc}] --- print Python include path and exit. + \end{description} +\item[\texttt{<fortran files>}] --- are the paths to Fortran files or + to signature files that will be scanned for \texttt{<fortran + functions>} in order to determine their signatures. +\item[\texttt{<fortran functons>}] --- are the names of Fortran + routines for which Python C/API wrapper functions will be generated. + Default is all that are found in \texttt{<fortran files>}. +\item[\texttt{only:}/\texttt{skip:}] --- are flags for filtering + in/out the names of fortran routines to be wrapped. Run \fpy without + arguments for more information about the usage of these flags. +\end{description} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "f2py2e" +%%% End: diff --git a/doc/f2py/pyforttest.pyf b/doc/f2py/pyforttest.pyf new file mode 100644 index 000000000..79a9ae205 --- /dev/null +++ b/doc/f2py/pyforttest.pyf @@ -0,0 +1,5 @@ +subroutine foo(a,m,n) +integer m = size(a,1) +integer n = size(a,2) +real, intent(inout) :: a(m,n) +end subroutine foo diff --git a/doc/f2py/pytest.py b/doc/f2py/pytest.py new file mode 100644 index 000000000..bf4ef917f --- /dev/null +++ b/doc/f2py/pytest.py @@ -0,0 +1,12 @@ +from __future__ import division, absolute_import, print_function + +#File: pytest.py +import Numeric +def foo(a): + a = Numeric.array(a) + m, n = a.shape + for i in range(m): + for j in range(n): + a[i, j] = a[i, j] + 10*(i+1) + (j+1) + return a +#eof diff --git a/doc/f2py/python9.tex b/doc/f2py/python9.tex new file mode 100644 index 000000000..fdcd32f46 --- /dev/null +++ b/doc/f2py/python9.tex @@ -0,0 +1,1044 @@ +\documentclass[twocolumn]{article} +\usepackage{epsfig} +\usepackage{xspace} +\usepackage{verbatim} + + +\headsep=0pt +\topmargin=0pt +\headheight=0pt +\oddsidemargin=0pt +\textwidth=6.5in +\textheight=9in +%%tth:\newcommand{\xspace}{ } +\newcommand{\fpy}{\texttt{f2py}\xspace} +\newcommand{\bs}{\symbol{`\\}} +% need bs here: +%%tth:\newcommand{\bs}{\texttt{<backslash>}} + +\newcommand{\tthhide}[1]{#1} +\newcommand{\latexhide}[1]{} +%%tth:\newcommand{\tthhide}[1]{} +%%tth:\newcommand{\latexhide}[1]{#1} + +\newcommand{\shell}[1]{ +\latexhide{ + \special{html: +<BLOCKQUOTE> +<pre> +sh> #1 +</pre> +</BLOCKQUOTE>} +} +\tthhide{ + \\[1ex] + \hspace*{1em} + \texttt{sh> \begin{minipage}[t]{0.8\textwidth}#1\end{minipage}}\\[1ex] +} +} + +\newcommand{\email}[1]{\special{html:<A href="mailto:#1">}\texttt{<#1>}\special{html:</A>}} +\newcommand{\wwwsite}[1]{\special{html:<A href="#1">}{#1}\special{html:</A>}} +\title{Fortran to Python Interface Generator with +an Application to Aerospace Engineering} +\author{ +\large Pearu Peterson\\ +\small \email{pearu@cens.ioc.ee}\\ +\small Center of Nonlinear Studies\\ +\small Institute of Cybernetics at TTU\\ +\small Akadeemia Rd 21, 12618 Tallinn, ESTONIA\\[2ex] +\large Joaquim R. R. A. Martins and Juan J. Alonso\\ +\small \email{joaquim.martins@stanford.edu}, \email{jjalonso@stanford.edu}\\ +\small Department of Aeronautics and Astronautics\\ +\small Stanford University, CA +} +\date{$Revision: 1.17 $\\\today} +\begin{document} + +\maketitle + +\special{html: Other formats of this document: +<A href=f2python9.ps.gz>Gzipped PS</A>, +<A href=f2python9.pdf>PDF</A> +} + +\begin{abstract} + FPIG --- Fortran to Python Interface Generator --- is a tool for + generating Python C/API extension modules that interface + Fortran~77/90/95 codes with Python. This tool automates the process + of interface generation by scanning the Fortran source code to + determine the signatures of Fortran routines and creating a + Python C/API module that contains the corresponding interface + functions. FPIG also attempts to find dependence relations between + the arguments of a Fortran routine call (e.g. an array and its + dimensions) and constructs interface functions with potentially + fewer arguments. The tool is extremely flexible since the user has + control over the generation process of the interface by specifying the + desired function signatures. The home page for FPIG can be found at + \wwwsite{http://cens.ioc.ee/projects/f2py2e/}. + + FPIG has been used successfully to wrap a large number of Fortran + programs and libraries. Advances in computational science have led + to large improvements in the modeling of physical systems which are + often a result of the coupling of a variety of physical models that + were typically run in isolation. Since a majority of the available + physical models have been previously written in Fortran, the + importance of FPIG in accomplishing these couplings cannot be + understated. In this paper, we present an application of FPIG to + create an object-oriented framework for aero-structural analysis and + design of aircraft. +\end{abstract} + +%%tth: +\tableofcontents + +\section{Preface} +\label{sec:preface} + +The use of high-performance computing has made it possible to tackle +many important problems and discover new physical phenomena in science +and engineering. These accomplishments would not have been achieved +without the computer's ability to process large amounts of data in a +reasonably short time. It can safely be said that the computer has +become an essential tool for scientists and engineers. However, the +diversity of problems in science and engineering has left its mark as +computer programs have been developed in different programming +languages, including languages developed to describe certain specific +classes of problems. + +In interdisciplinary fields it is not uncommon for scientists and +engineers to face problems that have already been solved in a +different programming environment from the one they are familiar with. +Unfortunately, researchers may not have the time or willingness to +learn a new programming language and typically end up developing the +corresponding tools in the language that they normally use. This +approach to the development of new software can substantially impact +the time to develop and the quality of the resulting product: firstly, +it usually takes longer to develop and test a new tool than to learn a +new programming environment, and secondly it is very unlikely that a +non-specialist in a given field can produce a program that is more +efficient than more established tools. + +To avoid situations such as the one described above, one alternative +would be to provide automatic or semi-automatic interfaces between programming +languages. Another possibility would be to provide language +translators, but these obviously require more work than interface +generators --- a translator must understand all language constructs +while an interface generator only needs to understand a subset of these +constructs. With an automatic interface between two languages, scientists or +engineers can effectively use programs written in other programming +languages without ever having to learn them. + +Although it is clear that it is impossible to interface arbitrary programming +languages with each other, there is no reason for doing so. Low-level languages such as C and Fortran are well known for +their speed and are therefore suitable for applications where +performance is critical. High-level scripting languages, on the other +hand, are generally slower but much easier to learn and use, +especially when performing interactive analysis. Therefore, it makes +sense to create interfaces only in one direction: from lower-level +languages to higher-level languages. + +In an ideal world, scientists and engineers would use higher-level +languages for the manipulation of the mathematical formulas in a problem +rather than having to struggle with tedious programming details. For tasks +that are computationally demanding, they would use interfaces to +high-performance routines that are written in a lower-level language +optimized for execution speed. + + +\section{Introduction} +\label{sec:intro} + +This paper presents a tool that has been developed for the creation of +interfaces between Fortran and Python. + + +The Fortran language is popular in +scientific computing, and is used mostly in applications that use +extensive matrix manipulations (e.g. linear algebra). Since Fortran + has been the standard language among scientists and engineers for + at least three decades, there is a large number of legacy codes available that + perform a variety of tasks using very sophisticated algorithms (see +e.g. \cite{netlib}). + +The Python language \cite{python}, on the other hand, is a relatively +new programming language. It is a very high-level scripting language +that supports object-oriented programming. What makes Python +especially appealing is its very clear and natural syntax, which makes it +easy to learn and use. With Python one can implement relatively +complicated algorithms and tasks in a short time with very compact +source code. + +Although there are ongoing projects for extending Python's usage in +scientific computation, it lacks reliable tools that are common in +scientific and engineering such as ODE integrators, equation solvers, +tools for FEM, etc. The implementation of all of these tools in Python +would be not only too time-consuming but also inefficient. On the +other hand, these tools are already developed in other, +computationally more efficient languages such as Fortran or C. +Therefore, the perfect role for Python in the context of scientific +computing would be that of a ``gluing'' language. That is, the role +of providing high-level interfaces to C, C++ and Fortran libraries. + +There are a number of widely-used tools that can be used for interfacing +software libraries to Python. For binding C libraries with various +scripting languages, including Python, the tool most often used is +SWIG \cite{swig}. Wrapping Fortran routines with Python is less +popular, mainly because there are many platform and compiler-specific +issues that need to be addressed. Nevertheless, there is great +interest in interfacing Fortran libraries because they provide +invaluable tools for scientific computing. At LLNL, for example, a tool +called PyFort has been developed for connecting Fortran and +Python~\cite{pyfort}. + +The tools mentioned above require an input file describing signatures +of functions to be interfaced. To create these input files, one needs +to have a good knowledge of either C or Fortran. In addition, +binding libraries that have thousands of routines can certainly constitute a +very tedious task, even with these tools. + +The tool that is introduced in this paper, FPIG (Fortran to Python +Interface Generator)~\cite{fpig}, automatically generates interfaces +between Fortran and Python. It is different from the tools mentioned +above in that FPIG can create signature files automatically by +scanning the source code of the libraries and then construct Python +C/API extension modules. Note that the user need not be experienced +in C or even Fortran. In addition, FPIG is designed to wrap large +Fortran libraries containing many routines with only one or two +commands. This process is very flexible since one can always modify +the generated signature files to insert additional attributes in order +to achieve more sophisticated interface functions such as taking care +of optional arguments, predicting the sizes of array arguments and +performing various checks on the correctness of the input arguments. + +The organization of this paper is as follows. First, a simple example +of FPIG usage is given. Then FPIG's basic features are described and +solutions to platform and compiler specific issues are discussed. +Unsolved problems and future work on FPIG's development are also +addressed. Finally, an application to a large aero-structural solver +is presented as real-world example of FPIG's usage. + +\section{Getting Started} +\label{sec:getstart} + +To get acquainted with FPIG, let us consider the simple Fortran~77 +subroutine shown in Fig. \ref{fig:exp1.f}. +\begin{figure}[htb] + \latexhide{\label{fig:exp1.f}} + \special{html:<BLOCKQUOTE>} + \verbatiminput{examples/exp1.f} + \special{html:</BLOCKQUOTE>} + \caption{Example Fortran code \texttt{exp1.f}. This routine calculates + the simplest rational lower and upper approximations to $e$ (for + details of + the algorithm see \cite{graham-etal}, p.122)} + \tthhide{\label{fig:exp1.f}} +\end{figure} +In the sections that follow, two ways of creating interfaces to this +Fortran subroutine are described. The first and simplest way is +suitable for Fortran codes that are developed in connection with \fpy. +The second and not much more difficult method, is suitable for +interfacing existing Fortran libraries which might have been developed +by other programmers. + +Numerical Python~\cite{numpy} is needed in order to compile extension +modules generated by FPIG. + +\subsection{Interfacing Simple Routines} +\label{sec:example1} + +In order to call the Fortran routine \texttt{exp1} from Python, let us +create an interface to it by using \fpy (FPIG's front-end program). In +order to do this, we issue the following command, \shell{f2py -m foo +exp1.f} where the option \texttt{-m foo} sets the name of the Python +C/API extension module that \fpy will create to +\texttt{foo}. To learn more about the \fpy command line options, run \fpy +without arguments. + +The output messages in Fig. \ref{fig:f2pyoutmess} +illustrate the procedure followed by \fpy: + (i) it scans the Fortran source code specified in the command line, + (ii) it analyses and determines the routine signatures, + (iii) it constructs the corresponding Python C/API extension modules, + (iv) it writes documentation to a LaTeX file, and + (v) it creates a GNU Makefile for building the shared modules. +\begin{figure}[htb] + \latexhide{\label{fig:f2pyoutmess}} + \special{html:<BLOCKQUOTE>} + {\tthhide{\small} + \verbatiminput{examples/exp1mess.txt} + } + \special{html:</BLOCKQUOTE>} + \caption{Output messages of \texttt{f2py -m foo exp1.f}.} + \tthhide{\label{fig:f2pyoutmess}} +\end{figure} + +Now we can build the \texttt{foo} module: +\shell{make -f Makefile-foo} + +Figure \ref{fig:exp1session} illustrates a sample session for + calling the Fortran routine \texttt{exp1} from Python. +\begin{figure}[htb] + \latexhide{\label{fig:exp1session}} + \special{html:<BLOCKQUOTE>} + \verbatiminput{examples/exp1session.txt} + \special{html:</BLOCKQUOTE>} + \caption{Calling Fortran routine \texttt{exp1} from Python. Here + \texttt{l[0]/l[1]} gives an estimate to $e$ with absolute error + less than \texttt{u[0]/u[1]-l[0]/l[1]} (this value may depend on + the platform and compiler used).} + \tthhide{\label{fig:exp1session}} +\end{figure} + +Note the difference between the signatures of the Fortran routine +\texttt{exp1(l,u,n)} and the corresponding wrapper function +\texttt{l,u=exp1([n])}. Clearly, the later is more informative to +the user: \texttt{exp1} takes one optional argument \texttt{n} and it +returns \texttt{l}, \texttt{u}. This exchange of signatures is +achieved by special comment lines (starting with \texttt{Cf2py}) in +the Fortran source code --- these lines are interpreted by \fpy as +normal Fortran code. Therefore, in the given example the line \texttt{Cf2py + integer*4 :: n = 1} informs \fpy that the variable \texttt{n} is +optional with a default value equal to one. The line \texttt{Cf2py + intent(out) l,u} informs \fpy that the variables \texttt{l,u} are to be +returned to Python after calling Fortran function \texttt{exp1}. + +\subsection{Interfacing Libraries} +\label{sec:example2} + +In our example the Fortran source \texttt{exp1.f} contains \fpy +specific information, though only as comments. When interfacing +libraries from other parties, it is not recommended to modify their +source. Instead, one should use a special auxiliary file to collect +the signatures of all Fortran routines and insert \fpy specific +declaration and attribute statements in that file. This auxiliary file +is called a \emph{signature file} and is identified by the extension +\texttt{.pyf}. + +We can use \fpy to generate these signature files by using the +\texttt{-h <filename>.pyf} option. +In our example, \fpy could have been called as follows, +\shell{f2py -m foo -h foo.pyf exp1.f} +where the option \texttt{-h foo.pyf} requests \fpy to read the +routine signatures, save them to the file \texttt{foo.pyf}, and then +exit. +If \texttt{exp1.f} in Fig.~\ref{fig:exp1.f} were to +contain no lines starting with \texttt{Cf2py}, the corresponding +signature file \texttt{foo.pyf} would be as shown in Fig.~\ref{fig:foo.pyf}. +In order to obtain the exchanged and more convenient signature +\texttt{l,u=foo.exp1([n])}, we would edit \texttt{foo.pyf} as shown in +Fig.~\ref{fig:foom.pyf}. +The Python C/API extension module \texttt{foo} can be constructed by +applying \fpy to the signature file with the following command: +\shell{f2py foo.pyf} +The procedure for building the corresponding shared module and using +it in Python is identical to the one described in the previous section. + +\begin{figure}[htb] + \latexhide{\label{fig:foo.pyf}} + \special{html:<BLOCKQUOTE>} + \verbatiminput{examples/foo.pyf} + \special{html:</BLOCKQUOTE>} + \caption{Raw signature file \texttt{foo.pyf} generated with + \texttt{f2py -m foo -h foo.pyf exp1.f}} + \tthhide{\label{fig:foo.pyf}} +\end{figure} +\begin{figure}[htb] + \latexhide{\label{fig:foom.pyf}} + \special{html:<BLOCKQUOTE>} + \verbatiminput{examples/foom.pyf} + \special{html:</BLOCKQUOTE>} + \caption{Modified signature file \texttt{foo.pyf}} + \tthhide{\label{fig:foom.pyf}} +\end{figure} + +As we can see, the syntax of the signature file is an +extension of the Fortran~90/95 syntax. This means that only a few new +constructs are introduced for \fpy in addition to all standard Fortran +constructs; signature files can even be written in fixed form. A +complete set of constructs that are used when creating interfaces, is +described in the \fpy User's Guide \cite{f2py-ug}. + + +\section{Basic Features} +\label{sec:features} + +In this section a short overview of \fpy features is given. +\begin{enumerate} +\item All basic Fortran types are supported. They include +the following type specifications: +\begin{verbatim} +integer[ | *1 | *2 | *4 | *8 ] +logical[ | *1 | *2 | *4 | *8 ] +real[ | *4 | *8 | *16 ] +complex[ | *8 | *16 | *32 ] +double precision, double complex +character[ |*(*)|*1|*2|*3|...] +\end{verbatim} +In addition, they can all be in the kind-selector form +(e.g. \texttt{real(kind=8)}) or char-selector form +(e.g. \texttt{character(len=5)}). +\item Arrays of all basic types are supported. Dimension + specifications can be of form \texttt{<dimension>} or + \texttt{<start>:<end>}. In addition, \texttt{*} and \texttt{:} + dimension specifications can be used for input arrays. + Dimension specifications may contain also \texttt{PARAMETER}'s. +\item The following attributes are supported: + \begin{itemize} + \item + \texttt{intent(in)}: used for input-only arguments. + \item + \texttt{intent(inout)}: used for arguments that are changed in + place. + \item + \texttt{intent(out)}: used for return arguments. + \item + \texttt{intent(hide)}: used for arguments to be removed from + the signature of the Python function. + \item + \texttt{intent(in,out)}, \texttt{intent(inout,out)}: used for + arguments with combined behavior. + \item + \texttt{dimension(<dimspec>)} + \item + \texttt{depend([<names>])}: used + for arguments that depend on other arguments in \texttt{<names>}. + \item + \texttt{check([<C booleanexpr>])}: used for checking the + correctness of input arguments. + \item + \texttt{note(<LaTeX text>)}: used for + adding notes to the module documentation. + \item + \texttt{optional}, \texttt{required} + \item + \texttt{external}: used for call-back arguments. + \item + \texttt{allocatable}: used for Fortran 90/95 allocatable arrays. + \end{itemize} +\item Using \fpy one can call arbitrary Fortran~77/90/95 subroutines + and functions from Python, including Fortran 90/95 module routines. +\item Using \fpy one can access data in Fortran~77 COMMON blocks and + variables in Fortran 90/95 modules, including allocatable arrays. +\item Using \fpy one can call Python functions from Fortran (call-back + functions). \fpy supports very flexible hooks for call-back functions. +\item Wrapper functions perform the necessary type conversations for their + arguments resulting in contiguous Numeric arrays that are suitable for + passing to Fortran routines. +\item \fpy generates documentation strings +for \texttt{\_\_doc\_\_} attributes of the wrapper functions automatically. +\item \fpy scans Fortran codes and creates the signature + files. It automatically detects the signatures of call-back functions, + solves argument dependencies, decides the order of initialization of + optional arguments, etc. +\item \fpy automatically generates GNU Makefiles for compiling Fortran + and C codes, and linking them to a shared module. + \fpy detects available Fortran and C compilers. The + supported compilers include the GNU project C Compiler (gcc), Compaq + Fortran, VAST/f90 Fortran, Absoft F77/F90, and MIPSpro 7 Compilers, etc. + \fpy has been tested to work on the following platforms: Intel/Alpha + Linux, HP-UX, IRIX64. +\item Finally, the complete \fpy User's Guide is available in various + formats (ps, pdf, html, dvi). A mailing list, + \email{f2py-users@cens.ioc.ee}, is open for support and feedback. See + the FPIG's home page for more information \cite{fpig}. +\end{enumerate} + + +\section{Implementation Issues} +\label{sec:impl} + +The Fortran to Python interface can be thought of as a three layer +``sandwich'' of different languages: Python, C, and Fortran. This +arrangement has two interfaces: Python-C and C-Fortran. Since Python +itself is written in C, there are no basic difficulties in +implementing the Python-C interface~\cite{python-doc:ext}. The C-Fortran +interface, on the other hand, results in many platform and compiler specific +issues that have to be dealt with. We will now discuss these issues +in some detail and describe how they are solved in FPIG. + +\subsection{Mapping Fortran Types to C Types} +\label{sec:mapF2Ctypes} + +Table \ref{tab:mapf2c} defines how Fortran types are mapped to C types +in \fpy. +\begin{table}[htb] + \begin{center} + \begin{tabular}[c]{l|l} + Fortran type & C type \\\hline + \texttt{integer *1} & \texttt{char}\\ + \texttt{byte} & \texttt{char}\\ + \texttt{integer *2} & \texttt{short}\\ + \texttt{integer[ | *4]} & \texttt{int}\\ + \texttt{integer *8} & \texttt{long long}\\ + \texttt{logical *1} & \texttt{char}\\ + \texttt{logical *2} & \texttt{short}\\ + \texttt{logical[ | *4]} & \texttt{int}\\ + \texttt{logical *8} & \texttt{int}\\ + \texttt{real[ | *4]} & \texttt{float}\\ + \texttt{real *8} & \texttt{double}\\ + \texttt{real *16} & \texttt{long double}\\ + \texttt{complex[ | *8]} & \texttt{struct \{float r,i;\}}\\ + \texttt{complex *16} & \texttt{struct \{double r,i;\}}\\ + \texttt{complex *32} & \texttt{struct \{long double r,i;\}}\\ + \texttt{character[*...]} & \texttt{char *}\\ + \end{tabular} + \caption{Mapping Fortran types to C types.} + \label{tab:mapf2c} + \end{center} +\end{table} +Users may redefine these mappings by creating a \texttt{.f2py\_f2cmap} +file in the working directory. This file should contain a Python +dictionary of dictionaries, e.g. \texttt{\{'real':\{'low':'float'\}\}}, +that informs \fpy to map Fortran type \texttt{real(low)} +to C type \texttt{float} (here \texttt{PARAMETER low = ...}). + + +\subsection{Calling Fortran (Module) Routines} +\label{sec:callrout} + +When mixing Fortran and C codes, one has to know how function names +are mapped to low-level symbols in their object files. Different +compilers may use different conventions for this purpose. For example, gcc +appends the underscore \texttt{\_} to a Fortran routine name. Other +compilers may use upper case names, prepend or append different +symbols to Fortran routine names or both. In any case, if the +low-level symbols corresponding to Fortran routines are valid for the +C language specification, compiler specific issues can be solved by +using CPP macro features. + +Unfortunately, there are Fortran compilers that use symbols in +constructing low-level routine names that are not valid for C. For +example, the (IRIX64) MIPSpro 7 Compilers use `\$' character in the +low-level names of module routines which makes it impossible (at +least directly) to call such routines from C when using the MIPSpro 7 +C Compiler. + +In order to overcome this difficulty, FPIG introduces an unique +solution: instead of using low-level symbols for calling Fortran +module routines from C, the references to such routines are determined +at run-time by using special wrappers. These wrappers are called once +during the initialization of an extension module. They are simple +Fortran subroutines that use a Fortran module and call another C +function with Fortran module routines as arguments in order to save +their references to C global variables that are later used for calling +the corresponding Fortran module routines. This arrangement is +set up as follows. Consider the following Fortran 90 module with the +subroutine \texttt{bar}: +\special{html:<BLOCKQUOTE>} +\begin{verbatim} +module fun + subroutine bar() + end +end +\end{verbatim} +\special{html:</BLOCKQUOTE>} +Figure \ref{fig:capi-sketch} illustrates a Python C/API extension +module for accessing the F90 module subroutine \texttt{bar} from Python. +When the Python module \texttt{foo} is loaded, \texttt{finitbar} is +called. \texttt{finitbar} calls \texttt{init\_bar} by passing the +reference of the Fortran 90 module subroutine \texttt{bar} to C where it is +saved to the variable \texttt{bar\_ptr}. Now, when one executes \texttt{foo.bar()} +from Python, \texttt{bar\_ptr} is used in \texttt{bar\_capi} to call +the F90 module subroutine \texttt{bar}. +\begin{figure}[htb] + \latexhide{\label{fig:capi-sketch}} + \special{html:<BLOCKQUOTE>} +\begin{verbatim} +#include "Python.h" +... +char *bar_ptr; +void init_bar(char *bar) { + bar_ptr = bar; +} +static PyObject * +bar_capi(PyObject *self,PyObject *args) { + ... + (*((void *)bar_ptr))(); + ... +} +static PyMethodDef +foo_module_methods[] = { + {"bar",bar_capi,METH_VARARGS}, + {NULL,NULL} +}; +extern void finitbar_; /* GCC convention */ +void initfoo() { + ... + finitbar_(init_bar); + Py_InitModule("foo",foo_module_methods); + ... +} +\end{verbatim} + \special{html:</BLOCKQUOTE>} + \caption{Sketch of Python C/API for accessing F90 module subroutine + \texttt{bar}. The Fortran function \texttt{finitbar} is defined in + Fig.~\ref{fig:wrapbar}.} + \tthhide{\label{fig:capi-sketch}} +\end{figure} +\begin{figure}[ht] + \latexhide{\label{fig:wrapbar}} +\special{html:<BLOCKQUOTE>} +\begin{verbatim} + subroutine finitbar(cinit) + use fun + extern cinit + call cinit(bar) + end +\end{verbatim} +\special{html:</BLOCKQUOTE>} + \caption{Wrapper for passing the reference of \texttt{bar} to C code.} + \tthhide{\label{fig:wrapbar}} +\end{figure} + +Surprisingly, mixing C code and Fortran modules in this way is as +portable and compiler independent as mixing C and ordinary Fortran~77 +code. + +Note that extension modules generated by \fpy actually use +\texttt{PyFortranObject} that implements above described scheme with +exchanged functionalities (see Section \ref{sec:PFO}). + + +\subsection{Wrapping Fortran Functions} +\label{sec:wrapfunc} + +The Fortran language has two types of routines: subroutines and +functions. When a Fortran function returns a composed type such as +\texttt{COMPLEX} or \texttt{CHARACTER}-array then calling this +function directly from C may not work for all compilers, as C +functions are not supposed to return such references. In order to +avoid this, FPIG constructs an additional Fortran wrapper subroutine +for each such Fortran function. These wrappers call just the +corresponding functions in the Fortran layer and return the result to +C through its first argument. + + +\subsection{Accessing Fortran Data} +\label{sec:accsdata} + +In Fortran one can use \texttt{COMMON} blocks and Fortran module +variables to save data that is accessible from other routines. Using +FPIG, one can also access these data containers from Python. To achieve +this, FPIG uses special wrapper functions (similar to the ones used +for wrapping Fortran module routines) to save the references to these +data containers so that they can later be used from C. + +FPIG can also handle \texttt{allocatable} arrays. For example, if a +Fortran array is not yet allocated, then by assigning it in Python, +the Fortran to Python interface will allocate and initialize the +array. For example, the F90 module allocatable array \texttt{bar} +defined in +\special{html:<BLOCKQUOTE>} +\begin{verbatim} +module fun + integer, allocatable :: bar(:) +end module +\end{verbatim} +\special{html:</BLOCKQUOTE>} +can be allocated from Python as follows +\special{html:<BLOCKQUOTE>} +\begin{verbatim} +>>> import foo +>>> foo.fun.bar = [1,2,3,4] +\end{verbatim} +\special{html:</BLOCKQUOTE>} + +\subsection{\texttt{PyFortranObject}} +\label{sec:PFO} + +In general, we would like to access from Python the following Fortran +objects: +\begin{itemize} +\item subroutines and functions, +\item F90 module subroutines and functions, +\item items in COMMON blocks, +\item F90 module data. +\end{itemize} +Assuming that the Fortran source is available, we can determine the signatures +of these objects (the full specification of routine arguments, the +layout of Fortran data, etc.). In fact, \fpy gets this information +while scanning the Fortran source. + +In order to access these Fortran objects from C, we need to determine +their references. Note that the direct access of F90 module objects is +extremely compiler dependent and in some cases even impossible. +Therefore, FPIG uses various wrapper functions for obtaining the +references to Fortran objects. These wrapper functions are ordinary +F77 subroutines that can easily access objects from F90 modules and +that pass the references to Fortran objects as C variables. + + +\fpy generated Python C/API extension modules use +\texttt{PyFortranObject} to store the references of Fortran objects. +In addition to the storing functionality, the \texttt{PyFortranObject} +also provides methods for accessing/calling Fortran objects from +Python in a user-friendly manner. For example, the item \texttt{a} in +\texttt{COMMON /bar/ a(2)} can be accessed from Python as +\texttt{foo.bar.a}. + +Detailed examples of \texttt{PyFortranObject} usage can be found in +\cite{PFO}. + +\subsection{Callback Functions} +\label{sec:callback} + +Fortran routines may have arguments specified as \texttt{external}. +These arguments are functions or subroutines names that the receiving Fortran routine +will call from its body. For such arguments FPIG +constructs a call-back mechanism (originally contributed by Travis +Oliphant) that allows Fortran routines to call Python functions. This +is actually realized using a C layer between Python and +Fortran. Currently, the call-back mechanism is compiler independent +unless a call-back function needs to return a composed type +(e.g. \texttt{COMPLEX}). + +The signatures of call-back functions are determined when \fpy scans +the Fortran source code. To illustrate this, consider the following +example: +\special{html:<BLOCKQUOTE>} +\begin{verbatim} + subroutine foo(bar, fun, boo) + integer i + real r + external bar,fun,boo + call bar(i, 1.2) + r = fun() + call sun(boo) + end +\end{verbatim} +\special{html:</BLOCKQUOTE>} +\fpy recognizes the signatures of the user routines \texttt{bar} and +\texttt{fun} using the information contained in the lines \texttt{call + bar(i, 1.2)} and \texttt{r = fun()}: +\special{html:<BLOCKQUOTE>} +\begin{verbatim} +subroutine bar(a,b) + integer a + real b +end +function fun() + real fun +end +\end{verbatim} +\special{html:</BLOCKQUOTE>} +But \fpy cannot determine the signature of the user routine +\texttt{boo} because the source contains no information at all about +the \texttt{boo} specification. Here user needs to provide the +signature of \texttt{boo} manually. + +\section{Future Work} +\label{sec:future} + +FPIG can be used to wrap almost any Fortran code. However, there are +still issues that need to be resolved. Some of them are listed below: +\begin{enumerate} +\item One of the FPIG's goals is to become as platform and compiler + independent as possible. Currently FPIG can be used on + any UN*X platform that has gcc installed in it. In the future, FPIG + should be also tested on Windows systems. +\item Another goal of FPIG is to become as simple to use as + possible. To achieve that, FPIG should start using the facilities of + \texttt{distutils}, the new Python standard to distribute and build + Python modules. Therefore, a contribution to \texttt{distutils} + that can handle Fortran extensions should be developed. +\item Currently users must be aware of + the fact that multi-dimensional arrays are stored differently in C + and Fortran (they must provide transposed multi-dimensional arrays + to wrapper functions). In the future a solution should be found such + that users do not need to worry about this rather + confusing and technical detail. +\item Finally, a repository of signature files for widely-used Fortran + libraries (e.g. BLAS, LAPACK, MINPACK, ODEPACK, EISPACK, LINPACK) should be + provided. +\end{enumerate} + + +\section{Application to a Large Aero-Structural Analysis Framework} +\label{sec:app} + + +\subsection{The Need for Python and FPIG} +\label{sec:appsub1} + +As a demonstration of the power and usefulness of FPIG, we will +present work that has been done at the Aerospace Computing Laboratory +at Stanford University. The focus of the research is on aircraft +design optimization using high-fidelity analysis tools such as +Computational Fluid Dynamics (CFD) and Computational Structural +Mechanics (CSM)~\cite{reno99}. + +The group's analysis programs are written mainly in Fortran and are the result +of many years of development. Until now, any researcher that needed +to use these tools would have to learn a less than user-friendly +interface and become relatively familiar with the inner workings of +the codes before starting the research itself. The need to +couple analyses of different disciplines revealed the additional +inconvenience of gluing and scripting the different codes with +Fortran. + +It was therefore decided that the existing tools should be wrapped +using an object-oriented language in order to improve their ease of +use and versatility. The use of several different languages such as +C++, Java and Perl was investigated but Python seemed to provide the +best solution. The fact that it combines scripting capability +with a fully-featured object-oriented programming language, and that +it has a clean syntax were factors that determined our choice. The +introduction of tools that greatly facilitate the task of wrapping +Fortran with Python provided the final piece needed to realize our +objective. + +\subsection{Wrapping the Fortran Programs} + +In theory, it would have been possible to wrap our Fortran programs +with C and then with Python by hand. However, this would have been a +labor intensive task that would detract from our research. The use of +tools that automate the task of wrapping has been extremely useful. + +The first such tool that we used was PyFort. This tool created the C +wrappers and Python modules automatically, based on signature files +(\texttt{.pyf}) provided by the user. Although it made the task of +wrapping considerably easier, PyFort was limited by the fact that any +Fortran data that was needed at the Python level had to be passed in +the argument list of the Fortran subroutine. Since the bulk of the +data in our programs is shared by using Fortran~77 common blocks and +Fortran~90 modules, this required adding many more arguments to the +subroutine headers. Furthermore, since Fortran does not allow common +block variables or module data to be specified in a subroutine +argument list, a dummy pointer for each desired variable had to be +created and initialized. + +The search for a better solution to this problem led us to \fpy. +Since \fpy provides a solution for accessing common block and module +variables, there was no need to change the Fortran source anymore, +making the wrapping process even easier. With \fpy we also +experienced an increased level of automation since it produces the +signature files automatically, as well as a Makefile for the joint +compilation of the original Fortran and C wrapper codes. This increased +automation did not detract from its flexibility since it was always +possible to edit the signature files to provide different functionality. + +Once Python interfaces were created for each Fortran application +by running \fpy, it was just a matter of using Python to achieve the +final objective of developing an object-oriented framework for our +multidisciplinary solvers. The Python modules that we designed are +discussed in the following section. + + +\subsection{Module Design} +\label{ssec:module} + +The first objective of this effort was to design the classes for each +type of analysis, each representing an independent Python module. In +our case, we are interested in performing aero-structural analysis and +optimization of aircraft wings. We therefore needed an analysis tool +for the flow (CFD), another for analyzing the structure (CSM), as well +as a geometry database. In addition, we needed to interface these two +tools in order to analyze the coupled system. The object design for +each of these modules should be general enough that the underlying +analysis code in Fortran can be changed without changing the Python +interface. Another requirement was that the modules be usable on +their own for single discipline analysis. + +\subsubsection{Geometry} + +The \emph{Geometry} class provides a database for the outer mold +geometry of the aircraft. This database needs to be accessed by both +the flow and structural solvers. It contains a parametric description +of the aircraft's surface as well as methods that extract and update +this information. + + +\subsubsection{Flow} + +The flow solver was wrapped in a class called \emph{Flow}. The class +was designed so that it can wrap any type of CFD solver. It contains +two main objects: the computational mesh and a solver object. A graph +showing the hierarchy of the objects in \emph{Flow} is shown in +Fig.~\ref{fig:flow}. +\tthhide{ +\begin{figure}[h] + \centering + \epsfig{file=./flow.eps, angle=0, width=.7\linewidth} + \caption{The \emph{Flow} container class.} + \label{fig:flow} +\end{figure} +} +\latexhide{ +\begin{figure}[h] + \label{fig:flow} +\special{html: +<CENTER> + <IMG SRC="flow.jpg" WIDTH="400"> +</CENTER> +} + \caption{The \emph{Flow} container class.} +\end{figure} +} +Methods in the flow class include those used for the initialization of +all the class components as well as methods that write the current +solution to a file. + + +\subsubsection{Structure} + +The \emph{Structure} class wraps a structural analysis code. The class +stores the information about the structure itself in an object called +\emph{Model} which also provides methods for changing and exporting +its information. A list of the objects contained in this class can be +seen in Fig.~\ref{fig:structure}. +\tthhide{ +\begin{figure}[h] + \centering + \epsfig{file=./structure.eps, angle=0, width=.7\linewidth} + \caption{The \emph{Structure} container class.} + \label{fig:structure} +\end{figure} +} +\latexhide{ +\begin{figure}[h] + \label{fig:structure} +\special{html: +<CENTER> + <IMG SRC="structure.jpg" WIDTH="400"> +</CENTER> +} + \caption{The \emph{Structure} container class.} +\end{figure} +} +Since the \emph{Structure} class contains a +dictionary of \emph{LoadCase} objects, it is able to store and solve +multiple load cases, a capability that the original Fortran code +does not have. + + +\subsubsection{Aerostructure} + +The \emph{Aerostructure} class is the main class in the +aero-structural analysis module and contains a \emph{Geometry}, a +\emph{Flow} and a \emph{Structure}. In addition, the class defines +all the functions that are necessary to translate aerodynamic +loads to structural loads and structural displacements to +geometry surface deformations. + +One of the main methods of this class is the one that solves the +aeroelastic system. This method is printed below: +\begin{verbatim} +def Iterate(self, load_case): + """Iterates the aero-structural solution.""" + self.flow.Iterate() + self._UpdateStructuralLoads() + self.structure.CalcDisplacements(load_case) + self.structure.CalcStresses(load_case) + self._UpdateFlowMesh() + return +\end{verbatim} +This is indeed a very readable script, thanks to Python, and any +high-level changes to the solution procedure can be easily +implemented. +The \emph{Aerostructure} class also contains methods that export all +the information on the current solution for visualization, an example +of which is shown in the next section. + + +\subsection{Results} + +In order to visualize results, and because we needed to view results +from multiple disciplines simultaneously, we selected OpenDX. Output +files in DX format are written at the Python level and the result can +be seen in Fig.~\ref{fig:aerostructure} for the case of a transonic +airliner configuration. +\tthhide{ +\begin{figure*}[t] + \centering + \epsfig{file=./aerostructure.eps, angle=-90, width=\linewidth} + \caption{Aero-structural model and results.} + \label{fig:aerostructure} +\end{figure*} +} +\latexhide{ +\begin{figure}[h] + \label{fig:aerostructure} +\special{html: +<CENTER> + <IMG SRC="aerostructure.jpg" WIDTH="600"> +</CENTER> +} + \caption{Aero-structural model and results.} +\end{figure} +} + + +The figure illustrates the multidisciplinary nature of the +problem. The grid pictured in the background is the mesh used by the +flow solver and is colored by the pressure values computed at the +cell centers. The wing in the foreground and its outer surface is +clipped to show the internal structural components which are colored +by their stress value. + +In conclusion, \fpy and Python have been extremely useful tools in our +pursuit for increasing the usability and flexibility of existing Fortran +tools. + + +\begin{thebibliography}{99} +\bibitem{netlib} +\newblock Netlib repository at UTK and ORNL. +\newblock \\\wwwsite{http://www.netlib.org/} +\bibitem{python} +Python language. +\newblock \\\wwwsite{http://www.python.org/} +\bibitem{swig} +SWIG --- Simplified Wrapper and Interface Generator. +\newblock \\\wwwsite{http://www.swig.org/} +\bibitem{pyfort} +PyFort --- The Python-Fortran connection tool. +\newblock \\\wwwsite{http://pyfortran.sourceforge.net/} +\bibitem{fpig} +FPIG --- Fortran to Python Interface Generator. +\newblock \\\wwwsite{http://cens.ioc.ee/projects/f2py2e/} +\bibitem{numpy} +Numerical Extension to Python. +\newblock \\\wwwsite{http://numpy.sourceforge.net/} +\bibitem{graham-etal} +R. L. Graham, D. E. Knuth, and O. Patashnik. +\newblock {\em {C}oncrete {M}athematics: a foundation for computer science.} +\newblock Addison-Wesley, 1988 +\bibitem{f2py-ug} +P. Peterson. +\newblock {\em {\tt f2py} - Fortran to Python Interface Generator. Second Edition.} +\newblock 2000 +\newblock +\\\wwwsite{http://cens.ioc.ee/projects/f2py2e/usersguide.html} +\bibitem{python-doc:ext} +Python Documentation: Extending and Embedding. +\newblock \\\wwwsite{http://www.python.org/doc/ext/} +\bibitem{PFO} +P. Peterson. {\em {\tt PyFortranObject} example usages.} +\newblock 2001 +\newblock \\\wwwsite{http://cens.ioc.ee/projects/f2py2e/pyfobj.html} +\bibitem{reno99} +Reuther, J., J. J. Alonso, J. R. R. A. Martins, and +S. C. Smith. +\newblock ``A Coupled Aero-Structural Optimization Method for + Complete Aircraft Configurations'', +\newblock {\em Proceedings of the 37th Aerospace Sciences Meeting}, +\newblock AIAA Paper 1999-0187. Reno, NV, January, 1999 +\end{thebibliography} + +%\end{multicols} + +%\begin{figure}[htbp] +% \begin{center} +% \epsfig{file=aerostructure2b.ps,width=0.75\textwidth} +% \end{center} +%\end{figure} + + + +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/doc/f2py/signaturefile.tex b/doc/f2py/signaturefile.tex new file mode 100644 index 000000000..3cd16d890 --- /dev/null +++ b/doc/f2py/signaturefile.tex @@ -0,0 +1,368 @@ + +\section{Signature file} +\label{sec:signaturefile} + +The syntax of a signature file is borrowed from the Fortran~90/95 +language specification. Almost all Fortran~90/95 standard constructs +are understood. Recall that Fortran~77 is a subset of Fortran~90/95. +This tool introduces also some new attributes that are used for +controlling the process of Fortran to Python interface construction. +In the following, a short overview of the constructs +used in signature files will be given. + + +\subsection{Module block} +\label{sec:moduleblock} + +A signature file contains one or more \texttt{pythonmodule} blocks. A +\texttt{pythonmodule} block has the following structure: +\begin{verbatim} +python module <modulename> + interface + <routine signatures> + end [interface] + interface + module <F90/95 modulename> + <F90 module data type declarations> + <F90 module routine signatures> + end [module [<F90/95 modulename>]] + end [interface] +end [pythonmodule [<modulename>]] +\end{verbatim} +For each \texttt{pythonmodule} block \fpy will generate a C-file +\texttt{<modulename>module.c} (see step (iii)). (This is not true if +\texttt{<modulename>} contains substring \texttt{\_\_user\_\_}, see +Sec.~\ref{sec:cbmodule} and \texttt{external} attribute). + +\subsection{Signatures of Fortran routines and Python functions} +\label{sec:routineblock} + + +The signature of a Fortran routine has the following structure: +\begin{verbatim} +[<typespec>] function|subroutine <routine name> [([<arguments>])] \ + [result (<entityname>)] + [<argument type declarations>] + [<argument attribute statements>] + [<use statements>] + [<common block statements>] + [<other statements>] +end [function|subroutine [<routine name>]] +\end{verbatim} + +Let us introduce also the signature of the corresponding wrapper +function: +\begin{verbatim} +def <routine name>(<required arguments>[,<optional arguments>]): + ... + return <return variables> +\end{verbatim} + +Before you edit the signature file, you should first decide what is the +desired signature of the corresponding Python function. \fpy offers +many possibilities to control the interface construction process: you +may want to insert/change/remove various attributes in the +declarations of the arguments in order to change the appearance +of the arguments in the Python wrapper function. + +\begin{itemize} +\item +The definition of the \texttt{<argument type declaration>} is +\begin{verbatim} +<typespec> [[<attrspec>]::] <entitydecl> +\end{verbatim} +where +\begin{verbatim} +<typespec> := byte | character[<charselector>] + | complex[<kindselector>] | real[<kindselector>] + | double complex | double precision + | integer[<kindselector>] | logical[<kindselector>] +\end{verbatim} +\begin{verbatim} +<charselector> := *<charlen> | ([len=]<len>[,[kind]<kind>]) + | (kind=<kind>[,len=<len>]) +<kindselector> := *<intlen> | ([kind=]<kind>) +\end{verbatim} +(there is no sense to modify \texttt{<typespec>}s generated by \fpy). +\texttt{<attrspec>} is a comma separated list of attributes (see +Sec.~\ref{sec:attributes}); +\begin{verbatim} +<entitydecl> := <name> [[*<charlen>][(<arrayspec>)] + | [(<arrayspec>)]*<charlen>] + | [/<init_expr>/ | =<init_expr>] [,<entitydecl>] +\end{verbatim} +where \texttt{<arrayspec>} is a comma separated list of dimension +bounds; \texttt{<init\_expr>} is a C-expression (see +Sec.~\ref{sec:C-expr}). If an argument is not defined with +\texttt{<argument type declaration>}, its type is determined by +applying \texttt{implicit} rules (if it is not specifyied, then +standard rules are applied). + +\item The definition of the \texttt{<argument attribute statement>} is +a short form of the \texttt{<argument type declaration>}: +\begin{verbatim} +<attrspec> <entitydecl> +\end{verbatim} + +\item \texttt{<use statement>} is defined as follows +\begin{verbatim} +use <modulename> [,<rename_list> | ,ONLY:<only_list>] +<rename_list> := local_name=>use_name [,<rename_list>] +\end{verbatim} + Currently the \texttt{use} statement is used to link call-back + modules (Sec.~\ref{sec:cbmodule}) and the \texttt{external} + arguments (call-back functions). + +\item \texttt{<common block statement>} is defined as follows +\begin{verbatim} +common /<commonname>/ <shortentitydecl> +\end{verbatim} +where +\begin{verbatim} +<shortentitydecl> := <name> [(<arrayspec>)] [,<shortentitydecl>] +\end{verbatim} +One \texttt{module} block should not contain two or more +\texttt{common} blocks with the same name. Otherwise, the later ones +are ignored. The types of variables in \texttt{<shortentitydecl>} can +be defined in \texttt{<argument type declarations>}. Note that there +you can specify also the array specifications; then you don't need to +do that in \texttt{<shortentitydecl>}. +\end{itemize} + +\subsection{Attributes} +\label{sec:attributes} + +The following attributes are used by \fpy: +\begin{description} +\item[\texttt{optional}] --- the variable is moved to the end of + optional argument list of the wrapper function. Default value of an + optional argument can be specified using \texttt{<init\_expr>} in + \texttt{entitydecl}. You can use \texttt{optional} attribute also for + \texttt{external} arguments (call-back functions), but it is your + responsibility to ensure that it is given by the user if Fortran + routine wants to call it. +\item[\texttt{required}] --- the variable is considered as a required + argument (that is default). You will need this in order to overwrite + the \texttt{optional} attribute that is automatically set when + \texttt{<init\_expr>} is used. However, usage of this attribute + should be rare. +\item[\texttt{dimension(<arrayspec>)}] --- used when the variable is + an array. For unbounded dimensions symbols `\texttt{*}' or + `\texttt{:}' can be used (then internally the corresponding + dimensions are set to -1; you'll notice this when certain exceptions + are raised). +\item[\texttt{external}] --- the variable is a call-back function. \fpy will + construct a call-back mechanism for this function. Also call-back + functions must be defined by their signatures, and there are several + ways to do that. In most cases, \fpy will be able to determine the signatures + of call-back functions from the Fortran source code; then it + builds an additional \texttt{module} block with a name containing + string `\texttt{\_\_user\_\_}' (see Sec.~\ref{sec:cbmodule}) and + includes \texttt{use} statement to the routines signature. Anyway, + you should check that the generated signature is correct. + + Alternatively, you can specify the signature by inserting to the + routines block a ``model'' how the call-back function would be called + from Fortran. For subroutines you should use\\ + \hspace*{2em}\texttt{call <call-back name>(<arguments>)}\\ + and for functions\\% + \hspace*{2em}\texttt{<return value> = <call-back name>(<arguments>)}\\ + The variables in \texttt{<arguments>} and \texttt{<return value>} + must be defined as well. You can use the arguments of the main + routine, for instance. +\item[\texttt{intent(<intentspec>)}] --- this specifies the + ``intention'' of the variable. \texttt{<intentspec>} is a comma + separated list of the following specifications: + \begin{description} + \item[\texttt{in}] --- the variable is considered to be an input + variable (default). It means that the Fortran function uses only + the value(s) of the variable and is assumed not to change it. + \item[\texttt{inout}] --- the variable is considered to be an + input/output variable which means that Fortran routine may change + the value(s) of the variable. Note that in Python only array + objects can be changed ``in place''. (\texttt{intent(outin)} is + \texttt{intent(inout)}.) + \item[\texttt{out}] --- the value of the (output) variable is + returned by the wrapper function: it is appended to the list of + \texttt{<returned variables>}. If \texttt{out} is specified alone, + also \texttt{hide} is assumed. + \item[\texttt{hide}] --- use this if the variable \emph{should not} + or \emph{need not} to be in the list of wrapper function arguments + (not even in optional ones). For example, this is assumed if + \texttt{intent(out)} is used. You can ``hide'' an argument if it + has always a constant value specified in \texttt{<init\_expr>}, + for instance. + \end{description} + The following rules apply: + \begin{itemize} + \item if no \texttt{intent} attribute is specified, \texttt{intent(in)} is + assumed; + \item \texttt{intent(in,inout)} is \texttt{intent(in)}; + \item \texttt{intent(in,hide)}, \texttt{intent(inout,hide)} are \texttt{intent(hide)}; + \item \texttt{intent(out)} is \texttt{intent(out,hide)}; +\item \texttt{intent(inout)} is NOT \texttt{intent(in,out)}. + \end{itemize} + In conclusion, the following combinations are ``minimal'': + \texttt{intent(in)}, \texttt{intent(inout)}, \texttt{intent(out)}, + \texttt{intent(hide)}, \texttt{intent(in,out)}, and + \texttt{intent(inout,out)}. +\item[\texttt{check([<C-booleanexpr>])}] --- if + \texttt{<C-booleanexpr>} evaluates to zero, an exception is raised + about incorrect value or size or any other incorrectness of the + variable. If \texttt{check()} or \texttt{check} is used then \fpy + will not try to guess the checks automatically. +\item[\texttt{depend([<names>])}] --- the variable depends on other + variables listed in \texttt{<names>}. These dependence relations + determine the order of internal initialization of the variables. If + you need to change these relations then be careful not to break the + dependence relations of other relevant variables. If + \texttt{depend()} or \texttt{depend} is used then \fpy will not try + to guess the dependence relations automatically. +\item[\texttt{note(<LaTeX text>)}] --- with this attribute you can + include human readable documentation strings to the LaTeX document + that \fpy generates. Do not insert here information that \fpy can + establish by itself, such as, types, sizes, lengths of the + variables. Here you can insert almost arbitrary LaTeX text. Note + that \texttt{<LaTeX text>} is mainly used inside the LaTeX + \texttt{description} environment. Hint: you can use + \texttt{\bs{}texttt\{<name>\}} for typesetting variable \texttt{<name>} + in LaTeX. In order to get a new line to the LaTeX document, use + \texttt{\bs{}n} followed by a space. For longer text, you may want + to use line continuation feature of Fortran 90/95 language: set + \texttt{\&} (ampersand) + to be the last character in a line. +\item[\texttt{parameter}] --- the variable is parameter and it must + have a value. If the parameter is used in dimension specification, + it is replaced by its value. (Are there any other usages of + parameters except in dimension specifications? Let me know and I'll + add support for it). +\end{description} + + +\subsection{C-expressions} +\label{sec:C-expr} + +The signature of a routine may contain C-expressions in +\begin{itemize} +\item \texttt{<init\_expr>} for initializing particular variable, or in +\item \texttt{<C-booleanexpr>} of the \texttt{check} attribute, or in +\item \texttt{<arrayspec>} of the \texttt{dimension} attribute. +\end{itemize} +A C-expression may contain +\begin{itemize} +\item standard C-statement, +\item functions offered in \texttt{math.h}, +\item previously initialized variables (study +the dependence relations) from the argument list, and +\item the following CPP-macros: + \begin{description} + \item[\texttt{len(<name>)}] --- the length of an array \texttt{<name>}; + \item[\texttt{shape(<name>,<n>)}] --- the $n$-th dimension of an array + \texttt{<name>}; + \item[\texttt{rank(<name>)}] --- the rank of an array \texttt{<name>}; + \item[\texttt{slen(<name>)}] --- the length of a string \texttt{<name>}. + \end{description} +\end{itemize} + + +In addition, when initializing arrays, an index vector \texttt{int + \_i[rank(<name>)];} +is available: \texttt{\_i[0]} refers to +the index of the first dimension, \texttt{\_i[1]} to the index of +the second dimension, etc. For example, the argument type declaration\\ +\hspace*{2em}\texttt{integer a(10) = \_i[0]}\\ +is equivalent with the following Python statement\\ +\hspace*{2em}\texttt{a = array(range(10))} + + +\subsection{Required/optional arguments} +\label{sec:reqoptargs} + +When \texttt{optional} attribute is used (including the usage of +\texttt{<init\_expr>} without the \texttt{required} attribute), the +corresponding variable in the argument list of a Fortran routine is +appended to the optional argument list of the wrapper function. + +For optional array argument all dimensions must be bounded (not +\texttt{(*)} or \texttt{(:)}) and defined at the time of +initialization (dependence relations). + +If the \texttt{None} object is passed in in place of a required array +argument, it will be considered as optional: that is, the memory is +allocated (of course, if it has unbounded dimensions, an exception +will be raised), and if \texttt{<init\_expr>} is defined, +initialization is carried out. + + +\subsection{Internal checks} +\label{sec:intchecks} + +All array arguments are checked against the correctness of their rank. +If there is a mismatch, \fpy attempts to fix that by constructing an +array with a correct rank from the given array argument (there will be +no performance hit as no data is copied). The freedom to do so is +given only if some dimensions are unbounded or their value is 1. An +exception is raised when the sizes will not match. + +All bounded dimensions of an array are checked to be larger or equal +to the dimensions specified in the signature. + +So, you don't need to give explicit \texttt{check} attributes to check +these internal checks. + + +\subsection{Call-back modules} +\label{sec:cbmodule} + +A Fortran routine may have \texttt{external} arguments (call-back +functions). The signatures of the call-back functions must be defined +in a call-back \texttt{module} block (its name contains +\texttt{\_\_user\_\_}), in general; other possibilities are described +in the \texttt{external} attribute specification (see +Sec.~\ref{sec:attributes}). For the signatures of call-back +functions the following restrictions apply: +\begin{itemize} +\item Attributes \texttt{external}, \texttt{check(...)}, and + initialization statements are ignored. +\item Attribute \texttt{optional} is used only for changing the order + of the arguments. +\item For arrays all dimension bounds must be specified. They may be + C-expressions containing variables from the argument list. + Note that here CPP-macros \texttt{len}, \texttt{shape}, + \texttt{rank}, and \texttt{slen} are not available. +\end{itemize} + + +\subsection{Common blocks} +\label{sec:commonblocks} + +All fields in a common block are mapped to arrays of appropriate sizes +and types. Scalars are mapped to rank-0 arrays. For multi-dimensional +fields the corresponding arrays are transposed. In the type +declarations of the variables representing the common block fields, +only \texttt{dimension(<arrayspec>)}, \texttt{intent(hide)}, and +\texttt{note(<LaTeX text>)} attributes are used, others are ignored. + +\subsection{Including files} +\label{sec:include} + +You can include files to the signature file using +\begin{verbatim} +include '<filename>' +\end{verbatim} +statement. It can be used in any part of the signature file. +If the file \texttt{<filename>} does not exists or it is not in the path, +the \texttt{include} line is ignored. + +\subsection{\fpy directives} +\label{sec:directives} + +You can insert signature statements directly to Fortran source codes +as comments. Anything that follows \texttt{<comment char>f2py} is +regarded as normal statement for \fpy. + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "f2py2e" +%%% End: + diff --git a/doc/f2py/simple.f b/doc/f2py/simple.f new file mode 100644 index 000000000..ba468a509 --- /dev/null +++ b/doc/f2py/simple.f @@ -0,0 +1,13 @@ +cFile: simple.f + subroutine foo(a,m,n) + integer m,n,i,j + real a(m,n) +cf2py intent(in,out) a +cf2py intent(hide) m,n + do i=1,m + do j=1,n + a(i,j) = a(i,j) + 10*i+j + enddo + enddo + end +cEOF diff --git a/doc/f2py/simple_session.dat b/doc/f2py/simple_session.dat new file mode 100644 index 000000000..10d9dc962 --- /dev/null +++ b/doc/f2py/simple_session.dat @@ -0,0 +1,51 @@ +>>> import pytest +>>> import f2pytest +>>> import pyforttest +>>> print f2pytest.foo.__doc__ +foo - Function signature: + a = foo(a) +Required arguments: + a : input rank-2 array('f') with bounds (m,n) +Return objects: + a : rank-2 array('f') with bounds (m,n) + +>>> print pyforttest.foo.__doc__ +foo(a) + +>>> pytest.foo([[1,2],[3,4]]) +array([[12, 14], + [24, 26]]) +>>> f2pytest.foo([[1,2],[3,4]]) # F2PY can handle arbitrary input sequences +array([[ 12., 14.], + [ 24., 26.]],'f') +>>> pyforttest.foo([[1,2],[3,4]]) +Traceback (most recent call last): + File "<stdin>", line 1, in ? +pyforttest.error: foo, argument A: Argument intent(inout) must be an array. + +>>> import Numeric +>>> a=Numeric.array([[1,2],[3,4]],'f') +>>> f2pytest.foo(a) +array([[ 12., 14.], + [ 24., 26.]],'f') +>>> a # F2PY makes a copy when input array is not Fortran contiguous +array([[ 1., 2.], + [ 3., 4.]],'f') +>>> a=Numeric.transpose(Numeric.array([[1,3],[2,4]],'f')) +>>> a +array([[ 1., 2.], + [ 3., 4.]],'f') +>>> f2pytest.foo(a) +array([[ 12., 14.], + [ 24., 26.]],'f') +>>> a # F2PY passes Fortran contiguous input array directly to Fortran +array([[ 12., 14.], + [ 24., 26.]],'f') +# See intent(copy), intent(overwrite), intent(inplace), intent(inout) +# attributes documentation to enhance the above behavior. + +>>> a=Numeric.array([[1,2],[3,4]],'f') +>>> pyforttest.foo(a) +>>> a # Huh? Pyfort 8.5 gives wrong results.. +array([[ 12., 23.], + [ 15., 26.]],'f') diff --git a/doc/f2py/using_F_compiler.txt b/doc/f2py/using_F_compiler.txt new file mode 100644 index 000000000..63bb0d68c --- /dev/null +++ b/doc/f2py/using_F_compiler.txt @@ -0,0 +1,147 @@ + +Title: Wrapping F compiled Fortran 90 modules with F2PY + ================================================ + +Rationale: The F compiler does not support external procedures which + makes it impossible to use it in F2PY in a normal way. + This document describes a workaround to this problem so + that F compiled codes can be still wrapped with F2PY. + +Author: Pearu Peterson +Date: May 8, 2002 + +Acknowledgement: Thanks to Siegfried Gonzi who hammered me to produce + this document. + +Normally wrapping Fortran 90 modules to Python using F2PY is carried +out with the following command + + f2py -c -m fun foo.f90 + +where file foo.f90 contains, for example, + +module foo + public :: bar + contains + subroutine bar (a) + integer,intent(inout) :: a + print *,"Hello from foo.bar" + print *,"a=",a + a = a + 5 + print *,"a=",a + end subroutine bar +end module foo + +Then with a supported F90 compiler (running `f2py -c --help-compiler' +will display the found compilers) f2py will generate an extension +module fun.so into the current directory and the Fortran module foo +subroutine bar can be called from Python as follows + +>>> import fun +>>> print fun.foo.bar.__doc__ +bar - Function signature: + bar(a) +Required arguments: + a : in/output rank-0 array(int,'i') + +>>> from Numeric import array +>>> a = array(3) +>>> fun.foo.bar(a) + Hello from foo.bar + a= 3 + a= 8 +>>> a +8 +>>> + +This works nicely with all supported Fortran compilers. + +However, the F compiler (http://www.fortran.com/F/compilers.html) is +an exception. Namely, the F compiler is designed to recognize only +module procedures (and main programs, of course) but F2PY needs to +compile also the so-called external procedures that it generates to +facilitate accessing Fortran F90 module procedures from C and +subsequently from Python. As a result, wrapping F compiled Fortran +procedures to Python is _not_ possible using the simple procedure as +described above. But, there is a workaround that I'll describe below +in five steps. + +1) Compile foo.f90: + + F -c foo.f90 + +This creates an object file foo.o into the current directory. + +2) Create the signature file: + + f2py foo.f90 -h foo.pyf + +This creates a file foo.pyf containing + +module foo ! in foo.f90 + real public :: bar + subroutine bar(a) ! in foo.f90:foo + integer intent(inout) :: a + end subroutine bar +end module foo + +3) Open the file foo.pyf with your favorite text editor and change the + above signature to + +python module foo + interface + subroutine bar(a) + fortranname foo_MP_bar + intent(c) bar + integer intent(in,out) :: a + end subroutine bar + end interface +end python module foo + +The most important modifications are + + a) adding `python' keyword everywhere before the `module' keyword + + b) including an `interface' block around the all subroutine blocks. + + c) specifying the real symbol name of the subroutine using + `fortranname' statement. F generated symbol names are in the form + <module name>_MP_<subroutine name> + + d) specifying that subroutine is `intent(c)'. + +Notice that the `intent(inout)' attribute is changed to +`intent(in,out)' that instructs the wrapper to return the modified +value of `a'. + +4) Build the extension module + + f2py -c foo.pyf foo.o --fcompiler=Gnu /opt/F/lib/quickfit.o \ + /opt/F/lib/libf96.a + +This will create the extension module foo.so into the current +directory. Notice that you must use Gnu compiler (gcc) for linking. +And the paths to F specific object files and libraries may differ for +your F installation. + +5) Finally, we can call the module subroutine `bar' from Python + +>>> import foo +>>> print foo.bar.__doc__ +bar - Function signature: + a = bar(a) +Required arguments: + a : input int +Return objects: + a : int + +>>> foo.bar(3) +8 +>>> + +Notice that the F compiled module procedures are called as ordinary +external procedures. Also I/O seems to be lacking for F compiled +Fortran modules. + +Enjoy, + Pearu diff --git a/doc/f2py/win32_notes.txt b/doc/f2py/win32_notes.txt new file mode 100644 index 000000000..691cac26e --- /dev/null +++ b/doc/f2py/win32_notes.txt @@ -0,0 +1,84 @@ +The following notes are from Eric Jones. + +My Setup: + +For Python/Fortran development, I run Windows 2000 and use the mingw32 +(www.mingw.org) set of gcc/g77 compilers and tools (gcc 2.95.2) to build python +extensions. I'll also ocassionally use MSVC for extension development, but +rarely on projects that include Fortran code. This short HOWTO describes how +I use f2py in the Windows environment. Pretty much everything is done from +a CMD (DOS) prompt, so you'll need to be familiar with using shell commands. + +Installing f2py: + +Before installing f2py, you'll need to install python. I use python2.1 (maybe +python2.2 will be out by the time you read this). Any version of Python beyond +version 1.52 should be fine. See www.python.org for info on installing Python. + +You'll also need Numeric which is available at +http://sourceforge.net/projects/numpy/. The latest version is 20.3. + +Since Pearu has moved to a setup.py script, installation is pretty easy. You +can download f2py from http://cens.ioc.ee/projects/f2py2e/. The latest public +release is http://cens.ioc.ee/projects/f2py2e/rel-3.x/f2py-3.latest.tgz. Even +though this is a .tgz file instead of a .zip file, most standard compression +utilities such as WinZip (www.winzip.com) handle unpacking .tgz files +automatically. Here are the download steps: + + 1. Download the latest version of f2py and save it to disk. + + 2. Use WinZip or some other tool to open the "f2py.xxx.tgz" file. + a. When WinZip says archive contains one file, "f2py.xxx.tar" + and ask if it should open it, respond with "yes". + b. Extract (use the extract button at the top) all the files + in the archive into a file. I'll use c:\f2py2e + + 3. Open a cmd prompt by clicking start->run and typing "cmd.exe". + Now type the following commands. + + C:\WINDOWS\SYSTEM32> cd c:\f2py2e + C:\F2PY2E> python setup.py install + + This will install f2py in the c:\python21\f2py2e directory. It + also copies a few scripts into the c:\python21\Scripts directory. + Thats all there is to installing f2py. Now lets set up the environment + so that f2py is easy to use. + + 4. You need to set up a couple of environement variables. The path + "c:\python21\Scripts" needs to be added to your path variables. + To do this, go to the enviroment variables settings page. This is + where it is on windows 2000: + + Desktop->(right click)My Computer->Properties->Advanced-> + Environment Variables + + a. Add "c:\python21\Scripts" to the end of the Path variable. + b. If it isn't already there, add ".py" to the PATHEXT variable. + This tells the OS to execute f2py.py even when just "f2py" is + typed at a command prompt. + + 5. Well, there actually isn't anything to be done here. The Python + installation should have taken care of associating .py files with + Python for execution, so you shouldn't have to do anything to + registry settings. + +To test your installation, open a new cmd prompt, and type the following: + + C:\WINDOWS\SYSTEM32> f2py + Usage: + f2py [<options>] <fortran files> [[[only:]||[skip:]] \ + <fortran functions> ] \ + [: <fortran files> ...] + ... + +This prints out the usage information for f2py. If it doesn't, there is +something wrong with the installation. + +Testing: +The f2py test scripts are kinda Unix-centric, so they don't work under windows. + +XXX include test script XXX. + +Compiler and setup.py issues: + +XXX |