summaryrefslogtreecommitdiff
path: root/numpy/f2py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/f2py')
-rw-r--r--numpy/f2py/BUGS.txt55
-rw-r--r--numpy/f2py/Makefile173
-rw-r--r--numpy/f2py/NEWS.txt2
-rw-r--r--numpy/f2py/README.txt5
-rw-r--r--numpy/f2py/TODO.txt67
-rw-r--r--numpy/f2py/__init__.py40
-rw-r--r--numpy/f2py/__version__.py9
-rw-r--r--numpy/f2py/auxfuncs.py489
-rw-r--r--numpy/f2py/capi_maps.py723
-rw-r--r--numpy/f2py/cb_rules.py534
-rw-r--r--numpy/f2py/cfuncs.py1134
-rw-r--r--numpy/f2py/common_rules.py132
-rwxr-xr-xnumpy/f2py/crackfortran.py2659
-rw-r--r--numpy/f2py/diagnose.py166
-rw-r--r--numpy/f2py/doc/Makefile76
-rw-r--r--numpy/f2py/doc/Release-1.x.txt27
-rw-r--r--numpy/f2py/doc/Release-2.x.txt77
-rw-r--r--numpy/f2py/doc/Release-3.x.txt87
-rw-r--r--numpy/f2py/doc/Release-4.x.txt91
-rw-r--r--numpy/f2py/doc/apps.tex71
-rw-r--r--numpy/f2py/doc/bugs.tex109
-rwxr-xr-xnumpy/f2py/doc/collectinput.py77
-rw-r--r--numpy/f2py/doc/commands.tex20
-rw-r--r--numpy/f2py/doc/ex1/arr.f4
-rw-r--r--numpy/f2py/doc/ex1/bar.f4
-rw-r--r--numpy/f2py/doc/ex1/foo.f5
-rw-r--r--numpy/f2py/doc/ex1/foobar-smart.f9024
-rw-r--r--numpy/f2py/doc/ex1/foobar.f9016
-rw-r--r--numpy/f2py/doc/ex1/foobarmodule.tex36
-rwxr-xr-xnumpy/f2py/doc/ex1/runme18
-rw-r--r--numpy/f2py/doc/f2py2e.tex50
-rw-r--r--numpy/f2py/doc/f2python9-final/README.txt38
-rw-r--r--numpy/f2py/doc/f2python9-final/aerostructure.jpgbin0 -> 72247 bytes
-rw-r--r--numpy/f2py/doc/f2python9-final/flow.jpgbin0 -> 13266 bytes
-rwxr-xr-xnumpy/f2py/doc/f2python9-final/mk_html.sh13
-rwxr-xr-xnumpy/f2py/doc/f2python9-final/mk_pdf.sh13
-rwxr-xr-xnumpy/f2py/doc/f2python9-final/mk_ps.sh14
-rw-r--r--numpy/f2py/doc/f2python9-final/src/examples/exp1.f26
-rw-r--r--numpy/f2py/doc/f2python9-final/src/examples/exp1mess.txt17
-rw-r--r--numpy/f2py/doc/f2python9-final/src/examples/exp1session.txt20
-rw-r--r--numpy/f2py/doc/f2python9-final/src/examples/foo.pyf13
-rw-r--r--numpy/f2py/doc/f2python9-final/src/examples/foom.pyf14
-rw-r--r--numpy/f2py/doc/f2python9-final/structure.jpgbin0 -> 17860 bytes
-rw-r--r--numpy/f2py/doc/fortranobject.tex574
-rw-r--r--numpy/f2py/doc/index.html265
-rw-r--r--numpy/f2py/doc/intro.tex158
-rw-r--r--numpy/f2py/doc/multiarray/array_from_pyobj.c323
-rw-r--r--numpy/f2py/doc/multiarray/bar.c15
-rw-r--r--numpy/f2py/doc/multiarray/foo.f13
-rw-r--r--numpy/f2py/doc/multiarray/fortran_array_from_pyobj.txt284
-rw-r--r--numpy/f2py/doc/multiarray/fun.pyf89
-rw-r--r--numpy/f2py/doc/multiarray/run.pyf91
-rw-r--r--numpy/f2py/doc/multiarray/transpose.txt1127
-rw-r--r--numpy/f2py/doc/multiarrays.txt120
-rw-r--r--numpy/f2py/doc/notes.tex310
-rw-r--r--numpy/f2py/doc/oldnews.html121
-rw-r--r--numpy/f2py/doc/options.tex63
-rw-r--r--numpy/f2py/doc/python9.tex1046
-rw-r--r--numpy/f2py/doc/signaturefile.tex368
-rw-r--r--numpy/f2py/doc/using_F_compiler.txt147
-rw-r--r--numpy/f2py/doc/win32_notes.txt85
-rw-r--r--numpy/f2py/docs/FAQ.txt615
-rw-r--r--numpy/f2py/docs/HISTORY.txt1044
-rw-r--r--numpy/f2py/docs/OLDNEWS.txt63
-rw-r--r--numpy/f2py/docs/README.txt457
-rw-r--r--numpy/f2py/docs/TESTING.txt108
-rw-r--r--numpy/f2py/docs/THANKS.txt63
-rw-r--r--numpy/f2py/docs/default.css180
-rw-r--r--numpy/f2py/docs/docutils.conf16
-rw-r--r--numpy/f2py/docs/hello.f7
-rw-r--r--numpy/f2py/docs/pyforttest.pyf5
-rw-r--r--numpy/f2py/docs/pytest.py10
-rw-r--r--numpy/f2py/docs/simple.f13
-rw-r--r--numpy/f2py/docs/simple_session.dat51
-rw-r--r--numpy/f2py/docs/usersguide/allocarr.f9016
-rw-r--r--numpy/f2py/docs/usersguide/allocarr_session.dat27
-rw-r--r--numpy/f2py/docs/usersguide/array.f17
-rw-r--r--numpy/f2py/docs/usersguide/array_session.dat65
-rw-r--r--numpy/f2py/docs/usersguide/calculate.f14
-rw-r--r--numpy/f2py/docs/usersguide/calculate_session.dat6
-rw-r--r--numpy/f2py/docs/usersguide/callback.f12
-rw-r--r--numpy/f2py/docs/usersguide/callback2.pyf19
-rw-r--r--numpy/f2py/docs/usersguide/callback_session.dat23
-rw-r--r--numpy/f2py/docs/usersguide/common.f13
-rw-r--r--numpy/f2py/docs/usersguide/common_session.dat27
-rw-r--r--numpy/f2py/docs/usersguide/compile_session.dat11
-rw-r--r--numpy/f2py/docs/usersguide/default.css180
-rw-r--r--numpy/f2py/docs/usersguide/docutils.conf16
-rw-r--r--numpy/f2py/docs/usersguide/extcallback.f14
-rw-r--r--numpy/f2py/docs/usersguide/extcallback_session.dat19
-rw-r--r--numpy/f2py/docs/usersguide/fib1.f18
-rw-r--r--numpy/f2py/docs/usersguide/fib1.pyf12
-rw-r--r--numpy/f2py/docs/usersguide/fib2.pyf9
-rw-r--r--numpy/f2py/docs/usersguide/fib3.f21
-rw-r--r--numpy/f2py/docs/usersguide/ftype.f9
-rw-r--r--numpy/f2py/docs/usersguide/ftype_session.dat21
-rw-r--r--numpy/f2py/docs/usersguide/index.txt1772
-rw-r--r--numpy/f2py/docs/usersguide/moddata.f9018
-rw-r--r--numpy/f2py/docs/usersguide/moddata_session.dat23
-rw-r--r--numpy/f2py/docs/usersguide/run_main_session.dat14
-rw-r--r--numpy/f2py/docs/usersguide/scalar.f12
-rw-r--r--numpy/f2py/docs/usersguide/scalar_session.dat21
-rw-r--r--numpy/f2py/docs/usersguide/setup_example.py19
-rw-r--r--numpy/f2py/docs/usersguide/spam.pyf19
-rw-r--r--numpy/f2py/docs/usersguide/spam_session.dat5
-rw-r--r--numpy/f2py/docs/usersguide/string.f21
-rw-r--r--numpy/f2py/docs/usersguide/string_session.dat27
-rw-r--r--numpy/f2py/docs/usersguide/var.pyf11
-rw-r--r--numpy/f2py/docs/usersguide/var_session.dat3
-rw-r--r--numpy/f2py/f2py.1209
-rwxr-xr-xnumpy/f2py/f2py2e.py555
-rw-r--r--numpy/f2py/f2py_testing.py74
-rw-r--r--numpy/f2py/f90mod_rules.py240
-rw-r--r--numpy/f2py/func2subr.py165
-rw-r--r--numpy/f2py/rules.py1345
-rw-r--r--numpy/f2py/setup.cfg3
-rwxr-xr-xnumpy/f2py/setup.py107
-rw-r--r--numpy/f2py/src/fortranobject.c756
-rw-r--r--numpy/f2py/src/fortranobject.h123
-rw-r--r--numpy/f2py/src/test/Makefile96
-rw-r--r--numpy/f2py/src/test/bar.f11
-rw-r--r--numpy/f2py/src/test/foo.f11
-rw-r--r--numpy/f2py/src/test/foo90.f9013
-rw-r--r--numpy/f2py/src/test/foomodule.c143
-rw-r--r--numpy/f2py/src/test/wrap.f70
-rw-r--r--numpy/f2py/tests/array_from_pyobj/__init__.py0
-rw-r--r--numpy/f2py/tests/array_from_pyobj/setup.py26
-rw-r--r--numpy/f2py/tests/array_from_pyobj/tests/test_array_from_pyobj.py512
-rw-r--r--numpy/f2py/tests/array_from_pyobj/wrapmodule.c194
-rw-r--r--numpy/f2py/tests/c/return_real.py108
-rw-r--r--numpy/f2py/tests/f77/callback.py99
-rw-r--r--numpy/f2py/tests/f77/return_character.py100
-rw-r--r--numpy/f2py/tests/f77/return_complex.py125
-rw-r--r--numpy/f2py/tests/f77/return_integer.py148
-rw-r--r--numpy/f2py/tests/f77/return_logical.py135
-rw-r--r--numpy/f2py/tests/f77/return_real.py127
-rw-r--r--numpy/f2py/tests/f90/return_character.py100
-rw-r--r--numpy/f2py/tests/f90/return_complex.py127
-rw-r--r--numpy/f2py/tests/f90/return_integer.py152
-rw-r--r--numpy/f2py/tests/f90/return_logical.py138
-rw-r--r--numpy/f2py/tests/f90/return_real.py129
-rw-r--r--numpy/f2py/tests/mixed/foo.f5
-rw-r--r--numpy/f2py/tests/mixed/foo_fixed.f908
-rw-r--r--numpy/f2py/tests/mixed/foo_free.f908
-rw-r--r--numpy/f2py/tests/mixed/run.py50
-rwxr-xr-xnumpy/f2py/tests/run_all.py55
-rw-r--r--numpy/f2py/use_rules.py115
147 files changed, 23895 insertions, 0 deletions
diff --git a/numpy/f2py/BUGS.txt b/numpy/f2py/BUGS.txt
new file mode 100644
index 000000000..ee08863bb
--- /dev/null
+++ b/numpy/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/numpy/f2py/Makefile b/numpy/f2py/Makefile
new file mode 100644
index 000000000..91c199f99
--- /dev/null
+++ b/numpy/f2py/Makefile
@@ -0,0 +1,173 @@
+# Makefile for f2py2e
+#
+# Use GNU make for making.
+# $Revision: 1.46 $
+# $Date: 2005/01/30 17:22:55 $
+# Pearu Peterson <pearu@ioc.ee>
+
+PYTHON=python
+MAJOR=2
+F2PY2E_CVSROOT=:pserver:anonymous@cens.ioc.ee:/home/cvs
+SCIPY_CVSROOT=:pserver:anonymous@scipy.org:/home/cvsroot
+
+UPLOADCMD = scp -r
+UPLOADDIR = pearu@kev.ioc.ee:/net/cens/home/www/unsecure/projects/f2py2e/
+
+REV=`python -c 'from __version__ import *;print version'`
+SCIPY_DISTUTILS_REV=`cd scipy_distutils && $(PYTHON) -c 'from scipy_distutils_version import *;print scipy_distutils_version' && cd ..`
+
+SRC_FILES = F2PY-$(MAJOR)-latest.tar.gz scipy_distutils-latest.tar.gz F2PY-$(MAJOR)-latest.win32.exe scipy_distutils-latest.win32.exe
+
+HTML_FILES = index.html FAQ.html HISTORY.html THANKS.html TESTING.html OLDNEWS.html
+FAQ_DEPS = simple.f pytest.py pyforttest.pyf simple_session.dat
+README_DEPS = hello.f
+UG_FILES = index.html f2py_usersguide.pdf
+UG_FILES_DEP = $(shell cd docs/usersguide && ls *.{f,f90,dat,pyf,py})
+
+WWW_SRC_FILES = $(SRC_FILES:%=upload/www/$(MAJOR).x/%)
+WWW_WEB_FILES = $(HTML_FILES:%=upload/www/%) $(README_DEPS:%=upload/www/%)
+WWW_UG_FILES = $(UG_FILES:%=upload/www/usersguide/%) $(UG_FILES_DEP:%=upload/www/usersguide/%)
+
+TMP_WEB_FILES = $(HTML_FILES:%=upload/tmp/%) $(README_DEPS:%=upload/tmp/%)
+
+##############################################################################
+
+all:
+ @echo "Use 'make install' to install f2py"
+ @echo "Use 'make generate' to build f2py docs to upload/tmp"
+install:
+ $(PYTHON) setup.py install
+test:
+ cd tests && $(PYTHON) run_all.py
+
+##############################################################################
+# Create F2PY tar-balls
+##############################################################################
+f2py2e:
+ test -d f2py2e && (cd f2py2e && cvs -d $(F2PY2E_CVSROOT) -z7 update -Pd && cd -) || cvs -d $(F2PY2E_CVSROOT) checkout f2py2e
+
+upload/tmp/$(MAJOR).x/F2PY-$(MAJOR)-latest.tar.gz: f2py2e
+ cd f2py2e && python setup.py sdist -f
+ mkdir -p upload/tmp/$(MAJOR).x
+ cp f2py2e/dist/F2PY-$(REV).tar.gz upload/tmp/$(MAJOR).x
+ ln -sf F2PY-$(REV).tar.gz F2PY-$(MAJOR)-latest.tar.gz
+ mv F2PY-$(MAJOR)-latest.tar.gz upload/tmp/$(MAJOR).x
+upload/tmp/$(MAJOR).x/F2PY-$(MAJOR)-latest.win32.exe: f2py2e
+ cd f2py2e && python setup.py bdist_wininst
+ mkdir -p upload/tmp/$(MAJOR).x
+ cp f2py2e/dist/F2PY-$(REV).win32.exe upload/tmp/$(MAJOR).x
+ ln -sf F2PY-$(REV).win32.exe F2PY-$(MAJOR)-latest.win32.exe
+ mv F2PY-$(MAJOR)-latest.win32.exe upload/tmp/$(MAJOR).x
+f2py2e_latest: upload/tmp/$(MAJOR).x/F2PY-$(MAJOR)-latest.tar.gz upload/tmp/$(MAJOR).x/F2PY-$(MAJOR)-latest.win32.exe
+
+##############################################################################
+# Create Scipy_distutils tar-balls
+##############################################################################
+
+scipy_distutils:
+ test -d scipy_distutils && (cd scipy_distutils && cvs -d $(SCIPY_CVSROOT) -z7 update -Pd && cd -) || cvs -d $(SCIPY_CVSROOT) checkout scipy_distutils
+
+upload/tmp/$(MAJOR).x/scipy_distutils-latest.tar.gz: scipy_distutils
+ cd scipy_distutils && python setup.py sdist -f
+ mkdir -p upload/tmp/$(MAJOR).x
+ cp scipy_distutils/dist/scipy_distutils-$(SCIPY_DISTUTILS_REV).tar.gz upload/tmp/$(MAJOR).x
+ ln -sf scipy_distutils-$(SCIPY_DISTUTILS_REV).tar.gz scipy_distutils-latest.tar.gz
+ mv scipy_distutils-latest.tar.gz upload/tmp/$(MAJOR).x
+upload/tmp/$(MAJOR).x/scipy_distutils-latest.win32.exe: scipy_distutils
+ cd scipy_distutils && python setup.py bdist_wininst
+ mkdir -p upload/tmp/$(MAJOR).x
+ cp scipy_distutils/dist/scipy_distutils-$(SCIPY_DISTUTILS_REV).win32.exe upload/tmp/$(MAJOR).x
+ ln -sf scipy_distutils-$(SCIPY_DISTUTILS_REV).win32.exe scipy_distutils-latest.win32.exe
+ mv scipy_distutils-latest.win32.exe upload/tmp/$(MAJOR).x
+
+scipy_distutils_latest: upload/tmp/$(MAJOR).x/scipy_distutils-latest.tar.gz upload/tmp/$(MAJOR).x/scipy_distutils-latest.win32.exe
+
+latest: f2py2e_latest scipy_distutils_latest
+
+##############################################################################
+# Upload files.
+##############################################################################
+
+upload/www/$(MAJOR).x/F2PY-$(MAJOR)-latest.tar.gz: upload/tmp/$(MAJOR).x/F2PY-$(MAJOR)-latest.tar.gz
+ -mkdir -p `dirname $@`
+ cp -P upload/tmp/$(MAJOR).x/F2PY-{$(MAJOR)-latest,$(REV)}.tar.gz upload/www/$(MAJOR).x
+ $(UPLOADCMD) upload/tmp/$(MAJOR).x/F2PY-{$(MAJOR)-latest,$(REV)}.tar.gz $(UPLOADDIR)/$(MAJOR).x/
+upload/www/$(MAJOR).x/scipy_distutils-latest.tar.gz: upload/tmp/$(MAJOR).x/scipy_distutils-latest.tar.gz
+ -mkdir -p `dirname $@`
+ cp -P upload/tmp/$(MAJOR).x/scipy_distutils-{latest,$(SCIPY_DISTUTILS_REV)}.tar.gz upload/www/$(MAJOR).x/
+ $(UPLOADCMD) upload/tmp/$(MAJOR).x/scipy_distutils-{latest,$(SCIPY_DISTUTILS_REV)}.tar.gz $(UPLOADDIR)/$(MAJOR).x
+upload/www/$(MAJOR).x/F2PY-$(MAJOR)-latest.win32.exe: upload/tmp/$(MAJOR).x/F2PY-$(MAJOR)-latest.win32.exe
+ -mkdir -p `dirname $@`
+ cp -P upload/tmp/$(MAJOR).x/F2PY-{$(MAJOR)-latest,$(REV)}.win32.exe upload/www/$(MAJOR).x
+ $(UPLOADCMD) upload/tmp/$(MAJOR).x/F2PY-{$(MAJOR)-latest,$(REV)}.win32.exe $(UPLOADDIR)/$(MAJOR).x/
+upload/www/$(MAJOR).x/scipy_distutils-latest.win32.exe: upload/tmp/$(MAJOR).x/scipy_distutils-latest.win32.exe
+ -mkdir -p `dirname $@`
+ cp -P upload/tmp/$(MAJOR).x/scipy_distutils-{latest,$(SCIPY_DISTUTILS_REV)}.win32.exe upload/www/$(MAJOR).x
+ $(UPLOADCMD) upload/tmp/$(MAJOR).x/scipy_distutils-{latest,$(SCIPY_DISTUTILS_REV)}.win32.exe $(UPLOADDIR)/$(MAJOR).x/
+
+upload/tmp/usersguide/index.html: docs/usersguide/index.txt $(UG_FILES_DEP:%=upload/www/usersguide/%)
+ -mkdir -p upload/tmp/usersguide
+ rest2html $< $@
+upload/tmp/usersguide/f2py_usersguide.tex: docs/usersguide/index.txt $(UG_FILES_DEP:%=upload/www/usersguide/%)
+ -mkdir -p upload/tmp/usersguide
+ rest2latex $< $@
+upload/tmp/usersguide/f2py_usersguide.pdf: upload/tmp/usersguide/f2py_usersguide.tex
+ cd `dirname $@` && pdflatex `basename $<`
+upload/tmp/usersguide/%.f: docs/usersguide/%.f
+ -mkdir -p upload/tmp/usersguide
+ cp $< $@
+upload/tmp/usersguide/%.f90: docs/usersguide/%.f90
+ -mkdir -p upload/tmp/usersguide
+ cp $< $@
+upload/tmp/usersguide/%.dat: docs/usersguide/%.dat
+ -mkdir -p upload/tmp/usersguide
+ cp $< $@
+upload/tmp/usersguide/%.pyf: docs/usersguide/%.pyf
+ -mkdir -p upload/tmp/usersguide
+ cp $< $@
+upload/tmp/usersguide/%.py: docs/usersguide/%.py
+ -mkdir -p upload/tmp/usersguide
+ cp $< $@
+upload/www/usersguide/%: upload/tmp/usersguide/%
+ -mkdir -p `dirname $@`
+ cp -P $< $@
+ $(UPLOADCMD) $@ $(UPLOADDIR)/usersguide
+
+upload/tmp/FAQ.html: docs/FAQ.txt $(FAQ_DEPS:%=docs/%)
+ -mkdir -p upload/tmp
+ rest2html $< $@
+upload/tmp/index.html: docs/README.txt $(README_DEPS:%=docs/%)
+ -mkdir -p upload/tmp
+ rest2html $< $@
+upload/tmp/%.f: docs/%.f
+ -mkdir -p upload/tmp
+ cp $< $@
+upload/tmp/%.html: docs/%.txt
+ -mkdir -p upload/tmp
+ rest2html $< $@
+upload/www/%: upload/tmp/%
+ -mkdir -p `dirname $@`
+ cp -P $< $@
+ $(UPLOADCMD) $@ $(UPLOADDIR)/
+
+upload_web: $(WWW_WEB_FILES)
+upload_ug: $(WWW_UG_FILES)
+upload_src: $(WWW_SRC_FILES)
+upload: upload_src upload_ug upload_web
+
+generate_web: $(TMP_WEB_FILES)
+generate: generate_web
+
+##############################################################################
+# Clean up
+##############################################################################
+clean:
+ rm -f {tests/,tests/{f77,f90,mixed}/,docs/,docs/usersguide/,}*.{o,a,so,sl,pyc}
+ rm -f {tests/,tests/{f77,f90,mixed}/,docs/,docs/usersguide/,}*~
+distclean: clean
+ rm -f {tests/,src/,}*~
+ rm -f tests/*.{f,f90}
+ rm -rf dist {docs/,docs/usersguide/,}build f2py2e scipy_distutils upload
+ rm -f MANIFEST f2py?.? f2py
+
+.PHONY: install test
diff --git a/numpy/f2py/NEWS.txt b/numpy/f2py/NEWS.txt
new file mode 100644
index 000000000..a4a254405
--- /dev/null
+++ b/numpy/f2py/NEWS.txt
@@ -0,0 +1,2 @@
+
+Read docs/HISTORY.txt \ No newline at end of file
diff --git a/numpy/f2py/README.txt b/numpy/f2py/README.txt
new file mode 100644
index 000000000..ebe7e8c88
--- /dev/null
+++ b/numpy/f2py/README.txt
@@ -0,0 +1,5 @@
+======================================================================
+ F2PY - Fortran to Python Interface Generator
+======================================================================
+
+Read docs/README.txt
diff --git a/numpy/f2py/TODO.txt b/numpy/f2py/TODO.txt
new file mode 100644
index 000000000..fd655f2e2
--- /dev/null
+++ b/numpy/f2py/TODO.txt
@@ -0,0 +1,67 @@
+Determine fixed/free format Fortran 90 dialect from the
+contents of Fortran files. See scipy_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/numpy/f2py/__init__.py b/numpy/f2py/__init__.py
new file mode 100644
index 000000000..5c2c3e927
--- /dev/null
+++ b/numpy/f2py/__init__.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+__all__ = ['run_main','compile','f2py_testing']
+
+import os
+import tempfile
+import sys
+import commands
+
+import f2py2e
+run_main = f2py2e.run_main
+main = f2py2e.main
+import f2py_testing
+
+def compile(source,
+ modulename = 'untitled',
+ extra_args = '',
+ verbose = 1,
+ source_fn = None
+ ):
+ ''' Build extension module from processing source with f2py.
+ Read the source of this function for more information.
+ '''
+ from scipy.distutils.exec_command import exec_command
+ if source_fn is None:
+ fname = os.path.join(tempfile.mktemp()+'.f')
+ else:
+ fname = source_fn
+
+ f = open(fname,'w')
+ f.write(source)
+ f.close()
+
+ args = ' -c -m %s %s %s'%(modulename,fname,extra_args)
+ c = '%s -c "import scipy.f2py as f2py2e;f2py2e.main()" %s' %(sys.executable,args)
+ s,o = exec_command(c)
+ if source_fn is None:
+ try: os.remove(fname)
+ except OSError: pass
+ return s
diff --git a/numpy/f2py/__version__.py b/numpy/f2py/__version__.py
new file mode 100644
index 000000000..11fb7b3d2
--- /dev/null
+++ b/numpy/f2py/__version__.py
@@ -0,0 +1,9 @@
+major = 2
+
+try:
+ from __svn_version__ import version
+ version_info = (major,version)
+ version = '%s_%s' % version_info
+except Exception,msg:
+ print msg
+ version = '%s_?' % (major)
diff --git a/numpy/f2py/auxfuncs.py b/numpy/f2py/auxfuncs.py
new file mode 100644
index 000000000..51eae0517
--- /dev/null
+++ b/numpy/f2py/auxfuncs.py
@@ -0,0 +1,489 @@
+#!/usr/bin/env python
+"""
+
+Auxiliary functions for f2py2e.
+
+Copyright 1999,2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/07/24 19:01:55 $
+Pearu Peterson
+"""
+__version__ = "$Revision: 1.65 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+import pprint
+import sys,string,time,types,os
+import cfuncs
+
+
+errmess=sys.stderr.write
+#outmess=sys.stdout.write
+show=pprint.pprint
+
+options={}
+debugoptions=[]
+wrapfuncs = 1
+
+def outmess(t):
+ if options.get('verbose',1):
+ sys.stdout.write(t)
+
+def debugcapi(var): return 'capi' in debugoptions
+def _isstring(var):
+ return var.has_key('typespec') and var['typespec']=='character' and (not isexternal(var))
+def isstring(var):
+ return _isstring(var) and not isarray(var)
+def ischaracter(var):
+ return isstring(var) and not (var.has_key('charselector'))
+def isstringarray(var):
+ return isarray(var) and _isstring(var)
+def isarrayofstrings(var):
+ # leaving out '*' for now so that
+ # `character*(*) a(m)` and `character a(m,*)`
+ # are treated differently. Luckily `character**` is illegal.
+ return isstringarray(var) and var['dimension'][-1]=='(*)'
+def isarray(var): return var.has_key('dimension') and (not isexternal(var))
+def isscalar(var): return not (isarray(var) or isstring(var) or isexternal(var))
+def iscomplex(var):
+ return isscalar(var) and var.get('typespec') in ['complex','double complex']
+def islogical(var):
+ return isscalar(var) and var.get('typespec')=='logical'
+def isinteger(var):
+ return isscalar(var) and var.get('typespec')=='integer'
+def isreal(var):
+ return isscalar(var) and var.get('typespec')=='real'
+def get_kind(var):
+ try: return var['kindselector']['*']
+ except KeyError:
+ try: return var['kindselector']['kind']
+ except KeyError: pass
+def islong_long(var):
+ if not isscalar(var): return 0
+ if var.get('typespec') not in ['integer','logical']: return 0
+ return get_kind(var)=='8'
+def isunsigned_char(var):
+ if not isscalar(var): return 0
+ if var.get('typespec') != 'integer': return 0
+ return get_kind(var)=='-1'
+def isunsigned_short(var):
+ if not isscalar(var): return 0
+ if var.get('typespec') != 'integer': return 0
+ return get_kind(var)=='-2'
+def isunsigned(var):
+ if not isscalar(var): return 0
+ if var.get('typespec') != 'integer': return 0
+ return get_kind(var)=='-4'
+def isunsigned_long_long(var):
+ if not isscalar(var): return 0
+ if var.get('typespec') != 'integer': return 0
+ return get_kind(var)=='-8'
+def isdouble(var):
+ if not isscalar(var): return 0
+ if not var.get('typespec')=='real': return 0
+ return get_kind(var)=='8'
+def islong_double(var):
+ if not isscalar(var): return 0
+ if not var.get('typespec')=='real': return 0
+ return get_kind(var)=='16'
+def islong_complex(var):
+ if not iscomplex(var): return 0
+ return get_kind(var)=='32'
+
+def iscomplexarray(var): return isarray(var) and var.get('typespec') in ['complex','double complex']
+def isint1array(var): return isarray(var) and var.get('typespec')=='integer' \
+ and get_kind(var)=='1'
+def isunsigned_chararray(var): return isarray(var) and var.get('typespec')=='integer' and get_kind(var)=='-1'
+def isunsigned_shortarray(var): return isarray(var) and var.get('typespec')=='integer' and get_kind(var)=='-2'
+def isunsignedarray(var): return isarray(var) and var.get('typespec')=='integer' and get_kind(var)=='-4'
+def isunsigned_long_longarray(var): return isarray(var) and var.get('typespec')=='integer' and get_kind(var)=='-8'
+def isallocatable(var):
+ return var.has_key('attrspec') and 'allocatable' in var['attrspec']
+def ismutable(var): return not (not var.has_key('dimension') or isstring(var))
+def ismoduleroutine(rout): return rout.has_key('modulename')
+def ismodule(rout): return (rout.has_key('block') and 'module'==rout['block'])
+def isfunction(rout): return (rout.has_key('block') and 'function'==rout['block'])
+#def isfunction_wrap(rout):
+# return wrapfuncs and (iscomplexfunction(rout) or isstringfunction(rout)) and (not isexternal(rout))
+def isfunction_wrap(rout):
+ if isintent_c(rout): return 0
+ return wrapfuncs and isfunction(rout) and (not isexternal(rout))
+def issubroutine(rout): return (rout.has_key('block') and 'subroutine'==rout['block'])
+def isroutine(rout): return isfunction(rout) or issubroutine(rout)
+def islogicalfunction(rout):
+ if not isfunction(rout): return 0
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ if rout['vars'].has_key(a): return islogical(rout['vars'][a])
+ return 0
+def islong_longfunction(rout):
+ if not isfunction(rout): return 0
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ if rout['vars'].has_key(a): return islong_long(rout['vars'][a])
+ return 0
+def islong_doublefunction(rout):
+ if not isfunction(rout): return 0
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ if rout['vars'].has_key(a): return islong_double(rout['vars'][a])
+ return 0
+def iscomplexfunction(rout):
+ if not isfunction(rout): return 0
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ if rout['vars'].has_key(a): return iscomplex(rout['vars'][a])
+ return 0
+def iscomplexfunction_warn(rout):
+ if iscomplexfunction(rout):
+ outmess("""\
+ **************************************************************
+ Warning: code with a function returning complex value
+ may not work correctly with your Fortran compiler.
+ Run the following test before using it in your applications:
+ $(f2py install dir)/test-site/{b/runme_scalar,e/runme}
+ When using GNU gcc/g77 compilers, codes should work correctly.
+ **************************************************************\n""")
+ return 1
+ return 0
+def isstringfunction(rout):
+ if not isfunction(rout): return 0
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ if rout['vars'].has_key(a): return isstring(rout['vars'][a])
+ return 0
+def hasexternals(rout): return rout.has_key('externals') and rout['externals']
+def isthreadsafe(rout): return rout.has_key('f2pyenhancements') and rout['f2pyenhancements'].has_key('threadsafe')
+def hasvariables(rout): return rout.has_key('vars') and rout['vars']
+def isoptional(var): return (var.has_key('attrspec') and 'optional' in var['attrspec'] and 'required' not in var['attrspec']) and isintent_nothide(var)
+def isexternal(var): return (var.has_key('attrspec') and 'external' in var['attrspec'])
+def isrequired(var): return not isoptional(var) and isintent_nothide(var)
+def isintent_in(var):
+ if not var.has_key('intent'): return 1
+ if 'hide' in var['intent']: return 0
+ if 'inplace' in var['intent']: return 0
+ if 'in' in var['intent']: return 1
+ if 'out' in var['intent']: return 0
+ if 'inout' in var['intent']: return 0
+ if 'outin' in var['intent']: return 0
+ return 1
+def isintent_inout(var): return var.has_key('intent') and ('inout' in var['intent'] or 'outin' in var['intent']) and 'in' not in var['intent'] and 'hide' not in var['intent'] and 'inplace' not in var['intent']
+def isintent_out(var):
+ return 'out' in var.get('intent',[])
+def isintent_hide(var): return (var.has_key('intent') and ('hide' in var['intent'] or ('out' in var['intent'] and 'in' not in var['intent'] and (not l_or(isintent_inout,isintent_inplace)(var)))))
+def isintent_nothide(var): return not isintent_hide(var)
+def isintent_c(var):
+ return 'c' in var.get('intent',[])
+# def isintent_f(var):
+# return not isintent_c(var)
+def isintent_cache(var):
+ return 'cache' in var.get('intent',[])
+def isintent_copy(var):
+ return 'copy' in var.get('intent',[])
+def isintent_overwrite(var):
+ return 'overwrite' in var.get('intent',[])
+def isintent_callback(var):
+ return 'callback' in var.get('intent',[])
+def isintent_inplace(var):
+ return 'inplace' in var.get('intent',[])
+def isintent_aux(var):
+ return 'aux' in var.get('intent',[])
+
+isintent_dict = {isintent_in:'INTENT_IN',isintent_inout:'INTENT_INOUT',
+ isintent_out:'INTENT_OUT',isintent_hide:'INTENT_HIDE',
+ isintent_cache:'INTENT_CACHE',
+ isintent_c:'INTENT_C',isoptional:'OPTIONAL',
+ isintent_inplace:'INTENT_INPLACE'
+ }
+
+def isprivate(var):
+ return var.has_key('attrspec') and 'private' in var['attrspec']
+
+def hasinitvalue(var): return var.has_key('=')
+def hasinitvalueasstring(var):
+ if not hasinitvalue(var): return 0
+ return var['='][0] in ['"',"'"]
+def hasnote(var):
+ return var.has_key('note')
+def hasresultnote(rout):
+ if not isfunction(rout): return 0
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ if rout['vars'].has_key(a): return hasnote(rout['vars'][a])
+ return 0
+def hascommon(rout):
+ return rout.has_key('common')
+def containscommon(rout):
+ if hascommon(rout): return 1
+ if hasbody(rout):
+ for b in rout['body']:
+ if containscommon(b): return 1
+ return 0
+def containsmodule(block):
+ if ismodule(block): return 1
+ if not hasbody(block): return 0
+ ret = []
+ for b in block['body']:
+ if containsmodule(b): return 1
+ return 0
+def hasbody(rout):
+ return rout.has_key('body')
+def hascallstatement(rout):
+ return getcallstatement(rout) is not None
+
+def istrue(var): return 1
+def isfalse(var): return 0
+
+class F2PYError(Exception):
+ pass
+
+class throw_error:
+ def __init__(self,mess):
+ self.mess = mess
+ def __call__(self,var):
+ mess = '\n\n var = %s\n Message: %s\n' % (var,self.mess)
+ raise F2PYError,mess
+
+def l_and(*f):
+ l,l2='lambda v',[]
+ for i in range(len(f)):
+ l='%s,f%d=f[%d]'%(l,i,i)
+ l2.append('f%d(v)'%(i))
+ return eval('%s:%s'%(l,string.join(l2,' and ')))
+def l_or(*f):
+ l,l2='lambda v',[]
+ for i in range(len(f)):
+ l='%s,f%d=f[%d]'%(l,i,i)
+ l2.append('f%d(v)'%(i))
+ return eval('%s:%s'%(l,string.join(l2,' or ')))
+def l_not(f):
+ return eval('lambda v,f=f:not f(v)')
+
+def isdummyroutine(rout):
+ try:
+ return rout['f2pyenhancements']['fortranname']==''
+ except KeyError:
+ return 0
+
+def getfortranname(rout):
+ try:
+ name = rout['f2pyenhancements']['fortranname']
+ if name=='':
+ raise KeyError
+ if not name:
+ errmess('Failed to use fortranname from %s\n'%(rout['f2pyenhancements']))
+ raise KeyError
+ except KeyError:
+ name = rout['name']
+ return name
+
+def getmultilineblock(rout,blockname,comment=1,counter=0):
+ try:
+ r = rout['f2pyenhancements'].get(blockname)
+ except KeyError:
+ return
+ if not r: return
+ if counter>0 and type(r) is type(''):
+ return
+ if type(r) is type([]):
+ if counter>=len(r): return
+ r = r[counter]
+ if r[:3]=="'''":
+ if comment:
+ r = '\t/* start ' + blockname + ' multiline ('+`counter`+') */\n' + r[3:]
+ else:
+ r = r[3:]
+ if r[-3:]=="'''":
+ if comment:
+ r = r[:-3] + '\n\t/* end multiline ('+`counter`+')*/'
+ else:
+ r = r[:-3]
+ else:
+ errmess("%s multiline block should end with `'''`: %s\n" \
+ % (blockname,repr(r)))
+ return r
+
+def getcallstatement(rout):
+ return getmultilineblock(rout,'callstatement')
+
+def getcallprotoargument(rout,cb_map={}):
+ r = getmultilineblock(rout,'callprotoargument',comment=0)
+ if r: return r
+ if hascallstatement(rout):
+ outmess('warning: callstatement is defined without callprotoargument\n')
+ return
+ from capi_maps import getctype
+ arg_types,arg_types2 = [],[]
+ if l_and(isstringfunction,l_not(isfunction_wrap))(rout):
+ arg_types.extend(['char*','size_t'])
+ for n in rout['args']:
+ var = rout['vars'][n]
+ if isintent_callback(var):
+ continue
+ if cb_map.has_key(n):
+ ctype = cb_map[n]+'_typedef'
+ else:
+ ctype = getctype(var)
+ if l_and(isintent_c,l_or(isscalar,iscomplex))(var):
+ pass
+ elif isstring(var):
+ pass
+ #ctype = 'void*'
+ else:
+ ctype = ctype+'*'
+ if isstring(var) or isarrayofstrings(var):
+ arg_types2.append('size_t')
+ arg_types.append(ctype)
+
+ proto_args = string.join(arg_types+arg_types2,',')
+ if not proto_args:
+ proto_args = 'void'
+ #print proto_args
+ return proto_args
+
+def getusercode(rout):
+ return getmultilineblock(rout,'usercode')
+def getusercode1(rout):
+ return getmultilineblock(rout,'usercode',counter=1)
+
+def getpymethoddef(rout):
+ return getmultilineblock(rout,'pymethoddef')
+
+def getargs(rout):
+ sortargs,args=[],[]
+ if rout.has_key('args'):
+ args=rout['args']
+ if rout.has_key('sortvars'):
+ for a in rout['sortvars']:
+ if a in args: sortargs.append(a)
+ for a in args:
+ if a not in sortargs:
+ sortargs.append(a)
+ else: sortargs=rout['args']
+ return args,sortargs
+
+def getargs2(rout):
+ sortargs,args=[],rout.get('args',[])
+ auxvars = [a for a in rout['vars'].keys() if isintent_aux(rout['vars'][a])\
+ and a not in args]
+ args = auxvars + args
+ if rout.has_key('sortvars'):
+ for a in rout['sortvars']:
+ if a in args: sortargs.append(a)
+ for a in args:
+ if a not in sortargs:
+ sortargs.append(a)
+ else: sortargs=auxvars + rout['args']
+ return args,sortargs
+
+def getrestdoc(rout):
+ if not rout.has_key('f2pymultilines'):
+ return None
+ k = None
+ if rout['block']=='python module':
+ k = rout['block'],rout['name']
+ return rout['f2pymultilines'].get(k,None)
+
+def gentitle(name):
+ l=(80-len(name)-6)/2
+ return '/*%s %s %s*/'%(l*'*',name,l*'*')
+def flatlist(l):
+ if type(l)==types.ListType:
+ return reduce(lambda x,y,f=flatlist:x+f(y),l,[])
+ return [l]
+def stripcomma(s):
+ if s and s[-1]==',': return s[:-1]
+ return s
+def replace(str,dict,defaultsep=''):
+ if type(dict)==types.ListType:
+ return map(lambda d,f=replace,sep=defaultsep,s=str:f(s,d,sep),dict)
+ if type(str)==types.ListType:
+ return map(lambda s,f=replace,sep=defaultsep,d=dict:f(s,d,sep),str)
+ for k in 2*dict.keys():
+ if k=='separatorsfor': continue
+ if dict.has_key('separatorsfor') and dict['separatorsfor'].has_key(k):
+ sep=dict['separatorsfor'][k]
+ else:
+ sep=defaultsep
+ if type(dict[k])==types.ListType:
+ str=string.replace(str,'#%s#'%(k),string.join(flatlist(dict[k]),sep))
+ else:
+ str=string.replace(str,'#%s#'%(k),dict[k])
+ return str
+
+def dictappend(rd,ar):
+ if type(ar)==types.ListType:
+ for a in ar: rd=dictappend(rd,a)
+ return rd
+ for k in ar.keys():
+ if k[0]=='_': continue
+ if rd.has_key(k):
+ if type(rd[k])==types.StringType: rd[k]=[rd[k]]
+ if type(rd[k])==types.ListType:
+ if type(ar[k])==types.ListType: rd[k]=rd[k]+ar[k]
+ else: rd[k].append(ar[k])
+ elif type(rd[k])==types.DictType:
+ if type(ar[k])==types.DictType:
+ if k=='separatorsfor':
+ for k1 in ar[k].keys():
+ if not rd[k].has_key(k1): rd[k][k1]=ar[k][k1]
+ else: rd[k]=dictappend(rd[k],ar[k])
+ else: rd[k]=ar[k]
+ return rd
+
+def applyrules(rules,dict,var={}):
+ ret={}
+ if type(rules)==types.ListType:
+ for r in rules:
+ rr=applyrules(r,dict,var)
+ ret=dictappend(ret,rr)
+ if rr.has_key('_break'): break
+ return ret
+ if rules.has_key('_check') and (not rules['_check'](var)): return ret
+ if rules.has_key('need'):
+ res = applyrules({'needs':rules['need']},dict,var)
+ if res.has_key('needs'):
+ cfuncs.append_needs(res['needs'])
+
+ for k in rules.keys():
+ if k=='separatorsfor': ret[k]=rules[k]; continue
+ if type(rules[k])==types.StringType:
+ ret[k]=replace(rules[k],dict)
+ elif type(rules[k])==types.ListType:
+ ret[k]=[]
+ for i in rules[k]:
+ ar=applyrules({k:i},dict,var)
+ if ar.has_key(k): ret[k].append(ar[k])
+ elif k[0]=='_':
+ continue
+ elif type(rules[k])==types.DictType:
+ ret[k]=[]
+ for k1 in rules[k].keys():
+ if type(k1)==types.FunctionType and k1(var):
+ if type(rules[k][k1])==types.ListType:
+ for i in rules[k][k1]:
+ if type(i)==types.DictType:
+ res=applyrules({'supertext':i},dict,var)
+ if res.has_key('supertext'): i=res['supertext']
+ else: i=''
+ ret[k].append(replace(i,dict))
+ else:
+ i=rules[k][k1]
+ if type(i)==types.DictType:
+ res=applyrules({'supertext':i},dict)
+ if res.has_key('supertext'): i=res['supertext']
+ else: i=''
+ ret[k].append(replace(i,dict))
+ else:
+ errmess('applyrules: ignoring rule %s.\n'%`rules[k]`)
+ if type(ret[k])==types.ListType:
+ if len(ret[k])==1: ret[k]=ret[k][0]
+ if ret[k]==[]: del ret[k]
+ return ret
+
+
diff --git a/numpy/f2py/capi_maps.py b/numpy/f2py/capi_maps.py
new file mode 100644
index 000000000..e4a542eaa
--- /dev/null
+++ b/numpy/f2py/capi_maps.py
@@ -0,0 +1,723 @@
+#!/usr/bin/env python
+"""
+
+Copyright 1999,2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 10:57:33 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.60 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+import string,copy,re,os
+from auxfuncs import *
+from crackfortran import markoutercomma
+import cb_rules
+
+# Numarray and Numeric users should set this False
+using_newcore = True
+
+depargs=[]
+lcb_map={}
+lcb2_map={}
+# forced casting: mainly caused by the fact that Python or Numeric
+# C/APIs do not support the corresponding C types.
+c2py_map={'double':'float',
+ 'float':'float', # forced casting
+ 'long_double':'float', # forced casting
+ 'char':'int', # forced casting
+ 'signed_char':'int', # forced casting
+ 'unsigned_char':'int', # forced casting
+ 'short':'int', # forced casting
+ 'unsigned_short':'int', # forced casting
+ 'int':'int', # (forced casting)
+ 'long':'int',
+ 'long_long':'long',
+ 'unsigned':'int', # forced casting
+ 'complex_float':'complex', # forced casting
+ 'complex_double':'complex',
+ 'complex_long_double':'complex', # forced casting
+ 'string':'string',
+ }
+c2capi_map={'double':'PyArray_DOUBLE',
+ 'float':'PyArray_FLOAT',
+ 'long_double':'PyArray_DOUBLE', # forced casting
+ 'char':'PyArray_CHAR',
+ 'unsigned_char':'PyArray_UBYTE',
+ 'signed_char':'PyArray_SBYTE',
+ 'short':'PyArray_SHORT',
+ 'unsigned_short':'PyArray_USHORT',
+ 'int':'PyArray_INT',
+ 'unsigned':'PyArray_UINT',
+ 'long':'PyArray_LONG',
+ 'long_long':'PyArray_LONG', # forced casting
+ 'complex_float':'PyArray_CFLOAT',
+ 'complex_double':'PyArray_CDOUBLE',
+ 'complex_long_double':'PyArray_CDOUBLE', # forced casting
+ 'string':'PyArray_CHAR'}
+
+#These new maps aren't used anyhere yet, but should be by default
+# unless building numeric or numarray extensions.
+if using_newcore:
+ c2capi_map={'double':'PyArray_DOUBLE',
+ 'float':'PyArray_FLOAT',
+ 'long_double':'PyArray_LONGDOUBLE',
+ 'char':'PyArray_BYTE',
+ 'unsigned_char':'PyArray_UBYTE',
+ 'signed_char':'PyArray_BYTE',
+ 'short':'PyArray_SHORT',
+ 'unsigned_short':'PyArray_USHORT',
+ 'int':'PyArray_INT',
+ 'unsigned':'PyArray_UINT',
+ 'long':'PyArray_LONG',
+ 'unsigned_long':'PyArray_ULONG',
+ 'long_long':'PyArray_LONGLONG',
+ 'unsigned_long_long':'Pyarray_ULONGLONG',
+ 'complex_float':'PyArray_CFLOAT',
+ 'complex_double':'PyArray_CDOUBLE',
+ 'complex_long_double':'PyArray_CDOUBLE',
+ 'string':'PyArray_STRING'}
+c2pycode_map={'double':'d',
+ 'float':'f',
+ 'long_double':'d', # forced casting
+ 'char':'1',
+ 'signed_char':'1',
+ 'unsigned_char':'b',
+ 'short':'s',
+ 'unsigned_short':'w',
+ 'int':'i',
+ 'unsigned':'u',
+ 'long':'l',
+ 'long_long':'L',
+ 'complex_float':'F',
+ 'complex_double':'D',
+ 'complex_long_double':'D', # forced casting
+ 'string':'c'
+ }
+if using_newcore:
+ c2pycode_map={'double':'d',
+ 'float':'f',
+ 'long_double':'g',
+ 'char':'b',
+ 'unsigned_char':'B',
+ 'signed_char':'b',
+ 'short':'h',
+ 'unsigned_short':'H',
+ 'int':'i',
+ 'unsigned':'I',
+ 'long':'l',
+ 'unsigned_long':'L',
+ 'long_long':'q',
+ 'unsigned_long_long':'Q',
+ 'complex_float':'F',
+ 'complex_double':'D',
+ 'complex_long_double':'G',
+ 'string':'S'}
+c2buildvalue_map={'double':'d',
+ 'float':'f',
+ 'char':'b',
+ 'signed_char':'b',
+ 'short':'h',
+ 'int':'i',
+ 'long':'l',
+ 'long_long':'L',
+ 'complex_float':'N',
+ 'complex_double':'N',
+ 'complex_long_double':'N',
+ 'string':'z'}
+if using_newcore:
+ #c2buildvalue_map=???
+ pass
+
+f2cmap_all={'real':{'':'float','4':'float','8':'double','12':'long_double','16':'long_double'},
+ 'integer':{'':'int','1':'signed_char','2':'short','4':'int','8':'long_long',
+ '-1':'unsigned_char','-2':'unsigned_short','-4':'unsigned',
+ '-8':'unsigned_long_long'},
+ 'complex':{'':'complex_float','8':'complex_float',
+ '16':'complex_double','24':'complex_long_double',
+ '32':'complex_long_double'},
+ 'complexkind':{'':'complex_float','4':'complex_float',
+ '8':'complex_double','12':'complex_long_double',
+ '16':'complex_long_double'},
+ 'logical':{'':'int','1':'char','2':'short','4':'int','8':'long_long'},
+ 'double complex':{'':'complex_double'},
+ 'double precision':{'':'double'},
+ 'byte':{'':'char'},
+ 'character':{'':'string'}
+ }
+
+if os.path.isfile('.f2py_f2cmap'):
+ # User defined additions to f2cmap_all.
+ # .f2py_f2cmap must contain a dictionary of dictionaries, only.
+ # For example, {'real':{'low':'float'}} means that Fortran 'real(low)' is
+ # interpreted as C 'float'.
+ # This feature is useful for F90/95 users if they use PARAMETERSs
+ # in type specifications.
+ try:
+ outmess('Reading .f2py_f2cmap ...\n')
+ f = open('.f2py_f2cmap','r')
+ d = eval(f.read(),{},{})
+ f.close()
+ for k,d1 in d.items():
+ for k1 in d1.keys():
+ d1[string.lower(k1)] = d1[k1]
+ d[string.lower(k)] = d[k]
+ for k in d.keys():
+ if not f2cmap_all.has_key(k): f2cmap_all[k]={}
+ for k1 in d[k].keys():
+ if c2py_map.has_key(d[k][k1]):
+ if f2cmap_all[k].has_key(k1):
+ outmess("\tWarning: redefinition of {'%s':{'%s':'%s'->'%s'}}\n"%(k,k1,f2cmap_all[k][k1],d[k][k1]))
+ f2cmap_all[k][k1] = d[k][k1]
+ outmess('\tMapping "%s(kind=%s)" to "%s"\n' % (k,k1,d[k][k1]))
+ else:
+ errmess("\tIgnoring map {'%s':{'%s':'%s'}}: '%s' must be in %s\n"%(k,k1,d[k][k1],d[k][k1],c2py_map.keys()))
+ outmess('Succesfully applied user defined changes from .f2py_f2cmap\n')
+ except:
+ errmess('Failed to apply user defined changes from .f2py_f2cmap. Skipping.\n')
+cformat_map={'double':'%g',
+ 'float':'%g',
+ 'long_double':'%Lg',
+ 'char':'%d',
+ 'signed_char':'%d',
+ 'unsigned_char':'%hhu',
+ 'short':'%hd',
+ 'unsigned_short':'%hu',
+ 'int':'%d',
+ 'unsigned':'%u',
+ 'long':'%ld',
+ 'unsigned_long':'%lu',
+ 'long_long':'%ld',
+ 'complex_float':'(%g,%g)',
+ 'complex_double':'(%g,%g)',
+ 'complex_long_double':'(%Lg,%Lg)',
+ 'string':'%s',
+ }
+
+############### Auxiliary functions
+def getctype(var):
+ """
+ Determines C type
+ """
+ ctype='void'
+ if isfunction(var):
+ if var.has_key('result'): a=var['result']
+ else: a=var['name']
+ if var['vars'].has_key(a): return getctype(var['vars'][a])
+ else: errmess('getctype: function %s has no return value?!\n'%a)
+ elif issubroutine(var):
+ return ctype
+ elif var.has_key('typespec') and f2cmap_all.has_key(string.lower(var['typespec'])):
+ typespec = string.lower(var['typespec'])
+ f2cmap=f2cmap_all[typespec]
+ ctype=f2cmap[''] # default type
+ if var.has_key('kindselector'):
+ if var['kindselector'].has_key('*'):
+ try:
+ ctype=f2cmap[var['kindselector']['*']]
+ except KeyError:
+ errmess('getctype: "%s %s %s" not supported.\n'%(var['typespec'],'*',var['kindselector']['*']))
+ elif var['kindselector'].has_key('kind'):
+ if f2cmap_all.has_key(typespec+'kind'):
+ f2cmap=f2cmap_all[typespec+'kind']
+ try:
+ ctype=f2cmap[var['kindselector']['kind']]
+ except KeyError:
+ if f2cmap_all.has_key(typespec):
+ f2cmap=f2cmap_all[typespec]
+ try:
+ ctype=f2cmap[str(var['kindselector']['kind'])]
+ except KeyError:
+ errmess('getctype: "%s(kind=%s)" not supported (use .f2py_f2cmap).\n'\
+ %(typespec,var['kindselector']['kind']))
+
+ else:
+ if not isexternal(var):
+ errmess('getctype: No C-type found in "%s", assuming void.\n'%var)
+ return ctype
+def getstrlength(var):
+ if isstringfunction(var):
+ if var.has_key('result'): a=var['result']
+ else: a=var['name']
+ if var['vars'].has_key(a): return getstrlength(var['vars'][a])
+ else: errmess('getstrlength: function %s has no return value?!\n'%a)
+ if not isstring(var):
+ errmess('getstrlength: expected a signature of a string but got: %s\n'%(`var`))
+ len='1'
+ if var.has_key('charselector'):
+ a=var['charselector']
+ if a.has_key('*'): len=a['*']
+ elif a.has_key('len'): len=a['len']
+ if re.match(r'\(\s*([*]|[:])\s*\)',len) or re.match(r'([*]|[:])',len):
+ #if len in ['(*)','*','(:)',':']:
+ if isintent_hide(var):
+ errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n'%(`var`))
+ len='-1'
+ return len
+def getarrdims(a,var,verbose=0):
+ global depargs
+ ret={}
+ if isstring(var) and not isarray(var):
+ ret['dims']=getstrlength(var)
+ ret['size']=ret['dims']
+ ret['rank']='1'
+ elif isscalar(var):
+ ret['size']='1'
+ ret['rank']='0'
+ ret['dims']=''
+ elif isarray(var):
+# if not isintent_c(var):
+# var['dimension'].reverse()
+ dim=copy.copy(var['dimension'])
+ ret['size']=string.join(dim,'*')
+ try: ret['size']=`eval(ret['size'])`
+ except: pass
+ ret['dims']=string.join(dim,',')
+ ret['rank']=`len(dim)`
+ ret['rank*[-1]']=`len(dim)*[-1]`[1:-1]
+ for i in range(len(dim)): # solve dim for dependecies
+ v=[]
+ if dim[i] in depargs: v=[dim[i]]
+ else:
+ for va in depargs:
+ if re.match(r'.*?\b%s\b.*'%va,dim[i]):
+ v.append(va)
+ for va in v:
+ if depargs.index(va)>depargs.index(a):
+ dim[i]='*'
+ break
+ ret['setdims'],i='',-1
+ for d in dim:
+ i=i+1
+ if d not in ['*',':','(*)','(:)']:
+ ret['setdims']='%s#varname#_Dims[%d]=%s,'%(ret['setdims'],i,d)
+ if ret['setdims']: ret['setdims']=ret['setdims'][:-1]
+ ret['cbsetdims'],i='',-1
+ for d in var['dimension']:
+ i=i+1
+ if d not in ['*',':','(*)','(:)']:
+ ret['cbsetdims']='%s#varname#_Dims[%d]=%s,'%(ret['cbsetdims'],i,d)
+ elif verbose :
+ errmess('getarrdims: If in call-back function: array argument %s must have bounded dimensions: got %s\n'%(`a`,`d`))
+ if ret['cbsetdims']: ret['cbsetdims']=ret['cbsetdims'][:-1]
+# if not isintent_c(var):
+# var['dimension'].reverse()
+ return ret
+def getpydocsign(a,var):
+ global lcb_map
+ if isfunction(var):
+ if var.has_key('result'): af=var['result']
+ else: af=var['name']
+ if var['vars'].has_key(af): return getpydocsign(af,var['vars'][af])
+ else: errmess('getctype: function %s has no return value?!\n'%af)
+ return '',''
+ sig,sigout=a,a
+ opt=''
+ if isintent_in(var): opt='input'
+ elif isintent_inout(var): opt='in/output'
+ out_a = a
+ if isintent_out(var):
+ for k in var['intent']:
+ if k[:4]=='out=':
+ out_a = k[4:]
+ break
+ init=''
+ ctype=getctype(var)
+
+ if hasinitvalue(var):
+ init,showinit=getinit(a,var)
+ init='= %s'%(showinit)
+ if isscalar(var):
+ if isintent_inout(var):
+ sig='%s :%s %s rank-0 array(%s,\'%s\')'%(a,init,opt,c2py_map[ctype],
+ c2pycode_map[ctype],)
+ else:
+ sig='%s :%s %s %s'%(a,init,opt,c2py_map[ctype])
+ sigout='%s : %s'%(out_a,c2py_map[ctype])
+ elif isstring(var):
+ if isintent_inout(var):
+ sig='%s :%s %s rank-0 array(string(len=%s),\'c\')'%(a,init,opt,getstrlength(var))
+ else:
+ sig='%s :%s %s string(len=%s)'%(a,init,opt,getstrlength(var))
+ sigout='%s : string(len=%s)'%(out_a,getstrlength(var))
+ elif isarray(var):
+ dim=var['dimension']
+ rank=`len(dim)`
+ sig='%s :%s %s rank-%s array(\'%s\') with bounds (%s)'%(a,init,opt,rank,
+ c2pycode_map[ctype],
+ string.join(dim,','))
+ if a==out_a:
+ sigout='%s : rank-%s array(\'%s\') with bounds (%s)'\
+ %(a,rank,c2pycode_map[ctype],string.join(dim,','))
+ else:
+ sigout='%s : rank-%s array(\'%s\') with bounds (%s) and %s storage'\
+ %(out_a,rank,c2pycode_map[ctype],string.join(dim,','),a)
+ elif isexternal(var):
+ ua=''
+ if lcb_map.has_key(a) and lcb2_map.has_key(lcb_map[a]) and lcb2_map[lcb_map[a]].has_key('argname'):
+ ua=lcb2_map[lcb_map[a]]['argname']
+ if not ua==a: ua=' => %s'%ua
+ else: ua=''
+ sig='%s : call-back function%s'%(a,ua)
+ sigout=sig
+ else:
+ errmess('getpydocsign: Could not resolve docsignature for "%s".\\n'%a)
+ return sig,sigout
+def getarrdocsign(a,var):
+ ctype=getctype(var)
+ if isstring(var) and (not isarray(var)):
+ sig='%s : rank-0 array(string(len=%s),\'c\')'%(a,getstrlength(var))
+ elif isscalar(var):
+ sig='%s : rank-0 array(%s,\'%s\')'%(a,c2py_map[ctype],
+ c2pycode_map[ctype],)
+ elif isarray(var):
+ dim=var['dimension']
+ rank=`len(dim)`
+ sig='%s : rank-%s array(\'%s\') with bounds (%s)'%(a,rank,
+ c2pycode_map[ctype],
+ string.join(dim,','))
+ return sig
+
+def getinit(a,var):
+ if isstring(var): init,showinit='""',"''"
+ else: init,showinit='',''
+ if hasinitvalue(var):
+ init=var['=']
+ showinit=init
+ if iscomplex(var) or iscomplexarray(var):
+ ret={}
+
+ try:
+ v = var["="]
+ if ',' in v:
+ ret['init.r'],ret['init.i']=string.split(markoutercomma(v[1:-1]),'@,@')
+ else:
+ v = eval(v,{},{})
+ ret['init.r'],ret['init.i']=str(v.real),str(v.imag)
+ except: raise 'sign2map: expected complex number `(r,i)\' but got `%s\' as initial value of %s.'%(init,`a`)
+ if isarray(var):
+ init='(capi_c.r=%s,capi_c.i=%s,capi_c)'%(ret['init.r'],ret['init.i'])
+ elif isstring(var):
+ if not init: init,showinit='""',"''"
+ if init[0]=="'":
+ init='"%s"'%(string.replace(init[1:-1],'"','\\"'))
+ if init[0]=='"': showinit="'%s'"%(init[1:-1])
+ return init,showinit
+
+def sign2map(a,var):
+ """
+ varname,ctype,atype
+ init,init.r,init.i,pytype
+ vardebuginfo,vardebugshowvalue,varshowvalue
+ varrfromat
+ intent
+ """
+ global lcb_map,cb_map
+ out_a = a
+ if isintent_out(var):
+ for k in var['intent']:
+ if k[:4]=='out=':
+ out_a = k[4:]
+ break
+ ret={'varname':a,'outvarname':out_a}
+ ret['ctype']=getctype(var)
+ intent_flags = []
+ for f,s in isintent_dict.items():
+ if f(var): intent_flags.append('F2PY_%s'%s)
+ if intent_flags:
+ #XXX: Evaluate intent_flags here.
+ ret['intent'] = string.join(intent_flags,'|')
+ else:
+ ret['intent'] = 'F2PY_INTENT_IN'
+ if isarray(var): ret['varrformat']='N'
+ elif c2buildvalue_map.has_key(ret['ctype']):
+ ret['varrformat']=c2buildvalue_map[ret['ctype']]
+ else: ret['varrformat']='O'
+ ret['init'],ret['showinit']=getinit(a,var)
+ if hasinitvalue(var) and iscomplex(var) and not isarray(var):
+ ret['init.r'],ret['init.i'] = string.split(markoutercomma(ret['init'][1:-1]),'@,@')
+ if isexternal(var):
+ ret['cbnamekey']=a
+ if lcb_map.has_key(a):
+ ret['cbname']=lcb_map[a]
+ ret['maxnofargs']=lcb2_map[lcb_map[a]]['maxnofargs']
+ ret['nofoptargs']=lcb2_map[lcb_map[a]]['nofoptargs']
+ ret['cbdocstr']=lcb2_map[lcb_map[a]]['docstr']
+ ret['cblatexdocstr']=lcb2_map[lcb_map[a]]['latexdocstr']
+ else:
+ ret['cbname']=a
+ errmess('sign2map: Confused: external %s is not in lcb_map%s.\n'%(a,lcb_map.keys()))
+ if isstring(var):
+ ret['length']=getstrlength(var)
+ if isarray(var):
+ ret=dictappend(ret,getarrdims(a,var))
+ dim=copy.copy(var['dimension'])
+ if c2capi_map.has_key(ret['ctype']): ret['atype']=c2capi_map[ret['ctype']]
+ # Debug info
+ if debugcapi(var):
+ il=[isintent_in,'input',isintent_out,'output',
+ isintent_inout,'inoutput',isrequired,'required',
+ isoptional,'optional',isintent_hide,'hidden',
+ iscomplex,'complex scalar',
+ l_and(isscalar,l_not(iscomplex)),'scalar',
+ isstring,'string',isarray,'array',
+ iscomplexarray,'complex array',isstringarray,'string array',
+ iscomplexfunction,'complex function',
+ l_and(isfunction,l_not(iscomplexfunction)),'function',
+ isexternal,'callback',
+ isintent_callback,'callback',
+ isintent_aux,'auxiliary',
+ #ismutable,'mutable',l_not(ismutable),'immutable',
+ ]
+ rl=[]
+ for i in range(0,len(il),2):
+ if il[i](var): rl.append(il[i+1])
+ if isstring(var):
+ rl.append('slen(%s)=%s'%(a,ret['length']))
+ if isarray(var):
+# if not isintent_c(var):
+# var['dimension'].reverse()
+ ddim=string.join(map(lambda x,y:'%s|%s'%(x,y),var['dimension'],dim),',')
+ rl.append('dims(%s)'%ddim)
+# if not isintent_c(var):
+# var['dimension'].reverse()
+ if isexternal(var):
+ ret['vardebuginfo']='debug-capi:%s=>%s:%s'%(a,ret['cbname'],string.join(rl,','))
+ else:
+ ret['vardebuginfo']='debug-capi:%s %s=%s:%s'%(ret['ctype'],a,ret['showinit'],string.join(rl,','))
+ if isscalar(var):
+ if cformat_map.has_key(ret['ctype']):
+ ret['vardebugshowvalue']='debug-capi:%s=%s'%(a,cformat_map[ret['ctype']])
+ if isstring(var):
+ ret['vardebugshowvalue']='debug-capi:slen(%s)=%%d %s=\\"%%s\\"'%(a,a)
+ if isexternal(var):
+ ret['vardebugshowvalue']='debug-capi:%s=%%p'%(a)
+ if cformat_map.has_key(ret['ctype']):
+ ret['varshowvalue']='#name#:%s=%s'%(a,cformat_map[ret['ctype']])
+ ret['showvalueformat']='%s'%(cformat_map[ret['ctype']])
+ if isstring(var):
+ ret['varshowvalue']='#name#:slen(%s)=%%d %s=\\"%%s\\"'%(a,a)
+ ret['pydocsign'],ret['pydocsignout']=getpydocsign(a,var)
+ if hasnote(var):
+ ret['note']=var['note']
+ return ret
+
+def routsign2map(rout):
+ """
+ name,NAME,begintitle,endtitle
+ rname,ctype,rformat
+ routdebugshowvalue
+ """
+ global lcb_map
+ name = rout['name']
+ fname = getfortranname(rout)
+ ret={'name':name,
+ 'texname':string.replace(name,'_','\\_'),
+ 'name_lower':string.lower(name),
+ 'NAME':string.upper(name),
+ 'begintitle':gentitle(name),
+ 'endtitle':gentitle('end of %s'%name),
+ 'fortranname':fname,
+ 'FORTRANNAME':string.upper(fname),
+ 'callstatement':getcallstatement(rout) or '',
+ 'usercode':getusercode(rout) or '',
+ 'usercode1':getusercode1(rout) or '',
+ }
+ if '_' in fname:
+ ret['F_FUNC'] = 'F_FUNC_US'
+ else:
+ ret['F_FUNC'] = 'F_FUNC'
+ if '_' in name:
+ ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC_US'
+ else:
+ ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC'
+ lcb_map={}
+ if rout.has_key('use'):
+ for u in rout['use'].keys():
+ if cb_rules.cb_map.has_key(u):
+ for un in cb_rules.cb_map[u]:
+ ln=un[0]
+ if rout['use'][u].has_key('map'):
+ for k in rout['use'][u]['map'].keys():
+ if rout['use'][u]['map'][k]==un[0]: ln=k;break
+ lcb_map[ln]=un[1]
+ #else:
+ # errmess('routsign2map: cb_map does not contain module "%s" used in "use" statement.\n'%(u))
+ elif rout.has_key('externals') and rout['externals']:
+ errmess('routsign2map: Confused: function %s has externals %s but no "use" statement.\n'%(ret['name'],`rout['externals']`))
+ ret['callprotoargument'] = getcallprotoargument(rout,lcb_map) or ''
+ if isfunction(rout):
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ ret['rname']=a
+ ret['pydocsign'],ret['pydocsignout']=getpydocsign(a,rout)
+ ret['ctype']=getctype(rout['vars'][a])
+ if hasresultnote(rout):
+ ret['resultnote']=rout['vars'][a]['note']
+ rout['vars'][a]['note']=['See elsewhere.']
+ if c2buildvalue_map.has_key(ret['ctype']):
+ ret['rformat']=c2buildvalue_map[ret['ctype']]
+ else:
+ ret['rformat']='O'
+ errmess('routsign2map: no c2buildvalue key for type %s\n'%(`ret['ctype']`))
+ if debugcapi(rout):
+ if cformat_map.has_key(ret['ctype']):
+ ret['routdebugshowvalue']='debug-capi:%s=%s'%(a,cformat_map[ret['ctype']])
+ if isstringfunction(rout):
+ ret['routdebugshowvalue']='debug-capi:slen(%s)=%%d %s=\\"%%s\\"'%(a,a)
+ if isstringfunction(rout):
+ ret['rlength']=getstrlength(rout['vars'][a])
+ if ret['rlength']=='-1':
+ errmess('routsign2map: expected explicit specification of the length of the string returned by the fortran function %s; taking 10.\n'%(`rout['name']`))
+ ret['rlength']='10'
+ if hasnote(rout):
+ ret['note']=rout['note']
+ rout['note']=['See elsewhere.']
+ return ret
+
+def modsign2map(m):
+ """
+ modulename
+ """
+ if ismodule(m):
+ ret={'f90modulename':m['name'],
+ 'F90MODULENAME':string.upper(m['name']),
+ 'texf90modulename':string.replace(m['name'],'_','\\_')}
+ else:
+ ret={'modulename':m['name'],
+ 'MODULENAME':string.upper(m['name']),
+ 'texmodulename':string.replace(m['name'],'_','\\_')}
+ ret['restdoc'] = getrestdoc(m) or []
+ if hasnote(m):
+ ret['note']=m['note']
+ #m['note']=['See elsewhere.']
+ ret['usercode'] = getusercode(m) or ''
+ ret['usercode1'] = getusercode1(m) or ''
+ if m['body']:
+ ret['interface_usercode'] = getusercode(m['body'][0]) or ''
+ else:
+ ret['interface_usercode'] = ''
+ ret['pymethoddef'] = getpymethoddef(m) or ''
+ return ret
+
+def cb_sign2map(a,var):
+ ret={'varname':a}
+ ret['ctype']=getctype(var)
+ if c2capi_map.has_key(ret['ctype']):
+ ret['atype']=c2capi_map[ret['ctype']]
+ if cformat_map.has_key(ret['ctype']):
+ ret['showvalueformat']='%s'%(cformat_map[ret['ctype']])
+ if isarray(var):
+ ret=dictappend(ret,getarrdims(a,var))
+ ret['pydocsign'],ret['pydocsignout']=getpydocsign(a,var)
+ if hasnote(var):
+ ret['note']=var['note']
+ var['note']=['See elsewhere.']
+ return ret
+
+def cb_routsign2map(rout,um):
+ """
+ name,begintitle,endtitle,argname
+ ctype,rctype,maxnofargs,nofoptargs,returncptr
+ """
+ ret={'name':'cb_%s_in_%s'%(rout['name'],um),
+ 'returncptr':''}
+ if isintent_callback(rout):
+ if '_' in rout['name']:
+ F_FUNC='F_FUNC_US'
+ else:
+ F_FUNC='F_FUNC'
+ ret['callbackname'] = '%s(%s,%s)' \
+ % (F_FUNC,
+ rout['name'].lower(),
+ rout['name'].upper(),
+ )
+ ret['static'] = 'extern'
+ else:
+ ret['callbackname'] = ret['name']
+ ret['static'] = 'static'
+ ret['argname']=rout['name']
+ ret['begintitle']=gentitle(ret['name'])
+ ret['endtitle']=gentitle('end of %s'%ret['name'])
+ ret['ctype']=getctype(rout)
+ ret['rctype']='void'
+ if ret['ctype']=='string': ret['rctype']='void'
+ else:
+ ret['rctype']=ret['ctype']
+ if ret['rctype']!='void':
+ if iscomplexfunction(rout):
+ ret['returncptr'] = """
+#ifdef F2PY_CB_RETURNCOMPLEX
+return_value=
+#endif
+"""
+ else:
+ ret['returncptr'] = 'return_value='
+ if cformat_map.has_key(ret['ctype']):
+ ret['showvalueformat']='%s'%(cformat_map[ret['ctype']])
+ if isstringfunction(rout):
+ ret['strlength']=getstrlength(rout)
+ if isfunction(rout):
+ if rout.has_key('result'): a=rout['result']
+ else: a=rout['name']
+ if hasnote(rout['vars'][a]):
+ ret['note']=rout['vars'][a]['note']
+ rout['vars'][a]['note']=['See elsewhere.']
+ ret['rname']=a
+ ret['pydocsign'],ret['pydocsignout']=getpydocsign(a,rout)
+ if iscomplexfunction(rout):
+ ret['rctype']="""
+#ifdef F2PY_CB_RETURNCOMPLEX
+#ctype#
+#else
+void
+#endif
+"""
+ else:
+ if hasnote(rout):
+ ret['note']=rout['note']
+ rout['note']=['See elsewhere.']
+ nofargs=0
+ nofoptargs=0
+ if rout.has_key('args') and rout.has_key('vars'):
+ for a in rout['args']:
+ var=rout['vars'][a]
+ if l_or(isintent_in,isintent_inout)(var):
+ nofargs=nofargs+1
+ if isoptional(var):
+ nofoptargs=nofoptargs+1
+ ret['maxnofargs']=`nofargs`
+ ret['nofoptargs']=`nofoptargs`
+ if hasnote(rout) and isfunction(rout) and rout.has_key('result'):
+ ret['routnote']=rout['note']
+ rout['note']=['See elsewhere.']
+ return ret
+
+def common_sign2map(a,var): # obsolute
+ ret={'varname':a}
+ ret['ctype']=getctype(var)
+ if isstringarray(var): ret['ctype']='char'
+ if c2capi_map.has_key(ret['ctype']):
+ ret['atype']=c2capi_map[ret['ctype']]
+ if cformat_map.has_key(ret['ctype']):
+ ret['showvalueformat']='%s'%(cformat_map[ret['ctype']])
+ if isarray(var):
+ ret=dictappend(ret,getarrdims(a,var))
+ elif isstring(var):
+ ret['size']=getstrlength(var)
+ ret['rank']='1'
+ ret['pydocsign'],ret['pydocsignout']=getpydocsign(a,var)
+ if hasnote(var):
+ ret['note']=var['note']
+ var['note']=['See elsewhere.']
+ ret['arrdocstr']=getarrdocsign(a,var) # for strings this returns 0-rank but actually is 1-rank
+ return ret
+
+
diff --git a/numpy/f2py/cb_rules.py b/numpy/f2py/cb_rules.py
new file mode 100644
index 000000000..666c1c6c8
--- /dev/null
+++ b/numpy/f2py/cb_rules.py
@@ -0,0 +1,534 @@
+#!/usr/bin/env python
+"""
+
+Build call-back mechanism for f2py2e.
+
+Copyright 2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/07/20 11:27:58 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.53 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+
+import pprint
+import sys,string,time,types,copy
+errmess=sys.stderr.write
+outmess=sys.stdout.write
+show=pprint.pprint
+
+from auxfuncs import *
+import capi_maps
+#from capi_maps import *
+import cfuncs
+
+################## Rules for callback function ##############
+
+cb_routine_rules={
+ 'cbtypedefs':'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);',
+ 'body':"""
+#begintitle#
+PyObject *#name#_capi = NULL;/*was Py_None*/
+PyTupleObject *#name#_args_capi = NULL;
+int #name#_nofargs = 0;
+jmp_buf #name#_jmpbuf;
+/*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/
+#static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) {
+\tPyTupleObject *capi_arglist = #name#_args_capi;
+\tPyObject *capi_return = NULL;
+\tPyObject *capi_tmp = NULL;
+\tint capi_j,capi_i = 0;
+\tint capi_longjmp_ok = 1;
+#decl#
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_start_clock();
+#endif
+\tCFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\");
+\tCFUNCSMESSPY(\"cb:#name#_capi=\",#name#_capi);
+\tif (#name#_capi==NULL) {
+\t\tcapi_longjmp_ok = 0;
+\t\t#name#_capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\");
+\t}
+\tif (#name#_capi==NULL) {
+\t\tPyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\");
+\t\tgoto capi_fail;
+\t}
+\tif (PyCObject_Check(#name#_capi)) {
+\t#name#_typedef #name#_cptr;
+\t#name#_cptr = PyCObject_AsVoidPtr(#name#_capi);
+\t#returncptr#(*#name#_cptr)(#optargs_nm##args_nm#);
+\t#return#
+\t}
+\tif (capi_arglist==NULL) {
+\t\tcapi_longjmp_ok = 0;
+\t\tcapi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\");
+\t\tif (capi_tmp) {
+\t\t\tcapi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp);
+\t\t\tif (capi_arglist==NULL) {
+\t\t\t\tPyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\");
+\t\t\t\tgoto capi_fail;
+\t\t\t}
+\t\t} else {
+\t\t\tPyErr_Clear();
+\t\t\tcapi_arglist = (PyTupleObject *)Py_BuildValue(\"()\");
+\t\t}
+\t}
+\tif (capi_arglist == NULL) {
+\t\tPyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\");
+\t\tgoto capi_fail;
+\t}
+#setdims#
+#pyobjfrom#
+\tCFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist);
+\tCFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\");
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_start_call_clock();
+#endif
+\tcapi_return = PyObject_CallObject(#name#_capi,(PyObject *)capi_arglist);
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_stop_call_clock();
+#endif
+\tCFUNCSMESSPY(\"cb:capi_return=\",capi_return);
+\tif (capi_return == NULL) {
+\t\tfprintf(stderr,\"capi_return is NULL\\n\");
+\t\tgoto capi_fail;
+\t}
+\tif (capi_return == Py_None) {
+\t\tPy_DECREF(capi_return);
+\t\tcapi_return = Py_BuildValue(\"()\");
+\t}
+\telse if (!PyTuple_Check(capi_return)) {
+\t\tcapi_return = Py_BuildValue(\"(N)\",capi_return);
+\t}
+\tcapi_j = PyTuple_Size(capi_return);
+\tcapi_i = 0;
+#frompyobj#
+\tCFUNCSMESS(\"cb:#name#:successful\\n\");
+\tPy_DECREF(capi_return);
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_stop_clock();
+#endif
+\tgoto capi_return_pt;
+capi_fail:
+\tfprintf(stderr,\"Call-back #name# failed.\\n\");
+\tPy_XDECREF(capi_return);
+\tif (capi_longjmp_ok)
+\t\tlongjmp(#name#_jmpbuf,-1);
+capi_return_pt:
+\t;
+#return#
+}
+#endtitle#
+""",
+ 'need':['setjmp.h','CFUNCSMESS'],
+ 'maxnofargs':'#maxnofargs#',
+ 'nofoptargs':'#nofoptargs#',
+ 'docstr':"""\
+\tdef #argname#(#docsignature#): return #docreturn#\\n\\
+#docstrsigns#""",
+ 'latexdocstr':"""
+{{}\\verb@def #argname#(#latexdocsignature#): return #docreturn#@{}}
+#routnote#
+
+#latexdocstrsigns#""",
+ 'docstrshort':'def #argname#(#docsignature#): return #docreturn#'
+ }
+cb_rout_rules=[
+ {# Init
+ 'separatorsfor':{'decl':'\n',
+ 'args':',','optargs':'','pyobjfrom':'\n','freemem':'\n',
+ 'args_td':',','optargs_td':'',
+ 'args_nm':',','optargs_nm':'',
+ 'frompyobj':'\n','setdims':'\n',
+ 'docstrsigns':'\\n"\n"',
+ 'latexdocstrsigns':'\n',
+ 'latexdocstrreq':'\n','latexdocstropt':'\n',
+ 'latexdocstrout':'\n','latexdocstrcbs':'\n',
+ },
+ 'decl':'/*decl*/','pyobjfrom':'/*pyobjfrom*/','frompyobj':'/*frompyobj*/',
+ 'args':[],'optargs':'','return':'','strarglens':'','freemem':'/*freemem*/',
+ 'args_td':[],'optargs_td':'','strarglens_td':'',
+ 'args_nm':[],'optargs_nm':'','strarglens_nm':'',
+ 'noargs':'',
+ 'setdims':'/*setdims*/',
+ 'docstrsigns':'','latexdocstrsigns':'',
+ 'docstrreq':'\tRequired arguments:',
+ 'docstropt':'\tOptional arguments:',
+ 'docstrout':'\tReturn objects:',
+ 'docstrcbs':'\tCall-back functions:',
+ 'docreturn':'','docsign':'','docsignopt':'',
+ 'latexdocstrreq':'\\noindent Required arguments:',
+ 'latexdocstropt':'\\noindent Optional arguments:',
+ 'latexdocstrout':'\\noindent Return objects:',
+ 'latexdocstrcbs':'\\noindent Call-back functions:',
+ 'routnote':{hasnote:'--- #note#',l_not(hasnote):''},
+ },{ # Function
+ 'decl':'\t#ctype# return_value;',
+ 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting return_value->");'},
+ '\tif (capi_j>capi_i)\n\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n");',
+ {debugcapi:'\tfprintf(stderr,"#showvalueformat#.\\n",return_value);'}
+ ],
+ 'need':['#ctype#_from_pyobj',{debugcapi:'CFUNCSMESS'},'GETSCALARFROMPYTUPLE'],
+ 'return':'\treturn return_value;',
+ '_check':l_and(isfunction,l_not(isstringfunction),l_not(iscomplexfunction))
+ },
+ {# String function
+ 'pyobjfrom':{debugcapi:'\tfprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'},
+ 'args':'#ctype# return_value,int return_value_len',
+ 'args_nm':'return_value,&return_value_len',
+ 'args_td':'#ctype# ,int',
+ 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting return_value->\\"");'},
+ """\tif (capi_j>capi_i)
+\t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);""",
+ {debugcapi:'\tfprintf(stderr,"#showvalueformat#\\".\\n",return_value);'}
+ ],
+ 'need':['#ctype#_from_pyobj',{debugcapi:'CFUNCSMESS'},
+ 'string.h','GETSTRFROMPYTUPLE'],
+ 'return':'return;',
+ '_check':isstringfunction
+ },
+ {# Complex function
+ 'optargs':"""
+#ifndef F2PY_CB_RETURNCOMPLEX
+#ctype# *return_value
+#endif
+""",
+ 'optargs_nm':"""
+#ifndef F2PY_CB_RETURNCOMPLEX
+return_value
+#endif
+""",
+ 'optargs_td':"""
+#ifndef F2PY_CB_RETURNCOMPLEX
+#ctype# *
+#endif
+""",
+ 'decl':"""
+#ifdef F2PY_CB_RETURNCOMPLEX
+\t#ctype# return_value;
+#endif
+""",
+ 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting return_value->");'},
+ """\
+\tif (capi_j>capi_i)
+#ifdef F2PY_CB_RETURNCOMPLEX
+\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
+#else
+\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#,\"#ctype#_from_pyobj failed in converting return_value of call-back function #name# to C #ctype#\\n\");
+#endif
+""",
+ {debugcapi:"""
+#ifdef F2PY_CB_RETURNCOMPLEX
+\tfprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i);
+#else
+\tfprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i);
+#endif
+
+"""}
+ ],
+ 'return':"""
+#ifdef F2PY_CB_RETURNCOMPLEX
+\treturn return_value;
+#else
+\treturn;
+#endif
+""",
+ 'need':['#ctype#_from_pyobj',{debugcapi:'CFUNCSMESS'},
+ 'string.h','GETSCALARFROMPYTUPLE','#ctype#'],
+ '_check':iscomplexfunction
+ },
+ {'docstrout':'\t\t#pydocsignout#',
+ 'latexdocstrout':['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {hasnote:'--- #note#'}],
+ 'docreturn':'#rname#,',
+ '_check':isfunction},
+ {'_check':issubroutine,'return':'return;'}
+ ]
+
+cb_arg_rules=[
+ { # Doc
+ 'docstropt':{l_and(isoptional,isintent_nothide):'\t\t#pydocsign#'},
+ 'docstrreq':{l_and(isrequired,isintent_nothide):'\t\t#pydocsign#'},
+ 'docstrout':{isintent_out:'\t\t#pydocsignout#'},
+ 'latexdocstropt':{l_and(isoptional,isintent_nothide):['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote:'--- #note#'}]},
+ 'latexdocstrreq':{l_and(isrequired,isintent_nothide):['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote:'--- #note#'}]},
+ 'latexdocstrout':{isintent_out:['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {l_and(hasnote,isintent_hide):'--- #note#',
+ l_and(hasnote,isintent_nothide):'--- See above.'}]},
+ 'docsign':{l_and(isrequired,isintent_nothide):'#varname#,'},
+ 'docsignopt':{l_and(isoptional,isintent_nothide):'#varname#,'},
+ 'depend':''
+ },
+ {
+ 'args':{
+ l_and (isscalar,isintent_c):'#ctype# #varname#',
+ l_and (isscalar,l_not(isintent_c)):'#ctype# *#varname#_cb_capi',
+ isarray:'#ctype# *#varname#',
+ isstring:'#ctype# #varname#'
+ },
+ 'args_nm':{
+ l_and (isscalar,isintent_c):'#varname#',
+ l_and (isscalar,l_not(isintent_c)):'#varname#_cb_capi',
+ isarray:'#varname#',
+ isstring:'#varname#'
+ },
+ 'args_td':{
+ l_and (isscalar,isintent_c):'#ctype#',
+ l_and (isscalar,l_not(isintent_c)):'#ctype# *',
+ isarray:'#ctype# *',
+ isstring:'#ctype#'
+ },
+ 'strarglens':{isstring:',int #varname#_cb_len'}, # untested with multiple args
+ 'strarglens_td':{isstring:',int'}, # untested with multiple args
+
+ },
+ { # Scalars
+ 'decl':{l_not(isintent_c):'\t#ctype# #varname#=(*#varname#_cb_capi);'},
+ 'error': {l_and(isintent_c,isintent_out,
+ throw_error('intent(c,out) is forbidden for callback scalar arguments')):\
+ ''},
+ 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting #varname#->");'},
+ {isintent_out:'\tif (capi_j>capi_i)\n\t\tGETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'},
+ {l_and(debugcapi,l_and(l_not(iscomplex),isintent_c)):'\tfprintf(stderr,"#showvalueformat#.\\n",#varname#);'},
+ {l_and(debugcapi,l_and(l_not(iscomplex),l_not(isintent_c))):'\tfprintf(stderr,"#showvalueformat#.\\n",*#varname#_cb_capi);'},
+ {l_and(debugcapi,l_and(iscomplex,isintent_c)):'\tfprintf(stderr,"#showvalueformat#.\\n",(#varname#).r,(#varname#).i);'},
+ {l_and(debugcapi,l_and(iscomplex,l_not(isintent_c))):'\tfprintf(stderr,"#showvalueformat#.\\n",(*#varname#_cb_capi).r,(*#varname#_cb_capi).i);'},
+ ],
+ 'need':[{isintent_out:['#ctype#_from_pyobj','GETSCALARFROMPYTUPLE']},
+ {debugcapi:'CFUNCSMESS'}],
+ '_check':isscalar
+ },{
+ 'pyobjfrom':[{isintent_in:"""\
+\tif (#name#_nofargs>capi_i)
+\t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyobj_from_#ctype#1(#varname#)))
+\t\t\tgoto capi_fail;"""},
+ {isintent_inout:"""\
+\tif (#name#_nofargs>capi_i)
+\t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyarr_from_p_#ctype#1(#varname#_cb_capi)))
+\t\t\tgoto capi_fail;"""}],
+ 'need':[{isintent_in:'pyobj_from_#ctype#1'},
+ {isintent_inout:'pyarr_from_p_#ctype#1'},
+ {iscomplex:'#ctype#'}],
+ '_check':l_and(isscalar,isintent_nothide),
+ '_optional':''
+ },{# String
+ 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting #varname#->\\"");'},
+ """\tif (capi_j>capi_i)
+\t\tGETSTRFROMPYTUPLE(capi_return,capi_i++,#varname#,#varname#_cb_len);""",
+ {debugcapi:'\tfprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname#,#varname#_cb_len);'},
+ ],
+ 'need':['#ctype#','GETSTRFROMPYTUPLE',
+ {debugcapi:'CFUNCSMESS'},'string.h'],
+ '_check':l_and(isstring,isintent_out)
+ },{
+ 'pyobjfrom':[{debugcapi:'\tfprintf(stderr,"debug-capi:cb:#varname#=\\"#showvalueformat#\\":%d:\\n",#varname#,#varname#_cb_len);'},
+ {isintent_in:"""\
+\tif (#name#_nofargs>capi_i)
+\t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyobj_from_#ctype#1(#varname#)))
+\t\t\tgoto capi_fail;"""},
+ {isintent_inout:"""\
+\tif (#name#_nofargs>capi_i) {
+\t\tint #varname#_cb_dims[] = {#varname#_cb_len};
+\t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyarr_from_p_#ctype#1(#varname#,#varname#_cb_dims)))
+\t\t\tgoto capi_fail;
+\t}"""}],
+ 'need':[{isintent_in:'pyobj_from_#ctype#1'},
+ {isintent_inout:'pyarr_from_p_#ctype#1'}],
+ '_check':l_and(isstring,isintent_nothide),
+ '_optional':''
+ },
+# Array ...
+ {
+ 'decl':'\tintp #varname#_Dims[#rank#] = {#rank*[-1]#};',
+ 'setdims':'\t#cbsetdims#;',
+ '_check':isarray,
+ '_depend':''
+ },
+ {
+ 'pyobjfrom':[{debugcapi:'\tfprintf(stderr,"debug-capi:cb:#varname#\\n");'},
+ {isintent_c:"""\
+\tif (#name#_nofargs>capi_i) {
+\t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname#_Dims,#atype#,NULL,(char*)#varname#,0,CARRAY_FLAGS,NULL); /*XXX: Hmm, what will destroy this array??? */
+""",
+ l_not(isintent_c):"""\
+\tif (#name#_nofargs>capi_i) {
+\t\tPyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,#rank#,#varname#_Dims,#atype#,NULL,(char*)#varname#,0,FARRAY_FLAGS,NULL); /*XXX: Hmm, what will destroy this array??? */
+""",
+ },
+ """
+\t\tif (tmp_arr==NULL)
+\t\t\tgoto capi_fail;
+\t\tif (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,(PyObject *)tmp_arr))
+\t\t\tgoto capi_fail;
+}"""],
+ '_check':l_and(isarray,isintent_nothide,l_or(isintent_in,isintent_inout)),
+ '_optional':'',
+ },{
+ 'frompyobj':[{debugcapi:'\tCFUNCSMESS("cb:Getting #varname#->");'},
+ """\tif (capi_j>capi_i) {
+\t\tPyArrayObject *rv_cb_arr = NULL;
+\t\tif ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail;
+\t\trv_cb_arr = array_from_pyobj(#atype#,#varname#_Dims,#rank#,F2PY_INTENT_IN""",
+ {isintent_c:'|F2PY_INTENT_C'},
+ """,capi_tmp);
+\t\tif (rv_cb_arr == NULL) {
+\t\t\tfprintf(stderr,\"rv_cb_arr is NULL\\n\");
+\t\t\tgoto capi_fail;
+\t\t}
+\t\tMEMCOPY(#varname#,rv_cb_arr->data,PyArray_NBYTES(rv_cb_arr));
+\t\tif (capi_tmp != (PyObject *)rv_cb_arr) {
+\t\t\tPy_DECREF(rv_cb_arr);
+\t\t}
+\t}""",
+ {debugcapi:'\tfprintf(stderr,"<-.\\n");'},
+ ],
+ 'need':['MEMCOPY',{iscomplexarray:'#ctype#'}],
+ '_check':l_and(isarray,isintent_out)
+ },{
+ 'docreturn':'#varname#,',
+ '_check':isintent_out
+ }
+ ]
+
+################## Build call-back module #############
+cb_map={}
+def buildcallbacks(m):
+ global cb_map
+ cb_map[m['name']]=[]
+ for bi in m['body']:
+ if bi['block']=='interface':
+ for b in bi['body']:
+ if b:
+ buildcallback(b,m['name'])
+ else:
+ errmess('warning: empty body for %s\n' % (m['name']))
+
+def buildcallback(rout,um):
+ global cb_map
+ outmess('\tConstructing call-back function "cb_%s_in_%s"\n'%(rout['name'],um))
+ args,depargs=getargs(rout)
+ capi_maps.depargs=depargs
+ var=rout['vars']
+ vrd=capi_maps.cb_routsign2map(rout,um)
+ rd=dictappend({},vrd)
+ cb_map[um].append([rout['name'],rd['name']])
+ for r in cb_rout_rules:
+ if (r.has_key('_check') and r['_check'](rout)) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,rout)
+ rd=dictappend(rd,ar)
+ savevrd={}
+ for a in args:
+ vrd=capi_maps.cb_sign2map(a,var[a])
+ savevrd[a]=vrd
+ for r in cb_arg_rules:
+ if r.has_key('_depend'): continue
+ if r.has_key('_optional') and isoptional(var[a]): continue
+ if (r.has_key('_check') and r['_check'](var[a])) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,var[a])
+ rd=dictappend(rd,ar)
+ if r.has_key('_break'): break
+ for a in args:
+ vrd=savevrd[a]
+ for r in cb_arg_rules:
+ if r.has_key('_depend'): continue
+ if (not r.has_key('_optional')) or (r.has_key('_optional') and isrequired(var[a])): continue
+ if (r.has_key('_check') and r['_check'](var[a])) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,var[a])
+ rd=dictappend(rd,ar)
+ if r.has_key('_break'): break
+ for a in depargs:
+ vrd=savevrd[a]
+ for r in cb_arg_rules:
+ if not r.has_key('_depend'): continue
+ if r.has_key('_optional'): continue
+ if (r.has_key('_check') and r['_check'](var[a])) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,var[a])
+ rd=dictappend(rd,ar)
+ if r.has_key('_break'): break
+ if rd.has_key('args') and rd.has_key('optargs'):
+ if type(rd['optargs'])==type([]):
+ rd['optargs']=rd['optargs']+["""
+#ifndef F2PY_CB_RETURNCOMPLEX
+,
+#endif
+"""]
+ rd['optargs_nm']=rd['optargs_nm']+["""
+#ifndef F2PY_CB_RETURNCOMPLEX
+,
+#endif
+"""]
+ rd['optargs_td']=rd['optargs_td']+["""
+#ifndef F2PY_CB_RETURNCOMPLEX
+,
+#endif
+"""]
+ if type(rd['docreturn'])==types.ListType:
+ rd['docreturn']=stripcomma(replace('#docreturn#',{'docreturn':rd['docreturn']}))
+ optargs=stripcomma(replace('#docsignopt#',
+ {'docsignopt':rd['docsignopt']}
+ ))
+ if optargs=='':
+ rd['docsignature']=stripcomma(replace('#docsign#',{'docsign':rd['docsign']}))
+ else:
+ rd['docsignature']=replace('#docsign#[#docsignopt#]',
+ {'docsign':rd['docsign'],
+ 'docsignopt':optargs,
+ })
+ rd['latexdocsignature']=string.replace(rd['docsignature'],'_','\\_')
+ rd['latexdocsignature']=string.replace(rd['latexdocsignature'],',',', ')
+ rd['docstrsigns']=[]
+ rd['latexdocstrsigns']=[]
+ for k in ['docstrreq','docstropt','docstrout','docstrcbs']:
+ if rd.has_key(k) and type(rd[k])==types.ListType:
+ rd['docstrsigns']=rd['docstrsigns']+rd[k]
+ k='latex'+k
+ if rd.has_key(k) and type(rd[k])==types.ListType:
+ rd['latexdocstrsigns']=rd['latexdocstrsigns']+rd[k][0:1]+\
+ ['\\begin{description}']+rd[k][1:]+\
+ ['\\end{description}']
+ if not rd.has_key('args'):
+ rd['args']=''
+ rd['args_td']=''
+ rd['args_nm']=''
+ if not (rd.get('args') or rd.get('optargs') or rd.get('strarglens')):
+ rd['noargs'] = 'void'
+
+ ar=applyrules(cb_routine_rules,rd)
+ cfuncs.callbacks[rd['name']]=ar['body']
+ if type(ar['need'])==types.StringType:
+ ar['need']=[ar['need']]
+
+ if rd.has_key('need'):
+ for t in cfuncs.typedefs.keys():
+ if t in rd['need']:
+ ar['need'].append(t)
+
+ cfuncs.typedefs_generated[rd['name']+'_typedef'] = ar['cbtypedefs']
+ ar['need'].append(rd['name']+'_typedef')
+ cfuncs.needs[rd['name']]=ar['need']
+
+ capi_maps.lcb2_map[rd['name']]={'maxnofargs':ar['maxnofargs'],
+ 'nofoptargs':ar['nofoptargs'],
+ 'docstr':ar['docstr'],
+ 'latexdocstr':ar['latexdocstr'],
+ 'argname':rd['argname']
+ }
+ outmess('\t %s\n'%(ar['docstrshort']))
+ #print ar['body']
+ return
+################## Build call-back function #############
+
+
+
+
+
diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py
new file mode 100644
index 000000000..aec1509ff
--- /dev/null
+++ b/numpy/f2py/cfuncs.py
@@ -0,0 +1,1134 @@
+#!/usr/bin/env python
+"""
+
+C declarations, CPP macros, and C functions for f2py2e.
+Only required declarations/macros/functions will be used.
+
+Copyright 1999,2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 11:42:34 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.75 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+import types,sys,copy,os
+errmess=sys.stderr.write
+
+##################### Definitions ##################
+
+outneeds={'includes0':[],'includes':[],'typedefs':[],'typedefs_generated':[],
+ 'userincludes':[],
+ 'cppmacros':[],'cfuncs':[],'callbacks':[],'f90modhooks':[],
+ 'commonhooks':[]}
+needs={}
+includes0={'includes0':'/*need_includes0*/'}
+includes={'includes':'/*need_includes*/'}
+userincludes={'userincludes':'/*need_userincludes*/'}
+typedefs={'typedefs':'/*need_typedefs*/'}
+typedefs_generated={'typedefs_generated':'/*need_typedefs_generated*/'}
+cppmacros={'cppmacros':'/*need_cppmacros*/'}
+cfuncs={'cfuncs':'/*need_cfuncs*/'}
+callbacks={'callbacks':'/*need_callbacks*/'}
+f90modhooks={'f90modhooks':'/*need_f90modhooks*/',
+ 'initf90modhooksstatic':'/*initf90modhooksstatic*/',
+ 'initf90modhooksdynamic':'/*initf90modhooksdynamic*/',
+ }
+commonhooks={'commonhooks':'/*need_commonhooks*/',
+ 'initcommonhooks':'/*need_initcommonhooks*/',
+ }
+
+############ Includes ###################
+
+includes0['math.h']='#include <math.h>'
+includes0['string.h']='#include <string.h>'
+includes0['setjmp.h']='#include <setjmp.h>'
+
+includes['Python.h']='#include "Python.h"'
+needs['arrayobject.h']=['Python.h']
+includes['arrayobject.h']='''#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API
+#include "arrayobject.h"'''
+
+includes['arrayobject.h']='#include "fortranobject.h"'
+
+############# Type definitions ###############
+
+typedefs['unsigned_char']='typedef unsigned char unsigned_char;'
+typedefs['unsigned_short']='typedef unsigned short unsigned_short;'
+typedefs['unsigned_long']='typedef unsigned long unsigned_long;'
+typedefs['signed_char']='typedef signed char signed_char;'
+typedefs['long_long']="""\
+#ifdef _WIN32
+typedef __int64 long_long;
+#else
+typedef long long long_long;
+typedef unsigned long long unsigned_long_long;
+#endif
+"""
+typedefs['insinged_long_long']="""\
+#ifdef _WIN32
+typedef __uint64 long_long;
+#else
+typedef unsigned long long unsigned_long_long;
+#endif
+"""
+typedefs['long_double']="""\
+#ifndef _LONG_DOUBLE
+typedef long double long_double;
+#endif
+"""
+typedefs['complex_long_double']='typedef struct {long double r,i;} complex_long_double;'
+typedefs['complex_float']='typedef struct {float r,i;} complex_float;'
+typedefs['complex_double']='typedef struct {double r,i;} complex_double;'
+typedefs['string']="""typedef char * string;"""
+
+
+############### CPP macros ####################
+cppmacros['CFUNCSMESS']="""\
+#ifdef DEBUGCFUNCS
+#define CFUNCSMESS(mess) fprintf(stderr,\"debug-capi:\"mess);
+#define CFUNCSMESSPY(mess,obj) CFUNCSMESS(mess) \\
+\tPyObject_Print((PyObject *)obj,stderr,Py_PRINT_RAW);\\
+\tfprintf(stderr,\"\\n\");
+#else
+#define CFUNCSMESS(mess)
+#define CFUNCSMESSPY(mess,obj)
+#endif
+"""
+cppmacros['F_FUNC']="""\
+#if defined(PREPEND_FORTRAN)
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F
+#else
+#define F_FUNC(f,F) _##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F##_
+#else
+#define F_FUNC(f,F) _##f##_
+#endif
+#endif
+#else
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F
+#else
+#define F_FUNC(f,F) f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F##_
+#else
+#define F_FUNC(f,F) f##_
+#endif
+#endif
+#endif
+#if defined(UNDERSCORE_G77)
+#define F_FUNC_US(f,F) F_FUNC(f##_,F##_)
+#else
+#define F_FUNC_US(f,F) F_FUNC(f,F)
+#endif
+"""
+cppmacros['F_WRAPPEDFUNC']="""\
+#if defined(PREPEND_FORTRAN)
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) _F2PYWRAP##F
+#else
+#define F_WRAPPEDFUNC(f,F) _f2pywrap##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) _F2PYWRAP##F##_
+#else
+#define F_WRAPPEDFUNC(f,F) _f2pywrap##f##_
+#endif
+#endif
+#else
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) F2PYWRAP##F
+#else
+#define F_WRAPPEDFUNC(f,F) f2pywrap##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) F2PYWRAP##F##_
+#else
+#define F_WRAPPEDFUNC(f,F) f2pywrap##f##_
+#endif
+#endif
+#endif
+#if defined(UNDERSCORE_G77)
+#define F_WRAPPEDFUNC_US(f,F) F_WRAPPEDFUNC(f##_,F##_)
+#else
+#define F_WRAPPEDFUNC_US(f,F) F_WRAPPEDFUNC(f,F)
+#endif
+"""
+cppmacros['F_MODFUNC']="""\
+#if defined(F90MOD2CCONV1) /*E.g. Compaq Fortran */
+#if defined(NO_APPEND_FORTRAN)
+#define F_MODFUNCNAME(m,f) $ ## m ## $ ## f
+#else
+#define F_MODFUNCNAME(m,f) $ ## m ## $ ## f ## _
+#endif
+#endif
+
+#if defined(F90MOD2CCONV2) /*E.g. IBM XL Fortran, not tested though */
+#if defined(NO_APPEND_FORTRAN)
+#define F_MODFUNCNAME(m,f) __ ## m ## _MOD_ ## f
+#else
+#define F_MODFUNCNAME(m,f) __ ## m ## _MOD_ ## f ## _
+#endif
+#endif
+
+#if defined(F90MOD2CCONV3) /*E.g. MIPSPro Compilers */
+#if defined(NO_APPEND_FORTRAN)
+#define F_MODFUNCNAME(m,f) f ## .in. ## m
+#else
+#define F_MODFUNCNAME(m,f) f ## .in. ## m ## _
+#endif
+#endif
+/*
+#if defined(UPPERCASE_FORTRAN)
+#define F_MODFUNC(m,M,f,F) F_MODFUNCNAME(M,F)
+#else
+#define F_MODFUNC(m,M,f,F) F_MODFUNCNAME(m,f)
+#endif
+*/
+
+#define F_MODFUNC(m,f) (*(f2pymodstruct##m##.##f))
+"""
+cppmacros['SWAPUNSAFE']="""\
+#define SWAP(a,b) (size_t)(a) = ((size_t)(a) ^ (size_t)(b));\\
+ (size_t)(b) = ((size_t)(a) ^ (size_t)(b));\\
+ (size_t)(a) = ((size_t)(a) ^ (size_t)(b))
+"""
+cppmacros['SWAP']="""\
+#define SWAP(a,b,t) {\\
+\tt *c;\\
+\tc = a;\\
+\ta = b;\\
+\tb = c;}
+"""
+#cppmacros['ISCONTIGUOUS']='#define ISCONTIGUOUS(m) ((m)->flags & CONTIGUOUS)'
+cppmacros['PRINTPYOBJERR']="""\
+#define PRINTPYOBJERR(obj)\\
+\tfprintf(stderr,\"#modulename#.error is related to \");\\
+\tPyObject_Print((PyObject *)obj,stderr,Py_PRINT_RAW);\\
+\tfprintf(stderr,\"\\n\");
+"""
+cppmacros['MINMAX']="""\
+#ifndef MAX
+#define MAX(a,b) ((a > b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a < b) ? (a) : (b))
+#endif
+"""
+cppmacros['len..']="""\
+#define rank(var) var ## _Rank
+#define shape(var,dim) var ## _Dims[dim]
+#define old_rank(var) (((PyArrayObject *)(capi_ ## var ## _tmp))->nd)
+#define old_shape(var,dim) (((PyArrayObject *)(capi_ ## var ## _tmp))->dimensions[dim])
+#define fshape(var,dim) shape(var,rank(var)-dim-1)
+#define len(var) shape(var,0)
+#define flen(var) fshape(var,0)
+#define size(var) PyArray_SIZE((PyArrayObject *)(capi_ ## var ## _tmp))
+/* #define index(i) capi_i ## i */
+#define slen(var) capi_ ## var ## _len
+"""
+
+cppmacros['pyobj_from_char1']='#define pyobj_from_char1(v) (PyInt_FromLong(v))'
+cppmacros['pyobj_from_short1']='#define pyobj_from_short1(v) (PyInt_FromLong(v))'
+needs['pyobj_from_int1']=['signed_char']
+cppmacros['pyobj_from_int1']='#define pyobj_from_int1(v) (PyInt_FromLong(v))'
+cppmacros['pyobj_from_long1']='#define pyobj_from_long1(v) (PyLong_FromLong(v))'
+needs['pyobj_from_long_long1']=['long_long']
+cppmacros['pyobj_from_long_long1']="""\
+#ifdef HAVE_LONG_LONG
+#define pyobj_from_long_long1(v) (PyLong_FromLongLong(v))
+#else
+#warning HAVE_LONG_LONG is not available. Redefining pyobj_from_long_long.
+#define pyobj_from_long_long1(v) (PyLong_FromLong(v))
+#endif
+"""
+needs['pyobj_from_long_double1']=['long_double']
+cppmacros['pyobj_from_long_double1']='#define pyobj_from_long_double1(v) (PyFloat_FromDouble(v))'
+cppmacros['pyobj_from_double1']='#define pyobj_from_double1(v) (PyFloat_FromDouble(v))'
+cppmacros['pyobj_from_float1']='#define pyobj_from_float1(v) (PyFloat_FromDouble(v))'
+needs['pyobj_from_complex_long_double1']=['complex_long_double']
+cppmacros['pyobj_from_complex_long_double1']='#define pyobj_from_complex_long_double1(v) (PyComplex_FromDoubles(v.r,v.i))'
+needs['pyobj_from_complex_double1']=['complex_double']
+cppmacros['pyobj_from_complex_double1']='#define pyobj_from_complex_double1(v) (PyComplex_FromDoubles(v.r,v.i))'
+needs['pyobj_from_complex_float1']=['complex_float']
+cppmacros['pyobj_from_complex_float1']='#define pyobj_from_complex_float1(v) (PyComplex_FromDoubles(v.r,v.i))'
+needs['pyobj_from_string1']=['string']
+cppmacros['pyobj_from_string1']='#define pyobj_from_string1(v) (PyString_FromString((char *)v))'
+needs['TRYPYARRAYTEMPLATE']=['PRINTPYOBJERR']
+cppmacros['TRYPYARRAYTEMPLATE']="""\
+/* New SciPy */
+#define TRYPYARRAYTEMPLATECHAR case PyArray_STRING: *(char *)(arr->data)=*v; break;
+#define TRYPYARRAYTEMPLATELONG case PyArray_LONG: *(long *)(arr->data)=*v; break;
+#define TRYPYARRAYTEMPLATEOBJECT case PyArray_OBJECT: (arr->descr->f->setitem)(pyobj_from_ ## ctype ## 1(*v),arr->data); break;
+
+#define TRYPYARRAYTEMPLATE(ctype,typecode) \\
+ PyArrayObject *arr = NULL;\\
+ if (!obj) return -2;\\
+ if (!PyArray_Check(obj)) return -1;\\
+ if (!(arr=(PyArrayObject *)obj)) {fprintf(stderr,\"TRYPYARRAYTEMPLATE:\");PRINTPYOBJERR(obj);return 0;}\\
+ if (arr->descr->type==typecode) {*(ctype *)(arr->data)=*v; return 1;}\\
+ switch (arr->descr->type_num) {\\
+ case PyArray_DOUBLE: *(double *)(arr->data)=*v; break;\\
+ case PyArray_INT: *(int *)(arr->data)=*v; break;\\
+ case PyArray_LONG: *(long *)(arr->data)=*v; break;\\
+ case PyArray_FLOAT: *(float *)(arr->data)=*v; break;\\
+ case PyArray_CDOUBLE: *(double *)(arr->data)=*v; break;\\
+ case PyArray_CFLOAT: *(float *)(arr->data)=*v; break;\\
+ case PyArray_BOOL: *(Bool *)(arr->data)=(*v!=0); break;\\
+ case PyArray_UBYTE: *(unsigned char *)(arr->data)=*v; break;\\
+ case PyArray_BYTE: *(signed char *)(arr->data)=*v; break;\\
+ case PyArray_SHORT: *(short *)(arr->data)=*v; break;\\
+ case PyArray_USHORT: *(ushort *)(arr->data)=*v; break;\\
+ case PyArray_UINT: *(uint *)(arr->data)=*v; break;\\
+ case PyArray_ULONG: *(ulong *)(arr->data)=*v; break;\\
+ case PyArray_LONGLONG: *(longlong *)(arr->data)=*v; break;\\
+ case PyArray_ULONGLONG: *(ulonglong *)(arr->data)=*v; break;\\
+ case PyArray_LONGDOUBLE: *(longdouble *)(arr->data)=*v; break;\\
+ case PyArray_CLONGDOUBLE: *(longdouble *)(arr->data)=*v; break;\\
+ case PyArray_OBJECT: (arr->descr->f->setitem)(pyobj_from_ ## ctype ## 1(*v),arr->data, arr); break;\\
+ default: return -2;\\
+ };\\
+ return 1
+"""
+
+needs['TRYCOMPLEXPYARRAYTEMPLATE']=['PRINTPYOBJERR']
+cppmacros['TRYCOMPLEXPYARRAYTEMPLATE']="""\
+#define TRYCOMPLEXPYARRAYTEMPLATEOBJECT case PyArray_OBJECT: (arr->descr->f->setitem)(pyobj_from_complex_ ## ctype ## 1((*v)),arr->data, arr); break;
+#define TRYCOMPLEXPYARRAYTEMPLATE(ctype,typecode)\\
+ PyArrayObject *arr = NULL;\\
+ if (!obj) return -2;\\
+ if (!PyArray_Check(obj)) return -1;\\
+ if (!(arr=(PyArrayObject *)obj)) {fprintf(stderr,\"TRYCOMPLEXPYARRAYTEMPLATE:\");PRINTPYOBJERR(obj);return 0;}\\
+ if (arr->descr->type==typecode) {\\
+ *(ctype *)(arr->data)=(*v).r;\\
+ *(ctype *)(arr->data+sizeof(ctype))=(*v).i;\\
+ return 1;\\
+ }\\
+ switch (arr->descr->type_num) {\\
+ case PyArray_CDOUBLE: *(double *)(arr->data)=(*v).r;*(double *)(arr->data+sizeof(double))=(*v).i;break;\\
+ case PyArray_CFLOAT: *(float *)(arr->data)=(*v).r;*(float *)(arr->data+sizeof(float))=(*v).i;break;\\
+ case PyArray_DOUBLE: *(double *)(arr->data)=(*v).r; break;\\
+ case PyArray_LONG: *(long *)(arr->data)=(*v).r; break;\\
+ case PyArray_FLOAT: *(float *)(arr->data)=(*v).r; break;\\
+ case PyArray_INT: *(int *)(arr->data)=(*v).r; break;\\
+ case PyArray_SHORT: *(short *)(arr->data)=(*v).r; break;\\
+ case PyArray_UBYTE: *(unsigned char *)(arr->data)=(*v).r; break;\\
+ case PyArray_BYTE: *(signed char *)(arr->data)=(*v).r; break;\\
+ case PyArray_BOOL: *(Bool *)(arr->data)=((*v).r!=0 && (*v).i!=0)); break;\\
+ case PyArray_UBYTE: *(unsigned char *)(arr->data)=(*v).r; break;\\
+ case PyArray_BYTE: *(signed char *)(arr->data)=(*v).r; break;\\
+ case PyArray_SHORT: *(short *)(arr->data)=(*v).r; break;\\
+ case PyArray_USHORT: *(ushort *)(arr->data)=(*v).r; break;\\
+ case PyArray_UINT: *(uint *)(arr->data)=(*v).r; break;\\
+ case PyArray_ULONG: *(ulong *)(arr->data)=(*v).r; break;\\
+ case PyArray_LONGLONG: *(longlong *)(arr->data)=(*v).r; break;\\
+ case PyArray_ULONGLONG: *(ulonglong *)(arr->data)=(*v).r; break;\\
+ case PyArray_LONGDOUBLE: *(longdouble *)(arr->data)=(*v).r; break;\\
+ case PyArray_CLONGDOUBLE: *(longdouble *)(arr->data)=(*v).r;*(longdouble *)(arr->data+sizeof(longdouble))=(*v).i;break;\\
+ case PyArray_OBJECT: (arr->descr->f->setitem)(pyobj_from_complex_ ## ctype ## 1((*v)),arr->data, arr); break;\\
+ default: return -2;\\
+ };\\
+ return -1;
+"""
+## cppmacros['NUMFROMARROBJ']="""\
+## #define NUMFROMARROBJ(typenum,ctype) \\
+## \tif (PyArray_Check(obj)) arr = (PyArrayObject *)obj;\\
+## \telse arr = (PyArrayObject *)PyArray_ContiguousFromObject(obj,typenum,0,0);\\
+## \tif (arr) {\\
+## \t\tif (arr->descr->type_num==PyArray_OBJECT) {\\
+## \t\t\tif (!ctype ## _from_pyobj(v,(arr->descr->getitem)(arr->data),\"\"))\\
+## \t\t\tgoto capi_fail;\\
+## \t\t} else {\\
+## \t\t\t(arr->descr->cast[typenum])(arr->data,1,(char*)v,1,1);\\
+## \t\t}\\
+## \t\tif ((PyObject *)arr != obj) { Py_DECREF(arr); }\\
+## \t\treturn 1;\\
+## \t}
+## """
+## #XXX: Note that CNUMFROMARROBJ is identical with NUMFROMARROBJ
+## cppmacros['CNUMFROMARROBJ']="""\
+## #define CNUMFROMARROBJ(typenum,ctype) \\
+## \tif (PyArray_Check(obj)) arr = (PyArrayObject *)obj;\\
+## \telse arr = (PyArrayObject *)PyArray_ContiguousFromObject(obj,typenum,0,0);\\
+## \tif (arr) {\\
+## \t\tif (arr->descr->type_num==PyArray_OBJECT) {\\
+## \t\t\tif (!ctype ## _from_pyobj(v,(arr->descr->getitem)(arr->data),\"\"))\\
+## \t\t\tgoto capi_fail;\\
+## \t\t} else {\\
+## \t\t\t(arr->descr->cast[typenum])((void *)(arr->data),1,(void *)(v),1,1);\\
+## \t\t}\\
+## \t\tif ((PyObject *)arr != obj) { Py_DECREF(arr); }\\
+## \t\treturn 1;\\
+## \t}
+## """
+
+
+needs['GETSTRFROMPYTUPLE']=['STRINGCOPYN','PRINTPYOBJERR']
+cppmacros['GETSTRFROMPYTUPLE']="""\
+#define GETSTRFROMPYTUPLE(tuple,index,str,len) {\\
+\t\tPyObject *rv_cb_str = PyTuple_GetItem((tuple),(index));\\
+\t\tif (rv_cb_str == NULL)\\
+\t\t\tgoto capi_fail;\\
+\t\tif (PyString_Check(rv_cb_str)) {\\
+\t\t\tstr[len-1]='\\0';\\
+\t\t\tSTRINGCOPYN((str),PyString_AS_STRING((PyStringObject*)rv_cb_str),(len));\\
+\t\t} else {\\
+\t\t\tPRINTPYOBJERR(rv_cb_str);\\
+\t\t\tPyErr_SetString(#modulename#_error,\"string object expected\");\\
+\t\t\tgoto capi_fail;\\
+\t\t}\\
+\t}
+"""
+cppmacros['GETSCALARFROMPYTUPLE']="""\
+#define GETSCALARFROMPYTUPLE(tuple,index,var,ctype,mess) {\\
+\t\tif ((capi_tmp = PyTuple_GetItem((tuple),(index)))==NULL) goto capi_fail;\\
+\t\tif (!(ctype ## _from_pyobj((var),capi_tmp,mess)))\\
+\t\t\tgoto capi_fail;\\
+\t}
+"""
+
+needs['MEMCOPY']=['string.h']
+cppmacros['MEMCOPY']="""\
+#define MEMCOPY(to,from,n)\\
+\tif ((memcpy(to,from,n)) == NULL) {\\
+\t\tPyErr_SetString(PyExc_MemoryError, \"memcpy failed\");\\
+\t\tgoto capi_fail;\\
+\t}
+"""
+cppmacros['STRINGMALLOC']="""\
+#define STRINGMALLOC(str,len)\\
+\tif ((str = (string)malloc(sizeof(char)*(len+1))) == NULL) {\\
+\t\tPyErr_SetString(PyExc_MemoryError, \"out of memory\");\\
+\t\tgoto capi_fail;\\
+\t} else {\\
+\t\t(str)[len] = '\\0';\\
+\t}
+"""
+cppmacros['STRINGFREE']="""\
+#define STRINGFREE(str)\\
+\tif (!(str == NULL)) free(str);
+"""
+needs['STRINGCOPYN']=['string.h']
+cppmacros['STRINGCOPYN']="""\
+#define STRINGCOPYN(to,from,n)\\
+\tif ((strncpy(to,from,sizeof(char)*(n))) == NULL) {\\
+\t\tPyErr_SetString(PyExc_MemoryError, \"strncpy failed\");\\
+\t\tgoto capi_fail;\\
+\t} else if (strlen(to)<(n)) {\\
+\t\tmemset((to)+strlen(to), ' ', (n)-strlen(to));\\
+\t} /* Padding with spaces instead of nulls. */
+"""
+needs['STRINGCOPY']=['string.h']
+cppmacros['STRINGCOPY']="""\
+#define STRINGCOPY(to,from)\\
+\tif ((strcpy(to,from)) == NULL) {\\
+\t\tPyErr_SetString(PyExc_MemoryError, \"strcpy failed\");\\
+\t\tgoto capi_fail;\\
+\t}
+"""
+cppmacros['CHECKGENERIC']="""\
+#define CHECKGENERIC(check,tcheck,name) \\
+\tif (!(check)) {\\
+\t\tPyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\
+\t\t/*goto capi_fail;*/\\
+\t} else """
+cppmacros['CHECKARRAY']="""\
+#define CHECKARRAY(check,tcheck,name) \\
+\tif (!(check)) {\\
+\t\tPyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\
+\t\t/*goto capi_fail;*/\\
+\t} else """
+cppmacros['CHECKSTRING']="""\
+#define CHECKSTRING(check,tcheck,name,show,var)\\
+\tif (!(check)) {\\
+\t\tPyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\
+\t\tfprintf(stderr,show\"\\n\",slen(var),var);\\
+\t\t/*goto capi_fail;*/\\
+\t} else """
+cppmacros['CHECKSCALAR']="""\
+#define CHECKSCALAR(check,tcheck,name,show,var)\\
+\tif (!(check)) {\\
+\t\tPyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\
+\t\tfprintf(stderr,show\"\\n\",var);\\
+\t\t/*goto capi_fail;*/\\
+\t} else """
+## cppmacros['CHECKDIMS']="""\
+## #define CHECKDIMS(dims,rank) \\
+## \tfor (int i=0;i<(rank);i++)\\
+## \t\tif (dims[i]<0) {\\
+## \t\t\tfprintf(stderr,\"Unspecified array argument requires a complete dimension specification.\\n\");\\
+## \t\t\tgoto capi_fail;\\
+## \t\t}
+## """
+cppmacros['ARRSIZE']='#define ARRSIZE(dims,rank) (_PyArray_multiply_list(dims,rank))'
+cppmacros['OLDPYNUM']="""\
+#ifdef OLDPYNUM
+#error You need to intall Numeric Python version 13 or higher. Get it from http:/sourceforge.net/project/?group_id=1369
+#endif
+"""
+################# C functions ###############
+
+cfuncs['calcarrindex']="""\
+static int calcarrindex(int *i,PyArrayObject *arr) {
+\tint k,ii = i[0];
+\tfor (k=1; k < arr->nd; k++)
+\t\tii += (ii*(arr->dimensions[k] - 1)+i[k]); /* assuming contiguous arr */
+\treturn ii;
+}"""
+cfuncs['calcarrindextr']="""\
+static int calcarrindextr(int *i,PyArrayObject *arr) {
+\tint k,ii = i[arr->nd-1];
+\tfor (k=1; k < arr->nd; k++)
+\t\tii += (ii*(arr->dimensions[arr->nd-k-1] - 1)+i[arr->nd-k-1]); /* assuming contiguous arr */
+\treturn ii;
+}"""
+cfuncs['forcomb']="""\
+static struct { int nd;intp *d;int *i,*i_tr,tr; } forcombcache;
+static int initforcomb(intp *dims,int nd,int tr) {
+ int k;
+ if (dims==NULL) return 0;
+ if (nd<0) return 0;
+ forcombcache.nd = nd;
+ forcombcache.d = dims;
+ forcombcache.tr = tr;
+ if ((forcombcache.i = (int *)malloc(sizeof(int)*nd))==NULL) return 0;
+ if ((forcombcache.i_tr = (int *)malloc(sizeof(int)*nd))==NULL) return 0;
+ for (k=1;k<nd;k++) {
+ forcombcache.i[k] = forcombcache.i_tr[nd-k-1] = 0;
+ }
+ forcombcache.i[0] = forcombcache.i_tr[nd-1] = -1;
+ return 1;
+}
+static int *nextforcomb(void) {
+ int j,*i,*i_tr,k;
+ int nd=forcombcache.nd;
+ if ((i=forcombcache.i) == NULL) return NULL;
+ if ((i_tr=forcombcache.i_tr) == NULL) return NULL;
+ if (forcombcache.d == NULL) return NULL;
+ i[0]++;
+ if (i[0]==forcombcache.d[0]) {
+ j=1;
+ while ((j<nd) && (i[j]==forcombcache.d[j]-1)) j++;
+ if (j==nd) {
+ free(i);
+ free(i_tr);
+ return NULL;
+ }
+ for (k=0;k<j;k++) i[k] = i_tr[nd-k-1] = 0;
+ i[j]++;
+ i_tr[nd-j-1]++;
+ } else
+ i_tr[nd-1]++;
+ if (forcombcache.tr) return i_tr;
+ return i;
+}"""
+needs['try_pyarr_from_string']=['STRINGCOPYN','PRINTPYOBJERR','string']
+cfuncs['try_pyarr_from_string']="""\
+static int try_pyarr_from_string(PyObject *obj,const string str) {
+\tPyArrayObject *arr = NULL;
+\tif (PyArray_Check(obj) && (!((arr = (PyArrayObject *)obj) == NULL)))
+\t\t{ STRINGCOPYN(arr->data,str,PyArray_NBYTES(arr)); }
+\treturn 1;
+capi_fail:
+\tPRINTPYOBJERR(obj);
+\tPyErr_SetString(#modulename#_error,\"try_pyarr_from_string failed\");
+\treturn 0;
+}
+"""
+needs['string_from_pyobj']=['string','STRINGMALLOC','STRINGCOPYN']
+cfuncs['string_from_pyobj']="""\
+static int string_from_pyobj(string *str,int *len,const string inistr,PyObject *obj,const char *errmess) {
+\tPyArrayObject *arr = NULL;
+\tPyObject *tmp = NULL;
+#ifdef DEBUGCFUNCS
+fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\",(char*)str,*len,(char *)inistr,obj);
+#endif
+\tif (obj == Py_None) {
+\t\tif (*len == -1)
+\t\t\t*len = strlen(inistr); /* Will this cause problems? */
+\t\tSTRINGMALLOC(*str,*len);
+\t\tSTRINGCOPYN(*str,inistr,*len);
+\t\treturn 1;
+\t}
+\tif (PyArray_Check(obj)) {
+\t\tif ((arr = (PyArrayObject *)obj) == NULL)
+\t\t\tgoto capi_fail;
+\t\tif (!ISCONTIGUOUS(arr)) {
+\t\t\tPyErr_SetString(PyExc_ValueError,\"array object is non-contiguous.\");
+\t\t\tgoto capi_fail;
+\t\t}
+\t\tif (*len == -1)
+\t\t\t*len = (arr->descr->elsize)*PyArray_SIZE(arr);
+\t\tSTRINGMALLOC(*str,*len);
+\t\tSTRINGCOPYN(*str,arr->data,*len);
+\t\treturn 1;
+\t}
+\tif (PyString_Check(obj)) {
+\t\ttmp = obj;
+\t\tPy_INCREF(tmp);
+\t}
+\telse
+\t\ttmp = PyObject_Str(obj);
+\tif (tmp == NULL) goto capi_fail;
+\tif (*len == -1)
+\t\t*len = PyString_GET_SIZE(tmp);
+\tSTRINGMALLOC(*str,*len);
+\tSTRINGCOPYN(*str,PyString_AS_STRING(tmp),*len);
+\tPy_DECREF(tmp);
+\treturn 1;
+capi_fail:
+\tPy_XDECREF(tmp);
+\t{
+\t\tPyObject* err = PyErr_Occurred();
+\t\tif (err==NULL) err = #modulename#_error;
+\t\tPyErr_SetString(err,errmess);
+\t}
+\treturn 0;
+}
+"""
+needs['char_from_pyobj']=['int_from_pyobj']
+cfuncs['char_from_pyobj']="""\
+static int char_from_pyobj(char* v,PyObject *obj,const char *errmess) {
+\tint i=0;
+\tif (int_from_pyobj(&i,obj,errmess)) {
+\t\t*v = (char)i;
+\t\treturn 1;
+\t}
+\treturn 0;
+}
+"""
+needs['signed_char_from_pyobj']=['int_from_pyobj','signed_char']
+cfuncs['signed_char_from_pyobj']="""\
+static int signed_char_from_pyobj(signed_char* v,PyObject *obj,const char *errmess) {
+\tint i=0;
+\tif (int_from_pyobj(&i,obj,errmess)) {
+\t\t*v = (signed_char)i;
+\t\treturn 1;
+\t}
+\treturn 0;
+}
+"""
+needs['short_from_pyobj']=['int_from_pyobj']
+cfuncs['short_from_pyobj']="""\
+static int short_from_pyobj(short* v,PyObject *obj,const char *errmess) {
+\tint i=0;
+\tif (int_from_pyobj(&i,obj,errmess)) {
+\t\t*v = (short)i;
+\t\treturn 1;
+\t}
+\treturn 0;
+}
+"""
+cfuncs['int_from_pyobj']="""\
+static int int_from_pyobj(int* v,PyObject *obj,const char *errmess) {
+\tPyObject* tmp = NULL;
+\tif (PyInt_Check(obj)) {
+\t\t*v = (int)PyInt_AS_LONG(obj);
+\t\treturn 1;
+\t}
+\ttmp = PyNumber_Int(obj);
+\tif (tmp) {
+\t\t*v = PyInt_AS_LONG(tmp);
+\t\tPy_DECREF(tmp);
+\t\treturn 1;
+\t}
+\tif (PyComplex_Check(obj))
+\t\ttmp = PyObject_GetAttrString(obj,\"real\");
+\telse if (PyString_Check(obj))
+\t\t/*pass*/;
+\telse if (PySequence_Check(obj))
+\t\ttmp = PySequence_GetItem(obj,0);
+\tif (tmp) {
+\t\tPyErr_Clear();
+\t\tif (int_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+\t\tPy_DECREF(tmp);
+\t}
+\t{
+\t\tPyObject* err = PyErr_Occurred();
+\t\tif (err==NULL) err = #modulename#_error;
+\t\tPyErr_SetString(err,errmess);
+\t}
+\treturn 0;
+}
+"""
+cfuncs['long_from_pyobj']="""\
+static int long_from_pyobj(long* v,PyObject *obj,const char *errmess) {
+\tPyObject* tmp = NULL;
+\tif (PyInt_Check(obj)) {
+\t\t*v = PyInt_AS_LONG(obj);
+\t\treturn 1;
+\t}
+\ttmp = PyNumber_Int(obj);
+\tif (tmp) {
+\t\t*v = PyInt_AS_LONG(tmp);
+\t\tPy_DECREF(tmp);
+\t\treturn 1;
+\t}
+\tif (PyComplex_Check(obj))
+\t\ttmp = PyObject_GetAttrString(obj,\"real\");
+\telse if (PyString_Check(obj))
+\t\t/*pass*/;
+\telse if (PySequence_Check(obj))
+\t\ttmp = PySequence_GetItem(obj,0);
+\tif (tmp) {
+\t\tPyErr_Clear();
+\t\tif (long_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+\t\tPy_DECREF(tmp);
+\t}
+\t{
+\t\tPyObject* err = PyErr_Occurred();
+\t\tif (err==NULL) err = #modulename#_error;
+\t\tPyErr_SetString(err,errmess);
+\t}
+\treturn 0;
+}
+"""
+needs['long_long_from_pyobj']=['long_long']
+cfuncs['long_long_from_pyobj']="""\
+static int long_long_from_pyobj(long_long* v,PyObject *obj,const char *errmess) {
+\tPyObject* tmp = NULL;
+\tif (PyLong_Check(obj)) {
+\t\t*v = PyLong_AsLongLong(obj);
+\t\treturn (!PyErr_Occurred());
+\t}
+\tif (PyInt_Check(obj)) {
+\t\t*v = (long_long)PyInt_AS_LONG(obj);
+\t\treturn 1;
+\t}
+\ttmp = PyNumber_Long(obj);
+\tif (tmp) {
+\t\t*v = PyLong_AsLongLong(tmp);
+\t\tPy_DECREF(tmp);
+\t\treturn (!PyErr_Occurred());
+\t}
+\tif (PyComplex_Check(obj))
+\t\ttmp = PyObject_GetAttrString(obj,\"real\");
+\telse if (PyString_Check(obj))
+\t\t/*pass*/;
+\telse if (PySequence_Check(obj))
+\t\ttmp = PySequence_GetItem(obj,0);
+\tif (tmp) {
+\t\tPyErr_Clear();
+\t\tif (long_long_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+\t\tPy_DECREF(tmp);
+\t}
+\t{
+\t\tPyObject* err = PyErr_Occurred();
+\t\tif (err==NULL) err = #modulename#_error;
+\t\tPyErr_SetString(err,errmess);
+\t}
+\treturn 0;
+}
+"""
+needs['long_double_from_pyobj']=['double_from_pyobj','long_double']
+cfuncs['long_double_from_pyobj']="""\
+static int long_double_from_pyobj(long_double* v,PyObject *obj,const char *errmess) {
+\tdouble d=0;
+\tif (PyArray_CheckScalar(obj)){
+\t\tif PyArray_IsScalar(obj, LongDouble) {
+\t\t\tPyArray_ScalarAsCtype(obj, v);
+\t\t\treturn 1;
+\t\t}
+\t\telse if (PyArray_Check(obj) && PyArray_TYPE(obj)==PyArray_LONGDOUBLE) {
+\t\t\t(*v) = *((longdouble *)PyArray_DATA(obj))
+\t\t\treturn 1;
+\t\t}
+\t}
+\tif (double_from_pyobj(&d,obj,errmess)) {
+\t\t*v = (long_double)d;
+\t\treturn 1;
+\t}
+\treturn 0;
+}
+"""
+cfuncs['double_from_pyobj']="""\
+static int double_from_pyobj(double* v,PyObject *obj,const char *errmess) {
+\tPyObject* tmp = NULL;
+\tif (PyFloat_Check(obj)) {
+#ifdef __sgi
+\t\t*v = PyFloat_AsDouble(obj);
+#else
+\t\t*v = PyFloat_AS_DOUBLE(obj);
+#endif
+\t\treturn 1;
+\t}
+\ttmp = PyNumber_Float(obj);
+\tif (tmp) {
+#ifdef __sgi
+\t\t*v = PyFloat_AsDouble(tmp);
+#else
+\t\t*v = PyFloat_AS_DOUBLE(tmp);
+#endif
+\t\tPy_DECREF(tmp);
+\t\treturn 1;
+\t}
+\tif (PyComplex_Check(obj))
+\t\ttmp = PyObject_GetAttrString(obj,\"real\");
+\telse if (PyString_Check(obj))
+\t\t/*pass*/;
+\telse if (PySequence_Check(obj))
+\t\ttmp = PySequence_GetItem(obj,0);
+\tif (tmp) {
+\t\tPyErr_Clear();
+\t\tif (double_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+\t\tPy_DECREF(tmp);
+\t}
+\t{
+\t\tPyObject* err = PyErr_Occurred();
+\t\tif (err==NULL) err = #modulename#_error;
+\t\tPyErr_SetString(err,errmess);
+\t}
+\treturn 0;
+}
+"""
+needs['float_from_pyobj']=['double_from_pyobj']
+cfuncs['float_from_pyobj']="""\
+static int float_from_pyobj(float* v,PyObject *obj,const char *errmess) {
+\tdouble d=0.0;
+\tif (double_from_pyobj(&d,obj,errmess)) {
+\t\t*v = (float)d;
+\t\treturn 1;
+\t}
+\treturn 0;
+}
+"""
+needs['complex_long_double_from_pyobj']=['complex_long_double','long_double',
+ 'complex_double_from_pyobj']
+cfuncs['complex_long_double_from_pyobj']="""\
+static int complex_long_double_from_pyobj(complex_long_double* v,PyObject *obj,const char *errmess) {
+\tcomplex_double cd={0.0,0.0};
+\tif (PyArray_CheckScalar(obj)){
+\t\tif PyArray_IsScalar(obj, CLongDouble) {
+\t\t\tPyArray_ScalarAsCtype(obj, v);
+\t\t\treturn 1;
+\t\t}
+\t\telse if (PyArray_Check(obj) && PyArray_TYPE(obj)==PyArray_CLONGDOUBLE) {
+\t\t\t(*v).r = ((clongdouble *)PyArray_DATA(obj))->real;
+\t\t\t(*v).i = ((clongdouble *)PyArray_DATA(obj))->imag;
+\t\t\treturn 1;
+\t\t}
+\t}
+\tif (complex_double_from_pyobj(&cd,obj,errmess)) {
+\t\t(*v).r = (long_double)cd.r;
+\t\t(*v).i = (long_double)cd.i;
+\t\treturn 1;
+\t}
+\treturn 0;
+}
+"""
+needs['complex_double_from_pyobj']=['complex_double']
+cfuncs['complex_double_from_pyobj']="""\
+static int complex_double_from_pyobj(complex_double* v,PyObject *obj,const char *errmess) {
+\tPy_complex c;
+\tif (PyComplex_Check(obj)) {
+\t\tc=PyComplex_AsCComplex(obj);
+\t\t(*v).r=c.real, (*v).i=c.imag;
+\t\treturn 1;
+\t}
+\tif (PyArray_IsScalar(obj, ComplexFloating)) {
+\t\tif (PyArray_IsScalar(obj, CFloat)) {
+\t\t\tcfloat new;
+\t\t\tPyArray_ScalarAsCtype(obj, &new);
+\t\t\t(*v).r = (double)new.real;
+\t\t\t(*v).i = (double)new.imag;
+\t\t}
+\t\telse if (PyArray_IsScalar(obj, CLongDouble)) {
+\t\t\tclongdouble new;
+\t\t\tPyArray_ScalarAsCtype(obj, &new);
+\t\t\t(*v).r = (double)new.real;
+\t\t\t(*v).i = (double)new.imag;
+\t\t}
+\t\telse { /* if (PyArray_IsScalar(obj, CDouble)) */
+\t\t\tPyArray_ScalarAsCtype(obj, v);
+\t\t}
+\t\treturn 1;
+\t}
+\tif (PyArray_CheckScalar(obj)) { /* 0-dim array or still array scalar */
+\t\tPyObject *arr;
+\t\tif (PyArray_Check(obj)) {
+\t\t\tarr = PyArray_Cast((PyArrayObject *)obj, PyArray_CDOUBLE);
+\t\t}
+\t\telse {
+\t\t\tarr = PyArray_FromScalar(obj, PyArray_DescrFromType(PyArray_CDOUBLE));
+\t\t}
+\t\tif (arr==NULL) return 0;
+\t\t(*v).r = ((cdouble *)PyArray_DATA(arr))->real;
+\t\t(*v).i = ((cdouble *)PyArray_DATA(arr))->imag;
+\t\treturn 1;
+\t}
+\t/* Python does not provide PyNumber_Complex function :-( */
+\t(*v).i=0.0;
+\tif (PyFloat_Check(obj)) {
+#ifdef __sgi
+\t\t(*v).r = PyFloat_AsDouble(obj);
+#else
+\t\t(*v).r = PyFloat_AS_DOUBLE(obj);
+#endif
+\t\treturn 1;
+\t}
+\tif (PyInt_Check(obj)) {
+\t\t(*v).r = (double)PyInt_AS_LONG(obj);
+\t\treturn 1;
+\t}
+\tif (PyLong_Check(obj)) {
+\t\t(*v).r = PyLong_AsDouble(obj);
+\t\treturn (!PyErr_Occurred());
+\t}
+\tif (PySequence_Check(obj) && (!PyString_Check(obj))) {
+\t\tPyObject *tmp = PySequence_GetItem(obj,0);
+\t\tif (tmp) {
+\t\t\tif (complex_double_from_pyobj(v,tmp,errmess)) {
+\t\t\t\tPy_DECREF(tmp);
+\t\t\t\treturn 1;
+\t\t\t}
+\t\t\tPy_DECREF(tmp);
+\t\t}
+\t}
+\t{
+\t\tPyObject* err = PyErr_Occurred();
+\t\tif (err==NULL)
+\t\t\terr = PyExc_TypeError;
+\t\tPyErr_SetString(err,errmess);
+\t}
+\treturn 0;
+}
+"""
+needs['complex_float_from_pyobj']=['complex_float','complex_double_from_pyobj']
+cfuncs['complex_float_from_pyobj']="""\
+static int complex_float_from_pyobj(complex_float* v,PyObject *obj,const char *errmess) {
+\tcomplex_double cd={0.0,0.0};
+\tif (complex_double_from_pyobj(&cd,obj,errmess)) {
+\t\t(*v).r = (float)cd.r;
+\t\t(*v).i = (float)cd.i;
+\t\treturn 1;
+\t}
+\treturn 0;
+}
+"""
+needs['try_pyarr_from_char']=['pyobj_from_char1','TRYPYARRAYTEMPLATE']
+cfuncs['try_pyarr_from_char']='static int try_pyarr_from_char(PyObject* obj,char* v) {\n\tTRYPYARRAYTEMPLATE(char,\'c\');\n}\n'
+needs['try_pyarr_from_signed_char']=['TRYPYARRAYTEMPLATE','unsigned_char']
+cfuncs['try_pyarr_from_unsigned_char']='static int try_pyarr_from_unsigned_char(PyObject* obj,unsigned_char* v) {\n\tTRYPYARRAYTEMPLATE(unsigned_char,\'b\');\n}\n'
+needs['try_pyarr_from_signed_char']=['TRYPYARRAYTEMPLATE','signed_char']
+cfuncs['try_pyarr_from_signed_char']='static int try_pyarr_from_signed_char(PyObject* obj,signed_char* v) {\n\tTRYPYARRAYTEMPLATE(signed_char,\'1\');\n}\n'
+needs['try_pyarr_from_short']=['pyobj_from_short1','TRYPYARRAYTEMPLATE']
+cfuncs['try_pyarr_from_short']='static int try_pyarr_from_short(PyObject* obj,short* v) {\n\tTRYPYARRAYTEMPLATE(short,\'s\');\n}\n'
+needs['try_pyarr_from_int']=['pyobj_from_int1','TRYPYARRAYTEMPLATE']
+cfuncs['try_pyarr_from_int']='static int try_pyarr_from_int(PyObject* obj,int* v) {\n\tTRYPYARRAYTEMPLATE(int,\'i\');\n}\n'
+needs['try_pyarr_from_long']=['pyobj_from_long1','TRYPYARRAYTEMPLATE']
+cfuncs['try_pyarr_from_long']='static int try_pyarr_from_long(PyObject* obj,long* v) {\n\tTRYPYARRAYTEMPLATE(long,\'l\');\n}\n'
+needs['try_pyarr_from_long_long']=['pyobj_from_long_long1','TRYPYARRAYTEMPLATE','long_long']
+cfuncs['try_pyarr_from_long_long']='static int try_pyarr_from_long_long(PyObject* obj,long_long* v) {\n\tTRYPYARRAYTEMPLATE(long_long,\'L\');\n}\n'
+needs['try_pyarr_from_float']=['pyobj_from_float1','TRYPYARRAYTEMPLATE']
+cfuncs['try_pyarr_from_float']='static int try_pyarr_from_float(PyObject* obj,float* v) {\n\tTRYPYARRAYTEMPLATE(float,\'f\');\n}\n'
+needs['try_pyarr_from_double']=['pyobj_from_double1','TRYPYARRAYTEMPLATE']
+cfuncs['try_pyarr_from_double']='static int try_pyarr_from_double(PyObject* obj,double* v) {\n\tTRYPYARRAYTEMPLATE(double,\'d\');\n}\n'
+needs['try_pyarr_from_complex_float']=['pyobj_from_complex_float1','TRYCOMPLEXPYARRAYTEMPLATE','complex_float']
+cfuncs['try_pyarr_from_complex_float']='static int try_pyarr_from_complex_float(PyObject* obj,complex_float* v) {\n\tTRYCOMPLEXPYARRAYTEMPLATE(float,\'F\');\n}\n'
+needs['try_pyarr_from_complex_double']=['pyobj_from_complex_double1','TRYCOMPLEXPYARRAYTEMPLATE','complex_double']
+cfuncs['try_pyarr_from_complex_double']='static int try_pyarr_from_complex_double(PyObject* obj,complex_double* v) {\n\tTRYCOMPLEXPYARRAYTEMPLATE(double,\'D\');\n}\n'
+
+needs['create_cb_arglist']=['CFUNCSMESS','PRINTPYOBJERR','MINMAX']
+cfuncs['create_cb_arglist']="""\
+static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofargs,const int nofoptargs,int *nofargs,PyTupleObject **args,const char *errmess) {
+\tPyObject *tmp = NULL;
+\tPyObject *tmp_fun = NULL;
+\tint tot,opt,ext,siz,i,di=0;
+\tCFUNCSMESS(\"create_cb_arglist\\n\");
+\ttot=opt=ext=siz=0;
+\t/* Get the total number of arguments */
+\tif (PyFunction_Check(fun))
+\t\ttmp_fun = fun;
+\telse {
+\t\tdi = 1;
+\t\tif (PyObject_HasAttrString(fun,\"im_func\")) {
+\t\t\ttmp_fun = PyObject_GetAttrString(fun,\"im_func\");
+\t\t}
+\t\telse if (PyObject_HasAttrString(fun,\"__call__\")) {
+\t\t\ttmp = PyObject_GetAttrString(fun,\"__call__\");
+\t\t\tif (PyObject_HasAttrString(tmp,\"im_func\"))
+\t\t\t\ttmp_fun = PyObject_GetAttrString(tmp,\"im_func\");
+\t\t\telse {
+\t\t\t\ttmp_fun = fun; /* built-in function */
+\t\t\t\ttot = maxnofargs;
+\t\t\t\tif (xa != NULL)
+\t\t\t\t\ttot += PyTuple_Size((PyObject *)xa);
+\t\t\t}
+\t\t\tPy_XDECREF(tmp);
+\t\t}
+\t\telse if (PyFortran_Check(fun) || PyFortran_Check1(fun)) {
+\t\t\ttot = maxnofargs;
+\t\t\tif (xa != NULL)
+\t\t\t\ttot += PyTuple_Size((PyObject *)xa);
+\t\t\ttmp_fun = fun;
+\t\t}
+\t\telse if (PyCObject_Check(fun)) {
+\t\t\ttot = maxnofargs;
+\t\t\tif (xa != NULL)
+\t\t\t\text = PyTuple_Size((PyObject *)xa);
+\t\t\tif(ext>0) {
+\t\t\t\tfprintf(stderr,\"extra arguments tuple cannot be used with CObject call-back\\n\");
+\t\t\t\tgoto capi_fail;
+\t\t\t}
+\t\t\ttmp_fun = fun;
+\t\t}
+\t}
+if (tmp_fun==NULL) {
+fprintf(stderr,\"Call-back argument must be function|instance|instance.__call__|f2py-function but got %s.\\n\",(fun==NULL?\"NULL\":fun->ob_type->tp_name));
+goto capi_fail;
+}
+\tif (PyObject_HasAttrString(tmp_fun,\"func_code\")) {
+\t\tif (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"func_code\"),\"co_argcount\"))
+\t\t\ttot = PyInt_AsLong(PyObject_GetAttrString(tmp,\"co_argcount\")) - di;
+\t\tPy_XDECREF(tmp);
+\t}
+\t/* Get the number of optional arguments */
+\tif (PyObject_HasAttrString(tmp_fun,\"func_defaults\"))
+\t\tif (PyTuple_Check(tmp = PyObject_GetAttrString(tmp_fun,\"func_defaults\")))
+\t\t\topt = PyTuple_Size(tmp);
+\t\tPy_XDECREF(tmp);
+\t/* Get the number of extra arguments */
+\tif (xa != NULL)
+\t\text = PyTuple_Size((PyObject *)xa);
+\t/* Calculate the size of call-backs argument list */
+\tsiz = MIN(maxnofargs+ext,tot);
+\t*nofargs = MAX(0,siz-ext);
+#ifdef DEBUGCFUNCS
+\tfprintf(stderr,\"debug-capi:create_cb_arglist:maxnofargs(-nofoptargs),tot,opt,ext,siz,nofargs=%d(-%d),%d,%d,%d,%d,%d\\n\",maxnofargs,nofoptargs,tot,opt,ext,siz,*nofargs);
+#endif
+\tif (siz<tot-opt) {
+\t\tfprintf(stderr,\"create_cb_arglist: Failed to build argument list (siz) with enough arguments (tot-opt) required by user-supplied function (siz,tot,opt=%d,%d,%d).\\n\",siz,tot,opt);
+\t\tgoto capi_fail;
+\t}
+\t/* Initialize argument list */
+\t*args = (PyTupleObject *)PyTuple_New(siz);
+\tfor (i=0;i<*nofargs;i++) {
+\t\tPy_INCREF(Py_None);
+\t\tPyTuple_SET_ITEM((PyObject *)(*args),i,Py_None);
+\t}
+\tif (xa != NULL)
+\t\tfor (i=(*nofargs);i<siz;i++) {
+\t\t\ttmp = PyTuple_GetItem((PyObject *)xa,i-(*nofargs));
+\t\t\tPy_INCREF(tmp);
+\t\t\tPyTuple_SET_ITEM(*args,i,tmp);
+\t\t}
+\tCFUNCSMESS(\"create_cb_arglist-end\\n\");
+\treturn 1;
+capi_fail:
+\tif ((PyErr_Occurred())==NULL)
+\t\tPyErr_SetString(#modulename#_error,errmess);
+\treturn 0;
+}
+"""
+
+def buildcfuncs():
+ from capi_maps import c2capi_map
+ for k in c2capi_map.keys():
+ m='pyarr_from_p_%s1'%k
+ cppmacros[m]='#define %s(v) (PyArray_SimpleNewFromData(0,NULL,%s,(char *)v))'%(m,c2capi_map[k])
+ k='string'
+ m='pyarr_from_p_%s1'%k
+ cppmacros[m]='#define %s(v,dims) (PyArray_SimpleNewFromData(1,dims,PyArray_CHAR,(char *)v))'%(m)
+
+
+############ Auxiliary functions for sorting needs ###################
+
+def append_needs(need,flag=1):
+ global outneeds,needs
+ if type(need)==types.ListType:
+ for n in need:
+ append_needs(n,flag)
+ elif type(need)==types.StringType:
+ if not need: return
+ if includes0.has_key(need): n = 'includes0'
+ elif includes.has_key(need): n = 'includes'
+ elif typedefs.has_key(need): n = 'typedefs'
+ elif typedefs_generated.has_key(need): n = 'typedefs_generated'
+ elif cppmacros.has_key(need): n = 'cppmacros'
+ elif cfuncs.has_key(need): n = 'cfuncs'
+ elif callbacks.has_key(need): n = 'callbacks'
+ elif f90modhooks.has_key(need): n = 'f90modhooks'
+ elif commonhooks.has_key(need): n = 'commonhooks'
+ else:
+ errmess('append_needs: unknown need %s\n'%(`need`))
+ return
+ if need in outneeds[n]: return
+ if flag:
+ tmp={}
+ if needs.has_key(need):
+ for nn in needs[need]:
+ t=append_needs(nn,0)
+ if type(t)==types.DictType:
+ for nnn in t.keys():
+ if tmp.has_key(nnn): tmp[nnn]=tmp[nnn]+t[nnn]
+ else: tmp[nnn]=t[nnn]
+ for nn in tmp.keys():
+ for nnn in tmp[nn]:
+ if nnn not in outneeds[nn]:
+ outneeds[nn]=[nnn]+outneeds[nn]
+ outneeds[n].append(need)
+ else:
+ tmp={}
+ if needs.has_key(need):
+ for nn in needs[need]:
+ t=append_needs(nn,flag)
+ if type(t)==types.DictType:
+ for nnn in t.keys():
+ if tmp.has_key(nnn): tmp[nnn]=t[nnn]+tmp[nnn]
+ else: tmp[nnn]=t[nnn]
+ if not tmp.has_key(n): tmp[n]=[]
+ tmp[n].append(need)
+ return tmp
+ else:
+ errmess('append_needs: expected list or string but got :%s\n'%(`need`))
+
+def get_needs():
+ global outneeds,needs
+ res={}
+ for n in outneeds.keys():
+ out=[]
+ saveout=copy.copy(outneeds[n])
+ while len(outneeds[n])>0:
+ if not needs.has_key(outneeds[n][0]):
+ out.append(outneeds[n][0])
+ del outneeds[n][0]
+ else:
+ flag=0
+ for k in outneeds[n][1:]:
+ if k in needs[outneeds[n][0]]:
+ flag=1
+ break
+ if flag:
+ outneeds[n]=outneeds[n][1:]+[outneeds[n][0]]
+ else:
+ out.append(outneeds[n][0])
+ del outneeds[n][0]
+ if saveout and (0 not in map(lambda x,y:x==y,saveout,outneeds[n])):
+ print n,saveout
+ errmess('get_needs: no progress in sorting needs, probably circular dependence, skipping.\n')
+ out=out+saveout
+ break
+ saveout=copy.copy(outneeds[n])
+ if out==[]: out=[n]
+ res[n]=out
+ return res
diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py
new file mode 100644
index 000000000..e7b4decca
--- /dev/null
+++ b/numpy/f2py/common_rules.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+"""
+
+Build common block mechanism for f2py2e.
+
+Copyright 2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 10:57:33 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.19 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+import pprint
+import sys,string,time,types,copy
+errmess=sys.stderr.write
+outmess=sys.stdout.write
+show=pprint.pprint
+
+from auxfuncs import *
+import capi_maps
+import cfuncs
+import func2subr
+from crackfortran import rmbadname
+##############
+
+def findcommonblocks(block,top=1):
+ ret = []
+ if hascommon(block):
+ for n in block['common'].keys():
+ vars={}
+ for v in block['common'][n]:
+ vars[v]=block['vars'][v]
+ ret.append((n,block['common'][n],vars))
+ elif hasbody(block):
+ for b in block['body']:
+ ret=ret+findcommonblocks(b,0)
+ if top:
+ tret=[]
+ names=[]
+ for t in ret:
+ if t[0] not in names:
+ names.append(t[0])
+ tret.append(t)
+ return tret
+ return ret
+
+def buildhooks(m):
+ ret = {'commonhooks':[],'initcommonhooks':[],'docs':['"COMMON blocks:\\n"']}
+ fwrap = ['']
+ def fadd(line,s=fwrap): s[0] = '%s\n %s'%(s[0],line)
+ chooks = ['']
+ def cadd(line,s=chooks): s[0] = '%s\n%s'%(s[0],line)
+ ihooks = ['']
+ def iadd(line,s=ihooks): s[0] = '%s\n%s'%(s[0],line)
+ doc = ['']
+ def dadd(line,s=doc): s[0] = '%s\n%s'%(s[0],line)
+ for (name,vnames,vars) in findcommonblocks(m):
+ lower_name = string.lower(name)
+ hnames,inames = [],[]
+ for n in vnames:
+ if isintent_hide(vars[n]): hnames.append(n)
+ else: inames.append(n)
+ if hnames:
+ outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n\t\t Hidden: %s\n'%(name,string.join(inames,','),string.join(hnames,',')))
+ else:
+ outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n'%(name,string.join(inames,',')))
+ fadd('subroutine f2pyinit%s(setupfunc)'%name)
+ fadd('external setupfunc')
+ for n in vnames:
+ fadd(func2subr.var2fixfortran(vars,n))
+ if name=='_BLNK_':
+ fadd('common %s'%(string.join(vnames,',')))
+ else:
+ fadd('common /%s/ %s'%(name,string.join(vnames,',')))
+ fadd('call setupfunc(%s)'%(string.join(inames,',')))
+ fadd('end\n')
+ cadd('static FortranDataDef f2py_%s_def[] = {'%(name))
+ idims=[]
+ for n in inames:
+ ct = capi_maps.getctype(vars[n])
+ at = capi_maps.c2capi_map[ct]
+ dm = capi_maps.getarrdims(n,vars[n])
+ if dm['dims']: idims.append('(%s)'%(dm['dims']))
+ else: idims.append('')
+ dms=string.strip(dm['dims'])
+ if not dms: dms='-1'
+ cadd('\t{\"%s\",%s,{{%s}},%s},'%(n,dm['rank'],dms,at))
+ cadd('\t{NULL}\n};')
+ inames1 = rmbadname(inames)
+ inames1_tps = string.join(map(lambda s:'char *'+s,inames1),',')
+ cadd('static void f2py_setup_%s(%s) {'%(name,inames1_tps))
+ cadd('\tint i_f2py=0;')
+ for n in inames1:
+ cadd('\tf2py_%s_def[i_f2py++].data = %s;'%(name,n))
+ cadd('}')
+ if '_' in lower_name:
+ F_FUNC='F_FUNC_US'
+ else:
+ F_FUNC='F_FUNC'
+ cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'\
+ %(F_FUNC,lower_name,string.upper(name),
+ string.join(['char*']*len(inames1),',')))
+ cadd('static void f2py_init_%s(void) {'%name)
+ cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'\
+ %(F_FUNC,lower_name,string.upper(name),name))
+ cadd('}\n')
+ iadd('\tPyDict_SetItemString(d, \"%s\", PyFortranObject_New(f2py_%s_def,f2py_init_%s));'%(name,name,name))
+ tname = string.replace(name,'_','\\_')
+ dadd('\\subsection{Common block \\texttt{%s}}\n'%(tname))
+ dadd('\\begin{description}')
+ for n in inames:
+ dadd('\\item[]{{}\\verb@%s@{}}'%(capi_maps.getarrdocsign(n,vars[n])))
+ if hasnote(vars[n]):
+ note = vars[n]['note']
+ if type(note) is type([]): note=string.join(note,'\n')
+ dadd('--- %s'%(note))
+ dadd('\\end{description}')
+ ret['docs'].append('"\t/%s/ %s\\n"'%(name,string.join(map(lambda v,d:v+d,inames,idims),',')))
+ ret['commonhooks']=chooks
+ ret['initcommonhooks']=ihooks
+ ret['latexdoc']=doc[0]
+ if len(ret['docs'])<=1: ret['docs']=''
+ return ret,fwrap[0]
+
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
new file mode 100755
index 000000000..2a91709bc
--- /dev/null
+++ b/numpy/f2py/crackfortran.py
@@ -0,0 +1,2659 @@
+#!/usr/bin/env python
+"""
+crackfortran --- read fortran (77,90) code and extract declaration information.
+ Usage is explained in the comment block below.
+
+Copyright 1999-2004 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/09/27 07:13:49 $
+Pearu Peterson
+"""
+__version__ = "$Revision: 1.177 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+"""
+ Usage of crackfortran:
+ ======================
+ Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h <pyffilename>
+ -m <module name for f77 routines>,--ignore-contains
+ Functions: crackfortran, crack2fortran
+ The following Fortran statements/constructions are supported
+ (or will be if needed):
+ block data,byte,call,character,common,complex,contains,data,
+ dimension,double complex,double precision,end,external,function,
+ implicit,integer,intent,interface,intrinsic,
+ logical,module,optional,parameter,private,public,
+ program,real,(sequence?),subroutine,type,use,virtual,
+ include,pythonmodule
+ Note: 'virtual' is mapped to 'dimension'.
+ Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug).
+ Note: code after 'contains' will be ignored until its scope ends.
+ Note: 'common' statement is extended: dimensions are moved to variable definitions
+ Note: f2py directive: <commentchar>f2py<line> is read as <line>
+ Note: pythonmodule is introduced to represent Python module
+
+ Usage:
+ `postlist=crackfortran(files,funcs)`
+ `postlist` contains declaration information read from the list of files `files`.
+ `crack2fortran(postlist)` returns a fortran code to be saved to pyf-file
+
+ `postlist` has the following structure:
+ *** it is a list of dictionaries containing `blocks':
+ B = {'block','body','vars','parent_block'[,'name','prefix','args','result',
+ 'implicit','externals','interfaced','common','sortvars',
+ 'commonvars','note']}
+ B['block'] = 'interface' | 'function' | 'subroutine' | 'module' |
+ 'program' | 'block data' | 'type' | 'pythonmodule'
+ B['body'] --- list containing `subblocks' with the same structure as `blocks'
+ B['parent_block'] --- dictionary of a parent block:
+ C['body'][<index>]['parent_block'] is C
+ B['vars'] --- dictionary of variable definitions
+ B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first)
+ B['name'] --- name of the block (not if B['block']=='interface')
+ B['prefix'] --- prefix string (only if B['block']=='function')
+ B['args'] --- list of argument names if B['block']== 'function' | 'subroutine'
+ B['result'] --- name of the return value (only if B['block']=='function')
+ B['implicit'] --- dictionary {'a':<variable definition>,'b':...} | None
+ B['externals'] --- list of variables being external
+ B['interfaced'] --- list of variables being external and defined
+ B['common'] --- dictionary of common blocks (list of objects)
+ B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions)
+ B['from'] --- string showing the 'parents' of the current block
+ B['use'] --- dictionary of modules used in current block:
+ {<modulename>:{['only':<0|1>],['map':{<local_name1>:<use_name1>,...}]}}
+ B['note'] --- list of LaTeX comments on the block
+ B['f2pyenhancements'] --- optional dictionary
+ {'threadsafe':'','fortranname':<name>,
+ 'callstatement':<C-expr>|<multi-line block>,
+ 'callprotoargument':<C-expr-list>,
+ 'usercode':<multi-line block>|<list of multi-line blocks>,
+ 'pymethoddef:<multi-line block>'
+ }
+ B['entry'] --- dictionary {entryname:argslist,..}
+ B['varnames'] --- list of variable names given in the order of reading the
+ Fortran code, useful for derived types.
+ *** Variable definition is a dictionary
+ D = B['vars'][<variable name>] =
+ {'typespec'[,'attrspec','kindselector','charselector','=','typename']}
+ D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' |
+ 'double precision' | 'integer' | 'logical' | 'real' | 'type'
+ D['attrspec'] --- list of attributes (e.g. 'dimension(<arrayspec>)',
+ 'external','intent(in|out|inout|hide|c|callback|cache)',
+ 'optional','required', etc)
+ K = D['kindselector'] = {['*','kind']} (only if D['typespec'] =
+ 'complex' | 'integer' | 'logical' | 'real' )
+ C = D['charselector'] = {['*','len','kind']}
+ (only if D['typespec']=='character')
+ D['='] --- initialization expression string
+ D['typename'] --- name of the type if D['typespec']=='type'
+ D['dimension'] --- list of dimension bounds
+ D['intent'] --- list of intent specifications
+ D['depend'] --- list of variable names on which current variable depends on
+ D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised
+ D['note'] --- list of LaTeX comments on the variable
+ *** Meaning of kind/char selectors (few examples):
+ D['typespec>']*K['*']
+ D['typespec'](kind=K['kind'])
+ character*C['*']
+ character(len=C['len'],kind=C['kind'])
+ (see also fortran type declaration statement formats below)
+
+ Fortran 90 type declaration statement format (F77 is subset of F90)
+====================================================================
+ (Main source: IBM XL Fortran 5.1 Language Reference Manual)
+ type declaration = <typespec> [[<attrspec>]::] <entitydecl>
+ <typespec> = byte |
+ character[<charselector>] |
+ complex[<kindselector>] |
+ double complex |
+ double precision |
+ integer[<kindselector>] |
+ logical[<kindselector>] |
+ real[<kindselector>] |
+ type(<typename>)
+ <charselector> = * <charlen> |
+ ([len=]<len>[,[kind=]<kind>]) |
+ (kind=<kind>[,len=<len>])
+ <kindselector> = * <intlen> |
+ ([kind=]<kind>)
+ <attrspec> = comma separated list of attributes.
+ Only the following attributes are used in
+ building up the interface:
+ external
+ (parameter --- affects '=' key)
+ optional
+ intent
+ Other attributes are ignored.
+ <intentspec> = in | out | inout
+ <arrayspec> = comma separated list of dimension bounds.
+ <entitydecl> = <name> [[*<charlen>][(<arrayspec>)] | [(<arrayspec>)]*<charlen>]
+ [/<init_expr>/ | =<init_expr>] [,<entitydecl>]
+
+ In addition, the following attributes are used: check,depend,note
+
+ TODO:
+ * Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)'
+ -> 'real x(2)')
+ The above may be solved by creating appropriate preprocessor program, for example.
+"""
+#
+import sys,string,fileinput,re,pprint,os,copy
+from auxfuncs import *
+
+# Global flags:
+strictf77=1 # Ignore `!' comments unless line[0]=='!'
+sourcecodeform='fix' # 'fix','free'
+quiet=0 # Be verbose if 0 (Obsolete: not used any more)
+verbose=1 # Be quiet if 0, extra verbose if > 1.
+tabchar=4*' '
+pyffilename=''
+f77modulename=''
+skipemptyends=0 # for old F77 programs without 'program' statement
+ignorecontains=1
+dolowercase=1
+debug=[]
+## do_analyze = 1
+
+###### global variables
+
+## use reload(crackfortran) to reset these variables
+
+groupcounter=0
+grouplist={groupcounter:[]}
+neededmodule=-1
+expectbegin=1
+skipblocksuntil=-1
+usermodules=[]
+f90modulevars={}
+gotnextfile=1
+filepositiontext=''
+currentfilename=''
+skipfunctions=[]
+skipfuncs=[]
+onlyfuncs=[]
+include_paths=[]
+previous_context = None
+
+###### Some helper functions
+def show(o,f=0):pprint.pprint(o)
+errmess=sys.stderr.write
+def outmess(line,flag=1):
+ global filepositiontext
+ if not verbose: return
+ if not quiet:
+ if flag:sys.stdout.write(filepositiontext)
+ sys.stdout.write(line)
+re._MAXCACHE=50
+defaultimplicitrules={}
+for c in "abcdefghopqrstuvwxyz$_": defaultimplicitrules[c]={'typespec':'real'}
+for c in "ijklmn": defaultimplicitrules[c]={'typespec':'integer'}
+del c
+badnames={}
+invbadnames={}
+for n in ['int','double','float','char','short','long','void','case','while',
+ 'return','signed','unsigned','if','for','typedef','sizeof','union',
+ 'struct','static','register','new','break','do','goto','switch',
+ 'continue','else','inline','extern','delete','const','auto',
+ 'len','rank','shape','index','slen','size','_i',
+ 'flen','fshape',
+ 'string','complex_double','float_double','stdin','stderr','stdout',
+ 'type','default']:
+ badnames[n]=n+'_bn'
+ invbadnames[n+'_bn']=n
+def rmbadname1(name):
+ if badnames.has_key(name):
+ errmess('rmbadname1: Replacing "%s" with "%s".\n'%(name,badnames[name]))
+ return badnames[name]
+ return name
+def rmbadname(names): return map(rmbadname1,names)
+
+def undo_rmbadname1(name):
+ if invbadnames.has_key(name):
+ errmess('undo_rmbadname1: Replacing "%s" with "%s".\n'\
+ %(name,invbadnames[name]))
+ return invbadnames[name]
+ return name
+def undo_rmbadname(names): return map(undo_rmbadname1,names)
+
+def getextension(name):
+ i=string.rfind(name,'.')
+ if i==-1: return ''
+ if '\\' in name[i:]: return ''
+ if '/' in name[i:]: return ''
+ return name[i+1:]
+
+is_f_file = re.compile(r'.*[.](for|ftn|f77|f)\Z',re.I).match
+_has_f_header = re.compile(r'-[*]-\s*fortran\s*-[*]-',re.I).search
+_has_f90_header = re.compile(r'-[*]-\s*f90\s*-[*]-',re.I).search
+_has_fix_header = re.compile(r'-[*]-\s*fix\s*-[*]-',re.I).search
+_free_f90_start = re.compile(r'[^c*]\s*[^\s\d\t]',re.I).match
+def is_free_format(file):
+ """Check if file is in free format Fortran."""
+ # f90 allows both fixed and free format, assuming fixed unless
+ # signs of free format are detected.
+ result = 0
+ f = open(file,'r')
+ line = f.readline()
+ n = 15 # the number of non-comment lines to scan for hints
+ if _has_f_header(line):
+ n = 0
+ elif _has_f90_header(line):
+ n = 0
+ result = 1
+ while n>0 and line:
+ if line[0]!='!':
+ n -= 1
+ if (line[0]!='\t' and _free_f90_start(line[:5])) or line[-2:-1]=='&':
+ result = 1
+ break
+ line = f.readline()
+ f.close()
+ return result
+
+
+####### Read fortran (77,90) code
+def readfortrancode(ffile,dowithline=show,istop=1):
+ """
+ Read fortran codes from files and
+ 1) Get rid of comments, line continuations, and empty lines; lower cases.
+ 2) Call dowithline(line) on every line.
+ 3) Recursively call itself when statement \"include '<filename>'\" is met.
+ """
+ global gotnextfile,filepositiontext,currentfilename,sourcecodeform,strictf77,\
+ beginpattern,quiet,verbose,dolowercase,include_paths
+ if not istop:
+ saveglobals=gotnextfile,filepositiontext,currentfilename,sourcecodeform,strictf77,\
+ beginpattern,quiet,verbose,dolowercase
+ if ffile==[]: return
+ localdolowercase = dolowercase
+ cont=0
+ finalline=''
+ ll=''
+ commentline=re.compile(r'(?P<line>([^"]*"[^"]*"[^"!]*|[^\']*\'[^\']*\'[^\'!]*|[^!]*))!{1}(?P<rest>.*)')
+ includeline=re.compile(r'\s*include\s*(\'|")(?P<name>[^\'"]*)(\'|")',re.I)
+ cont1=re.compile(r'(?P<line>.*)&\s*\Z')
+ cont2=re.compile(r'(\s*&|)(?P<line>.*)')
+ mline_mark = re.compile(r".*?'''")
+ if istop: dowithline('',-1)
+ ll,l1='',''
+ spacedigits=[' ']+map(str,range(10))
+ filepositiontext=''
+ fin=fileinput.FileInput(ffile)
+ while 1:
+ l=fin.readline()
+ if not l: break
+ if fin.isfirstline():
+ filepositiontext=''
+ currentfilename=fin.filename()
+ gotnextfile=1
+ l1=l
+ strictf77=0
+ sourcecodeform='fix'
+ ext = os.path.splitext(currentfilename)[1]
+ if is_f_file(currentfilename) and \
+ not (_has_f90_header(l) or _has_fix_header(l)):
+ strictf77=1
+ elif is_free_format(currentfilename) and not _has_fix_header(l):
+ sourcecodeform='free'
+ if strictf77: beginpattern=beginpattern77
+ else: beginpattern=beginpattern90
+ outmess('\tReading file %s (format:%s%s)\n'\
+ %(`currentfilename`,sourcecodeform,
+ strictf77 and ',strict' or ''))
+
+ l=string.expandtabs(l).replace('\xa0',' ')
+ while not l=='': # Get rid of newline characters
+ if l[-1] not in "\n\r\f": break
+ l=l[:-1]
+ if not strictf77:
+ r=commentline.match(l)
+ if r:
+ l=r.group('line')+' ' # Strip comments starting with `!'
+ rl=r.group('rest')
+ if string.lower(rl[:4])=='f2py': # f2py directive
+ l = l + 4*' '
+ r=commentline.match(rl[4:])
+ if r: l=l+r('line')
+ else: l = l + rl[4:]
+ if string.strip(l)=='': # Skip empty line
+ cont=0
+ continue
+ if sourcecodeform=='fix':
+ if l[0] in ['*','c','!','C','#']:
+ if string.lower(l[1:5])=='f2py': # f2py directive
+ l=' '+l[5:]
+ else: # Skip comment line
+ cont=0
+ continue
+ elif strictf77:
+ if len(l)>72: l=l[:72]
+ if not (l[0] in spacedigits):
+ raise 'readfortrancode: Found non-(space,digit) char in the first column.\n\tAre you sure that this code is in fix form?\n\tline=%s'%`l`
+
+ if (not cont or strictf77) and (len(l)>5 and not l[5]==' '):
+ # Continuation of a previous line
+ ll=ll+l[6:]
+ finalline=''
+ origfinalline=''
+ else:
+ if not strictf77:
+ # F90 continuation
+ r=cont1.match(l)
+ if r: l=r.group('line') # Continuation follows ..
+ if cont:
+ ll=ll+cont2.match(l).group('line')
+ finalline=''
+ origfinalline=''
+ else:
+ l=' '+l[5:] # clean up line beginning from possible digits.
+ if localdolowercase: finalline=string.lower(ll)
+ else: finalline=ll
+ origfinalline=ll
+ ll=l
+ cont=(r is not None)
+ else:
+ l=' '+l[5:] # clean up line beginning from possible digits.
+ if localdolowercase: finalline=string.lower(ll)
+ else: finalline=ll
+ origfinalline =ll
+ ll=l
+
+ elif sourcecodeform=='free':
+ if not cont and ext=='.pyf' and mline_mark.match(l):
+ l = l + '\n'
+ while 1:
+ lc = fin.readline()
+ if not lc:
+ errmess('Unexpected end of file when reading multiline\n')
+ break
+ l = l + lc
+ if mline_mark.match(lc):
+ break
+ l = l.rstrip()
+ r=cont1.match(l)
+ if r: l=r.group('line') # Continuation follows ..
+ if cont:
+ ll=ll+cont2.match(l).group('line')
+ finalline=''
+ origfinalline=''
+ else:
+ if localdolowercase: finalline=string.lower(ll)
+ else: finalline=ll
+ origfinalline =ll
+ ll=l
+ cont=(r is not None)
+ else:
+ raise ValueError,"Flag sourcecodeform must be either 'fix' or 'free': %s"%`sourcecodeform`
+ filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1,currentfilename,l1)
+ m=includeline.match(origfinalline)
+ if m:
+ fn=m.group('name')
+ if os.path.isfile(fn):
+ readfortrancode(fn,dowithline=dowithline,istop=0)
+ else:
+ include_dirs = [os.path.dirname(currentfilename)] + include_paths
+ foundfile = 0
+ for inc_dir in include_dirs:
+ fn1 = os.path.join(inc_dir,fn)
+ if os.path.isfile(fn1):
+ foundfile = 1
+ readfortrancode(fn1,dowithline=dowithline,istop=0)
+ break
+ if not foundfile:
+ outmess('readfortrancode: could not find include file %s. Ignoring.\n'%(`fn`))
+ else:
+ dowithline(finalline)
+ l1=ll
+ if localdolowercase:
+ finalline=string.lower(ll)
+ else: finalline=ll
+ origfinalline = ll
+ filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1,currentfilename,l1)
+ m=includeline.match(origfinalline)
+ if m:
+ fn=m.group('name')
+ fn1=os.path.join(os.path.dirname(currentfilename),fn)
+ if os.path.isfile(fn):
+ readfortrancode(fn,dowithline=dowithline,istop=0)
+ elif os.path.isfile(fn1):
+ readfortrancode(fn1,dowithline=dowithline,istop=0)
+ else:
+ outmess('readfortrancode: could not find include file %s. Ignoring.\n'%(`fn`))
+ else:
+ dowithline(finalline)
+ filepositiontext=''
+ fin.close()
+ if istop: dowithline('',1)
+ else:
+ gotnextfile,filepositiontext,currentfilename,sourcecodeform,strictf77,\
+ beginpattern,quiet,verbose,dolowercase=saveglobals
+
+########### Crack line
+beforethisafter=r'\s*(?P<before>%s(?=\s*(\b(%s)\b)))'+ \
+ r'\s*(?P<this>(\b(%s)\b))'+ \
+ r'\s*(?P<after>%s)\s*\Z'
+##
+fortrantypes='character|logical|integer|real|complex|double\s*(precision\s*(complex|)|complex)|type(?=\s*\([\w\s,=(*)]*\))|byte'
+typespattern=re.compile(beforethisafter%('',fortrantypes,fortrantypes,'.*'),re.I),'type'
+typespattern4implicit=re.compile(beforethisafter%('',fortrantypes+'|static|automatic|undefined',fortrantypes+'|static|automatic|undefined','.*'),re.I)
+#
+functionpattern=re.compile(beforethisafter%('([a-z]+[\w\s(=*+-/)]*?|)','function','function','.*'),re.I),'begin'
+subroutinepattern=re.compile(beforethisafter%('[a-z\s]*?','subroutine','subroutine','.*'),re.I),'begin'
+#modulepattern=re.compile(beforethisafter%('[a-z\s]*?','module','module','.*'),re.I),'begin'
+#
+groupbegins77=r'program|block\s*data'
+beginpattern77=re.compile(beforethisafter%('',groupbegins77,groupbegins77,'.*'),re.I),'begin'
+groupbegins90=groupbegins77+r'|module|python\s*module|interface|type(?!\s*\()'
+beginpattern90=re.compile(beforethisafter%('',groupbegins90,groupbegins90,'.*'),re.I),'begin'
+groupends=r'end|endprogram|endblockdata|endmodule|endpythonmodule|endinterface'
+endpattern=re.compile(beforethisafter%('',groupends,groupends,'[\w\s]*'),re.I),'end'
+#endifs='end\s*(if|do|where|select|while|forall)'
+endifs='(end\s*(if|do|where|select|while|forall))|(module\s*procedure)'
+endifpattern=re.compile(beforethisafter%('[\w]*?',endifs,endifs,'[\w\s]*'),re.I),'endif'
+#
+implicitpattern=re.compile(beforethisafter%('','implicit','implicit','.*'),re.I),'implicit'
+dimensionpattern=re.compile(beforethisafter%('','dimension|virtual','dimension|virtual','.*'),re.I),'dimension'
+externalpattern=re.compile(beforethisafter%('','external','external','.*'),re.I),'external'
+optionalpattern=re.compile(beforethisafter%('','optional','optional','.*'),re.I),'optional'
+requiredpattern=re.compile(beforethisafter%('','required','required','.*'),re.I),'required'
+publicpattern=re.compile(beforethisafter%('','public','public','.*'),re.I),'public'
+privatepattern=re.compile(beforethisafter%('','private','private','.*'),re.I),'private'
+intrisicpattern=re.compile(beforethisafter%('','intrisic','intrisic','.*'),re.I),'intrisic'
+intentpattern=re.compile(beforethisafter%('','intent|depend|note|check','intent|depend|note|check','\s*\(.*?\).*'),re.I),'intent'
+parameterpattern=re.compile(beforethisafter%('','parameter','parameter','\s*\(.*'),re.I),'parameter'
+datapattern=re.compile(beforethisafter%('','data','data','.*'),re.I),'data'
+callpattern=re.compile(beforethisafter%('','call','call','.*'),re.I),'call'
+entrypattern=re.compile(beforethisafter%('','entry','entry','.*'),re.I),'entry'
+callfunpattern=re.compile(beforethisafter%('','callfun','callfun','.*'),re.I),'callfun'
+commonpattern=re.compile(beforethisafter%('','common','common','.*'),re.I),'common'
+usepattern=re.compile(beforethisafter%('','use','use','.*'),re.I),'use'
+containspattern=re.compile(beforethisafter%('','contains','contains',''),re.I),'contains'
+formatpattern=re.compile(beforethisafter%('','format','format','.*'),re.I),'format'
+## Non-fortran and f2py-specific statements
+f2pyenhancementspattern=re.compile(beforethisafter%('','threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef','threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef','.*'),re.I|re.S),'f2pyenhancements'
+multilinepattern = re.compile(r"\s*(?P<before>''')(?P<this>.*?)(?P<after>''')\s*\Z",re.S),'multiline'
+##
+
+def _simplifyargs(argsline):
+ a = []
+ for n in string.split(markoutercomma(argsline),'@,@'):
+ for r in '(),':
+ n = string.replace(n,r,'_')
+ a.append(n)
+ return string.join(a,',')
+
+crackline_re_1 = re.compile(r'\s*(?P<result>\b[a-z]+[\w]*\b)\s*[=].*',re.I)
+def crackline(line,reset=0):
+ """
+ reset=-1 --- initialize
+ reset=0 --- crack the line
+ reset=1 --- final check if mismatch of blocks occured
+
+ Cracked data is saved in grouplist[0].
+ """
+ global beginpattern,groupcounter,groupname,groupcache,grouplist,gotnextfile,\
+ filepositiontext,currentfilename,neededmodule,expectbegin,skipblocksuntil,\
+ skipemptyends,previous_context
+ if ';' in line and not (f2pyenhancementspattern[0].match(line) or
+ multilinepattern[0].match(line)):
+ for l in line.split(';'):
+ assert reset==0,`reset` # XXX: non-zero reset values need testing
+ crackline(l,reset)
+ return
+ if reset<0:
+ groupcounter=0
+ groupname={groupcounter:''}
+ groupcache={groupcounter:{}}
+ grouplist={groupcounter:[]}
+ groupcache[groupcounter]['body']=[]
+ groupcache[groupcounter]['vars']={}
+ groupcache[groupcounter]['block']=''
+ groupcache[groupcounter]['name']=''
+ neededmodule=-1
+ skipblocksuntil=-1
+ return
+ if reset>0:
+ fl=0
+ if f77modulename and neededmodule==groupcounter: fl=2
+ while groupcounter>fl:
+ outmess('crackline: groupcounter=%s groupname=%s\n'%(`groupcounter`,`groupname`))
+ outmess('crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.\n')
+ grouplist[groupcounter-1].append(groupcache[groupcounter])
+ grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter=groupcounter-1
+ if f77modulename and neededmodule==groupcounter:
+ grouplist[groupcounter-1].append(groupcache[groupcounter])
+ grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter=groupcounter-1 # end interface
+ grouplist[groupcounter-1].append(groupcache[groupcounter])
+ grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter=groupcounter-1 # end module
+ neededmodule=-1
+ return
+ if line=='': return
+ flag=0
+ for pat in [dimensionpattern,externalpattern,intentpattern,optionalpattern,
+ requiredpattern,
+ parameterpattern,datapattern,publicpattern,privatepattern,
+ intrisicpattern,
+ endifpattern,endpattern,
+ formatpattern,
+ beginpattern,functionpattern,subroutinepattern,
+ implicitpattern,typespattern,commonpattern,
+ callpattern,usepattern,containspattern,
+ entrypattern,
+ f2pyenhancementspattern,
+ multilinepattern
+ ]:
+ m = pat[0].match(line)
+ if m:
+ break
+ flag=flag+1
+ if not m:
+ re_1 = crackline_re_1
+ if 0<=skipblocksuntil<=groupcounter:return
+ if groupcache[groupcounter].has_key('externals'):
+ for name in groupcache[groupcounter]['externals']:
+ if invbadnames.has_key(name):
+ name=invbadnames[name]
+ if groupcache[groupcounter].has_key('interfaced') and name in groupcache[groupcounter]['interfaced']: continue
+ m1=re.match(r'(?P<before>[^"]*)\b%s\b\s*@\(@(?P<args>[^@]*)@\)@.*\Z'%name,markouterparen(line),re.I)
+ if m1:
+ m2 = re_1.match(m1.group('before'))
+ a = _simplifyargs(m1.group('args'))
+ if m2:
+ line='callfun %s(%s) result (%s)'%(name,a,m2.group('result'))
+ else: line='callfun %s(%s)'%(name,a)
+ m = callfunpattern[0].match(line)
+ if not m:
+ outmess('crackline: could not resolve function call for line=%s.\n'%`line`)
+ return
+ analyzeline(m,'callfun',line)
+ return
+ if verbose>1:
+ previous_context = None
+ outmess('crackline:%d: No pattern for line\n'%(groupcounter))
+ return
+ elif pat[1]=='end':
+ if 0<=skipblocksuntil<groupcounter:
+ groupcounter=groupcounter-1
+ if skipblocksuntil<=groupcounter: return
+ if groupcounter<=0:
+ raise 'crackline: groupcounter(=%s) is nonpositive. Check the blocks.'\
+ % (groupcounter)
+ m1 = beginpattern[0].match((line))
+ if (m1) and (not m1.group('this')==groupname[groupcounter]):
+ raise 'crackline: End group %s does not match with previous Begin group %s\n\t%s'%(`m1.group('this')`,`groupname[groupcounter]`,filepositiontext)
+ if skipblocksuntil==groupcounter:
+ skipblocksuntil=-1
+ grouplist[groupcounter-1].append(groupcache[groupcounter])
+ grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter=groupcounter-1
+ if not skipemptyends:
+ expectbegin=1
+ elif pat[1] == 'begin':
+ if 0<=skipblocksuntil<=groupcounter:
+ groupcounter=groupcounter+1
+ return
+ gotnextfile=0
+ analyzeline(m,pat[1],line)
+ expectbegin=0
+ elif pat[1]=='endif':
+ pass
+ elif pat[1]=='contains':
+ if ignorecontains: return
+ if 0<=skipblocksuntil<=groupcounter: return
+ skipblocksuntil=groupcounter
+ else:
+ if 0<=skipblocksuntil<=groupcounter:return
+ analyzeline(m,pat[1],line)
+
+def markouterparen(line):
+ l='';f=0
+ for c in line:
+ if c=='(':
+ f=f+1
+ if f==1: l=l+'@(@'; continue
+ elif c==')':
+ f=f-1
+ if f==0: l=l+'@)@'; continue
+ l=l+c
+ return l
+def markoutercomma(line,comma=','):
+ l='';f=0
+ cc=''
+ for c in line:
+ if (not cc or cc==')') and c=='(':
+ f=f+1
+ cc = ')'
+ elif not cc and c=='\'' and (not l or l[-1]!='\\'):
+ f=f+1
+ cc = '\''
+ elif c==cc:
+ f=f-1
+ if f==0:
+ cc=''
+ elif c==comma and f==0:
+ l=l+'@'+comma+'@'
+ continue
+ l=l+c
+ assert not f,`f,line,l,cc`
+ return l
+def unmarkouterparen(line):
+ r = string.replace(string.replace(line,'@(@','('),'@)@',')')
+ return r
+def appenddecl(decl,decl2,force=1):
+ if not decl: decl={}
+ if not decl2: return decl
+ if decl is decl2: return decl
+ for k in decl2.keys():
+ if k=='typespec':
+ if force or not decl.has_key(k): decl[k]=decl2[k]
+ elif k=='attrspec':
+ for l in decl2[k]:
+ decl=setattrspec(decl,l,force)
+ elif k=='kindselector':
+ decl=setkindselector(decl,decl2[k],force)
+ elif k=='charselector':
+ decl=setcharselector(decl,decl2[k],force)
+ elif k in ['=','typename']:
+ if force or not decl.has_key(k): decl[k]=decl2[k]
+ elif k=='note':
+ pass
+ elif k in ['intent','check','dimension','optional','required']:
+ errmess('appenddecl: "%s" not implemented.\n'%k)
+ else:
+ raise 'appenddecl: Unknown variable definition key:', k
+ return decl
+
+selectpattern=re.compile(r'\s*(?P<this>(@\(@.*?@\)@|[*][\d*]+|[*]\s*@\(@.*?@\)@|))(?P<after>.*)\Z',re.I)
+nameargspattern=re.compile(r'\s*(?P<name>\b[\w$]+\b)\s*(@\(@\s*(?P<args>[\w\s,]*)\s*@\)@|)\s*(result(\s*@\(@\s*(?P<result>\b[\w$]+\b)\s*@\)@|))*\s*\Z',re.I)
+callnameargspattern=re.compile(r'\s*(?P<name>\b[\w$]+\b)\s*@\(@\s*(?P<args>.*)\s*@\)@\s*\Z',re.I)
+real16pattern = re.compile(r'([-+]?(?:\d+(?:\.\d*)?|\d*\.\d+))[dD]((?:[-+]?\d+)?)')
+real8pattern = re.compile(r'([-+]?((?:\d+(?:\.\d*)?|\d*\.\d+))[eE]((?:[-+]?\d+)?)|(\d+\.\d*))')
+
+_intentcallbackpattern = re.compile(r'intent\s*\(.*?\bcallback\b',re.I)
+def _is_intent_callback(vdecl):
+ for a in vdecl.get('attrspec',[]):
+ if _intentcallbackpattern.match(a):
+ return 1
+ return 0
+
+def _resolvenameargspattern(line):
+ line = markouterparen(line)
+ m1=nameargspattern.match(line)
+ if m1: return m1.group('name'),m1.group('args'),m1.group('result')
+ m1=callnameargspattern.match(line)
+ if m1: return m1.group('name'),m1.group('args'),None
+ return None,[],None
+
+def analyzeline(m,case,line):
+ global groupcounter,groupname,groupcache,grouplist,filepositiontext,\
+ currentfilename,f77modulename,neededinterface,neededmodule,expectbegin,\
+ gotnextfile,previous_context
+ block=m.group('this')
+ if case != 'multiline':
+ previous_context = None
+ if expectbegin and case not in ['begin','call','callfun','type'] \
+ and not skipemptyends and groupcounter<1:
+ newname=string.split(os.path.basename(currentfilename),'.')[0]
+ outmess('analyzeline: no group yet. Creating program group with name "%s".\n'%newname)
+ gotnextfile=0
+ groupcounter=groupcounter+1
+ groupname[groupcounter]='program'
+ groupcache[groupcounter]={}
+ grouplist[groupcounter]=[]
+ groupcache[groupcounter]['body']=[]
+ groupcache[groupcounter]['vars']={}
+ groupcache[groupcounter]['block']='program'
+ groupcache[groupcounter]['name']=newname
+ groupcache[groupcounter]['from']='fromsky'
+ expectbegin=0
+ if case in ['begin','call','callfun']:
+ # Crack line => block,name,args,result
+ block = block.lower()
+ if re.match(r'block\s*data',block,re.I): block='block data'
+ if re.match(r'python\s*module',block,re.I): block='python module'
+ name,args,result = _resolvenameargspattern(m.group('after'))
+ if name is None:
+ if block=='block data':
+ name = '_BLOCK_DATA_'
+ else:
+ name = ''
+ if block not in ['interface','block data']:
+ outmess('analyzeline: No name/args pattern found for line.\n')
+
+ previous_context = (block,name,groupcounter)
+ if args: args=rmbadname(map(string.strip,string.split(markoutercomma(args),'@,@')))
+ else: args=[]
+ if '' in args:
+ while '' in args:
+ args.remove('')
+ outmess('analyzeline: argument list is malformed (missing argument).\n')
+
+ # end of crack line => block,name,args,result
+ needmodule=0
+ needinterface=0
+
+ if case in ['call','callfun']:
+ needinterface=1
+ if not groupcache[groupcounter].has_key('args'): return
+ if name not in groupcache[groupcounter]['args']:
+ return
+ for it in grouplist[groupcounter]:
+ if it['name']==name: return
+ if name in groupcache[groupcounter]['interfaced']: return
+ block={'call':'subroutine','callfun':'function'}[case]
+ if f77modulename and neededmodule==-1 and groupcounter<=1:
+ neededmodule=groupcounter+2
+ needmodule=1
+ needinterface=1
+ # Create new block(s)
+ groupcounter=groupcounter+1
+ groupcache[groupcounter]={}
+ grouplist[groupcounter]=[]
+ if needmodule:
+ if verbose>1:
+ outmess('analyzeline: Creating module block %s\n'%`f77modulename`,0)
+ groupname[groupcounter]='module'
+ groupcache[groupcounter]['block']='python module'
+ groupcache[groupcounter]['name']=f77modulename
+ groupcache[groupcounter]['from']=''
+ groupcache[groupcounter]['body']=[]
+ groupcache[groupcounter]['externals']=[]
+ groupcache[groupcounter]['interfaced']=[]
+ groupcache[groupcounter]['vars']={}
+ groupcounter=groupcounter+1
+ groupcache[groupcounter]={}
+ grouplist[groupcounter]=[]
+ if needinterface:
+ if verbose>1:
+ outmess('analyzeline: Creating additional interface block.\n',0)
+ groupname[groupcounter]='interface'
+ groupcache[groupcounter]['block']='interface'
+ groupcache[groupcounter]['name']='unknown_interface'
+ groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'],groupcache[groupcounter-1]['name'])
+ groupcache[groupcounter]['body']=[]
+ groupcache[groupcounter]['externals']=[]
+ groupcache[groupcounter]['interfaced']=[]
+ groupcache[groupcounter]['vars']={}
+ groupcounter=groupcounter+1
+ groupcache[groupcounter]={}
+ grouplist[groupcounter]=[]
+ groupname[groupcounter]=block
+ groupcache[groupcounter]['block']=block
+ if not name: name='unknown_'+block
+ groupcache[groupcounter]['prefix']=m.group('before')
+ groupcache[groupcounter]['name']=rmbadname1(name)
+ groupcache[groupcounter]['result']=result
+ if groupcounter==1:
+ groupcache[groupcounter]['from']=currentfilename
+ else:
+ if f77modulename and groupcounter==3:
+ groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'],currentfilename)
+ else:
+ groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'],groupcache[groupcounter-1]['name'])
+ for k in groupcache[groupcounter].keys():
+ if not groupcache[groupcounter][k]: del groupcache[groupcounter][k]
+ groupcache[groupcounter]['args']=args
+ groupcache[groupcounter]['body']=[]
+ groupcache[groupcounter]['externals']=[]
+ groupcache[groupcounter]['interfaced']=[]
+ groupcache[groupcounter]['vars']={}
+ groupcache[groupcounter]['entry']={}
+ # end of creation
+ if block=='type':
+ groupcache[groupcounter]['varnames'] = []
+
+ if case in ['call','callfun']: # set parents variables
+ if name not in groupcache[groupcounter-2]['externals']:
+ groupcache[groupcounter-2]['externals'].append(name)
+ groupcache[groupcounter]['vars']=copy.deepcopy(groupcache[groupcounter-2]['vars'])
+ #try: del groupcache[groupcounter]['vars'][groupcache[groupcounter-2]['name']]
+ #except: pass
+ try: del groupcache[groupcounter]['vars'][name][groupcache[groupcounter]['vars'][name]['attrspec'].index('external')]
+ except: pass
+ if block in ['function','subroutine']: # set global attributes
+ try: groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name],groupcache[groupcounter-2]['vars'][''])
+ except: pass
+ if case=='callfun': # return type
+ if result and groupcache[groupcounter]['vars'].has_key(result):
+ if not name==result:
+ groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name],groupcache[groupcounter]['vars'][result])
+ #if groupcounter>1: # name is interfaced
+ try: groupcache[groupcounter-2]['interfaced'].append(name)
+ except: pass
+ if block=='function':
+ t=typespattern[0].match(m.group('before')+' '+name)
+ if t:
+ typespec,selector,attr,edecl=cracktypespec0(t.group('this'),t.group('after'))
+ updatevars(typespec,selector,attr,edecl)
+ if case in ['call','callfun']:
+ grouplist[groupcounter-1].append(groupcache[groupcounter])
+ grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter=groupcounter-1 # end routine
+ grouplist[groupcounter-1].append(groupcache[groupcounter])
+ grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter=groupcounter-1 # end interface
+ elif case=='entry':
+ name,args,result=_resolvenameargspattern(m.group('after'))
+ if name is not None:
+ if args:
+ args=rmbadname(map(string.strip,string.split(markoutercomma(args),'@,@')))
+ else: args=[]
+ assert result is None,`result`
+ groupcache[groupcounter]['entry'][name] = args
+ previous_context = ('entry',name,groupcounter)
+ elif case=='type':
+ typespec,selector,attr,edecl=cracktypespec0(block,m.group('after'))
+ last_name = updatevars(typespec,selector,attr,edecl)
+ if last_name is not None:
+ previous_context = ('variable',last_name,groupcounter)
+ elif case in ['dimension','intent','optional','required','external','public','private','intrisic']:
+ edecl=groupcache[groupcounter]['vars']
+ ll=m.group('after')
+ i=string.find(ll,'::')
+ if i<0 and case=='intent':
+ i=string.find(markouterparen(ll),'@)@')-2
+ ll=ll[:i+1]+'::'+ll[i+1:]
+ i=string.find(ll,'::')
+ if ll[i:]=='::' and groupcache[groupcounter].has_key('args'):
+ outmess('All arguments will have attribute %s%s\n'%(m.group('this'),ll[:i]))
+ ll = ll + string.join(groupcache[groupcounter]['args'],',')
+ if i<0:i=0;pl=''
+ else: pl=string.strip(ll[:i]);ll=ll[i+2:]
+ ch = string.split(markoutercomma(pl),'@,@')
+ if len(ch)>1:
+ pl = ch[0]
+ outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % (','.join(ch[1:])))
+ last_name = None
+ for e in map(string.strip,string.split(markoutercomma(ll),'@,@')):
+ m1=namepattern.match(e)
+ if not m1:
+ if case in ['public','private']: k=''
+ else:
+ print m.groupdict()
+ outmess('analyzeline: no name pattern found in %s statement for %s. Skipping.\n'%(case,`e`))
+ continue
+ else:
+ k=rmbadname1(m1.group('name'))
+ if not edecl.has_key(k): edecl[k]={}
+ if case=='dimension': ap=case+m1.group('after')
+ if case=='intent':
+ ap=m.group('this')+pl
+ if _intentcallbackpattern.match(ap):
+ if k not in groupcache[groupcounter]['args']:
+ if groupcounter>1 and \
+ string.find(groupcache[groupcounter-2]['name'],
+ '__user__')==-1:
+ outmess('analyzeline: appending intent(callback) %s'\
+ ' to %s arguments\n' % (k,groupcache[groupcounter]['name']))
+ groupcache[groupcounter]['args'].append(k)
+ else:
+ errmess('analyzeline: intent(callback) %s is already'\
+ ' in argument list' % (k))
+ if case in ['optional','required','public','external','private','intrisic']: ap=case
+ if edecl[k].has_key('attrspec'): edecl[k]['attrspec'].append(ap)
+ else: edecl[k]['attrspec']=[ap]
+ if case=='external':
+ if groupcache[groupcounter]['block']=='program':
+ outmess('analyzeline: ignoring program arguments\n')
+ continue
+ if k not in groupcache[groupcounter]['args']:
+ #outmess('analyzeline: ignoring external %s (not in arguments list)\n'%(`k`))
+ continue
+ if not groupcache[groupcounter].has_key('externals'):
+ groupcache[groupcounter]['externals']=[]
+ groupcache[groupcounter]['externals'].append(k)
+ last_name = k
+ groupcache[groupcounter]['vars']=edecl
+ if last_name is not None:
+ previous_context = ('variable',last_name,groupcounter)
+ elif case=='parameter':
+ edecl=groupcache[groupcounter]['vars']
+ ll=string.strip(m.group('after'))[1:-1]
+ last_name = None
+ for e in string.split(markoutercomma(ll),'@,@'):
+ try:
+ k,initexpr=map(string.strip,string.split(e,'='))
+ except:
+ outmess('analyzeline: could not extract name,expr in parameter statement "%s" of "%s"\n'%(e,ll));continue
+ params = get_parameters(edecl)
+ k=rmbadname1(k)
+ if not edecl.has_key(k): edecl[k]={}
+ if edecl[k].has_key('=') and (not edecl[k]['=']==initexpr):
+ outmess('analyzeline: Overwriting the value of parameter "%s" ("%s") with "%s".\n'%(k,edecl[k]['='],initexpr))
+ t = determineexprtype(initexpr,params)
+ if t:
+ if t.get('typespec')=='real':
+ tt = list(initexpr)
+ for m in real16pattern.finditer(initexpr):
+ tt[m.start():m.end()] = list(\
+ initexpr[m.start():m.end()].lower().replace('d', 'e'))
+ initexpr = "".join(tt)
+ elif t.get('typespec')=='complex':
+ initexpr = initexpr[1:].lower().replace('d','e').\
+ replace(',','+1j*(')
+ try:
+ v = eval(initexpr,{},params)
+ except (SyntaxError,NameError),msg:
+ errmess('analyzeline: Failed to evaluate %r. Ignoring: %s\n'\
+ % (initexpr, msg))
+ continue
+ edecl[k]['='] = repr(v)
+ if edecl[k].has_key('attrspec'):
+ edecl[k]['attrspec'].append('parameter')
+ else: edecl[k]['attrspec']=['parameter']
+ last_name = k
+ groupcache[groupcounter]['vars']=edecl
+ if last_name is not None:
+ previous_context = ('variable',last_name,groupcounter)
+ elif case=='implicit':
+ if string.lower(string.strip(m.group('after')))=='none':
+ groupcache[groupcounter]['implicit']=None
+ elif m.group('after'):
+ if groupcache[groupcounter].has_key('implicit'):
+ impl=groupcache[groupcounter]['implicit']
+ else: impl={}
+ if impl is None:
+ outmess('analyzeline: Overwriting earlier "implicit none" statement.\n')
+ impl={}
+ for e in string.split(markoutercomma(m.group('after')),'@,@'):
+ decl={}
+ m1=re.match(r'\s*(?P<this>.*?)\s*(\(\s*(?P<after>[a-z-, ]+)\s*\)\s*|)\Z',e,re.I)
+ if not m1:
+ outmess('analyzeline: could not extract info of implicit statement part "%s"\n'%(e));continue
+ m2=typespattern4implicit.match(m1.group('this'))
+ if not m2:
+ outmess('analyzeline: could not extract types pattern of implicit statement part "%s"\n'%(e));continue
+ typespec,selector,attr,edecl=cracktypespec0(m2.group('this'),m2.group('after'))
+ kindselect,charselect,typename=cracktypespec(typespec,selector)
+ decl['typespec']=typespec
+ decl['kindselector']=kindselect
+ decl['charselector']=charselect
+ decl['typename']=typename
+ for k in decl.keys():
+ if not decl[k]: del decl[k]
+ for r in string.split(markoutercomma(m1.group('after')),'@,@'):
+ if '-' in r:
+ try: begc,endc=map(string.strip,string.split(r,'-'))
+ except:
+ outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement\n'%r);continue
+ else: begc=endc=string.strip(r)
+ if not len(begc)==len(endc)==1:
+ outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement (2)\n'%r);continue
+ for o in range(ord(begc),ord(endc)+1):
+ impl[chr(o)]=decl
+ groupcache[groupcounter]['implicit']=impl
+ elif case=='data':
+ ll=[]
+ dl='';il='';f=0;fc=1
+ for c in m.group('after'):
+ if c=="'": fc=not fc
+ if c=='/' and fc: f=f+1;continue
+ if f==0: dl=dl+c
+ elif f==1: il=il+c
+ elif f==2:
+ dl = dl.strip()
+ if dl.startswith(','):
+ dl = dl[1:].strip()
+ ll.append([dl,il])
+ dl=c;il='';f=0
+ if f==2:
+ dl = dl.strip()
+ if dl.startswith(','):
+ dl = dl[1:].strip()
+ ll.append([dl,il])
+ vars={}
+ if groupcache[groupcounter].has_key('vars'):
+ vars=groupcache[groupcounter]['vars']
+ last_name = None
+ for l in ll:
+ l=map(string.strip,l)
+ if l[0][0]==',':l[0]=l[0][1:]
+ if l[0][0]=='(':
+ outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n'%l[0])
+ continue
+ #if '(' in l[0]:
+ # #outmess('analyzeline: ignoring this data statement.\n')
+ # continue
+ i=0;j=0;llen=len(l[1])
+ for v in rmbadname(map(string.strip,string.split(markoutercomma(l[0]),'@,@'))):
+ fc=0
+ while (i<llen) and (fc or not l[1][i]==','):
+ if l[1][i]=="'": fc=not fc
+ i=i+1
+ i=i+1
+ #v,l[1][j:i-1]=name,initvalue
+ if not vars.has_key(v):
+ vars[v]={}
+ if vars[v].has_key('=') and not vars[v]['=']==l[1][j:i-1]:
+ outmess('analyzeline: changing init expression of "%s" ("%s") to "%s"\n'%(v,vars[v]['='],l[1][j:i-1]))
+ vars[v]['=']=l[1][j:i-1]
+ j=i
+ last_name = v
+ groupcache[groupcounter]['vars']=vars
+ if last_name is not None:
+ previous_context = ('variable',last_name,groupcounter)
+ elif case=='common':
+ line=string.strip(m.group('after'))
+ if not line[0]=='/':line='//'+line
+ cl=[]
+ f=0;bn='';ol=''
+ for c in line:
+ if c=='/':f=f+1;continue
+ if f>=3:
+ bn = string.strip(bn)
+ if not bn: bn='_BLNK_'
+ cl.append([bn,ol])
+ f=f-2;bn='';ol=''
+ if f%2: bn=bn+c
+ else: ol=ol+c
+ bn = string.strip(bn)
+ if not bn: bn='_BLNK_'
+ cl.append([bn,ol])
+ commonkey={}
+ if groupcache[groupcounter].has_key('common'):
+ commonkey=groupcache[groupcounter]['common']
+ for c in cl:
+ if commonkey.has_key(c[0]):
+ outmess('analyzeline: previously defined common block encountered. Skipping.\n')
+ continue
+ commonkey[c[0]]=[]
+ for i in map(string.strip,string.split(markoutercomma(c[1]),'@,@')):
+ if i: commonkey[c[0]].append(i)
+ groupcache[groupcounter]['common']=commonkey
+ previous_context = ('common',bn,groupcounter)
+ elif case=='use':
+ m1=re.match(r'\A\s*(?P<name>\b[\w]+\b)\s*((,(\s*\bonly\b\s*:|(?P<notonly>))\s*(?P<list>.*))|)\s*\Z',m.group('after'),re.I)
+ if m1:
+ mm=m1.groupdict()
+ if not groupcache[groupcounter].has_key('use'): groupcache[groupcounter]['use']={}
+ name=m1.group('name')
+ groupcache[groupcounter]['use'][name]={}
+ isonly=0
+ if mm.has_key('list') and mm['list'] is not None:
+ if mm.has_key('notonly') and mm['notonly'] is None:isonly=1
+ groupcache[groupcounter]['use'][name]['only']=isonly
+ ll=map(string.strip,string.split(mm['list'],','))
+ rl={}
+ for l in ll:
+ if '=' in l:
+ m2=re.match(r'\A\s*(?P<local>\b[\w]+\b)\s*=\s*>\s*(?P<use>\b[\w]+\b)\s*\Z',l,re.I)
+ if m2: rl[string.strip(m2.group('local'))]=string.strip(m2.group('use'))
+ else:
+ outmess('analyzeline: Not local=>use pattern found in %s\n'%`l`)
+ else:
+ rl[l]=l
+ groupcache[groupcounter]['use'][name]['map']=rl
+ else:
+ pass
+
+ else:
+ print m.groupdict()
+ outmess('analyzeline: Could not crack the use statement.\n')
+ elif case in ['f2pyenhancements']:
+ if not groupcache[groupcounter].has_key ('f2pyenhancements'):
+ groupcache[groupcounter]['f2pyenhancements'] = {}
+ d = groupcache[groupcounter]['f2pyenhancements']
+ if m.group('this')=='usercode' and d.has_key('usercode'):
+ if type(d['usercode']) is type(''):
+ d['usercode'] = [d['usercode']]
+ d['usercode'].append(m.group('after'))
+ else:
+ d[m.group('this')] = m.group('after')
+ elif case=='multiline':
+ if previous_context is None:
+ if verbose:
+ outmess('analyzeline: No context for multiline block.\n')
+ return
+ gc = groupcounter
+ #gc = previous_context[2]
+ appendmultiline(groupcache[gc],
+ previous_context[:2],
+ m.group('this'))
+ else:
+ if verbose>1:
+ print m.groupdict()
+ outmess('analyzeline: No code implemented for line.\n')
+
+def appendmultiline(group, context_name,ml):
+ if not group.has_key('f2pymultilines'):
+ group['f2pymultilines'] = {}
+ d = group['f2pymultilines']
+ if not d.has_key(context_name):
+ d[context_name] = []
+ d[context_name].append(ml)
+ return
+
+def cracktypespec0(typespec,ll):
+ selector=None
+ attr=None
+ if re.match(r'double\s*complex',typespec,re.I): typespec='double complex'
+ elif re.match(r'double\s*precision',typespec,re.I): typespec='double precision'
+ else: typespec=string.lower(string.strip(typespec))
+ m1=selectpattern.match(markouterparen(ll))
+ if not m1:
+ outmess('cracktypespec0: no kind/char_selector pattern found for line.\n')
+ return
+ d=m1.groupdict()
+ for k in d.keys(): d[k]=unmarkouterparen(d[k])
+ if typespec in ['complex','integer','logical','real','character','type']:
+ selector=d['this']
+ ll=d['after']
+ i=string.find(ll,'::')
+ if i>=0:
+ attr=string.strip(ll[:i])
+ ll=ll[i+2:]
+ return typespec,selector,attr,ll
+#####
+namepattern=re.compile(r'\s*(?P<name>\b[\w]+\b)\s*(?P<after>.*)\s*\Z',re.I)
+kindselector=re.compile(r'\s*(\(\s*(kind\s*=)?\s*(?P<kind>.*)\s*\)|[*]\s*(?P<kind2>.*?))\s*\Z',re.I)
+charselector=re.compile(r'\s*(\((?P<lenkind>.*)\)|[*]\s*(?P<charlen>.*))\s*\Z',re.I)
+lenkindpattern=re.compile(r'\s*(kind\s*=\s*(?P<kind>.*?)\s*(@,@\s*len\s*=\s*(?P<len>.*)|)|(len\s*=\s*|)(?P<len2>.*?)\s*(@,@\s*(kind\s*=\s*|)(?P<kind2>.*)|))\s*\Z',re.I)
+lenarraypattern=re.compile(r'\s*(@\(@\s*(?!/)\s*(?P<array>.*?)\s*@\)@\s*[*]\s*(?P<len>.*?)|([*]\s*(?P<len2>.*?)|)\s*(@\(@\s*(?!/)\s*(?P<array2>.*?)\s*@\)@|))\s*(=\s*(?P<init>.*?)|(@\(@|)/\s*(?P<init2>.*?)\s*/(@\)@|)|)\s*\Z',re.I)
+def removespaces(expr):
+ expr=string.strip(expr)
+ if len(expr)<=1: return expr
+ expr2=expr[0]
+ for i in range(1,len(expr)-1):
+ if expr[i]==' ' and \
+ ((expr[i+1] in "()[]{}= ") or (expr[i-1] in "()[]{}= ")): continue
+ expr2=expr2+expr[i]
+ expr2=expr2+expr[-1]
+ return expr2
+def markinnerspaces(line):
+ l='';f=0
+ cc='\''
+ cc1='"'
+ cb=''
+ for c in line:
+ if cb=='\\' and c in ['\\','\'','"']:
+ l=l+c;
+ cb=c
+ continue
+ if f==0 and c in ['\'','"']: cc=c; cc1={'\'':'"','"':'\''}[c]
+ if c==cc:f=f+1
+ elif c==cc:f=f-1
+ elif c==' ' and f==1: l=l+'@_@'; continue
+ l=l+c;cb=c
+ return l
+def updatevars(typespec,selector,attrspec,entitydecl):
+ global groupcache,groupcounter
+ last_name = None
+ kindselect,charselect,typename=cracktypespec(typespec,selector)
+ if attrspec:
+ attrspec=map(string.strip,string.split(markoutercomma(attrspec),'@,@'))
+ l = []
+ c = re.compile(r'(?P<start>[a-zA-Z]+)')
+ for a in attrspec:
+ m = c.match(a)
+ if m:
+ s = string.lower(m.group('start'))
+ a = s + a[len(s):]
+ l.append(a)
+ attrspec = l
+ el=map(string.strip,string.split(markoutercomma(entitydecl),'@,@'))
+ el1=[]
+ for e in el:
+ for e1 in map(string.strip,string.split(markoutercomma(removespaces(markinnerspaces(e)),comma=' '),'@ @')):
+ if e1: el1.append(string.replace(e1,'@_@',' '))
+ for e in el1:
+ m=namepattern.match(e)
+ if not m:
+ outmess('updatevars: no name pattern found for entity=%s. Skipping.\n'%(`e`))
+ continue
+ ename=rmbadname1(m.group('name'))
+ edecl={}
+ if groupcache[groupcounter]['vars'].has_key(ename):
+ edecl=groupcache[groupcounter]['vars'][ename].copy()
+ has_typespec = edecl.has_key('typespec')
+ if not has_typespec:
+ edecl['typespec']=typespec
+ elif typespec and (not typespec==edecl['typespec']):
+ outmess('updatevars: attempt to change the type of "%s" ("%s") to "%s". Ignoring.\n' % (ename,edecl['typespec'],typespec))
+ if not edecl.has_key('kindselector'):
+ edecl['kindselector']=copy.copy(kindselect)
+ elif kindselect:
+ for k in kindselect.keys():
+ if edecl['kindselector'].has_key(k) and (not kindselect[k]==edecl['kindselector'][k]):
+ outmess('updatevars: attempt to change the kindselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k,ename,edecl['kindselector'][k],kindselect[k]))
+ else: edecl['kindselector'][k]=copy.copy(kindselect[k])
+ if not edecl.has_key('charselector') and charselect:
+ if not has_typespec:
+ edecl['charselector']=charselect
+ else:
+ errmess('updatevars:%s: attempt to change empty charselector to %r. Ignoring.\n' \
+ %(ename,charselect))
+ elif charselect:
+ for k in charselect.keys():
+ if edecl['charselector'].has_key(k) and (not charselect[k]==edecl['charselector'][k]):
+ outmess('updatevars: attempt to change the charselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k,ename,edecl['charselector'][k],charselect[k]))
+ else: edecl['charselector'][k]=copy.copy(charselect[k])
+ if not edecl.has_key('typename'):
+ edecl['typename']=typename
+ elif typename and (not edecl['typename']==typename):
+ outmess('updatevars: attempt to change the typename of "%s" ("%s") to "%s". Ignoring.\n' % (ename,edecl['typename'],typename))
+ if not edecl.has_key('attrspec'):
+ edecl['attrspec']=copy.copy(attrspec)
+ elif attrspec:
+ for a in attrspec:
+ if a not in edecl['attrspec']:
+ edecl['attrspec'].append(a)
+ else:
+ edecl['typespec']=copy.copy(typespec)
+ edecl['kindselector']=copy.copy(kindselect)
+ edecl['charselector']=copy.copy(charselect)
+ edecl['typename']=typename
+ edecl['attrspec']=copy.copy(attrspec)
+ if m.group('after'):
+ m1=lenarraypattern.match(markouterparen(m.group('after')))
+ if m1:
+ d1=m1.groupdict()
+ for lk in ['len','array','init']:
+ if d1[lk+'2'] is not None: d1[lk]=d1[lk+'2']; del d1[lk+'2']
+ for k in d1.keys():
+ if d1[k] is not None: d1[k]=unmarkouterparen(d1[k])
+ else: del d1[k]
+ if d1.has_key('len') and d1.has_key('array'):
+ if d1['len']=='':
+ d1['len']=d1['array']
+ del d1['array']
+ else:
+ d1['array']=d1['array']+','+d1['len']
+ del d1['len']
+ errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n'%(typespec,e,typespec,ename,d1['array']))
+ if d1.has_key('array'):
+ dm = 'dimension(%s)'%d1['array']
+ if not edecl.has_key('attrspec') or (not edecl['attrspec']):
+ edecl['attrspec']=[dm]
+ else:
+ edecl['attrspec'].append(dm)
+ for dm1 in edecl['attrspec']:
+ if dm1[:9]=='dimension' and dm1!=dm:
+ del edecl['attrspec'][-1]
+ errmess('updatevars:%s: attempt to change %r to %r. Ignoring.\n' \
+ % (ename,dm1,dm))
+ break
+
+ if d1.has_key('len'):
+ if typespec in ['complex','integer','logical','real']:
+ if (not edecl.has_key('kindselector')) or (not edecl['kindselector']):
+ edecl['kindselector']={}
+ edecl['kindselector']['*']=d1['len']
+ elif typespec == 'character':
+ if (not edecl.has_key('charselector')) or (not edecl['charselector']): edecl['charselector']={}
+ if edecl['charselector'].has_key('len'): del edecl['charselector']['len']
+ edecl['charselector']['*']=d1['len']
+ if d1.has_key('init'):
+ if edecl.has_key('=') and (not edecl['=']==d1['init']):
+ outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % (ename,edecl['='],d1['init']))
+ else:
+ edecl['=']=d1['init']
+ else:
+ outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n'%(ename+m.group('after')))
+ for k in edecl.keys():
+ if not edecl[k]: del edecl[k]
+ groupcache[groupcounter]['vars'][ename]=edecl
+ if groupcache[groupcounter].has_key('varnames'):
+ groupcache[groupcounter]['varnames'].append(ename)
+ last_name = ename
+ return last_name
+
+def cracktypespec(typespec,selector):
+ kindselect=None
+ charselect=None
+ typename=None
+ if selector:
+ if typespec in ['complex','integer','logical','real']:
+ kindselect=kindselector.match(selector)
+ if not kindselect:
+ outmess('cracktypespec: no kindselector pattern found for %s\n'%(`selector`))
+ return
+ kindselect=kindselect.groupdict()
+ kindselect['*']=kindselect['kind2']
+ del kindselect['kind2']
+ for k in kindselect.keys():
+ if not kindselect[k]: del kindselect[k]
+ for k,i in kindselect.items():
+ kindselect[k] = rmbadname1(i)
+ elif typespec=='character':
+ charselect=charselector.match(selector)
+ if not charselect:
+ outmess('cracktypespec: no charselector pattern found for %s\n'%(`selector`))
+ return
+ charselect=charselect.groupdict()
+ charselect['*']=charselect['charlen']
+ del charselect['charlen']
+ if charselect['lenkind']:
+ lenkind=lenkindpattern.match(markoutercomma(charselect['lenkind']))
+ lenkind=lenkind.groupdict()
+ for lk in ['len','kind']:
+ if lenkind[lk+'2']:
+ lenkind[lk]=lenkind[lk+'2']
+ charselect[lk]=lenkind[lk]
+ del lenkind[lk+'2']
+ del charselect['lenkind']
+ for k in charselect.keys():
+ if not charselect[k]: del charselect[k]
+ for k,i in charselect.items():
+ charselect[k] = rmbadname1(i)
+ elif typespec=='type':
+ typename=re.match(r'\s*\(\s*(?P<name>\w+)\s*\)',selector,re.I)
+ if typename: typename=typename.group('name')
+ else: outmess('cracktypespec: no typename found in %s\n'%(`typespec+selector`))
+ else:
+ outmess('cracktypespec: no selector used for %s\n'%(`selector`))
+ return kindselect,charselect,typename
+######
+def setattrspec(decl,attr,force=0):
+ if not decl: decl={}
+ if not attr: return decl
+ if not decl.has_key('attrspec'):
+ decl['attrspec']=[attr]
+ return decl
+ if force: decl['attrspec'].append(attr)
+ if attr in decl['attrspec']: return decl
+ if attr=='static' and 'automatic' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ elif attr=='automatic' and 'static' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ elif attr=='public' and 'private' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ elif attr=='private' and 'public' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ else:
+ decl['attrspec'].append(attr)
+ return decl
+def setkindselector(decl,sel,force=0):
+ if not decl: decl={}
+ if not sel: return decl
+ if not decl.has_key('kindselector'):
+ decl['kindselector']=sel
+ return decl
+ for k in sel.keys():
+ if force or not decl['kindselector'].has_key(k):
+ decl['kindselector'][k]=sel[k]
+ return decl
+def setcharselector(decl,sel,force=0):
+ if not decl: decl={}
+ if not sel: return decl
+ if not decl.has_key('charselector'):
+ decl['charselector']=sel
+ return decl
+ for k in sel.keys():
+ if force or not decl['charselector'].has_key(k):
+ decl['charselector'][k]=sel[k]
+ return decl
+def getblockname(block,unknown='unknown'):
+ if block.has_key('name'): return block['name']
+ return unknown
+###### post processing
+def setmesstext(block):
+ global filepositiontext
+ try: filepositiontext='In: %s:%s\n'%(block['from'],block['name'])
+ except: pass
+
+def get_usedict(block):
+ usedict = {}
+ if block.has_key('parent_block'):
+ usedict = get_usedict(block['parent_block'])
+ if block.has_key('use'):
+ usedict.update(block['use'])
+ return usedict
+
+def get_useparameters(block, param_map=None):
+ global f90modulevars
+ if param_map is None:
+ param_map = {}
+ usedict = get_usedict(block)
+ if not usedict:
+ return param_map
+ for usename,mapping in usedict.items():
+ usename = string.lower(usename)
+ if not f90modulevars.has_key(usename):
+ continue
+ mvars = f90modulevars[usename]
+ params = get_parameters(mvars)
+ if not params:
+ continue
+ # XXX: apply mapping
+ if mapping:
+ errmess('get_useparameters: mapping for %s not impl.' % (mapping))
+ for k,v in params.items():
+ if param_map.has_key(k):
+ outmess('get_useparameters: overriding parameter %s with'\
+ ' value from module %s' % (`k`,`usename`))
+ param_map[k] = v
+ return param_map
+
+def postcrack2(block,tab='',param_map=None):
+ global f90modulevars
+ if not f90modulevars:
+ return block
+ if type(block)==types.ListType:
+ ret = []
+ for g in block:
+ g = postcrack2(g,tab=tab+'\t',param_map=param_map)
+ ret.append(g)
+ return ret
+ setmesstext(block)
+ outmess('%sBlock: %s\n'%(tab,block['name']),0)
+
+ if param_map is None:
+ param_map = get_useparameters(block)
+
+ if param_map is not None and block.has_key('vars'):
+ vars = block['vars']
+ for n in vars.keys():
+ var = vars[n]
+ if var.has_key('kindselector'):
+ kind = var['kindselector']
+ if kind.has_key('kind'):
+ val = kind['kind']
+ if param_map.has_key(val):
+ kind['kind'] = param_map[val]
+ new_body = []
+ for b in block['body']:
+ b = postcrack2(b,tab=tab+'\t',param_map=param_map)
+ new_body.append(b)
+ block['body'] = new_body
+
+ return block
+
+def postcrack(block,args=None,tab=''):
+ """
+ TODO:
+ function return values
+ determine expression types if in argument list
+ """
+ global usermodules,onlyfunctions
+ if type(block)==types.ListType:
+ gret=[]
+ uret=[]
+ for g in block:
+ setmesstext(g)
+ g=postcrack(g,tab=tab+'\t')
+ if g.has_key('name') and string.find(g['name'],'__user__')>=0: # sort user routines to appear first
+ uret.append(g)
+ else:
+ gret.append(g)
+ return uret+gret
+ setmesstext(block)
+ if (not type(block)==types.DictType) and not block.has_key('block'):
+ raise 'postcrack: Expected block dictionary instead of ',block
+ if block.has_key('name') and not block['name']=='unknown_interface':
+ outmess('%sBlock: %s\n'%(tab,block['name']),0)
+ blocktype=block['block']
+ block=analyzeargs(block)
+ block=analyzecommon(block)
+ block['vars']=analyzevars(block)
+ block['sortvars']=sortvarnames(block['vars'])
+ if block.has_key('args') and block['args']:
+ args=block['args']
+ block['body']=analyzebody(block,args,tab=tab)
+
+ userisdefined=[]
+## fromuser = []
+ if block.has_key('use'):
+ useblock=block['use']
+ for k in useblock.keys():
+ if string.find(k,'__user__')>=0:
+ userisdefined.append(k)
+## if useblock[k].has_key('map'):
+## for n in useblock[k]['map'].values():
+## if n not in fromuser: fromuser.append(n)
+ else: useblock={}
+ name=''
+ if block.has_key('name'):name=block['name']
+ if block.has_key('externals') and block['externals']:# and not userisdefined: # Build a __user__ module
+ interfaced=[]
+ if block.has_key('interfaced'): interfaced=block['interfaced']
+ mvars=copy.copy(block['vars'])
+ if name: mname=name+'__user__routines'
+ else: mname='unknown__user__routines'
+ if mname in userisdefined:
+ i=1
+ while '%s_%i'%(mname,i) in userisdefined: i=i+1
+ mname='%s_%i'%(mname,i)
+ interface={'block':'interface','body':[],'vars':{},'name':name+'_user_interface'}
+ for e in block['externals']:
+## if e in fromuser:
+## outmess(' Skipping %s that is defined explicitly in another use statement\n'%(`e`))
+## continue
+ if e in interfaced:
+ edef=[]
+ j=-1
+ for b in block['body']:
+ j=j+1
+ if b['block']=='interface':
+ i=-1
+ for bb in b['body']:
+ i=i+1
+ if bb.has_key('name') and bb['name']==e:
+ edef=copy.copy(bb)
+ del b['body'][i]
+ break
+ if edef:
+ if not b['body']: del block['body'][j]
+ del interfaced[interfaced.index(e)]
+ break
+ interface['body'].append(edef)
+ else:
+ if mvars.has_key(e) and not isexternal(mvars[e]):
+ interface['vars'][e]=mvars[e]
+ if interface['vars'] or interface['body']:
+ block['interfaced']=interfaced
+ mblock={'block':'python module','body':[interface],'vars':{},'name':mname,'interfaced':block['externals']}
+ useblock[mname]={}
+ usermodules.append(mblock)
+ if useblock:
+ block['use']=useblock
+ return block
+
+def sortvarnames(vars):
+ indep = []
+ dep = []
+ for v in vars.keys():
+ if vars[v].has_key('depend') and vars[v]['depend']:
+ dep.append(v)
+ #print '%s depends on %s'%(v,vars[v]['depend'])
+ else: indep.append(v)
+ n = len(dep)
+ i = 0
+ while dep: #XXX: How to catch dependence cycles correctly?
+ v = dep[0]
+ fl = 0
+ for w in dep[1:]:
+ if w in vars[v]['depend']:
+ fl = 1
+ break
+ if fl:
+ dep = dep[1:]+[v]
+ i = i + 1
+ if i>n:
+ errmess('sortvarnames: failed to compute dependencies because'
+ ' of cyclic dependencies between '
+ +string.join(dep,', ')+'\n')
+ indep = indep + dep
+ break
+ else:
+ indep.append(v)
+ dep = dep[1:]
+ n = len(dep)
+ i = 0
+ #print indep
+ return indep
+
+def analyzecommon(block):
+ if not hascommon(block): return block
+ commonvars=[]
+ for k in block['common'].keys():
+ comvars=[]
+ for e in block['common'][k]:
+ m=re.match(r'\A\s*\b(?P<name>.*?)\b\s*(\((?P<dims>.*?)\)|)\s*\Z',e,re.I)
+ if m:
+ dims=[]
+ if m.group('dims'):
+ dims=map(string.strip,string.split(markoutercomma(m.group('dims')),'@,@'))
+ n=string.strip(m.group('name'))
+ if block['vars'].has_key(n):
+ if block['vars'][n].has_key('attrspec'):
+ block['vars'][n]['attrspec'].append('dimension(%s)'%(string.join(dims,',')))
+ else:
+ block['vars'][n]['attrspec']=['dimension(%s)'%(string.join(dims,','))]
+ else:
+ if dims:
+ block['vars'][n]={'attrspec':['dimension(%s)'%(string.join(dims,','))]}
+ else: block['vars'][n]={}
+ if n not in commonvars: commonvars.append(n)
+ else:
+ n=e
+ errmess('analyzecommon: failed to extract "<name>[(<dims>)]" from "%s" in common /%s/.\n'%(e,k))
+ comvars.append(n)
+ block['common'][k]=comvars
+ if not block.has_key('commonvars'):
+ block['commonvars']=commonvars
+ else:
+ block['commonvars']=block['commonvars']+commonvars
+ return block
+def analyzebody(block,args,tab=''):
+ global usermodules,skipfuncs,onlyfuncs,f90modulevars
+ setmesstext(block)
+ body=[]
+ for b in block['body']:
+ b['parent_block'] = block
+ if b['block'] in ['function','subroutine']:
+ if args is not None and b['name'] not in args:
+ continue
+ else:
+ as=b['args']
+ if b['name'] in skipfuncs:
+ continue
+ if onlyfuncs and b['name'] not in onlyfuncs:
+ continue
+ else: as=args
+ b=postcrack(b,as,tab=tab+'\t')
+ if b['block']=='interface' and not b['body']:
+ if not b.has_key('f2pyenhancements'):
+ continue
+ if string.replace(b['block'],' ','')=='pythonmodule':
+ usermodules.append(b)
+ else:
+ if b['block']=='module':
+ f90modulevars[b['name']] = b['vars']
+ body.append(b)
+ return body
+def buildimplicitrules(block):
+ setmesstext(block)
+ implicitrules=defaultimplicitrules
+ attrrules={}
+ if block.has_key('implicit'):
+ if block['implicit'] is None:
+ implicitrules=None
+ if verbose>1:
+ outmess('buildimplicitrules: no implicit rules for routine %s.\n'%`block['name']`)
+ else:
+ for k in block['implicit'].keys():
+ if block['implicit'][k].get('typespec') not in ['static','automatic']:
+ implicitrules[k]=block['implicit'][k]
+ else:
+ attrrules[k]=block['implicit'][k]['typespec']
+ return implicitrules,attrrules
+
+def myeval(e,g=None,l=None):
+ r = eval(e,g,l)
+ if type(r) in [type(0),type(0.0)]:
+ return r
+ raise ValueError,'r=%r' % (r)
+
+getlincoef_re_1 = re.compile(r'\A\b\w+\b\Z',re.I)
+def getlincoef(e,xset): # e = a*x+b ; x in xset
+ try:
+ c = int(myeval(e,{},{}))
+ return 0,c,None
+ except: pass
+ if getlincoef_re_1.match(e):
+ return 1,0,e
+ len_e = len(e)
+ for x in xset:
+ if len(x)>len_e: continue
+ re_1 = re.compile(r'(?P<before>.*?)\b'+x+r'\b(?P<after>.*)',re.I)
+ m = re_1.match(e)
+ if m:
+ try:
+ m1 = re_1.match(e)
+ while m1:
+ ee = '%s(%s)%s'%(m1.group('before'),0,m1.group('after'))
+ m1 = re_1.match(ee)
+ b = myeval(ee,{},{})
+ m1 = re_1.match(e)
+ while m1:
+ ee = '%s(%s)%s'%(m1.group('before'),1,m1.group('after'))
+ m1 = re_1.match(ee)
+ a = myeval(ee,{},{}) - b
+ m1 = re_1.match(e)
+ while m1:
+ ee = '%s(%s)%s'%(m1.group('before'),0.5,m1.group('after'))
+ m1 = re_1.match(ee)
+ c = myeval(ee,{},{})
+ if (a*0.5+b==c):
+ return a,b,x
+ except: pass
+ break
+ return None,None,None
+
+_varname_match = re.compile(r'\A[a-z]\w*\Z').match
+def getarrlen(dl,args,star='*'):
+ edl = []
+ try: edl.append(myeval(dl[0],{},{}))
+ except: edl.append(dl[0])
+ try: edl.append(myeval(dl[1],{},{}))
+ except: edl.append(dl[1])
+ if type(edl[0]) is type(0):
+ p1 = 1-edl[0]
+ if p1==0: d = str(dl[1])
+ elif p1<0: d = '%s-%s'%(dl[1],-p1)
+ else: d = '%s+%s'%(dl[1],p1)
+ elif type(edl[1]) is type(0):
+ p1 = 1+edl[1]
+ if p1==0: d='-(%s)' % (dl[0])
+ else: d='%s-(%s)' % (p1,dl[0])
+ else: d = '%s-(%s)+1'%(dl[1],dl[0])
+ try: return `myeval(d,{},{})`,None,None
+ except: pass
+ d1,d2=getlincoef(dl[0],args),getlincoef(dl[1],args)
+ if None not in [d1[0],d2[0]]:
+ if (d1[0],d2[0])==(0,0):
+ return `d2[1]-d1[1]+1`,None,None
+ b = d2[1] - d1[1] + 1
+ d1 = (d1[0],0,d1[2])
+ d2 = (d2[0],b,d2[2])
+ if d1[0]==0 and d2[2] in args:
+ if b<0: return '%s * %s - %s'%(d2[0],d2[2],-b),d2[2],'+%s)/(%s)'%(-b,d2[0])
+ elif b: return '%s * %s + %s'%(d2[0],d2[2],b),d2[2],'-%s)/(%s)'%(b,d2[0])
+ else: return '%s * %s'%(d2[0],d2[2]),d2[2],')/(%s)'%(d2[0])
+ if d2[0]==0 and d1[2] in args:
+
+ if b<0: return '%s * %s - %s'%(-d1[0],d1[2],-b),d1[2],'+%s)/(%s)'%(-b,-d1[0])
+ elif b: return '%s * %s + %s'%(-d1[0],d1[2],b),d1[2],'-%s)/(%s)'%(b,-d1[0])
+ else: return '%s * %s'%(-d1[0],d1[2]),d1[2],')/(%s)'%(-d1[0])
+ if d1[2]==d2[2] and d1[2] in args:
+ a = d2[0] - d1[0]
+ if not a: return `b`,None,None
+ if b<0: return '%s * %s - %s'%(a,d1[2],-b),d2[2],'+%s)/(%s)'%(-b,a)
+ elif b: return '%s * %s + %s'%(a,d1[2],b),d2[2],'-%s)/(%s)'%(b,a)
+ else: return '%s * %s'%(a,d1[2]),d2[2],')/(%s)'%(a)
+ if d1[0]==d2[0]==1:
+ c = str(d1[2])
+ if c not in args:
+ if _varname_match(c):
+ outmess('\tgetarrlen:variable "%s" undefined\n' % (c))
+ c = '(%s)'%c
+ if b==0: d='%s-%s' % (d2[2],c)
+ elif b<0: d='%s-%s-%s' % (d2[2],c,-b)
+ else: d='%s-%s+%s' % (d2[2],c,b)
+ elif d1[0]==0:
+ c2 = str(d2[2])
+ if c2 not in args:
+ if _varname_match(c2):
+ outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
+ c2 = '(%s)'%c2
+ if d2[0]==1: pass
+ elif d2[0]==-1: c2='-%s' %c2
+ else: c2='%s*%s'%(d2[0],c2)
+
+ if b==0: d=c2
+ elif b<0: d='%s-%s' % (c2,-b)
+ else: d='%s+%s' % (c2,b)
+ elif d2[0]==0:
+ c1 = str(d1[2])
+ if c1 not in args:
+ if _varname_match(c1):
+ outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
+ c1 = '(%s)'%c1
+ if d1[0]==1: c1='-%s'%c1
+ elif d1[0]==-1: c1='+%s'%c1
+ elif d1[0]<0: c1='+%s*%s'%(-d1[0],c1)
+ else: c1 = '-%s*%s' % (d1[0],c1)
+
+ if b==0: d=c1
+ elif b<0: d='%s-%s' % (c1,-b)
+ else: d='%s+%s' % (c1,b)
+ else:
+ c1 = str(d1[2])
+ if c1 not in args:
+ if _varname_match(c1):
+ outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
+ c1 = '(%s)'%c1
+ if d1[0]==1: c1='-%s'%c1
+ elif d1[0]==-1: c1='+%s'%c1
+ elif d1[0]<0: c1='+%s*%s'%(-d1[0],c1)
+ else: c1 = '-%s*%s' % (d1[0],c1)
+
+ c2 = str(d2[2])
+ if c2 not in args:
+ if _varname_match(c2):
+ outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
+ c2 = '(%s)'%c2
+ if d2[0]==1: pass
+ elif d2[0]==-1: c2='-%s' %c2
+ else: c2='%s*%s'%(d2[0],c2)
+
+ if b==0: d='%s%s' % (c2,c1)
+ elif b<0: d='%s%s-%s' % (c2,c1,-b)
+ else: d='%s%s+%s' % (c2,c1,b)
+ return d,None,None
+
+word_pattern = re.compile(r'\b[a-z][\w$]*\b',re.I)
+
+def _get_depend_dict(name, vars, deps):
+ if vars.has_key(name):
+ words = vars[name].get('depend',[])
+
+ if vars[name].has_key('=') and not isstring(vars[name]):
+ for word in word_pattern.findall(vars[name]['=']):
+ if word not in words and vars.has_key(word):
+ words.append(word)
+ for word in words[:]:
+ for w in deps.get(word,[]) \
+ or _get_depend_dict(word, vars, deps):
+ if w not in words:
+ words.append(w)
+ else:
+ outmess('_get_depend_dict: no dependence info for %s\n' % (`name`))
+ words = []
+ deps[name] = words
+ return words
+
+def _calc_depend_dict(vars):
+ names = vars.keys()
+ depend_dict = {}
+ for n in names:
+ _get_depend_dict(n, vars, depend_dict)
+ return depend_dict
+
+def get_sorted_names(vars):
+ """
+ """
+ depend_dict = _calc_depend_dict(vars)
+ names = []
+ for name in depend_dict.keys():
+ if not depend_dict[name]:
+ names.append(name)
+ del depend_dict[name]
+ while depend_dict:
+ for name, lst in depend_dict.items():
+ new_lst = [n for n in lst if depend_dict.has_key(n)]
+ if not new_lst:
+ names.append(name)
+ del depend_dict[name]
+ else:
+ depend_dict[name] = new_lst
+ return [name for name in names if vars.has_key(name)]
+
+def _kind_func(string):
+ #XXX: return something sensible.
+ if string[0] in "'\"":
+ string = string[1:-1]
+ if real16pattern.match(string):
+ return 16
+ elif real8pattern.match(string):
+ return 8
+ return 'kind('+string+')'
+
+def _selected_int_kind_func(r):
+ #XXX: This should be processor dependent
+ m = 10**r
+ if m<=2**8: return 1
+ if m<=2**16: return 2
+ if m<=2**32: return 4
+ if m<=2**64: return 8
+ if m<=2**128: return 16
+ return -1
+
+def get_parameters(vars, global_params={}):
+ params = copy.copy(global_params)
+ g_params = copy.copy(global_params)
+ for name,func in [('kind',_kind_func),
+ ('selected_int_kind',_selected_int_kind_func),
+ ]:
+ if not g_params.has_key(name):
+ g_params[name] = func
+ param_names = []
+ for n in get_sorted_names(vars):
+ if vars[n].has_key('attrspec') and 'parameter' in vars[n]['attrspec']:
+ param_names.append(n)
+ kind_re = re.compile(r'\bkind\s*\(\s*(?P<value>.*)\s*\)',re.I)
+ selected_int_kind_re = re.compile(r'\bselected_int_kind\s*\(\s*(?P<value>.*)\s*\)',re.I)
+ for n in param_names:
+ if vars[n].has_key('='):
+ v = vars[n]['=']
+ if islogical(vars[n]):
+ v = v.lower()
+ for repl in [
+ ('.false.','False'),
+ ('.true.','True'),
+ #TODO: test .eq., .neq., etc replacements.
+ ]:
+ v = v.replace(*repl)
+ v = kind_re.sub(r'kind("\1")',v)
+ v = selected_int_kind_re.sub(r'selected_int_kind(\1)',v)
+ if isinteger(vars[n]) and not selected_int_kind_re.match(v):
+ v = v.split('_')[0]
+ if isdouble(vars[n]):
+ tt = list(v)
+ for m in real16pattern.finditer(v):
+ tt[m.start():m.end()] = list(\
+ v[m.start():m.end()].lower().replace('d', 'e'))
+ v = string.join(tt,'')
+ if iscomplex(vars[n]):
+ if v[0]=='(' and v[-1]==')':
+ l = markoutercomma(v[1:-1]).split('@,@')
+ print n,params
+ try:
+ params[n] = eval(v,g_params,params)
+ except Exception,msg:
+ params[n] = v
+ #print params
+ outmess('get_parameters: got "%s" on %s\n' % (msg,`v`))
+ if isstring(vars[n]) and type(params[n]) is type(0):
+ params[n] = chr(params[n])
+ nl = string.lower(n)
+ if nl!=n:
+ params[nl] = params[n]
+ else:
+ print vars[n]
+ outmess('get_parameters:parameter %s does not have value?!\n'%(`n`))
+ return params
+
+def _eval_length(length,params):
+ if length in ['(:)','(*)','*']:
+ return '(*)'
+ return _eval_scalar(length,params)
+
+_is_kind_number = re.compile('\d+_').match
+
+def _eval_scalar(value,params):
+ if _is_kind_number(value):
+ value = value.split('_')[0]
+ try:
+ value = str(eval(value,{},params))
+ except (NameError, SyntaxError):
+ return value
+ except Exception,msg:
+ errmess('"%s" in evaluating %r '\
+ '(available names: %s)\n' \
+ % (msg,value,params.keys()))
+ return value
+
+def analyzevars(block):
+ global f90modulevars
+ setmesstext(block)
+ implicitrules,attrrules=buildimplicitrules(block)
+ vars=copy.copy(block['vars'])
+ if block['block']=='function' and not vars.has_key(block['name']):
+ vars[block['name']]={}
+ if block['vars'].has_key(''):
+ del vars['']
+ if block['vars'][''].has_key('attrspec'):
+ gen=block['vars']['']['attrspec']
+ for n in vars.keys():
+ for k in ['public','private']:
+ if k in gen:
+ vars[n]=setattrspec(vars[n],k)
+ svars=[]
+ args = block['args']
+ for a in args:
+ try:
+ vars[a]
+ svars.append(a)
+ except KeyError:
+ pass
+ for n in vars.keys():
+ if n not in args: svars.append(n)
+
+ params = get_parameters(vars, get_useparameters(block))
+
+ dep_matches = {}
+ name_match = re.compile(r'\w[\w\d_$]*').match
+ for v in vars.keys():
+ m = name_match(v)
+ if m:
+ n = v[m.start():m.end()]
+ try:
+ dep_matches[n]
+ except KeyError:
+ dep_matches[n] = re.compile(r'.*\b%s\b'%(v),re.I).match
+ for n in svars:
+ if n[0] in attrrules.keys():
+ vars[n]=setattrspec(vars[n],attrrules[n[0]])
+ if not vars[n].has_key('typespec'):
+ if not(vars[n].has_key('attrspec') and 'external' in vars[n]['attrspec']):
+ if implicitrules:
+ ln0 = string.lower(n[0])
+ for k in implicitrules[ln0].keys():
+ if k=='typespec' and implicitrules[ln0][k]=='undefined':
+ continue
+ if not vars[n].has_key(k):
+ vars[n][k]=implicitrules[ln0][k]
+ elif k=='attrspec':
+ for l in implicitrules[ln0][k]:
+ vars[n]=setattrspec(vars[n],l)
+ elif n in block['args']:
+ outmess('analyzevars: typespec of variable %s is not defined in routine %s.\n'%(`n`,block['name']))
+
+ if vars[n].has_key('charselector'):
+ if vars[n]['charselector'].has_key('len'):
+ l = vars[n]['charselector']['len']
+ try:
+ l = str(eval(l,{},params))
+ except:
+ pass
+ vars[n]['charselector']['len'] = l
+
+ if vars[n].has_key('kindselector'):
+ if vars[n]['kindselector'].has_key('kind'):
+ l = vars[n]['kindselector']['kind']
+ try:
+ l = str(eval(l,{},params))
+ except:
+ pass
+ vars[n]['kindselector']['kind'] = l
+
+ savelindims = {}
+ if vars[n].has_key('attrspec'):
+ attr=vars[n]['attrspec']
+ attr.reverse()
+ vars[n]['attrspec']=[]
+ dim,intent,depend,check,note=None,None,None,None,None
+ for a in attr:
+ if a[:9]=='dimension': dim=(string.strip(a[9:]))[1:-1]
+ elif a[:6]=='intent': intent=(string.strip(a[6:]))[1:-1]
+ elif a[:6]=='depend': depend=(string.strip(a[6:]))[1:-1]
+ elif a[:5]=='check': check=(string.strip(a[5:]))[1:-1]
+ elif a[:4]=='note': note=(string.strip(a[4:]))[1:-1]
+ else: vars[n]=setattrspec(vars[n],a)
+ if intent:
+ if not vars[n].has_key('intent'): vars[n]['intent']=[]
+ for c in map(string.strip,string.split(markoutercomma(intent),'@,@')):
+ if not c in vars[n]['intent']:
+ vars[n]['intent'].append(c)
+ intent=None
+ if note:
+ note=string.replace(note,'\\n\\n','\n\n')
+ note=string.replace(note,'\\n ','\n')
+ if not vars[n].has_key('note'): vars[n]['note']=[note]
+ else: vars[n]['note'].append(note)
+ note=None
+ if depend is not None:
+ if not vars[n].has_key('depend'): vars[n]['depend']=[]
+ for c in rmbadname(map(string.strip,string.split(markoutercomma(depend),'@,@'))):
+ if c not in vars[n]['depend']:
+ vars[n]['depend'].append(c)
+ depend=None
+ if check is not None:
+ if not vars[n].has_key('check'): vars[n]['check']=[]
+ for c in map(string.strip,string.split(markoutercomma(check),'@,@')):
+ if not c in vars[n]['check']:
+ vars[n]['check'].append(c)
+ check=None
+ if dim and not vars[n].has_key('dimension'):
+ vars[n]['dimension']=[]
+ for d in rmbadname(map(string.strip,string.split(markoutercomma(dim),'@,@'))):
+ star = '*'
+ if d==':': star=':'
+ if params.has_key(d):
+ d = str(params[d])
+ for p in params.keys():
+ m = re.match(r'(?P<before>.*?)\b'+p+r'\b(?P<after>.*)',d,re.I)
+ if m:
+ #outmess('analyzevars:replacing parameter %s in %s (dimension of %s) with %s\n'%(`p`,`d`,`n`,`params[p]`))
+ d = m.group('before')+str(params[p])+m.group('after')
+ if d==star:
+ dl = [star]
+ else:
+ dl=string.split(markoutercomma(d,':'),'@:@')
+ if len(dl)==2 and '*' in dl: # e.g. dimension(5:*)
+ dl = ['*']
+ d = '*'
+ if len(dl)==1 and not dl[0]==star: dl = ['1',dl[0]]
+ if len(dl)==2:
+ d,v,di = getarrlen(dl,block['vars'].keys())
+ if d[:4] == '1 * ': d = d[4:]
+ if di and di[-4:] == '/(1)': di = di[:-4]
+ if v: savelindims[d] = v,di
+ vars[n]['dimension'].append(d)
+ if vars[n].has_key('dimension'):
+ if isintent_c(vars[n]):
+ shape_macro = 'shape'
+ else:
+ shape_macro = 'shape'#'fshape'
+ if isstringarray(vars[n]):
+ if vars[n].has_key('charselector'):
+ d = vars[n]['charselector']
+ if d.has_key('*'):
+ d = d['*']
+ errmess('analyzevars: character array "character*%s %s(%s)" is considered as "character %s(%s)"; "intent(c)" is forced.\n'\
+ %(d,n,
+ ','.join(vars[n]['dimension']),
+ n,','.join(vars[n]['dimension']+[d])))
+ vars[n]['dimension'].append(d)
+ del vars[n]['charselector']
+ if not vars[n].has_key('intent'):
+ vars[n]['intent'] = []
+ if 'c' not in vars[n]['intent']:
+ vars[n]['intent'].append('c')
+ else:
+ errmess("analyzevars: charselector=%r unhandled." % (d))
+ if not vars[n].has_key('check') and block.has_key('args') and n in block['args']:
+ flag=not vars[n].has_key('depend')
+ if flag: vars[n]['depend']=[]
+ vars[n]['check']=[]
+ if vars[n].has_key('dimension'):
+ #/----< no check
+ #vars[n]['check'].append('rank(%s)==%s'%(n,len(vars[n]['dimension'])))
+ i=-1; ni=len(vars[n]['dimension'])
+ for d in vars[n]['dimension']:
+ ddeps=[] # dependecies of 'd'
+ ad=''
+ pd=''
+ #origd = d
+ if not vars.has_key(d):
+ if savelindims.has_key(d):
+ pd,ad='(',savelindims[d][1]
+ d = savelindims[d][0]
+ else:
+ for r in block['args']:
+ #for r in block['vars'].keys():
+ if not vars.has_key(r): continue
+ if re.match(r'.*?\b'+r+r'\b',d,re.I):
+ ddeps.append(r)
+ if vars.has_key(d):
+ if vars[d].has_key('attrspec'):
+ for aa in vars[d]['attrspec']:
+ if aa[:6]=='depend':
+ ddeps=ddeps+string.split((string.strip(aa[6:]))[1:-1],',')
+ if vars[d].has_key('depend'):
+ ddeps=ddeps+vars[d]['depend']
+ i=i+1
+ if vars.has_key(d) and (not vars[d].has_key('depend')) \
+ and (not vars[d].has_key('=')) and (d not in vars[n]['depend']) \
+ and l_or(isintent_in,isintent_inout,isintent_inplace)(vars[n]):
+ vars[d]['depend']=[n]
+ if ni>1:
+ vars[d]['=']='%s%s(%s,%s)%s'% (pd,shape_macro,n,i,ad)
+ else:
+ vars[d]['=']='%slen(%s)%s'% (pd,n,ad)
+ # /---< no check
+ if 1 and not vars[d].has_key('check'):
+ if ni>1:
+ vars[d]['check']=['%s%s(%s,%i)%s==%s'\
+ %(pd,shape_macro,n,i,ad,d)]
+ else:
+ vars[d]['check']=['%slen(%s)%s>=%s'%(pd,n,ad,d)]
+ if not vars[d].has_key('attrspec'): vars[d]['attrspec']=['optional']
+ if ('optional' not in vars[d]['attrspec']) and\
+ ('required' not in vars[d]['attrspec']):
+ vars[d]['attrspec'].append('optional')
+ elif d not in ['*',':']:
+ #/----< no check
+ #if ni>1: vars[n]['check'].append('shape(%s,%i)==%s'%(n,i,d))
+ #else: vars[n]['check'].append('len(%s)>=%s'%(n,d))
+ if flag:
+ if vars.has_key(d):
+ if n not in ddeps:
+ vars[n]['depend'].append(d)
+ else:
+ vars[n]['depend'] = vars[n]['depend'] + ddeps
+ elif isstring(vars[n]):
+ length='1'
+ if vars[n].has_key('charselector'):
+ if vars[n]['charselector'].has_key('*'):
+ length = _eval_length(vars[n]['charselector']['*'],
+ params)
+ vars[n]['charselector']['*']=length
+ elif vars[n]['charselector'].has_key('len'):
+ length = _eval_length(vars[n]['charselector']['len'],
+ params)
+ del vars[n]['charselector']['len']
+ vars[n]['charselector']['*']=length
+
+ if not vars[n]['check']: del vars[n]['check']
+ if flag and not vars[n]['depend']: del vars[n]['depend']
+ if vars[n].has_key('='):
+ if not vars[n].has_key('attrspec'): vars[n]['attrspec']=[]
+ if ('optional' not in vars[n]['attrspec']) and \
+ ('required' not in vars[n]['attrspec']):
+ vars[n]['attrspec'].append('optional')
+ if not vars[n].has_key('depend'):
+ vars[n]['depend']=[]
+ for v,m in dep_matches.items():
+ if m(vars[n]['=']): vars[n]['depend'].append(v)
+ if not vars[n]['depend']: del vars[n]['depend']
+ if isscalar(vars[n]):
+ vars[n]['='] = _eval_scalar(vars[n]['='],params)
+
+ for n in vars.keys():
+ if n==block['name']: # n is block name
+ if vars[n].has_key('note'):
+ block['note']=vars[n]['note']
+ if block['block']=='function':
+ if block.has_key('result') and vars.has_key(block['result']):
+ vars[n]=appenddecl(vars[n],vars[block['result']])
+ if block.has_key('prefix'):
+ pr=block['prefix']; ispure=0; isrec=1
+ pr1=string.replace(pr,'pure','')
+ ispure=(not pr==pr1)
+ pr=string.replace(pr1,'recursive','')
+ isrec=(not pr==pr1)
+ m=typespattern[0].match(pr)
+ if m:
+ typespec,selector,attr,edecl=cracktypespec0(m.group('this'),m.group('after'))
+ kindselect,charselect,typename=cracktypespec(typespec,selector)
+ vars[n]['typespec']=typespec
+ if kindselect:
+ if kindselect.has_key('kind'):
+ try:
+ kindselect['kind'] = eval(kindselect['kind'],{},params)
+ except:
+ pass
+ vars[n]['kindselector']=kindselect
+ if charselect: vars[n]['charselector']=charselect
+ if typename: vars[n]['typename']=typename
+ if ispure: vars[n]=setattrspec(vars[n],'pure')
+ if isrec: vars[n]=setattrspec(vars[n],'recursive')
+ else:
+ outmess('analyzevars: prefix (%s) were not used\n'%`block['prefix']`)
+ if not block['block'] in ['module','pythonmodule','python module','block data']:
+ if block.has_key('commonvars'):
+ neededvars=copy.copy(block['args']+block['commonvars'])
+ else:
+ neededvars=copy.copy(block['args'])
+ for n in vars.keys():
+ if l_or(isintent_callback,isintent_aux)(vars[n]):
+ neededvars.append(n)
+ if block.has_key('entry'):
+ neededvars.extend(block['entry'].keys())
+ for k in block['entry'].keys():
+ for n in block['entry'][k]:
+ if n not in neededvars:
+ neededvars.append(n)
+ if block['block']=='function':
+ if block.has_key('result'):
+ neededvars.append(block['result'])
+ else:
+ neededvars.append(block['name'])
+ if block['block'] in ['subroutine','function']:
+ name = block['name']
+ if vars.has_key(name) and vars[name].has_key('intent'):
+ block['intent'] = vars[name]['intent']
+ if block['block'] == 'type':
+ neededvars.extend(vars.keys())
+ for n in vars.keys():
+ if n not in neededvars:
+ del vars[n]
+ return vars
+analyzeargs_re_1 = re.compile(r'\A[a-z]+[\w$]*\Z',re.I)
+def analyzeargs(block):
+ setmesstext(block)
+ implicitrules,attrrules=buildimplicitrules(block)
+ if not block.has_key('args'): block['args']=[]
+ args=[]
+ re_1 = analyzeargs_re_1
+ for a in block['args']:
+ if not re_1.match(a): # `a` is an expression
+ at=determineexprtype(a,block['vars'],implicitrules)
+ na='e_'
+ for c in a:
+ if c not in string.lowercase+string.digits: c='_'
+ na=na+c
+ if na[-1]=='_': na=na+'e'
+ else: na=na+'_e'
+ a=na
+ while block['vars'].has_key(a) or a in block['args']: a=a+'r'
+ block['vars'][a]=at
+ args.append(a)
+ if not block['vars'].has_key(a):
+ block['vars'][a]={}
+ if block.has_key('externals') and a in block['externals']+block['interfaced']:
+ block['vars'][a]=setattrspec(block['vars'][a],'external')
+ block['args']=args
+
+ if block.has_key('entry'):
+ for k,args1 in block['entry'].items():
+ for a in args1:
+ if not block['vars'].has_key(a):
+ block['vars'][a]={}
+
+ for b in block['body']:
+ if b['name'] in args:
+ if not block.has_key('externals'): block['externals']=[]
+ if b['name'] not in block['externals']:
+ block['externals'].append(b['name'])
+ if block.has_key('result') and not block['vars'].has_key(block['result']):
+ block['vars'][block['result']]={}
+ return block
+determineexprtype_re_1 = re.compile(r'\A\(.+?[,].+?\)\Z',re.I)
+determineexprtype_re_2 = re.compile(r'\A[+-]?\d+(_(P<name>[\w]+)|)\Z',re.I)
+determineexprtype_re_3 = re.compile(r'\A[+-]?[\d.]+[\d+-de.]*(_(P<name>[\w]+)|)\Z',re.I)
+determineexprtype_re_4 = re.compile(r'\A\(.*\)\Z',re.I)
+determineexprtype_re_5 = re.compile(r'\A(?P<name>\w+)\s*\(.*?\)\s*\Z',re.I)
+def _ensure_exprdict(r):
+ if type(r) is type(0):
+ return {'typespec':'integer'}
+ if type(r) is type(0.0):
+ return {'typespec':'real'}
+ if type(r) is type(0j):
+ return {'typespec':'complex'}
+ assert type(r) is type({}),`r`
+ return r
+
+def determineexprtype(expr,vars,rules={}):
+ if vars.has_key(expr):
+ return _ensure_exprdict(vars[expr])
+ expr=string.strip(expr)
+ if determineexprtype_re_1.match(expr):
+ return {'typespec':'complex'}
+ m=determineexprtype_re_2.match(expr)
+ if m:
+ if m.groupdict().has_key('name') and m.group('name'):
+ outmess('determineexprtype: selected kind types not supported (%s)\n'%`expr`)
+ return {'typespec':'integer'}
+ m = determineexprtype_re_3.match(expr)
+ if m:
+ if m.groupdict().has_key('name') and m.group('name'):
+ outmess('determineexprtype: selected kind types not supported (%s)\n'%`expr`)
+ return {'typespec':'real'}
+ for op in ['+','-','*','/']:
+ for e in map(string.strip,string.split(markoutercomma(expr,comma=op),'@'+op+'@')):
+ if vars.has_key(e):
+ return _ensure_exprdict(vars[e])
+ t={}
+ if determineexprtype_re_4.match(expr): # in parenthesis
+ t=determineexprtype(expr[1:-1],vars,rules)
+ else:
+ m = determineexprtype_re_5.match(expr)
+ if m:
+ rn=m.group('name')
+ t=determineexprtype(m.group('name'),vars,rules)
+ if t and t.has_key('attrspec'): del t['attrspec']
+ if not t:
+ if rules.has_key(rn[0]):
+ return _ensure_exprdict(rules[rn[0]])
+ if expr[0] in '\'"':
+ return {'typespec':'character','charselector':{'*':'*'}}
+ if not t:
+ outmess('determineexprtype: could not determine expressions (%s) type.\n'%(`expr`))
+ return t
+######
+def crack2fortrangen(block,tab='\n'):
+ setmesstext(block)
+ ret=''
+ if type(block) is type([]):
+ for g in block:
+ ret=ret+crack2fortrangen(g,tab)
+ return ret
+ prefix=''
+ name=''
+ args=''
+ blocktype=block['block']
+ if blocktype=='program': return ''
+ al=[]
+ if block.has_key('name'): name=block['name']
+ if block.has_key('args'):
+ vars = block['vars']
+ al = [a for a in block['args'] if not isintent_callback(vars[a])]
+ if block['block']=='function' or al:
+ args='(%s)'%string.join(al,',')
+ f2pyenhancements = ''
+ if block.has_key('f2pyenhancements'):
+ for k in block['f2pyenhancements'].keys():
+ f2pyenhancements = '%s%s%s %s'%(f2pyenhancements,tab+tabchar,k,block['f2pyenhancements'][k])
+ intent_lst = block.get('intent',[])[:]
+ if blocktype=='function' and 'callback' in intent_lst:
+ intent_lst.remove('callback')
+ if intent_lst:
+ f2pyenhancements = '%s%sintent(%s) %s'%\
+ (f2pyenhancements,tab+tabchar,
+ string.join(intent_lst,','),name)
+ use=''
+ if block.has_key('use'):
+ use=use2fortran(block['use'],tab+tabchar)
+ common=''
+ if block.has_key('common'):
+ common=common2fortran(block['common'],tab+tabchar)
+ if name=='unknown_interface': name=''
+ result=''
+ if block.has_key('result'):
+ result=' result (%s)'%block['result']
+ if block['result'] not in al:
+ al.append(block['result'])
+ #if block.has_key('prefix'): prefix=block['prefix']+' '
+ body=crack2fortrangen(block['body'],tab+tabchar)
+ vars=vars2fortran(block,block['vars'],al,tab+tabchar)
+ mess=''
+ if block.has_key('from'):
+ mess='! in %s'%block['from']
+ if block.has_key('entry'):
+ entry_stmts = ''
+ for k,i in block['entry'].items():
+ entry_stmts = '%s%sentry %s(%s)' \
+ % (entry_stmts,tab+tabchar,k,string.join(i,','))
+ body = body + entry_stmts
+ if blocktype=='block data' and name=='_BLOCK_DATA_':
+ name = ''
+ ret='%s%s%s %s%s%s %s%s%s%s%s%s%send %s %s'%(tab,prefix,blocktype,name,args,result,mess,f2pyenhancements,use,vars,common,body,tab,blocktype,name)
+ return ret
+def common2fortran(common,tab=''):
+ ret=''
+ for k in common.keys():
+ if k=='_BLNK_':
+ ret='%s%scommon %s'%(ret,tab,string.join(common[k],','))
+ else:
+ ret='%s%scommon /%s/ %s'%(ret,tab,k,string.join(common[k],','))
+ return ret
+def use2fortran(use,tab=''):
+ ret=''
+ for m in use.keys():
+ ret='%s%suse %s,'%(ret,tab,m)
+ if use[m]=={}:
+ if ret and ret[-1]==',': ret=ret[:-1]
+ continue
+ if use[m].has_key('only') and use[m]['only']:
+ ret='%s,only:'%(ret)
+ if use[m].has_key('map') and use[m]['map']:
+ c=' '
+ for k in use[m]['map'].keys():
+ if k==use[m]['map'][k]:
+ ret='%s%s%s'%(ret,c,k); c=','
+ else:
+ ret='%s%s%s=>%s'%(ret,c,k,use[m]['map'][k]); c=','
+ if ret and ret[-1]==',': ret=ret[:-1]
+ return ret
+def true_intent_list(var):
+ lst = var['intent']
+ ret = []
+ for intent in lst:
+ try:
+ exec('c = isintent_%s(var)' % intent)
+ except NameError:
+ c = 0
+ if c:
+ ret.append(intent)
+ return ret
+def vars2fortran(block,vars,args,tab=''):
+ """
+ TODO:
+ public sub
+ ...
+ """
+ setmesstext(block)
+ ret=''
+ nout=[]
+ for a in args:
+ if block['vars'].has_key(a): nout.append(a)
+ if block.has_key('commonvars'):
+ for a in block['commonvars']:
+ if vars.has_key(a):
+ if a not in nout: nout.append(a)
+ else: errmess('vars2fortran: Confused?!: "%s" is not defined in vars.\n'%a)
+ if block.has_key('varnames'):
+ nout.extend(block['varnames'])
+ for a in vars.keys():
+ if a not in nout: nout.append(a)
+ for a in nout:
+ if vars[a].has_key('depend'):
+ for d in vars[a]['depend']:
+ if vars.has_key(d) and vars[d].has_key('depend') and a in vars[d]['depend']:
+ errmess('vars2fortran: Warning: cross-dependence between variables "%s" and "%s"\n'%(a,d))
+ if block.has_key('externals') and a in block['externals']:
+ if isintent_callback(vars[a]):
+ ret='%s%sintent(callback) %s'%(ret,tab,a)
+ ret='%s%sexternal %s'%(ret,tab,a)
+ if isoptional(vars[a]):
+ ret='%s%soptional %s'%(ret,tab,a)
+ if vars.has_key(a) and not vars[a].has_key('typespec'):
+ continue
+ cont=1
+ for b in block['body']:
+ if a==b['name'] and b['block']=='function': cont=0;break
+ if cont: continue
+ if not vars.has_key(a):
+ show(vars)
+ outmess('vars2fortran: No definition for argument "%s".\n'%a)
+ continue
+ if a==block['name'] and not block['block']=='function':
+ continue
+ if not vars[a].has_key('typespec'):
+ if vars[a].has_key('attrspec') and 'external' in vars[a]['attrspec']:
+ if a in args:
+ ret='%s%sexternal %s'%(ret,tab,a)
+ continue
+ show(vars[a])
+ outmess('vars2fortran: No typespec for argument "%s".\n'%a)
+ continue
+ vardef=vars[a]['typespec']
+ if vardef=='type' and vars[a].has_key('typename'):
+ vardef='%s(%s)'%(vardef,vars[a]['typename'])
+ selector={}
+ if vars[a].has_key('kindselector'): selector=vars[a]['kindselector']
+ elif vars[a].has_key('charselector'): selector=vars[a]['charselector']
+ if selector.has_key('*'):
+ if selector['*'] in ['*',':']:
+ vardef='%s*(%s)'%(vardef,selector['*'])
+ else:
+ vardef='%s*%s'%(vardef,selector['*'])
+ else:
+ if selector.has_key('len'):
+ vardef='%s(len=%s'%(vardef,selector['len'])
+ if selector.has_key('kind'):
+ vardef='%s,kind=%s)'%(vardef,selector['kind'])
+ else:
+ vardef='%s)'%(vardef)
+ elif selector.has_key('kind'):
+ vardef='%s(kind=%s)'%(vardef,selector['kind'])
+ c=' '
+ if vars[a].has_key('attrspec'):
+ attr=[]
+ for l in vars[a]['attrspec']:
+ if l not in ['external']:
+ attr.append(l)
+ if attr:
+ vardef='%s %s'%(vardef,string.join(attr,','))
+ c=','
+ if vars[a].has_key('dimension'):
+# if not isintent_c(vars[a]):
+# vars[a]['dimension'].reverse()
+ vardef='%s%sdimension(%s)'%(vardef,c,string.join(vars[a]['dimension'],','))
+ c=','
+ if vars[a].has_key('intent'):
+ lst = true_intent_list(vars[a])
+ if lst:
+ vardef='%s%sintent(%s)'%(vardef,c,string.join(lst,','))
+ c=','
+ if vars[a].has_key('check'):
+ vardef='%s%scheck(%s)'%(vardef,c,string.join(vars[a]['check'],','))
+ c=','
+ if vars[a].has_key('depend'):
+ vardef='%s%sdepend(%s)'%(vardef,c,string.join(vars[a]['depend'],','))
+ c=','
+ if vars[a].has_key('='):
+ v = vars[a]['=']
+ if vars[a]['typespec'] in ['complex','double complex']:
+ try:
+ v = eval(v)
+ v = '(%s,%s)' % (v.real,v.imag)
+ except:
+ pass
+ vardef='%s :: %s=%s'%(vardef,a,v)
+ else:
+ vardef='%s :: %s'%(vardef,a)
+ ret='%s%s%s'%(ret,tab,vardef)
+ return ret
+######
+
+def crackfortran(files):
+ global usermodules
+ outmess('Reading fortran codes...\n',0)
+ readfortrancode(files,crackline)
+ outmess('Post-processing...\n',0)
+ usermodules=[]
+ postlist=postcrack(grouplist[0])
+ outmess('Post-processing (stage 2)...\n',0)
+ postlist=postcrack2(postlist)
+ return usermodules+postlist
+def crack2fortran(block):
+ global f2py_version
+ pyf=crack2fortrangen(block)+'\n'
+ header="""! -*- f90 -*-
+! Note: the context of this file is case sensitive.
+"""
+ footer="""
+! This file was auto-generated with f2py (version:%s).
+! See http://cens.ioc.ee/projects/f2py2e/
+"""%(f2py_version)
+ return header+pyf+footer
+
+if __name__ == "__main__":
+ files=[]
+ funcs=[]
+ f=1;f2=0;f3=0
+ showblocklist=0
+ for l in sys.argv[1:]:
+ if l=='': pass
+ elif l[0]==':':
+ f=0
+ elif l=='-quiet':
+ quiet=1
+ verbose=0
+ elif l=='-verbose':
+ verbose=2
+ quiet=0
+ elif l=='-fix':
+ if strictf77:
+ outmess('Use option -f90 before -fix if Fortran 90 code is in fix form.\n',0)
+ skipemptyends=1
+ sourcecodeform='fix'
+ elif l=='-skipemptyends':
+ skipemptyends=1
+ elif l=='--ignore-contains':
+ ignorecontains=1
+ elif l=='-f77':
+ strictf77=1
+ sourcecodeform='fix'
+ elif l=='-f90':
+ strictf77=0
+ sourcecodeform='free'
+ skipemptyends=1
+ elif l=='-h':
+ f2=1
+ elif l=='-show':
+ showblocklist=1
+ elif l=='-m':
+ f3=1
+ elif l[0]=='-':
+ errmess('Unknown option %s\n'%`l`)
+ elif f2:
+ f2=0
+ pyffilename=l
+ elif f3:
+ f3=0
+ f77modulename=l
+ elif f:
+ try:
+ open(l).close()
+ files.append(l)
+ except IOError,detail:
+ errmess('IOError: %s\n'%str(detail))
+ else:
+ funcs.append(l)
+ if not strictf77 and f77modulename and not skipemptyends:
+ outmess("""\
+ Warning: You have specifyied module name for non Fortran 77 code
+ that should not need one (expect if you are scanning F90 code
+ for non module blocks but then you should use flag -skipemptyends
+ and also be sure that the files do not contain programs without program statement).
+""",0)
+
+ postlist=crackfortran(files,funcs)
+ if pyffilename:
+ outmess('Writing fortran code to file %s\n'%`pyffilename`,0)
+ pyf=crack2fortran(postlist)
+ f=open(pyffilename,'w')
+ f.write(pyf)
+ f.close()
+ if showblocklist:
+ show(postlist)
diff --git a/numpy/f2py/diagnose.py b/numpy/f2py/diagnose.py
new file mode 100644
index 000000000..34784b39c
--- /dev/null
+++ b/numpy/f2py/diagnose.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+
+import os,sys,tempfile
+
+def run_command(cmd):
+ print 'Running %r:' % (cmd)
+ s = os.system(cmd)
+ print '------'
+def run():
+ _path = os.getcwd()
+ os.chdir(tempfile.gettempdir())
+ print '------'
+ print 'os.name=%r' % (os.name)
+ print '------'
+ print 'sys.platform=%r' % (sys.platform)
+ print '------'
+ print 'sys.version:'
+ print sys.version
+ print '------'
+ print 'sys.prefix:'
+ print sys.prefix
+ print '------'
+ print 'sys.path=%r' % (':'.join(sys.path))
+ print '------'
+ try:
+ import Numeric
+ has_Numeric = 1
+ except ImportError:
+ print 'Failed to import Numeric:',sys.exc_value
+ has_Numeric = 0
+ try:
+ import numarray
+ has_numarray = 1
+ except ImportError:
+ print 'Failed to import numarray:',sys.exc_value
+ has_numarray = 0
+ try:
+ import scipy.base
+ has_newscipy = 1
+ except ImportError:
+ print 'Failed to import new scipy:', sys.exc_value
+ has_newscipy = 0
+ try:
+ import f2py2e
+ has_f2py2e = 1
+ except ImportError:
+ print 'Failed to import f2py2e:',sys.exc_value
+ has_f2py2e = 0
+ try:
+ import scipy.distutils
+ has_scipy_distutils = 2
+ except ImportError:
+ try:
+ import scipy_distutils
+ has_scipy_distutils = 1
+ except ImportError:
+ print 'Failed to import scipy_distutils:',sys.exc_value
+ has_scipy_distutils = 0
+ if has_Numeric:
+ try:
+ print 'Found Numeric version %r in %s' % \
+ (Numeric.__version__,Numeric.__file__)
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ if has_numarray:
+ try:
+ print 'Found numarray version %r in %s' % \
+ (numarray.__version__,numarray.__file__)
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ if has_newscipy:
+ try:
+ print 'Found new scipy version %r in %s' % \
+ (scipy.__version__, scipy.__file__)
+ except Exception,msg:
+ print 'error:', msg
+ print '------'
+ if has_f2py2e:
+ try:
+ print 'Found f2py2e version %r in %s' % \
+ (f2py2e.__version__.version,f2py2e.__file__)
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ if has_scipy_distutils:
+ try:
+ if has_scipy_distutils==2:
+ print 'Found scipy.distutils version %r in %r' % (\
+ scipy.distutils.__version__,
+ scipy.distutils.__file__)
+ else:
+ print 'Found scipy_distutils version %r in %r' % (\
+ scipy_distutils.scipy_distutils_version.scipy_distutils_version,
+ scipy_distutils.__file__)
+ print '------'
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ try:
+ if has_scipy_distutils==1:
+ print 'Importing scipy_distutils.command.build_flib ...',
+ import scipy_distutils.command.build_flib as build_flib
+ print 'ok'
+ print '------'
+ try:
+ print 'Checking availability of supported Fortran compilers:'
+ for compiler_class in build_flib.all_compilers:
+ compiler_class(verbose=1).is_available()
+ print '------'
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ except Exception,msg:
+ print 'error:',msg,'(ignore it, build_flib is obsolute for scipy.distutils 0.2.2 and up)'
+ print '------'
+ try:
+ if has_scipy_distutils==2:
+ print 'Importing scipy.distutils.fcompiler ...',
+ import scipy.distutils.fcompiler as fcompiler
+ else:
+ print 'Importing scipy_distutils.fcompiler ...',
+ import scipy_distutils.fcompiler as fcompiler
+ print 'ok'
+ print '------'
+ try:
+ print 'Checking availability of supported Fortran compilers:'
+ fcompiler.show_fcompilers()
+ print '------'
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ try:
+ if has_scipy_distutils==2:
+ print 'Importing scipy.distutils.cpuinfo ...',
+ from scipy.distutils.cpuinfo import cpuinfo
+ print 'ok'
+ print '------'
+ else:
+ try:
+ print 'Importing scipy_distutils.command.cpuinfo ...',
+ from scipy_distutils.command.cpuinfo import cpuinfo
+ print 'ok'
+ print '------'
+ except Exception,msg:
+ print 'error:',msg,'(ignore it)'
+ print 'Importing scipy_distutils.cpuinfo ...',
+ from scipy_distutils.cpuinfo import cpuinfo
+ print 'ok'
+ print '------'
+ cpu = cpuinfo()
+ print 'CPU information:',
+ for name in dir(cpuinfo):
+ if name[0]=='_' and name[1]!='_' and getattr(cpu,name[1:])():
+ print name[1:],
+ print '------'
+ except Exception,msg:
+ print 'error:',msg
+ print '------'
+ os.chdir(_path)
+if __name__ == "__main__":
+ run()
diff --git a/numpy/f2py/doc/Makefile b/numpy/f2py/doc/Makefile
new file mode 100644
index 000000000..2f241da0a
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/Release-1.x.txt b/numpy/f2py/doc/Release-1.x.txt
new file mode 100644
index 000000000..46d6fbf09
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/Release-2.x.txt b/numpy/f2py/doc/Release-2.x.txt
new file mode 100644
index 000000000..807eb0ca8
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/Release-3.x.txt b/numpy/f2py/doc/Release-3.x.txt
new file mode 100644
index 000000000..940771015
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/Release-4.x.txt b/numpy/f2py/doc/Release-4.x.txt
new file mode 100644
index 000000000..ed071a0cb
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/apps.tex b/numpy/f2py/doc/apps.tex
new file mode 100644
index 000000000..513c048bd
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/bugs.tex b/numpy/f2py/doc/bugs.tex
new file mode 100644
index 000000000..699ecf530
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/collectinput.py b/numpy/f2py/doc/collectinput.py
new file mode 100755
index 000000000..c2ce2bf89
--- /dev/null
+++ b/numpy/f2py/doc/collectinput.py
@@ -0,0 +1,77 @@
+#!/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 LGPL. See http://www.fsf.org
+
+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
+"""
+
+__version__ = "0.0"
+
+stdoutflag=0
+import sys,os,string,fileinput,re,commands
+
+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=string.strip(l)
+ 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 commands.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/numpy/f2py/doc/commands.tex b/numpy/f2py/doc/commands.tex
new file mode 100644
index 000000000..5101a9ff5
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/ex1/arr.f b/numpy/f2py/doc/ex1/arr.f
new file mode 100644
index 000000000..c4e49988f
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/ex1/bar.f b/numpy/f2py/doc/ex1/bar.f
new file mode 100644
index 000000000..c723b5af1
--- /dev/null
+++ b/numpy/f2py/doc/ex1/bar.f
@@ -0,0 +1,4 @@
+ function bar(a,b)
+ integer a,b,bar
+ bar = a + b
+ end
diff --git a/numpy/f2py/doc/ex1/foo.f b/numpy/f2py/doc/ex1/foo.f
new file mode 100644
index 000000000..cdcac4103
--- /dev/null
+++ b/numpy/f2py/doc/ex1/foo.f
@@ -0,0 +1,5 @@
+ subroutine foo(a)
+ integer a
+cf2py intent(in,out) :: a
+ a = a + 5
+ end
diff --git a/numpy/f2py/doc/ex1/foobar-smart.f90 b/numpy/f2py/doc/ex1/foobar-smart.f90
new file mode 100644
index 000000000..61385a685
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/ex1/foobar.f90 b/numpy/f2py/doc/ex1/foobar.f90
new file mode 100644
index 000000000..53ac5b506
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/ex1/foobarmodule.tex b/numpy/f2py/doc/ex1/foobarmodule.tex
new file mode 100644
index 000000000..32411ec03
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/ex1/runme b/numpy/f2py/doc/ex1/runme
new file mode 100755
index 000000000..2aac6158e
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2py2e.tex b/numpy/f2py/doc/f2py2e.tex
new file mode 100644
index 000000000..6e3e9d68c
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/README.txt b/numpy/f2py/doc/f2python9-final/README.txt
new file mode 100644
index 000000000..b907216b6
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/aerostructure.jpg b/numpy/f2py/doc/f2python9-final/aerostructure.jpg
new file mode 100644
index 000000000..896ad6e12
--- /dev/null
+++ b/numpy/f2py/doc/f2python9-final/aerostructure.jpg
Binary files differ
diff --git a/numpy/f2py/doc/f2python9-final/flow.jpg b/numpy/f2py/doc/f2python9-final/flow.jpg
new file mode 100644
index 000000000..cfe0f85f3
--- /dev/null
+++ b/numpy/f2py/doc/f2python9-final/flow.jpg
Binary files differ
diff --git a/numpy/f2py/doc/f2python9-final/mk_html.sh b/numpy/f2py/doc/f2python9-final/mk_html.sh
new file mode 100755
index 000000000..944110e93
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/mk_pdf.sh b/numpy/f2py/doc/f2python9-final/mk_pdf.sh
new file mode 100755
index 000000000..b773028b7
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/mk_ps.sh b/numpy/f2py/doc/f2python9-final/mk_ps.sh
new file mode 100755
index 000000000..4b0863fcd
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/src/examples/exp1.f b/numpy/f2py/doc/f2python9-final/src/examples/exp1.f
new file mode 100644
index 000000000..36bee50b0
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/src/examples/exp1mess.txt b/numpy/f2py/doc/f2python9-final/src/examples/exp1mess.txt
new file mode 100644
index 000000000..ae1545718
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/src/examples/exp1session.txt b/numpy/f2py/doc/f2python9-final/src/examples/exp1session.txt
new file mode 100644
index 000000000..9bec9198e
--- /dev/null
+++ b/numpy/f2py/doc/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 \ No newline at end of file
diff --git a/numpy/f2py/doc/f2python9-final/src/examples/foo.pyf b/numpy/f2py/doc/f2python9-final/src/examples/foo.pyf
new file mode 100644
index 000000000..516bb292f
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/src/examples/foom.pyf b/numpy/f2py/doc/f2python9-final/src/examples/foom.pyf
new file mode 100644
index 000000000..6392ebc95
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/f2python9-final/structure.jpg b/numpy/f2py/doc/f2python9-final/structure.jpg
new file mode 100644
index 000000000..9aa691339
--- /dev/null
+++ b/numpy/f2py/doc/f2python9-final/structure.jpg
Binary files differ
diff --git a/numpy/f2py/doc/fortranobject.tex b/numpy/f2py/doc/fortranobject.tex
new file mode 100644
index 000000000..dbb244cdd
--- /dev/null
+++ b/numpy/f2py/doc/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; /* PyArray_<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},PyArray_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},PyArray_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},PyArray_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/numpy/f2py/doc/index.html b/numpy/f2py/doc/index.html
new file mode 100644
index 000000000..abddd7d43
--- /dev/null
+++ b/numpy/f2py/doc/index.html
@@ -0,0 +1,265 @@
+<!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 &shy; 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 &shy; 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> is released under the terms of <a
+href="http://www.fsf.org/copyleft/lesser.html">GNU LGPL</a>.
+
+
+<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(&lt;LaTeX text&gt;)</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.scipy.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://scipy.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">&lt;pearu(at)ioc.ee&gt;</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-->
+
+<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/numpy/f2py/doc/intro.tex b/numpy/f2py/doc/intro.tex
new file mode 100644
index 000000000..d9625b09c
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/multiarray/array_from_pyobj.c b/numpy/f2py/doc/multiarray/array_from_pyobj.c
new file mode 100644
index 000000000..7e0de9a74
--- /dev/null
+++ b/numpy/f2py/doc/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 &= ~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 &= ~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 &= ~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 &= ~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 &= ~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 &= ~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/numpy/f2py/doc/multiarray/bar.c b/numpy/f2py/doc/multiarray/bar.c
new file mode 100644
index 000000000..350636ea6
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/multiarray/foo.f b/numpy/f2py/doc/multiarray/foo.f
new file mode 100644
index 000000000..f8c39c4d1
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/multiarray/fortran_array_from_pyobj.txt b/numpy/f2py/doc/multiarray/fortran_array_from_pyobj.txt
new file mode 100644
index 000000000..c7b945c84
--- /dev/null
+++ b/numpy/f2py/doc/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> \ No newline at end of file
diff --git a/numpy/f2py/doc/multiarray/fun.pyf b/numpy/f2py/doc/multiarray/fun.pyf
new file mode 100644
index 000000000..ed5d1923f
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/multiarray/run.pyf b/numpy/f2py/doc/multiarray/run.pyf
new file mode 100644
index 000000000..bb12a439b
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/multiarray/transpose.txt b/numpy/f2py/doc/multiarray/transpose.txt
new file mode 100644
index 000000000..a8d41e6df
--- /dev/null
+++ b/numpy/f2py/doc/multiarray/transpose.txt
@@ -0,0 +1,1127 @@
+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/numpy/f2py/doc/multiarrays.txt b/numpy/f2py/doc/multiarrays.txt
new file mode 100644
index 000000000..704208976
--- /dev/null
+++ b/numpy/f2py/doc/multiarrays.txt
@@ -0,0 +1,120 @@
+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/numpy/f2py/doc/notes.tex b/numpy/f2py/doc/notes.tex
new file mode 100644
index 000000000..2746b049d
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/oldnews.html b/numpy/f2py/doc/oldnews.html
new file mode 100644
index 000000000..914265bbe
--- /dev/null
+++ b/numpy/f2py/doc/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>scipy_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">&lt;pearu(at)ioc.ee&gt;</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/numpy/f2py/doc/options.tex b/numpy/f2py/doc/options.tex
new file mode 100644
index 000000000..84d9410f8
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/python9.tex b/numpy/f2py/doc/python9.tex
new file mode 100644
index 000000000..cda3cd18b
--- /dev/null
+++ b/numpy/f2py/doc/python9.tex
@@ -0,0 +1,1046 @@
+\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/numpy/f2py/doc/signaturefile.tex b/numpy/f2py/doc/signaturefile.tex
new file mode 100644
index 000000000..3cd16d890
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/using_F_compiler.txt b/numpy/f2py/doc/using_F_compiler.txt
new file mode 100644
index 000000000..3067f0776
--- /dev/null
+++ b/numpy/f2py/doc/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/numpy/f2py/doc/win32_notes.txt b/numpy/f2py/doc/win32_notes.txt
new file mode 100644
index 000000000..1b7b9029c
--- /dev/null
+++ b/numpy/f2py/doc/win32_notes.txt
@@ -0,0 +1,85 @@
+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
+
diff --git a/numpy/f2py/docs/FAQ.txt b/numpy/f2py/docs/FAQ.txt
new file mode 100644
index 000000000..e2ed79445
--- /dev/null
+++ b/numpy/f2py/docs/FAQ.txt
@@ -0,0 +1,615 @@
+
+======================================================================
+ 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?
+----------------------
+
+You can send bug reports directly to me. Please, include information
+about your platform (operating system, version) and
+compilers/linkers, e.g. the output (both stdout/stderr) of
+::
+
+ python -c 'import f2py2e.diagnose;f2py2e.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.
+
+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 scipy_distutils when using F2PY from CVS?
+---------------------------------------------------------------
+
+To get scipy_distutils from SciPy CVS repository, run
+::
+
+ cd cvs/f2py2e/
+ make scipy_distutils
+
+This will checkout scipy_distutils to the current directory.
+
+You can upgrade scipy_distutils by executing
+::
+
+ cd cvs/f2py2e/scipy_distutils
+ cvs update -Pd
+
+and install it by executing
+::
+
+ cd cvs/f2py2e/scipy_distutils
+ python setup_scipy_distutils.py install
+
+In most of the time, f2py2e and scipy_distutils can be upgraded
+independently.
+
+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`_.
+
+
+Q: How to run tests and examples in f2py2e/test-suite/ directory?
+---------------------------------------------------------------------
+
+You shouldn't. These tests are obsolete and I have no intention to
+make them work. They will be removed in future.
+
+
+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/scipy/BUILD_WIN32.html#setting-up-environment
+
+Install scipy_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 scipy_distutils
+ from scipy_distutils.fcompiler import new_fcompiler
+ compiler = new_fcompiler() # or new_fcompiler(compiler='intel')
+ compiler.dump_properties()
+
+ # Using pre-0.2.2 scipy_distutils
+ import os
+ from scipy_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.scipy.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.scipy.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 scipy, 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/numpy/f2py/docs/HISTORY.txt b/numpy/f2py/docs/HISTORY.txt
new file mode 100644
index 000000000..876ab2362
--- /dev/null
+++ b/numpy/f2py/docs/HISTORY.txt
@@ -0,0 +1,1044 @@
+.. -*- 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 scipy.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_scipy_distutils`` function. From now on it is assumed
+ that proper version of ``scipy_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 scipy_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 scipy_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 scipy_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 scipy_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-scipy_distutils`` that is useful when making
+ f2py tar-ball with scipy_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 scipy_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 ``PyArray_LONG != PyArray_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 scipy_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 scipy_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 scipy_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 scipy_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 scipy_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 scipy_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 scipy_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 scipy_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 --scipy-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/numpy/f2py/docs/OLDNEWS.txt b/numpy/f2py/docs/OLDNEWS.txt
new file mode 100644
index 000000000..b21215464
--- /dev/null
+++ b/numpy/f2py/docs/OLDNEWS.txt
@@ -0,0 +1,63 @@
+
+.. topic:: Old F2PY NEWS
+
+ 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 scipy_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 \ No newline at end of file
diff --git a/numpy/f2py/docs/README.txt b/numpy/f2py/docs/README.txt
new file mode 100644
index 000000000..fc7149645
--- /dev/null
+++ b/numpy/f2py/docs/README.txt
@@ -0,0 +1,457 @@
+.. -*- rest -*-
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ F2PY: Fortran to Python interface generator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:Author: Pearu Peterson <pearu@cens.ioc.ee>
+:License: LGPL_.
+: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
+
+-------------------------------
+
+.. topic:: 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
+
+ `History of NEWS`__
+
+ __ OLDNEWS.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 ``scipy_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 scipy_distutils
+releases as:
+
+* `2.x`__/`F2PY-2-latest.tar.gz`__
+* `2.x`__/`scipy_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`__/`scipy_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/scipy_distutils-latest.tar.gz
+.. __: 2.x/
+.. __: 2.x/F2PY-2-latest.win32.exe
+.. __: 2.x/
+.. __: 2.x/scipy_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 ``scipy_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`_ (in CVS__)
+ The first thing to read about F2PY -- this document.
+
+__ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/README.txt?rev=HEAD&content-type=text/x-cvsweb-markup
+
+`usersguide/index.txt`_, `usersguide/f2py_usersguide.pdf`_
+ F2PY Users Guide and Reference Manual. Contains lots of examples.
+
+`FAQ.txt`_ (in CVS__)
+ F2PY Frequently Asked Questions.
+
+__ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/FAQ.txt?rev=HEAD&content-type=text/x-cvsweb-markup
+
+`TESTING.txt`_ (in CVS__)
+ About F2PY testing site. What tests are available and how to run them.
+
+__ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/TESTING.txt?rev=HEAD&content-type=text/x-cvsweb-markup
+
+`HISTORY.txt`_ (in CVS__)
+ A list of latest changes in F2PY. This is the most up-to-date
+ document on F2PY.
+
+__ http://cens.ioc.ee/cgi-bin/cvsweb/python/f2py2e/docs/HISTORY.txt?rev=HEAD&content-type=text/x-cvsweb-markup
+
+`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.scipy.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/
+.. _LGPL: http://www.fsf.org/copyleft/lesser.html
+.. _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/numpy/f2py/docs/TESTING.txt b/numpy/f2py/docs/TESTING.txt
new file mode 100644
index 000000000..feae18dc6
--- /dev/null
+++ b/numpy/f2py/docs/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 ``scipy_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/numpy/f2py/docs/THANKS.txt b/numpy/f2py/docs/THANKS.txt
new file mode 100644
index 000000000..cbaa083fc
--- /dev/null
+++ b/numpy/f2py/docs/THANKS.txt
@@ -0,0 +1,63 @@
+
+=================
+ Acknowledgments
+=================
+
+F2PY__ is a LGPL'd 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
+scipy_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/numpy/f2py/docs/default.css b/numpy/f2py/docs/default.css
new file mode 100644
index 000000000..9289e2826
--- /dev/null
+++ b/numpy/f2py/docs/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/numpy/f2py/docs/docutils.conf b/numpy/f2py/docs/docutils.conf
new file mode 100644
index 000000000..4e5a8425b
--- /dev/null
+++ b/numpy/f2py/docs/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/numpy/f2py/docs/hello.f b/numpy/f2py/docs/hello.f
new file mode 100644
index 000000000..3e0dc6d21
--- /dev/null
+++ b/numpy/f2py/docs/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/numpy/f2py/docs/pyforttest.pyf b/numpy/f2py/docs/pyforttest.pyf
new file mode 100644
index 000000000..79a9ae205
--- /dev/null
+++ b/numpy/f2py/docs/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/numpy/f2py/docs/pytest.py b/numpy/f2py/docs/pytest.py
new file mode 100644
index 000000000..abd3487df
--- /dev/null
+++ b/numpy/f2py/docs/pytest.py
@@ -0,0 +1,10 @@
+#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/numpy/f2py/docs/simple.f b/numpy/f2py/docs/simple.f
new file mode 100644
index 000000000..ba468a509
--- /dev/null
+++ b/numpy/f2py/docs/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/numpy/f2py/docs/simple_session.dat b/numpy/f2py/docs/simple_session.dat
new file mode 100644
index 000000000..10d9dc962
--- /dev/null
+++ b/numpy/f2py/docs/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/numpy/f2py/docs/usersguide/allocarr.f90 b/numpy/f2py/docs/usersguide/allocarr.f90
new file mode 100644
index 000000000..e0d6c2ec8
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/allocarr.f90
@@ -0,0 +1,16 @@
+module mod
+ real, allocatable, dimension(:,:) :: b
+contains
+ subroutine foo
+ integer k
+ if (allocated(b)) then
+ print*, "b=["
+ do k = 1,size(b,1)
+ print*, b(k,1:size(b,2))
+ enddo
+ print*, "]"
+ else
+ print*, "b is not allocated"
+ endif
+ end subroutine foo
+end module mod
diff --git a/numpy/f2py/docs/usersguide/allocarr_session.dat b/numpy/f2py/docs/usersguide/allocarr_session.dat
new file mode 100644
index 000000000..fc91959b7
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/allocarr_session.dat
@@ -0,0 +1,27 @@
+>>> import allocarr
+>>> print allocarr.mod.__doc__
+b - 'f'-array(-1,-1), not allocated
+foo - Function signature:
+ foo()
+
+>>> allocarr.mod.foo()
+ b is not allocated
+>>> allocarr.mod.b = [[1,2,3],[4,5,6]] # allocate/initialize b
+>>> allocarr.mod.foo()
+ b=[
+ 1.000000 2.000000 3.000000
+ 4.000000 5.000000 6.000000
+ ]
+>>> allocarr.mod.b # b is Fortran-contiguous
+array([[ 1., 2., 3.],
+ [ 4., 5., 6.]],'f')
+>>> allocarr.mod.b = [[1,2,3],[4,5,6],[7,8,9]] # reallocate/initialize b
+>>> allocarr.mod.foo()
+ b=[
+ 1.000000 2.000000 3.000000
+ 4.000000 5.000000 6.000000
+ 7.000000 8.000000 9.000000
+ ]
+>>> allocarr.mod.b = None # deallocate array
+>>> allocarr.mod.foo()
+ b is not allocated
diff --git a/numpy/f2py/docs/usersguide/array.f b/numpy/f2py/docs/usersguide/array.f
new file mode 100644
index 000000000..ef20c9c20
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/array.f
@@ -0,0 +1,17 @@
+C FILE: ARRAY.F
+ SUBROUTINE FOO(A,N,M)
+C
+C INCREMENT THE FIRST ROW AND DECREMENT THE FIRST COLUMN OF A
+C
+ INTEGER N,M,I,J
+ REAL*8 A(N,M)
+Cf2py intent(in,out,copy) a
+Cf2py integer intent(hide),depend(a) :: n=shape(a,0), m=shape(a,1)
+ DO J=1,M
+ A(1,J) = A(1,J) + 1D0
+ ENDDO
+ DO I=1,N
+ A(I,1) = A(I,1) - 1D0
+ ENDDO
+ END
+C END OF FILE ARRAY.F
diff --git a/numpy/f2py/docs/usersguide/array_session.dat b/numpy/f2py/docs/usersguide/array_session.dat
new file mode 100644
index 000000000..f64933482
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/array_session.dat
@@ -0,0 +1,65 @@
+>>> import arr
+>>> from Numeric import array
+>>> print arr.foo.__doc__
+foo - Function signature:
+ a = foo(a,[overwrite_a])
+Required arguments:
+ a : input rank-2 array('d') with bounds (n,m)
+Optional arguments:
+ overwrite_a := 0 input int
+Return objects:
+ a : rank-2 array('d') with bounds (n,m)
+
+>>> a=arr.foo([[1,2,3],
+... [4,5,6]])
+copied an array using PyArray_CopyFromObject: size=6, elsize=8
+>>> print a
+[[ 1. 3. 4.]
+ [ 3. 5. 6.]]
+>>> a.iscontiguous(), arr.has_column_major_storage(a)
+(0, 1)
+>>> b=arr.foo(a) # even if a is proper-contiguous
+... # and has proper type, a copy is made
+... # forced by intent(copy) attribute
+... # to preserve its original contents
+...
+copied an array using copy_ND_array: size=6, elsize=8
+>>> print a
+[[ 1. 3. 4.]
+ [ 3. 5. 6.]]
+>>> print b
+[[ 1. 4. 5.]
+ [ 2. 5. 6.]]
+>>> b=arr.foo(a,overwrite_a=1) # a is passed directly to Fortran
+... # routine and its contents is discarded
+...
+>>> print a
+[[ 1. 4. 5.]
+ [ 2. 5. 6.]]
+>>> print b
+[[ 1. 4. 5.]
+ [ 2. 5. 6.]]
+>>> a is b # a and b are acctually the same objects
+1
+>>> print arr.foo([1,2,3]) # different rank arrays are allowed
+copied an array using PyArray_CopyFromObject: size=3, elsize=8
+[ 1. 1. 2.]
+>>> print arr.foo([[[1],[2],[3]]])
+copied an array using PyArray_CopyFromObject: size=3, elsize=8
+[ [[ 1.]
+ [ 3.]
+ [ 4.]]]
+>>>
+>>> # Creating arrays with column major data storage order:
+...
+>>> s = arr.as_column_major_storage(array([[1,2,3],[4,5,6]]))
+copied an array using copy_ND_array: size=6, elsize=4
+>>> arr.has_column_major_storage(s)
+1
+>>> print s
+[[1 2 3]
+ [4 5 6]]
+>>> s2 = arr.as_column_major_storage(s)
+>>> s2 is s # an array with column major storage order
+ # is returned immediately
+1 \ No newline at end of file
diff --git a/numpy/f2py/docs/usersguide/calculate.f b/numpy/f2py/docs/usersguide/calculate.f
new file mode 100644
index 000000000..1cda1c8dd
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/calculate.f
@@ -0,0 +1,14 @@
+ subroutine calculate(x,n)
+cf2py intent(callback) func
+ external func
+c The following lines define the signature of func for F2PY:
+cf2py real*8 y
+cf2py y = func(y)
+c
+cf2py intent(in,out,copy) x
+ integer n,i
+ real*8 x(n)
+ do i=1,n
+ x(i) = func(x(i))
+ end do
+ end
diff --git a/numpy/f2py/docs/usersguide/calculate_session.dat b/numpy/f2py/docs/usersguide/calculate_session.dat
new file mode 100644
index 000000000..2fe64f522
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/calculate_session.dat
@@ -0,0 +1,6 @@
+>>> import foo
+>>> foo.calculate(range(5), lambda x: x*x)
+array([ 0., 1., 4., 9., 16.])
+>>> import math
+>>> foo.calculate(range(5), math.exp)
+array([ 1. , 2.71828175, 7.38905621, 20.08553696, 54.59814835])
diff --git a/numpy/f2py/docs/usersguide/callback.f b/numpy/f2py/docs/usersguide/callback.f
new file mode 100644
index 000000000..6e9bfb920
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/callback.f
@@ -0,0 +1,12 @@
+C FILE: CALLBACK.F
+ SUBROUTINE FOO(FUN,R)
+ EXTERNAL FUN
+ INTEGER I
+ REAL*8 R
+Cf2py intent(out) r
+ R = 0D0
+ DO I=-5,5
+ R = R + FUN(I)
+ ENDDO
+ END
+C END OF FILE CALLBACK.F
diff --git a/numpy/f2py/docs/usersguide/callback2.pyf b/numpy/f2py/docs/usersguide/callback2.pyf
new file mode 100644
index 000000000..3d77eed24
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/callback2.pyf
@@ -0,0 +1,19 @@
+! -*- f90 -*-
+python module __user__routines
+ interface
+ function fun(i) result (r)
+ integer :: i
+ real*8 :: r
+ end function fun
+ end interface
+end python module __user__routines
+
+python module callback2
+ interface
+ subroutine foo(f,r)
+ use __user__routines, f=>fun
+ external f
+ real*8 intent(out) :: r
+ end subroutine foo
+ end interface
+end python module callback2
diff --git a/numpy/f2py/docs/usersguide/callback_session.dat b/numpy/f2py/docs/usersguide/callback_session.dat
new file mode 100644
index 000000000..cd2f26084
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/callback_session.dat
@@ -0,0 +1,23 @@
+>>> import callback
+>>> print callback.foo.__doc__
+foo - Function signature:
+ r = foo(fun,[fun_extra_args])
+Required arguments:
+ fun : call-back function
+Optional arguments:
+ fun_extra_args := () input tuple
+Return objects:
+ r : float
+Call-back functions:
+ def fun(i): return r
+ Required arguments:
+ i : input int
+ Return objects:
+ r : float
+
+>>> def f(i): return i*i
+...
+>>> print callback.foo(f)
+110.0
+>>> print callback.foo(lambda i:1)
+11.0
diff --git a/numpy/f2py/docs/usersguide/common.f b/numpy/f2py/docs/usersguide/common.f
new file mode 100644
index 000000000..b098ab20c
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/common.f
@@ -0,0 +1,13 @@
+C FILE: COMMON.F
+ SUBROUTINE FOO
+ INTEGER I,X
+ REAL A
+ COMMON /DATA/ I,X(4),A(2,3)
+ PRINT*, "I=",I
+ PRINT*, "X=[",X,"]"
+ PRINT*, "A=["
+ PRINT*, "[",A(1,1),",",A(1,2),",",A(1,3),"]"
+ PRINT*, "[",A(2,1),",",A(2,2),",",A(2,3),"]"
+ PRINT*, "]"
+ END
+C END OF COMMON.F
diff --git a/numpy/f2py/docs/usersguide/common_session.dat b/numpy/f2py/docs/usersguide/common_session.dat
new file mode 100644
index 000000000..846fdaa07
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/common_session.dat
@@ -0,0 +1,27 @@
+>>> import common
+>>> print common.data.__doc__
+i - 'i'-scalar
+x - 'i'-array(4)
+a - 'f'-array(2,3)
+
+>>> common.data.i = 5
+>>> common.data.x[1] = 2
+>>> common.data.a = [[1,2,3],[4,5,6]]
+>>> common.foo()
+ I= 5
+ X=[ 0 2 0 0]
+ A=[
+ [ 1., 2., 3.]
+ [ 4., 5., 6.]
+ ]
+>>> common.data.a[1] = 45
+>>> common.foo()
+ I= 5
+ X=[ 0 2 0 0]
+ A=[
+ [ 1., 2., 3.]
+ [ 45., 45., 45.]
+ ]
+>>> common.data.a # a is Fortran-contiguous
+array([[ 1., 2., 3.],
+ [ 45., 45., 45.]],'f')
diff --git a/numpy/f2py/docs/usersguide/compile_session.dat b/numpy/f2py/docs/usersguide/compile_session.dat
new file mode 100644
index 000000000..0d8408198
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/compile_session.dat
@@ -0,0 +1,11 @@
+>>> import f2py2e
+>>> fsource = '''
+... subroutine foo
+... print*, "Hello world!"
+... end
+... '''
+>>> f2py2e.compile(fsource,modulename='hello',verbose=0)
+0
+>>> import hello
+>>> hello.foo()
+ Hello world!
diff --git a/numpy/f2py/docs/usersguide/default.css b/numpy/f2py/docs/usersguide/default.css
new file mode 100644
index 000000000..bb7226161
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/default.css
@@ -0,0 +1,180 @@
+/*
+:Author: David Goodger
+:Contact: goodger@users.sourceforge.net
+:date: $Date: 2002/12/07 23:59:33 $
+:version: $Revision: 1.2 $
+: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: #ee9e9e }
+
+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/numpy/f2py/docs/usersguide/docutils.conf b/numpy/f2py/docs/usersguide/docutils.conf
new file mode 100644
index 000000000..b772fd137
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/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: f2py_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/numpy/f2py/docs/usersguide/extcallback.f b/numpy/f2py/docs/usersguide/extcallback.f
new file mode 100644
index 000000000..9a800628e
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/extcallback.f
@@ -0,0 +1,14 @@
+ subroutine f1()
+ print *, "in f1, calling f2 twice.."
+ call f2()
+ call f2()
+ return
+ end
+
+ subroutine f2()
+cf2py intent(callback, hide) fpy
+ external fpy
+ print *, "in f2, calling f2py.."
+ call fpy()
+ return
+ end
diff --git a/numpy/f2py/docs/usersguide/extcallback_session.dat b/numpy/f2py/docs/usersguide/extcallback_session.dat
new file mode 100644
index 000000000..c22935ea0
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/extcallback_session.dat
@@ -0,0 +1,19 @@
+>>> import pfromf
+>>> pfromf.f2()
+Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+pfromf.error: Callback fpy not defined (as an argument or module pfromf attribute).
+
+>>> def f(): print "python f"
+...
+>>> pfromf.fpy = f
+>>> pfromf.f2()
+ in f2, calling f2py..
+python f
+>>> pfromf.f1()
+ in f1, calling f2 twice..
+ in f2, calling f2py..
+python f
+ in f2, calling f2py..
+python f
+>>> \ No newline at end of file
diff --git a/numpy/f2py/docs/usersguide/fib1.f b/numpy/f2py/docs/usersguide/fib1.f
new file mode 100644
index 000000000..cfbb1eea0
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/fib1.f
@@ -0,0 +1,18 @@
+C FILE: FIB1.F
+ SUBROUTINE FIB(A,N)
+C
+C CALCULATE FIRST N FIBONACCI NUMBERS
+C
+ INTEGER N
+ REAL*8 A(N)
+ DO I=1,N
+ IF (I.EQ.1) THEN
+ A(I) = 0.0D0
+ ELSEIF (I.EQ.2) THEN
+ A(I) = 1.0D0
+ ELSE
+ A(I) = A(I-1) + A(I-2)
+ ENDIF
+ ENDDO
+ END
+C END FILE FIB1.F
diff --git a/numpy/f2py/docs/usersguide/fib1.pyf b/numpy/f2py/docs/usersguide/fib1.pyf
new file mode 100644
index 000000000..3d6cc0a54
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/fib1.pyf
@@ -0,0 +1,12 @@
+! -*- f90 -*-
+python module fib2 ! in
+ interface ! in :fib2
+ subroutine fib(a,n) ! in :fib2:fib1.f
+ real*8 dimension(n) :: a
+ integer optional,check(len(a)>=n),depend(a) :: n=len(a)
+ end subroutine fib
+ end interface
+end python module fib2
+
+! This file was auto-generated with f2py (version:2.28.198-1366).
+! See http://cens.ioc.ee/projects/f2py2e/
diff --git a/numpy/f2py/docs/usersguide/fib2.pyf b/numpy/f2py/docs/usersguide/fib2.pyf
new file mode 100644
index 000000000..4a5ae29f1
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/fib2.pyf
@@ -0,0 +1,9 @@
+! -*- f90 -*-
+python module fib2
+ interface
+ subroutine fib(a,n)
+ real*8 dimension(n),intent(out),depend(n) :: a
+ integer intent(in) :: n
+ end subroutine fib
+ end interface
+end python module fib2
diff --git a/numpy/f2py/docs/usersguide/fib3.f b/numpy/f2py/docs/usersguide/fib3.f
new file mode 100644
index 000000000..08b050cd2
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/fib3.f
@@ -0,0 +1,21 @@
+C FILE: FIB3.F
+ SUBROUTINE FIB(A,N)
+C
+C CALCULATE FIRST N FIBONACCI NUMBERS
+C
+ INTEGER N
+ REAL*8 A(N)
+Cf2py intent(in) n
+Cf2py intent(out) a
+Cf2py depend(n) a
+ DO I=1,N
+ IF (I.EQ.1) THEN
+ A(I) = 0.0D0
+ ELSEIF (I.EQ.2) THEN
+ A(I) = 1.0D0
+ ELSE
+ A(I) = A(I-1) + A(I-2)
+ ENDIF
+ ENDDO
+ END
+C END FILE FIB3.F
diff --git a/numpy/f2py/docs/usersguide/ftype.f b/numpy/f2py/docs/usersguide/ftype.f
new file mode 100644
index 000000000..cabbb9e2d
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/ftype.f
@@ -0,0 +1,9 @@
+C FILE: FTYPE.F
+ SUBROUTINE FOO(N)
+ INTEGER N
+Cf2py integer optional,intent(in) :: n = 13
+ REAL A,X
+ COMMON /DATA/ A,X(3)
+ PRINT*, "IN FOO: N=",N," A=",A," X=[",X(1),X(2),X(3),"]"
+ END
+C END OF FTYPE.F
diff --git a/numpy/f2py/docs/usersguide/ftype_session.dat b/numpy/f2py/docs/usersguide/ftype_session.dat
new file mode 100644
index 000000000..01f9febaf
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/ftype_session.dat
@@ -0,0 +1,21 @@
+>>> import ftype
+>>> print ftype.__doc__
+This module 'ftype' is auto-generated with f2py (version:2.28.198-1366).
+Functions:
+ foo(n=13)
+COMMON blocks:
+ /data/ a,x(3)
+.
+>>> type(ftype.foo),type(ftype.data)
+(<type 'fortran'>, <type 'fortran'>)
+>>> ftype.foo()
+ IN FOO: N= 13 A= 0. X=[ 0. 0. 0.]
+>>> ftype.data.a = 3
+>>> ftype.data.x = [1,2,3]
+>>> ftype.foo()
+ IN FOO: N= 13 A= 3. X=[ 1. 2. 3.]
+>>> ftype.data.x[1] = 45
+>>> ftype.foo(24)
+ IN FOO: N= 24 A= 3. X=[ 1. 45. 3.]
+>>> ftype.data.x
+array([ 1., 45., 3.],'f')
diff --git a/numpy/f2py/docs/usersguide/index.txt b/numpy/f2py/docs/usersguide/index.txt
new file mode 100644
index 000000000..9fafb99fb
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/index.txt
@@ -0,0 +1,1772 @@
+.. -*- rest -*-
+
+//////////////////////////////////////////////////////////////////////
+ F2PY Users Guide and Reference Manual
+//////////////////////////////////////////////////////////////////////
+
+:Author: Pearu Peterson
+:Contact: pearu@cens.ioc.ee
+:Web site: http://cens.ioc.ee/projects/f2py2e/
+:Date: $Date: 2005/04/02 10:03:26 $
+:Revision: $Revision: 1.27 $
+
+
+.. section-numbering::
+
+.. Contents::
+
+
+================
+ Introduction
+================
+
+The purpose of the F2PY_ --*Fortran to Python interface generator*--
+project is to provide a connection between Python and Fortran
+languages. F2PY is a Python_ package (with a command line tool
+``f2py`` and a module ``f2py2e``) that facilitates creating/building
+Python C/API extension modules that make it possible
+
+* to call Fortran 77/90/95 external subroutines and Fortran 90/95
+ module subroutines as well as C functions;
+* to access Fortran 77 ``COMMON`` blocks and Fortran 90/95 module data,
+ including allocatable arrays
+
+from Python. See F2PY_ web site for more information and installation
+instructions.
+
+======================================
+ Three ways to wrap - getting started
+======================================
+
+Wrapping Fortran or C functions to Python using F2PY consists of the
+following steps:
+
+* Creating the so-called signature file that contains descriptions of
+ wrappers to Fortran or C functions, also called as signatures of the
+ functions. In the case of Fortran routines, F2PY can create initial
+ signature file by scanning Fortran source codes and
+ catching all relevant information needed to create wrapper
+ functions.
+
+* Optionally, F2PY created signature files can be edited to optimize
+ wrappers functions, make them "smarter" and more "Pythonic".
+
+* F2PY reads a signature file and writes a Python C/API module containing
+ Fortran/C/Python bindings.
+
+* F2PY compiles all sources and builds an extension module containing
+ the wrappers. In building extension modules, F2PY uses
+ ``scipy_distutils`` that supports a number of Fortran 77/90/95
+ compilers, including Gnu, Intel,
+ Sun Fortre, SGI MIPSpro, Absoft, NAG, Compaq etc. compilers.
+
+Depending on a particular situation, these steps can be carried out
+either by just in one command or step-by-step, some steps can be
+ommited or combined with others.
+
+Below I'll describe three typical approaches of using F2PY.
+The following `example Fortran 77 code`__ will be used for
+illustration:
+
+.. include:: fib1.f
+ :literal:
+
+__ fib1.f
+
+The quick way
+==============
+
+The quickest way to wrap the Fortran subroutine ``FIB`` to Python is
+to run
+
+::
+
+ f2py -c fib1.f -m fib1
+
+This command builds (see ``-c`` flag, execute ``f2py`` without
+arguments to see the explanation of command line options) an extension
+module ``fib1.so`` (see ``-m`` flag) to the current directory. Now, in
+Python the Fortran subroutine ``FIB`` is accessible via ``fib1.fib``::
+
+ >>> import Numeric
+ >>> import fib1
+ >>> print fib1.fib.__doc__
+ fib - Function signature:
+ fib(a,[n])
+ Required arguments:
+ a : input rank-1 array('d') with bounds (n)
+ Optional arguments:
+ n := len(a) input int
+
+ >>> a=Numeric.zeros(8,'d')
+ >>> fib1.fib(a)
+ >>> print a
+ [ 0. 1. 1. 2. 3. 5. 8. 13.]
+
+.. topic:: Comments
+
+ * Note that F2PY found that the second argument ``n`` is the
+ dimension of the first array argument ``a``. Since by default all
+ arguments are input-only arguments, F2PY concludes that ``n`` can
+ be optional with the default value ``len(a)``.
+
+ * One can use different values for optional ``n``::
+
+ >>> a1=Numeric.zeros(8,'d')
+ >>> fib1.fib(a1,6)
+ >>> print a1
+ [ 0. 1. 1. 2. 3. 5. 0. 0.]
+
+ but an exception is raised when it is incompatible with the input
+ array ``a``::
+
+ >>> fib1.fib(a,10)
+ fib:n=10
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+ fib.error: (len(a)>=n) failed for 1st keyword n
+ >>>
+
+ This demonstrates one of the useful features in F2PY, that it,
+ F2PY implements basic compatibility checks between related
+ arguments in order to avoid any unexpected crashes.
+
+ * When a Numeric array, that is Fortran contiguous and has a typecode
+ corresponding to presumed Fortran type, is used as an input array
+ argument, then its C pointer is directly passed to Fortran.
+
+ Otherwise F2PY makes a contiguous copy (with a proper typecode) of
+ the input array and passes C pointer of the copy to Fortran
+ subroutine. As a result, any possible changes to the (copy of)
+ input array have no effect to the original argument, as
+ demonstrated below::
+
+ >>> a=Numeric.ones(8,'i')
+ >>> fib1.fib(a)
+ >>> print a
+ [1 1 1 1 1 1 1 1]
+
+ Clearly, this is not an expected behaviour. The fact that the
+ above example worked with ``typecode='d'`` is considered
+ accidental.
+
+ F2PY provides ``intent(inplace)`` attribute that would modify
+ the attributes of an input array so that any changes made by
+ Fortran routine will be effective also in input argument. For example,
+ if one specifies ``intent(inplace) a`` (see below, how), then
+ the example above would read:
+
+ >>> a=Numeric.ones(8,'i')
+ >>> fib1.fib(a)
+ >>> print a
+ [ 0. 1. 1. 2. 3. 5. 8. 13.]
+
+ However, the recommended way to get changes made by Fortran
+ subroutine back to python is to use ``intent(out)`` attribute. It
+ is more efficient and a cleaner solution.
+
+ * The usage of ``fib1.fib`` in Python is very similar to using
+ ``FIB`` in Fortran. However, using *in situ* output arguments in
+ Python indicates a poor style as there is no safety mechanism
+ in Python with respect to wrong argument types. When using Fortran
+ or C, compilers naturally discover any type mismatches during
+ compile time but in Python the types must be checked in
+ runtime. So, using *in situ* output arguments in Python may cause
+ difficult to find bugs, not to mention that the codes will be less
+ readable when all required type checks are implemented.
+
+ Though the demonstrated way of wrapping Fortran routines to Python
+ is very straightforward, it has several drawbacks (see the comments
+ above). These drawbacks are due to the fact that there is no way
+ that F2PY can determine what is the acctual intention of one or the
+ other argument, is it input or output argument, or both, or
+ something else. So, F2PY conservatively assumes that all arguments
+ are input arguments by default.
+
+ However, there are ways (see below) how to "teach" F2PY about the
+ true intentions (among other things) of function arguments; and then
+ F2PY is able to generate more Pythonic (more explicit, easier to
+ use, and less error prone) wrappers to Fortran functions.
+
+The smart way
+==============
+
+Let's apply the steps of wrapping Fortran functions to Python one by
+one.
+
+* First, we create a signature file from ``fib1.f`` by running
+
+ ::
+
+ f2py fib1.f -m fib2 -h fib1.pyf
+
+ The signature file is saved to ``fib1.pyf`` (see ``-h`` flag) and
+ its contents is shown below.
+
+ .. include:: fib1.pyf
+ :literal:
+
+* Next, we'll teach F2PY that the argument ``n`` is a input argument
+ (use ``intent(in)`` attribute) and that the result, i.e. the
+ contents of ``a`` after calling Fortran function ``FIB``, should be
+ returned to Python (use ``intent(out)`` attribute). In addition, an
+ array ``a`` should be created dynamically using the size given by
+ the input argument ``n`` (use ``depend(n)`` attribute to indicate
+ dependence relation).
+
+ The content of a modified version of ``fib1.pyf`` (saved as
+ ``fib2.pyf``) is as follows:
+
+ .. include:: fib2.pyf
+ :literal:
+
+* And finally, we build the extension module by running
+
+ ::
+
+ f2py -c fib2.pyf fib1.f
+
+In Python::
+
+ >>> import fib2
+ >>> print fib2.fib.__doc__
+ fib - Function signature:
+ a = fib(n)
+ Required arguments:
+ n : input int
+ Return objects:
+ a : rank-1 array('d') with bounds (n)
+
+ >>> print fib2.fib(8)
+ [ 0. 1. 1. 2. 3. 5. 8. 13.]
+
+.. topic:: Comments
+
+ * Clearly, the signature of ``fib2.fib`` now corresponds to the
+ intention of Fortran subroutine ``FIB`` more closely: given the
+ number ``n``, ``fib2.fib`` returns the first ``n`` Fibonacci numbers
+ as a Numeric array. Also, the new Python signature ``fib2.fib``
+ rules out any surprises that we experienced with ``fib1.fib``.
+
+ * Note that by default using single ``intent(out)`` also implies
+ ``intent(hide)``. Argument that has ``intent(hide)`` attribute
+ specified, will not be listed in the argument list of a wrapper
+ function.
+
+The quick and smart way
+========================
+
+The "smart way" of wrapping Fortran functions, as explained above, is
+suitable for wrapping (e.g. third party) Fortran codes for which
+modifications to their source codes are not desirable nor even
+possible.
+
+However, if editing Fortran codes is acceptable, then the generation
+of an intermediate signature file can be skipped in most
+cases. Namely, F2PY specific attributes can be inserted directly to
+Fortran source codes using the so-called F2PY directive. A F2PY
+directive defines special comment lines (starting with ``Cf2py``, for
+example) which are ignored by Fortran compilers but F2PY interprets
+them as normal lines.
+
+Here is shown a `modified version of the example Fortran code`__, saved
+as ``fib3.f``:
+
+.. include:: fib3.f
+ :literal:
+
+__ fib3.f
+
+Building the extension module can be now carried out in one command::
+
+ f2py -c -m fib3 fib3.f
+
+Notice that the resulting wrapper to ``FIB`` is as "smart" as in
+previous case::
+
+ >>> import fib3
+ >>> print fib3.fib.__doc__
+ fib - Function signature:
+ a = fib(n)
+ Required arguments:
+ n : input int
+ Return objects:
+ a : rank-1 array('d') with bounds (n)
+
+ >>> print fib3.fib(8)
+ [ 0. 1. 1. 2. 3. 5. 8. 13.]
+
+
+==================
+ Signature file
+==================
+
+The syntax specification for signature files (.pyf files) is borrowed
+from the Fortran 90/95 language specification. Almost all Fortran
+90/95 standard constructs are understood, both in free and fixed
+format (recall that Fortran 77 is a subset of Fortran 90/95). F2PY
+introduces also some extensions to Fortran 90/95 language
+specification that help designing Fortran to Python interface, make it
+more "Pythonic".
+
+Signature files may contain arbitrary Fortran code (so that Fortran
+codes can be considered as signature files). F2PY silently ignores
+Fortran constructs that are irrelevant for creating the interface.
+However, this includes also syntax errors. So, be careful not making
+ones;-).
+
+In general, the contents of signature files is case-sensitive. When
+scanning Fortran codes and writing a signature file, F2PY lowers all
+cases automatically except in multi-line blocks or when ``--no-lower``
+option is used.
+
+The syntax of signature files is overvied below.
+
+Python module block
+=====================
+
+A signature file may contain one (recommended) or more ``python
+module`` blocks. ``python module`` block describes the contents of
+a Python/C extension module ``<modulename>module.c`` that F2PY
+generates.
+
+Exception: if ``<modulename>`` contains a substring ``__user__``, then
+the corresponding ``python module`` block describes the signatures of
+so-called call-back functions (see `Call-back arguments`_).
+
+A ``python module`` block has the following structure::
+
+ python module <modulename>
+ [<usercode statement>]...
+ [
+ interface
+ <usercode statement>
+ <Fortran block data signatures>
+ <Fortran/C routine signatures>
+ end [interface]
+ ]...
+ [
+ interface
+ module <F90 modulename>
+ [<F90 module data type declarations>]
+ [<F90 module routine signatures>]
+ end [module [<F90 modulename>]]
+ end [interface]
+ ]...
+ end [python module [<modulename>]]
+
+Here brackets ``[]`` indicate a optional part, dots ``...`` indicate
+one or more of a previous part. So, ``[]...`` reads zero or more of a
+previous part.
+
+
+Fortran/C routine signatures
+=============================
+
+The signature of a Fortran routine has the following structure::
+
+ [<typespec>] function | subroutine <routine name> \
+ [ ( [<arguments>] ) ] [ result ( <entityname> ) ]
+ [<argument/variable type declarations>]
+ [<argument/variable attribute statements>]
+ [<use statements>]
+ [<common block statements>]
+ [<other statements>]
+ end [ function | subroutine [<routine name>] ]
+
+From a Fortran routine signature F2PY generates a Python/C extension
+function that has the following signature::
+
+ def <routine name>(<required arguments>[,<optional arguments>]):
+ ...
+ return <return variables>
+
+The signature of a Fortran block data has the following structure::
+
+ block data [ <block data name> ]
+ [<variable type declarations>]
+ [<variable attribute statements>]
+ [<use statements>]
+ [<common block statements>]
+ [<include statements>]
+ end [ block data [<block data name>] ]
+
+Type declarations
+-------------------
+
+ The definition of the ``<argument/variable type declaration>`` part
+ is
+
+ ::
+
+ <typespec> [ [<attrspec>] :: ] <entitydecl>
+
+ where
+
+ ::
+
+ <typespec> := byte | character [<charselector>]
+ | complex [<kindselector>] | real [<kindselector>]
+ | double complex | double precision
+ | integer [<kindselector>] | logical [<kindselector>]
+
+ <charselector> := * <charlen>
+ | ( [len=] <len> [ , [kind=] <kind>] )
+ | ( kind= <kind> [ , len= <len> ] )
+ <kindselector> := * <intlen> | ( [kind=] <kind> )
+
+ <entitydecl> := <name> [ [ * <charlen> ] [ ( <arrayspec> ) ]
+ | [ ( <arrayspec> ) ] * <charlen> ]
+ | [ / <init_expr> / | = <init_expr> ] \
+ [ , <entitydecl> ]
+
+ and
+
+ + ``<attrspec>`` is a comma separated list of attributes_;
+
+ + ``<arrayspec>`` is a comma separated list of dimension bounds;
+
+ + ``<init_expr>`` is a `C expression`__.
+
+ + ``<intlen>`` may be negative integer for ``integer`` type
+ specifications. In such cases ``integer*<negintlen>`` represents
+ unsigned C integers.
+
+__ `C expressions`_
+
+ If an argument has no ``<argument type declaration>``, its type is
+ determined by applying ``implicit`` rules to its name.
+
+
+Statements
+------------
+
+Attribute statements:
+
+ The ``<argument/variable attribute statement>`` is
+ ``<argument/variable type declaration>`` without ``<typespec>``.
+ In addition, in an attribute statement one cannot use other
+ attributes, also ``<entitydecl>`` can be only a list of names.
+
+Use statements:
+
+ The definition of the ``<use statement>`` part is
+
+ ::
+
+ use <modulename> [ , <rename_list> | , ONLY : <only_list> ]
+
+ where
+
+ ::
+
+ <rename_list> := <local_name> => <use_name> [ , <rename_list> ]
+
+ Currently F2PY uses ``use`` statement only for linking call-back
+ modules and ``external`` arguments (call-back functions), see
+ `Call-back arguments`_.
+
+Common block statements:
+
+ The definition of the ``<common block statement>`` part is
+
+ ::
+
+ common / <common name> / <shortentitydecl>
+
+ where
+
+ ::
+
+ <shortentitydecl> := <name> [ ( <arrayspec> ) ] [ , <shortentitydecl> ]
+
+ One ``python module`` block should not contain two or more
+ ``common`` blocks with the same name. Otherwise, the latter ones are
+ ignored. The types of variables in ``<shortentitydecl>`` are defined
+ using ``<argument type declarations>``. Note that the corresponding
+ ``<argument type declarations>`` may contain array specifications;
+ then you don't need to specify these in ``<shortentitydecl>``.
+
+Other statements:
+
+ The ``<other statement>`` part refers to any other Fortran language
+ constructs that are not described above. F2PY ignores most of them
+ except
+
+ + ``call`` statements and function calls of ``external`` arguments
+ (`more details`__?);
+
+__ external_
+
+ + ``include`` statements
+
+ ::
+
+ include '<filename>'
+ include "<filename>"
+
+ If a file ``<filename>`` does not exist, the ``include``
+ statement is ignored. Otherwise, the file ``<filename>`` is
+ included to a signature file. ``include`` statements can be used
+ in any part of a signature file, also outside the Fortran/C
+ routine signature blocks.
+
+ + ``implicit`` statements
+
+ ::
+
+ implicit none
+ implicit <list of implicit maps>
+
+ where
+
+ ::
+
+ <implicit map> := <typespec> ( <list of letters or range of letters> )
+
+ Implicit rules are used to deterimine the type specification of
+ a variable (from the first-letter of its name) if the variable
+ is not defined using ``<variable type declaration>``. Default
+ implicit rule is given by
+
+ ::
+
+ implicit real (a-h,o-z,$_), integer (i-m)
+
+ + ``entry`` statements
+
+ ::
+
+ entry <entry name> [([<arguments>])]
+
+ F2PY generates wrappers to all entry names using the signature
+ of the routine block.
+
+ Tip: ``entry`` statement can be used to describe the signature
+ of an arbitrary routine allowing F2PY to generate a number of
+ wrappers from only one routine block signature. There are few
+ restrictions while doing this: ``fortranname`` cannot be used,
+ ``callstatement`` and ``callprotoargument`` can be used only if
+ they are valid for all entry routines, etc.
+
+ In addition, F2PY introduces the following statements:
+
+ + ``threadsafe``
+ Use ``Py_BEGIN_ALLOW_THREADS .. Py_END_ALLOW_THREADS`` block
+ around the call to Fortran/C function.
+
+ + ``callstatement <C-expr|multi-line block>``
+ Replace F2PY generated call statement to Fortran/C function with
+ ``<C-expr|multi-line block>``. The wrapped Fortran/C function
+ is available as ``(*f2py_func)``. To raise an exception, set
+ ``f2py_success = 0`` in ``<C-expr|multi-line block>``.
+
+ + ``callprotoargument <C-typespecs>``
+ When ``callstatement`` statement is used then F2PY may not
+ generate proper prototypes for Fortran/C functions (because
+ ``<C-expr>`` may contain any function calls and F2PY has no way
+ to determine what should be the proper prototype). With this
+ statement you can explicitely specify the arguments of the
+ corresponding prototype::
+
+ extern <return type> FUNC_F(<routine name>,<ROUTINE NAME>)(<callprotoargument>);
+
+ + ``fortranname [<acctual Fortran/C routine name>]``
+ You can use arbitrary ``<routine name>`` for a given Fortran/C
+ function. Then you have to specify
+ ``<acctual Fortran/C routine name>`` with this statement.
+
+ If ``fortranname`` statement is used without
+ ``<acctual Fortran/C routine name>`` then a dummy wrapper is
+ generated.
+
+ + ``usercode <multi-line block>``
+ When used inside ``python module`` block, then given C code
+ will be inserted to generated C/API source just before
+ wrapper function definitions. Here you can define arbitrary
+ C functions to be used in initialization of optional arguments,
+ for example. If ``usercode`` is used twise inside ``python
+ module`` block then the second multi-line block is inserted
+ after the definition of external routines.
+
+ When used inside ``<routine singature>``, then given C code will
+ be inserted to the corresponding wrapper function just after
+ declaring variables but before any C statements. So, ``usercode``
+ follow-up can contain both declarations and C statements.
+
+ When used inside the first ``interface`` block, then given C
+ code will be inserted at the end of the initialization
+ function of the extension module. Here you can modify extension
+ modules dictionary. For example, for defining additional
+ variables etc.
+
+ + ``pymethoddef <multi-line block>``
+ Multiline block will be inserted to the definition of
+ module methods ``PyMethodDef``-array. It must be a
+ comma-separated list of C arrays (see `Extending and Embedding`__
+ Python documentation for details).
+ ``pymethoddef`` statement can be used only inside
+ ``python module`` block.
+
+ __ http://www.python.org/doc/current/ext/ext.html
+
+Attributes
+------------
+
+The following attributes are used by F2PY:
+
+``optional``
+ The corresponding argument is moved to the end of ``<optional
+ arguments>`` list. A default value for an optional argument can be
+ specified ``<init_expr>``, see ``entitydecl`` definition. Note that
+ the default value must be given as a valid C expression.
+
+ Note that whenever ``<init_expr>`` is used, ``optional`` attribute
+ is set automatically by F2PY.
+
+ For an optional array argument, all its dimensions must be bounded.
+
+``required``
+ The corresponding argument is considered as a required one. This is
+ default. You need to specify ``required`` only if there is a need to
+ disable automatic ``optional`` setting when ``<init_expr>`` is used.
+
+ If Python ``None`` object is used as an required argument, the
+ argument is treated as optional. That is, in the case of array
+ argument, the memory is allocated. And if ``<init_expr>`` is given,
+ the corresponding initialization is carried out.
+
+``dimension(<arrayspec>)``
+ The corresponding variable is considered as an array with given
+ dimensions in ``<arrayspec>``.
+
+``intent(<intentspec>)``
+ This specifies the "intention" of the corresponding
+ argument. ``<intentspec>`` is a comma separated list of the
+ following keys:
+
+ + ``in``
+ The argument is considered as an input-only argument. It means
+ that the value of the argument is passed to Fortran/C function and
+ that function is expected not to change the value of an argument.
+
+ + ``inout``
+ The argument is considered as an input/output or *in situ*
+ output argument. ``intent(inout)`` arguments can be only
+ "contiguous" Numeric arrays with proper type and size. Here
+ "contiguous" can be either in Fortran or C sense. The latter one
+ coincides with the contiguous concept used in Numeric and is
+ effective only if ``intent(c)`` is used. Fortran-contiguousness
+ is assumed by default.
+
+ Using ``intent(inout)`` is generally not recommended, use
+ ``intent(in,out)`` instead. See also ``intent(inplace)`` attribute.
+
+ + ``inplace``
+ The argument is considered as an input/output or *in situ*
+ output argument. ``intent(inplace)`` arguments must be
+ Numeric arrays with proper size. If the type of an array is
+ not "proper" or the array is non-contiguous then the array
+ will be changed in-place to fix the type and make it contiguous.
+
+ Using ``intent(inplace)`` is generally not recommended either.
+ For example, when slices have been taken from an
+ ``intent(inplace)`` argument then after in-place changes,
+ slices data pointers may point to unallocated memory area.
+
+ + ``out``
+ The argument is considered as an return variable. It is appended
+ to the ``<returned variables>`` list. Using ``intent(out)``
+ sets ``intent(hide)`` automatically, unless also
+ ``intent(in)`` or ``intent(inout)`` were used.
+
+ By default, returned multidimensional arrays are
+ Fortran-contiguous. If ``intent(c)`` is used, then returned
+ multi-dimensional arrays are C-contiguous.
+
+ + ``hide``
+ The argument is removed from the list of required or optional
+ arguments. Typically ``intent(hide)`` is used with ``intent(out)``
+ or when ``<init_expr>`` completely determines the value of the
+ argument like in the following example::
+
+ integer intent(hide),depend(a) :: n = len(a)
+ real intent(in),dimension(n) :: a
+
+ + ``c``
+ The argument is treated as a C scalar or C array argument. In
+ the case of a scalar argument, its value is passed to C function
+ as a C scalar argument (recall that Fortran scalar arguments are
+ actually C pointer arguments). In the case of an array
+ argument, the wrapper function is assumed to treat
+ multi-dimensional arrays as C-contiguous arrays.
+
+ There is no need to use ``intent(c)`` for one-dimensional
+ arrays, no matter if the wrapped function is either a Fortran or
+ a C function. This is because the concepts of Fortran- and
+ C-contiguousness overlap in one-dimensional cases.
+
+ If ``intent(c)`` is used as an statement but without entity
+ declaration list, then F2PY adds ``intent(c)`` attibute to all
+ arguments.
+
+ Also, when wrapping C functions, one must use ``intent(c)``
+ attribute for ``<routine name>`` in order to disable Fortran
+ specific ``F_FUNC(..,..)`` macros.
+
+ + ``cache``
+ The argument is treated as a junk of memory. No Fortran nor C
+ contiguousness checks are carried out. Using ``intent(cache)``
+ makes sense only for array arguments, also in connection with
+ ``intent(hide)`` or ``optional`` attributes.
+
+ + ``copy``
+ Ensure that the original contents of ``intent(in)`` argument is
+ preserved. Typically used in connection with ``intent(in,out)``
+ attribute. F2PY creates an optional argument
+ ``overwrite_<argument name>`` with the default value ``0``.
+
+ + ``overwrite``
+ The original contents of the ``intent(in)`` argument may be
+ altered by the Fortran/C function. F2PY creates an optional
+ argument ``overwrite_<argument name>`` with the default value
+ ``1``.
+
+ + ``out=<new name>``
+ Replace the return name with ``<new name>`` in the ``__doc__``
+ string of a wrapper function.
+
+ + ``callback``
+ Construct an external function suitable for calling Python function
+ from Fortran. ``intent(callback)`` must be specified before the
+ corresponding ``external`` statement. If 'argument' is not in
+ argument list then it will be added to Python wrapper but only
+ initializing external function.
+
+ Use ``intent(callback)`` in situations where a Fortran/C code
+ assumes that a user implements a function with given prototype
+ and links it to an executable. Don't use ``intent(callback)``
+ if function appears in the argument list of a Fortran routine.
+
+ With ``intent(hide)`` or ``optional`` attributes specified and
+ using a wrapper function without specifying the callback argument
+ in argument list then call-back function is looked in the
+ namespace of F2PY generated extension module where it can be
+ set as a module attribute by a user.
+
+ + ``aux``
+ Define auxiliary C variable in F2PY generated wrapper function.
+ Useful to save parameter values so that they can be accessed
+ in initialization expression of other variables. Note that
+ ``intent(aux)`` silently implies ``intent(c)``.
+
+ The following rules apply:
+
+ + If no ``intent(in | inout | out | hide)`` is specified,
+ ``intent(in)`` is assumed.
+ + ``intent(in,inout)`` is ``intent(in)``.
+ + ``intent(in,hide)`` or ``intent(inout,hide)`` is
+ ``intent(hide)``.
+ + ``intent(out)`` is ``intent(out,hide)`` unless ``intent(in)`` or
+ ``intent(inout)`` is specified.
+ + If ``intent(copy)`` or ``intent(overwrite)`` is used, then an
+ additional optional argument is introduced with a name
+ ``overwrite_<argument name>`` and a default value 0 or 1, respectively.
+ + ``intent(inout,inplace)`` is ``intent(inplace)``.
+ + ``intent(in,inplace)`` is ``intent(inplace)``.
+ + ``intent(hide)`` disables ``optional`` and ``required``.
+
+``check([<C-booleanexpr>])``
+ Perform consistency check of arguments by evaluating
+ ``<C-booleanexpr>``; if ``<C-booleanexpr>`` returns 0, an exception
+ is raised.
+
+ If ``check(..)`` is not used then F2PY generates few standard checks
+ (e.g. in a case of an array argument, check for the proper shape
+ and size) automatically. Use ``check()`` to disable checks generated
+ by F2PY.
+
+``depend([<names>])``
+ This declares that the corresponding argument depends on the values
+ of variables in the list ``<names>``. For example, ``<init_expr>``
+ may use the values of other arguments. Using information given by
+ ``depend(..)`` attributes, F2PY ensures that arguments are
+ initialized in a proper order. If ``depend(..)`` attribute is not
+ used then F2PY determines dependence relations automatically. Use
+ ``depend()`` to disable dependence relations generated by F2PY.
+
+ When you edit dependence relations that were initially generated by
+ F2PY, be careful not to break the dependence relations of other
+ relevant variables. Another thing to watch out is cyclic
+ dependencies. F2PY is able to detect cyclic dependencies
+ when constructing wrappers and it complains if any are found.
+
+``allocatable``
+ The corresponding variable is Fortran 90 allocatable array defined
+ as Fortran 90 module data.
+
+.. _external:
+
+``external``
+ The corresponding argument is a function provided by user. The
+ signature of this so-called call-back function can be defined
+
+ - in ``__user__`` module block,
+ - or by demonstrative (or real, if the signature file is a real Fortran
+ code) call in the ``<other statements>`` block.
+
+ For example, F2PY generates from
+
+ ::
+
+ external cb_sub, cb_fun
+ integer n
+ real a(n),r
+ call cb_sub(a,n)
+ r = cb_fun(4)
+
+ the following call-back signatures::
+
+ subroutine cb_sub(a,n)
+ real dimension(n) :: a
+ integer optional,check(len(a)>=n),depend(a) :: n=len(a)
+ end subroutine cb_sub
+ function cb_fun(e_4_e) result (r)
+ integer :: e_4_e
+ real :: r
+ end function cb_fun
+
+ The corresponding user-provided Python function are then::
+
+ def cb_sub(a,[n]):
+ ...
+ return
+ def cb_fun(e_4_e):
+ ...
+ return r
+
+ See also ``intent(callback)`` attribute.
+
+``parameter``
+ The corresponding variable is a parameter and it must have a fixed
+ value. F2PY replaces all parameter occurrences by their
+ corresponding values.
+
+Extensions
+============
+
+F2PY directives
+-----------------
+
+The so-called F2PY directives allow using F2PY signature file
+constructs also in Fortran 77/90 source codes. With this feature you
+can skip (almost) completely intermediate signature file generations
+and apply F2PY directly to Fortran source codes.
+
+F2PY directive has the following form::
+
+ <comment char>f2py ...
+
+where allowed comment characters for fixed and free format Fortran
+codes are ``cC*!#`` and ``!``, respectively. Everything that follows
+``<comment char>f2py`` is ignored by a compiler but read by F2PY as a
+normal Fortran (non-comment) line:
+
+ When F2PY finds a line with F2PY directive, the directive is first
+ replaced by 5 spaces and then the line is reread.
+
+For fixed format Fortran codes, ``<comment char>`` must be at the
+first column of a file, of course. For free format Fortran codes,
+F2PY directives can appear anywhere in a file.
+
+C expressions
+--------------
+
+C expressions are used in the following parts of signature files:
+
+* ``<init_expr>`` of variable initialization;
+* ``<C-booleanexpr>`` of the ``check`` attribute;
+* ``<arrayspec> of the ``dimension`` attribute;
+* ``callstatement`` statement, here also a C multi-line block can be used.
+
+A C expression may contain:
+
+* standard C constructs;
+* functions from ``math.h`` and ``Python.h``;
+* variables from the argument list, presumably initialized before
+ according to given dependence relations;
+* the following CPP macros:
+
+ ``rank(<name>)``
+ Returns the rank of an array ``<name>``.
+ ``shape(<name>,<n>)``
+ Returns the ``<n>``-th dimension of an array ``<name>``.
+ ``len(<name>)``
+ Returns the lenght of an array ``<name>``.
+ ``size(<name>)``
+ Returns the size of an array ``<name>``.
+ ``slen(<name>)``
+ Returns the length of a string ``<name>``.
+
+For initializing an array ``<array name>``, F2PY generates a loop over
+all indices and dimensions that executes the following
+pseudo-statement::
+
+ <array name>(_i[0],_i[1],...) = <init_expr>;
+
+where ``_i[<i>]`` refers to the ``<i>``-th index value and that runs
+from ``0`` to ``shape(<array name>,<i>)-1``.
+
+For example, a function ``myrange(n)`` generated from the following
+signature
+
+::
+
+ subroutine myrange(a,n)
+ fortranname ! myrange is a dummy wrapper
+ integer intent(in) :: n
+ real*8 intent(c,out),dimension(n),depend(n) :: a = _i[0]
+ end subroutine myrange
+
+is equivalent to ``Numeric.arange(n,typecode='d')``.
+
+.. topic:: Warning!
+
+ F2PY may lower cases also in C expressions when scanning Fortran codes
+ (see ``--[no]-lower`` option).
+
+Multi-line blocks
+------------------
+
+A multi-line block starts with ``'''`` (triple single-quotes) and ends
+with ``'''`` in some *strictly* subsequent line. Multi-line blocks can
+be used only within .pyf files. The contents of a multi-line block can
+be arbitrary (except that it cannot contain ``'''``) and no
+transformations (e.g. lowering cases) are applied to it.
+
+Currently, multi-line blocks can be used in the following constructs:
+
++ as a C expression of the ``callstatement`` statement;
+
++ as a C type specification of the ``callprotoargument`` statement;
+
++ as a C code block of the ``usercode`` statement;
+
++ as a list of C arrays of the ``pymethoddef`` statement;
+
++ as documentation string.
+
+==================================
+Using F2PY bindings in Python
+==================================
+
+All wrappers (to Fortran/C routines or to common blocks or to Fortran
+90 module data) generated by F2PY are exposed to Python as ``fortran``
+type objects. Routine wrappers are callable ``fortran`` type objects
+while wrappers to Fortran data have attributes referring to data
+objects.
+
+All ``fortran`` type object have attribute ``_cpointer`` that contains
+CObject referring to the C pointer of the corresponding Fortran/C
+function or variable in C level. Such CObjects can be used as an
+callback argument of F2PY generated functions to bypass Python C/API
+layer of calling Python functions from Fortran or C when the
+computational part of such functions is implemented in C or Fortran
+and wrapped with F2PY (or any other tool capable of providing CObject
+of a function).
+
+.. topic:: Example
+
+ Consider a `Fortran 77 file`__ ``ftype.f``:
+
+ .. include:: ftype.f
+ :literal:
+
+ and build a wrapper using::
+
+ f2py -c ftype.f -m ftype
+
+ __ ftype.f
+
+ In Python:
+
+ .. include:: ftype_session.dat
+ :literal:
+
+
+Scalar arguments
+=================
+
+In general, a scalar argument of a F2PY generated wrapper function can
+be ordinary Python scalar (integer, float, complex number) as well as
+an arbitrary sequence object (list, tuple, array, string) of
+scalars. In the latter case, the first element of the sequence object
+is passed to Fortran routine as a scalar argument.
+
+Note that when type-casting is required and there is possible loss of
+information (e.g. when type-casting float to integer or complex to
+float), F2PY does not raise any exception. In complex to real
+type-casting only the real part of a complex number is used.
+
+``intent(inout)`` scalar arguments are assumed to be array objects in
+order to *in situ* changes to be effective. It is recommended to use
+arrays with proper type but also other types work.
+
+.. topic:: Example
+
+ Consider the following `Fortran 77 code`__:
+
+ .. include:: scalar.f
+ :literal:
+
+ and wrap it using ``f2py -c -m scalar scalar.f``.
+
+ __ scalar.f
+
+ In Python:
+
+ .. include:: scalar_session.dat
+ :literal:
+
+
+String arguments
+=================
+
+F2PY generated wrapper functions accept (almost) any Python object as
+a string argument, ``str`` is applied for non-string objects.
+Exceptions are Numeric arrays that must have type code ``'c'`` or
+``'1'`` when used as string arguments.
+
+A string can have arbitrary length when using it as a string argument
+to F2PY generated wrapper function. If the length is greater than
+expected, the string is truncated. If the length is smaller that
+expected, additional memory is allocated and filled with ``\0``.
+
+Because Python strings are immutable, an ``intent(inout)`` argument
+expects an array version of a string in order to *in situ* changes to
+be effective.
+
+.. topic:: Example
+
+ Consider the following `Fortran 77 code`__:
+
+ .. include:: string.f
+ :literal:
+
+ and wrap it using ``f2py -c -m mystring string.f``.
+
+ __ string.f
+
+ Python session:
+
+ .. include:: string_session.dat
+ :literal:
+
+
+Array arguments
+================
+
+In general, array arguments of F2PY generated wrapper functions accept
+arbitrary sequences that can be transformed to Numeric array objects.
+An exception is ``intent(inout)`` array arguments that always must be
+proper-contiguous and have proper type, otherwise an exception is
+raised. Another exception is ``intent(inplace)`` array arguments that
+attributes will be changed in-situ if the argument has different type
+than expected (see ``intent(inplace)`` attribute for more
+information).
+
+In general, if a Numeric array is proper-contiguous and has a proper
+type then it is directly passed to wrapped Fortran/C function.
+Otherwise, an element-wise copy of an input array is made and the
+copy, being proper-contiguous and with proper type, is used as an
+array argument.
+
+There are two types of proper-contiguous Numeric arrays:
+
+* Fortran-contiguous arrays when data is stored column-wise,
+ i.e. indexing of data as stored in memory starts from the lowest
+ dimension;
+* C-contiguous or simply contiguous arrays when data is stored
+ row-wise, i.e. indexing of data as stored in memory starts from the
+ highest dimension.
+
+For one-dimensional arrays these notions coincide.
+
+For example, an 2x2 array ``A`` is Fortran-contiguous if its elements
+are stored in memory in the following order::
+
+ A[0,0] A[1,0] A[0,1] A[1,1]
+
+and C-contiguous if the order is as follows::
+
+ A[0,0] A[0,1] A[1,0] A[1,1]
+
+To test whether an array is C-contiguous, use ``.iscontiguous()``
+method of Numeric arrays. To test for Fortran-contiguousness, all
+F2PY generated extension modules provide a function
+``has_column_major_storage(<array>)``. This function is equivalent to
+``Numeric.transpose(<array>).iscontiguous()`` but more efficient.
+
+Usually there is no need to worry about how the arrays are stored in
+memory and whether the wrapped functions, being either Fortran or C
+functions, assume one or another storage order. F2PY automatically
+ensures that wrapped functions get arguments with proper storage
+order; the corresponding algorithm is designed to make copies of
+arrays only when absolutely necessary. However, when dealing with very
+large multi-dimensional input arrays with sizes close to the size of
+the physical memory in your computer, then a care must be taken to use
+always proper-contiguous and proper type arguments.
+
+To transform input arrays to column major storage order before passing
+them to Fortran routines, use a function
+``as_column_major_storage(<array>)`` that is provided by all F2PY
+generated extension modules.
+
+.. topic:: Example
+
+ Consider `Fortran 77 code`__:
+
+ .. include:: array.f
+ :literal:
+
+ and wrap it using ``f2py -c -m arr array.f -DF2PY_REPORT_ON_ARRAY_COPY=1``.
+
+ __ array.f
+
+ In Python:
+
+ .. include:: array_session.dat
+ :literal:
+
+Call-back arguments
+====================
+
+F2PY supports calling Python functions from Fortran or C codes.
+
+
+.. topic:: Example
+
+ Consider the following `Fortran 77 code`__
+
+ .. include:: callback.f
+ :literal:
+
+ and wrap it using ``f2py -c -m callback callback.f``.
+
+ __ callback.f
+
+ In Python:
+
+ .. include:: callback_session.dat
+ :literal:
+
+In the above example F2PY was able to guess accurately the signature
+of a call-back function. However, sometimes F2PY cannot establish the
+signature as one would wish and then the signature of a call-back
+function must be modified in the signature file manually. Namely,
+signature files may contain special modules (the names of such modules
+contain a substring ``__user__``) that collect various signatures of
+call-back functions. Callback arguments in routine signatures have
+attribute ``external`` (see also ``intent(callback)`` attribute). To
+relate a callback argument and its signature in ``__user__`` module
+block, use ``use`` statement as illustrated below. The same signature
+of a callback argument can be referred in different routine
+signatures.
+
+.. topic:: Example
+
+ We use the same `Fortran 77 code`__ as in previous example but now
+ we'll pretend that F2PY was not able to guess the signatures of
+ call-back arguments correctly. First, we create an initial signature
+ file ``callback2.pyf`` using F2PY::
+
+ f2py -m callback2 -h callback2.pyf callback.f
+
+ Then modify it as follows
+
+ .. include:: callback2.pyf
+ :literal:
+
+ Finally, build the extension module using::
+
+ f2py -c callback2.pyf callback.f
+
+ An example Python session would be identical to the previous example
+ except that argument names would differ.
+
+ __ callback.f
+
+Sometimes a Fortran package may require that users provide routines
+that the package will use. F2PY can construct an interface to such
+routines so that Python functions could be called from Fortran.
+
+.. topic:: Example
+
+ Consider the following `Fortran 77 subroutine`__ that takes an array
+ and applies a function ``func`` to its elements.
+
+ .. include:: calculate.f
+ :literal:
+
+ __ calculate.f
+
+ It is expected that function ``func`` has been defined
+ externally. In order to use a Python function as ``func``, it must
+ have an attribute ``intent(callback)`` (it must be specified before
+ the ``external`` statement).
+
+ Finally, build an extension module using::
+
+ f2py -c -m foo calculate.f
+
+ In Python:
+
+ .. include:: calculate_session.dat
+ :literal:
+
+The function is included as an argument to the python function call to
+the FORTRAN subroutine eventhough it was NOT in the FORTRAN subroutine argument
+list. The "external" refers to the C function generated by f2py, not the python
+function itself. The python function must be supplied to the C function.
+
+The callback function may also be explicitly set in the module.
+Then it is not necessary to pass the function in the argument list to
+the FORTRAN function. This may be desired if the FORTRAN function calling
+the python callback function is itself called by another FORTRAN function.
+
+.. topic:: Example
+
+ Consider the following `Fortran 77 subroutine`__.
+
+ .. include:: extcallback.f
+ :literal:
+
+ __ extcallback.f
+
+ and wrap it using ``f2py -c -m pfromf extcallback.f``.
+
+ In Python:
+
+ .. include:: extcallback_session.dat
+ :literal:
+
+Resolving arguments to call-back functions
+------------------------------------------
+
+F2PY generated interface is very flexible with respect to call-back
+arguments. For each call-back argument an additional optional
+argument ``<name>_extra_args`` is introduced by F2PY. This argument
+can be used to pass extra arguments to user provided call-back
+arguments.
+
+If a F2PY generated wrapper function expects the following call-back
+argument::
+
+ def fun(a_1,...,a_n):
+ ...
+ return x_1,...,x_k
+
+but the following Python function
+
+::
+
+ def gun(b_1,...,b_m):
+ ...
+ return y_1,...,y_l
+
+is provided by an user, and in addition,
+
+::
+
+ fun_extra_args = (e_1,...,e_p)
+
+is used, then the following rules are applied when a Fortran or C
+function calls the call-back argument ``gun``:
+
+* If ``p==0`` then ``gun(a_1,...,a_q)`` is called, here
+ ``q=min(m,n)``.
+* If ``n+p<=m`` then ``gun(a_1,...,a_n,e_1,...,e_p)`` is called.
+* If ``p<=m<n+p`` then ``gun(a_1,...,a_q,e_1,...,e_p)`` is called, here
+ ``q=m-p``.
+* If ``p>m`` then ``gun(e_1,...,e_m)`` is called.
+* If ``n+p`` is less than the number of required arguments to ``gun``
+ then an exception is raised.
+
+The function ``gun`` may return any number of objects as a tuple. Then
+following rules are applied:
+
+* If ``k<l``, then ``y_{k+1},...,y_l`` are ignored.
+* If ``k>l``, then only ``x_1,...,x_l`` are set.
+
+
+
+Common blocks
+==============
+
+F2PY generates wrappers to ``common`` blocks defined in a routine
+signature block. Common blocks are visible by all Fortran codes linked
+with the current extension module, but not to other extension modules
+(this restriction is due to how Python imports shared libraries). In
+Python, the F2PY wrappers to ``common`` blocks are ``fortran`` type
+objects that have (dynamic) attributes related to data members of
+common blocks. When accessed, these attributes return as Numeric array
+objects (multi-dimensional arrays are Fortran-contiguous) that
+directly link to data members in common blocks. Data members can be
+changed by direct assignment or by in-place changes to the
+corresponding array objects.
+
+.. topic:: Example
+
+ Consider the following `Fortran 77 code`__
+
+ .. include:: common.f
+ :literal:
+
+ and wrap it using ``f2py -c -m common common.f``.
+
+ __ common.f
+
+ In Python:
+
+ .. include:: common_session.dat
+ :literal:
+
+Fortran 90 module data
+=======================
+
+The F2PY interface to Fortran 90 module data is similar to Fortran 77
+common blocks.
+
+.. topic:: Example
+
+ Consider the following `Fortran 90 code`__
+
+ .. include:: moddata.f90
+ :literal:
+
+ and wrap it using ``f2py -c -m moddata moddata.f90``.
+
+ __ moddata.f90
+
+ In Python:
+
+ .. include:: moddata_session.dat
+ :literal:
+
+Allocatable arrays
+-------------------
+
+F2PY has basic support for Fortran 90 module allocatable arrays.
+
+.. topic:: Example
+
+ Consider the following `Fortran 90 code`__
+
+ .. include:: allocarr.f90
+ :literal:
+
+ and wrap it using ``f2py -c -m allocarr allocarr.f90``.
+
+ __ allocarr.f90
+
+ In Python:
+
+ .. include:: allocarr_session.dat
+ :literal:
+
+
+===========
+Using F2PY
+===========
+
+F2PY can be used either as a command line tool ``f2py`` or as a Python
+module ``f2py2e``.
+
+Command ``f2py``
+=================
+
+When used as a command line tool, ``f2py`` has three major modes,
+distinguished by the usage of ``-c`` and ``-h`` switches:
+
+1. To scan Fortran sources and generate a signature file, use
+
+ ::
+
+ f2py -h <filename.pyf> <options> <fortran files> \
+ [[ only: <fortran functions> : ] \
+ [ skip: <fortran functions> : ]]... \
+ [<fortran files> ...]
+
+ Note that a Fortran source file can contain many routines, and not
+ necessarily all routines are needed to be used from Python. So, you
+ can either specify which routines should be wrapped (in ``only: .. :``
+ part) or which routines F2PY should ignored (in ``skip: .. :`` part).
+
+ If ``<filename.pyf>`` is specified as ``stdout`` then signatures
+ are send to standard output instead of a file.
+
+ Among other options (see below), the following options can be used
+ in this mode:
+
+ ``--overwrite-signature``
+ Overwrite existing signature file.
+
+2. To construct an extension module, use
+
+ ::
+
+ f2py <options> <fortran files> \
+ [[ only: <fortran functions> : ] \
+ [ skip: <fortran functions> : ]]... \
+ [<fortran files> ...]
+
+ The constructed extension module is saved as
+ ``<modulename>module.c`` to the current directory.
+
+ Here ``<fortran files>`` may also contain signature files.
+ Among other options (see below), the following options can be used
+ in this mode:
+
+ ``--debug-capi``
+ Add debugging hooks to the extension module. When using this
+ extension module, various information about the wrapper is printed
+ to standard output, for example, the values of variables, the
+ steps taken, etc.
+
+ ``-include'<includefile>'``
+ Add a CPP ``#include`` statement to the extension module source.
+ ``<includefile>`` should be given in one of the following forms::
+
+ "filename.ext"
+ <filename.ext>
+
+ The include statement is inserted just before the wrapper
+ functions. This feature enables using arbitrary C functions
+ (defined in ``<includefile>``) in F2PY generated wrappers.
+
+ This option is deprecated. Use ``usercode`` statement to specify
+ C codelets directly in signature filess
+
+
+ ``--[no-]wrap-functions``
+
+ Create Fortran subroutine wrappers to Fortran functions.
+ ``--wrap-functions`` is default because it ensures maximum
+ portability and compiler independence.
+
+ ``--include-paths <path1>:<path2>:..``
+ Search include files from given directories.
+
+ ``--help-link [<list of resources names>]``
+ List system resources found by ``scipy_distutils/system_info.py``.
+ For example, try ``f2py --help-link lapack_opt``.
+
+3. To build an extension module, use
+
+ ::
+
+ f2py -c <options> <fortran files> \
+ [[ only: <fortran functions> : ] \
+ [ skip: <fortran functions> : ]]... \
+ [ <fortran/c source files> ] [ <.o, .a, .so files> ]
+
+ If ``<fortran files>`` contains a signature file, then a source for
+ an extension module is constructed, all Fortran and C sources are
+ compiled, and finally all object and library files are linked to the
+ extension module ``<modulename>.so`` which is saved into the current
+ directory.
+
+ If ``<fortran files>`` does not contain a signature file, then an
+ extension module is constructed by scanning all Fortran source codes
+ for routine signatures.
+
+ Among other options (see below) and options described in previous
+ mode, the following options can be used in this mode:
+
+ ``--help-fcompiler``
+ List available Fortran compilers.
+ ``--help-compiler`` [depreciated]
+ List available Fortran compilers.
+ ``--fcompiler=<Vendor>``
+ Specify Fortran compiler type by vendor.
+ ``--f77exec=<path>``
+ Specify the path to F77 compiler
+ ``--fcompiler-exec=<path>`` [depreciated]
+ Specify the path to F77 compiler
+ ``--f90exec=<path>``
+ Specify the path to F90 compiler
+ ``--f90compiler-exec=<path>`` [depreciated]
+ Specify the path to F90 compiler
+
+ ``--f77flags=<string>``
+ Specify F77 compiler flags
+ ``--f90flags=<string>``
+ Specify F90 compiler flags
+ ``--opt=<string>``
+ Specify optimization flags
+ ``--arch=<string>``
+ Specify architecture specific optimization flags
+ ``--noopt``
+ Compile without optimization
+ ``--noarch``
+ Compile without arch-dependent optimization
+ ``--debug``
+ Compile with debugging information
+
+ ``-l<libname>``
+ Use the library ``<libname>`` when linking.
+ ``-D<macro>[=<defn=1>]``
+ Define macro ``<macro>`` as ``<defn>``.
+ ``-U<macro>``
+ Define macro ``<macro>``
+ ``-I<dir>``
+ Append directory ``<dir>`` to the list of directories searched for
+ include files.
+ ``-L<dir>``
+ Add directory ``<dir>`` to the list of directories to be searched
+ for ``-l``.
+
+ ``link-<resource>``
+
+ Link extension module with <resource> as defined by
+ ``scipy_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.
+
+ When building an extension module, a combination of the following
+ macros may be required for non-gcc Fortran compilers::
+
+ -DPREPEND_FORTRAN
+ -DNO_APPEND_FORTRAN
+ -DUPPERCASE_FORTRAN
+
+ To test the performance of F2PY generated interfaces, use
+ ``-DF2PY_REPORT_ATEXIT``. Then a report of various timings is
+ printed out at the exit of Python. This feature may not work on
+ all platforms, currently only Linux platform is supported.
+
+ To see whether F2PY generated interface performs copies of array
+ arguments, use ``-DF2PY_REPORT_ON_ARRAY_COPY=<int>``. When the size
+ of an array argument is larger than ``<int>``, a message about
+ the coping is sent to ``stderr``.
+
+Other options:
+
+``-m <modulename>``
+ Name of an extension module. Default is ``untitled``. Don't use this option
+ if a signature file (*.pyf) is used.
+``--[no-]lower``
+ Do [not] lower the cases in ``<fortran files>``. By default,
+ ``--lower`` is assumed with ``-h`` switch, and ``--no-lower``
+ without the ``-h`` switch.
+``--build-dir <dirname>``
+ All F2PY generated files are created in ``<dirname>``. Default is
+ ``tempfile.mktemp()``.
+``--quiet``
+ Run quietly.
+``--verbose``
+ Run with extra verbosity.
+``-v``
+ Print f2py version ID and exit.
+
+Execute ``f2py`` without any options to get an up-to-date list of
+available options.
+
+Python module ``f2py2e``
+=========================
+
+.. topic:: Warning
+
+ The current Python interface to ``f2py2e`` module is not mature and
+ may change in future depending on users needs.
+
+The following functions are provided by the ``f2py2e`` module:
+
+``run_main(<list>)``
+ Equivalent to running::
+
+ f2py <args>
+
+ where ``<args>=string.join(<list>,' ')``, but in Python. Unless
+ ``-h`` is used, this function returns a dictionary containing
+ information on generated modules and their dependencies on source
+ files. For example, the command ``f2py -m scalar scalar.f`` can be
+ executed from Python as follows
+
+ .. include:: run_main_session.dat
+ :literal:
+
+ You cannot build extension modules with this function, that is,
+ using ``-c`` is not allowed. Use ``compile`` command instead, see
+ below.
+
+``compile(source, modulename='untitled', extra_args='', verbose=1, source_fn=None)``
+
+ Build extension module from Fortran 77 source string ``source``.
+ Return 0 if successful.
+ Note that this function actually calls ``f2py -c ..`` from shell to
+ ensure safety of the current Python process.
+ For example,
+
+ .. include:: compile_session.dat
+ :literal:
+
+==========================
+Using ``scipy_distutils``
+==========================
+
+``scipy_distutils`` is part of the SciPy_ project and aims to extend
+standard Python ``distutils`` to deal with Fortran sources and F2PY
+signature files, e.g. compile Fortran sources, call F2PY to construct
+extension modules, etc.
+
+.. topic:: Example
+
+ Consider the following `setup file`__:
+
+ .. include:: setup_example.py
+ :literal:
+
+ Running
+
+ ::
+
+ python setup_example.py build
+
+ will build two extension modules ``scalar`` and ``fib2`` to the
+ build directory.
+
+ __ setup_example.py
+
+``scipy_distutils`` extends ``distutils`` with the following features:
+
+* ``Extension`` class argument ``sources`` may contain Fortran source
+ files. In addition, the list ``sources`` may contain at most one
+ F2PY signature file, and then the name of an Extension module must
+ match with the ``<modulename>`` used in signature file. It is
+ assumed that an F2PY signature file contains exactly one ``python
+ module`` block.
+
+ If ``sources`` does not contain a signature files, then F2PY is used
+ to scan Fortran source files for routine signatures to construct the
+ wrappers to Fortran codes.
+
+ Additional options to F2PY process can be given using ``Extension``
+ class argument ``f2py_options``.
+
+``scipy_distutils`` 0.2.2 and up
+================================
+
+* The following new ``distutils`` commands are defined:
+
+ ``build_src``
+ to construct Fortran wrapper extension modules, among many other things.
+ ``config_fc``
+ to change Fortran compiler options
+
+ as well as ``build_ext`` and ``build_clib`` commands are enhanced
+ to support Fortran sources.
+
+ Run
+
+ ::
+
+ python <setup.py file> config_fc build_src build_ext --help
+
+ to see available options for these commands.
+
+* When building Python packages containing Fortran sources, then one
+ can choose different Fortran compilers by using ``build_ext``
+ command option ``--fcompiler=<Vendor>``. Here ``<Vendor>`` can be one of the
+ following names::
+
+ absoft sun mips intel intelv intele intelev nag compaq compaqv gnu vast pg hpux
+
+ See ``scipy_distutils/fcompiler.py`` for up-to-date list of
+ supported compilers or run
+
+ ::
+
+ f2py -c --help-fcompiler
+
+``scipy_distutils`` pre 0.2.2
+=============================
+
+* The following new ``distutils`` commands are defined:
+
+ ``build_flib``
+ to build f77/f90 libraries used by Python extensions;
+ ``run_f2py``
+ to construct Fortran wrapper extension modules.
+
+ Run
+
+ ::
+
+ python <setup.py file> build_flib run_f2py --help
+
+ to see available options for these commands.
+
+* When building Python packages containing Fortran sources, then one
+ can choose different Fortran compilers either by using ``build_flib``
+ command option ``--fcompiler=<Vendor>`` or by defining environment
+ variable ``FC_VENDOR=<Vendor>``. Here ``<Vendor>`` can be one of the
+ following names::
+
+ Absoft Sun SGI Intel Itanium NAG Compaq Digital Gnu VAST PG
+
+ See ``scipy_distutils/command/build_flib.py`` for up-to-date list of
+ supported compilers.
+
+======================
+ Extended F2PY usages
+======================
+
+Adding self-written functions to F2PY generated modules
+=======================================================
+
+Self-written Python C/API functions can be defined inside
+signature files using ``usercode`` and ``pymethoddef`` statements
+(they must be used inside the ``python module`` block). For
+example, the following signature file ``spam.pyf``
+
+.. include:: spam.pyf
+ :literal:
+
+wraps the C library function ``system()``::
+
+ f2py -c spam.pyf
+
+In Python:
+
+.. include:: spam_session.dat
+ :literal:
+
+Modifying the dictionary of a F2PY generated module
+===================================================
+
+The following example illustrates how to add an user-defined
+variables to a F2PY generated extension module. Given the following
+signature file
+
+.. include:: var.pyf
+ :literal:
+
+compile it as ``f2py -c var.pyf``.
+
+Notice that the second ``usercode`` statement must be defined inside
+an ``interface`` block and where the module dictionary is available through
+the variable ``d`` (see ``f2py var.pyf``-generated ``varmodule.c`` for
+additional details).
+
+In Python:
+
+.. include:: var_session.dat
+ :literal:
+
+.. References
+ ==========
+.. _F2PY: http://cens.ioc.ee/projects/f2py2e/
+.. _Python: http://www.python.org/
+.. _NumPy: http://www.numpy.org/
+.. _SciPy: http://www.scipy.org/
diff --git a/numpy/f2py/docs/usersguide/moddata.f90 b/numpy/f2py/docs/usersguide/moddata.f90
new file mode 100644
index 000000000..0e98f0467
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/moddata.f90
@@ -0,0 +1,18 @@
+module mod
+ integer i
+ integer :: x(4)
+ real, dimension(2,3) :: a
+ real, allocatable, dimension(:,:) :: b
+contains
+ subroutine foo
+ integer k
+ print*, "i=",i
+ print*, "x=[",x,"]"
+ print*, "a=["
+ print*, "[",a(1,1),",",a(1,2),",",a(1,3),"]"
+ print*, "[",a(2,1),",",a(2,2),",",a(2,3),"]"
+ print*, "]"
+ print*, "Setting a(1,2)=a(1,2)+3"
+ a(1,2) = a(1,2)+3
+ end subroutine foo
+end module mod
diff --git a/numpy/f2py/docs/usersguide/moddata_session.dat b/numpy/f2py/docs/usersguide/moddata_session.dat
new file mode 100644
index 000000000..1ec212f8b
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/moddata_session.dat
@@ -0,0 +1,23 @@
+>>> import moddata
+>>> print moddata.mod.__doc__
+i - 'i'-scalar
+x - 'i'-array(4)
+a - 'f'-array(2,3)
+foo - Function signature:
+ foo()
+
+
+>>> moddata.mod.i = 5
+>>> moddata.mod.x[:2] = [1,2]
+>>> moddata.mod.a = [[1,2,3],[4,5,6]]
+>>> moddata.mod.foo()
+ i= 5
+ x=[ 1 2 0 0 ]
+ a=[
+ [ 1.000000 , 2.000000 , 3.000000 ]
+ [ 4.000000 , 5.000000 , 6.000000 ]
+ ]
+ Setting a(1,2)=a(1,2)+3
+>>> moddata.mod.a # a is Fortran-contiguous
+array([[ 1., 5., 3.],
+ [ 4., 5., 6.]],'f')
diff --git a/numpy/f2py/docs/usersguide/run_main_session.dat b/numpy/f2py/docs/usersguide/run_main_session.dat
new file mode 100644
index 000000000..29ecc3dfe
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/run_main_session.dat
@@ -0,0 +1,14 @@
+>>> import f2py2e
+>>> r=f2py2e.run_main(['-m','scalar','docs/usersguide/scalar.f'])
+Reading fortran codes...
+ Reading file 'docs/usersguide/scalar.f'
+Post-processing...
+ Block: scalar
+ Block: FOO
+Building modules...
+ Building module "scalar"...
+ Wrote C/API module "scalar" to file "./scalarmodule.c"
+>>> print r
+{'scalar': {'h': ['/home/users/pearu/src_cvs/f2py2e/src/fortranobject.h'],
+ 'csrc': ['./scalarmodule.c',
+ '/home/users/pearu/src_cvs/f2py2e/src/fortranobject.c']}}
diff --git a/numpy/f2py/docs/usersguide/scalar.f b/numpy/f2py/docs/usersguide/scalar.f
new file mode 100644
index 000000000..c22f639ed
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/scalar.f
@@ -0,0 +1,12 @@
+C FILE: SCALAR.F
+ SUBROUTINE FOO(A,B)
+ REAL*8 A, B
+Cf2py intent(in) a
+Cf2py intent(inout) b
+ PRINT*, " A=",A," B=",B
+ PRINT*, "INCREMENT A AND B"
+ A = A + 1D0
+ B = B + 1D0
+ PRINT*, "NEW A=",A," B=",B
+ END
+C END OF FILE SCALAR.F
diff --git a/numpy/f2py/docs/usersguide/scalar_session.dat b/numpy/f2py/docs/usersguide/scalar_session.dat
new file mode 100644
index 000000000..4fe8c03b1
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/scalar_session.dat
@@ -0,0 +1,21 @@
+>>> import scalar
+>>> print scalar.foo.__doc__
+foo - Function signature:
+ foo(a,b)
+Required arguments:
+ a : input float
+ b : in/output rank-0 array(float,'d')
+
+>>> scalar.foo(2,3)
+ A= 2. B= 3.
+ INCREMENT A AND B
+ NEW A= 3. B= 4.
+>>> import Numeric
+>>> a=Numeric.array(2) # these are integer rank-0 arrays
+>>> b=Numeric.array(3)
+>>> scalar.foo(a,b)
+ A= 2. B= 3.
+ INCREMENT A AND B
+ NEW A= 3. B= 4.
+>>> print a,b # note that only b is changed in situ
+2 4 \ No newline at end of file
diff --git a/numpy/f2py/docs/usersguide/setup_example.py b/numpy/f2py/docs/usersguide/setup_example.py
new file mode 100644
index 000000000..a7d27403a
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/setup_example.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# File: setup_example.py
+
+from scipy_distutils.core import Extension
+
+ext1 = Extension(name = 'scalar',
+ sources = ['scalar.f'])
+ext2 = Extension(name = 'fib2',
+ sources = ['fib2.pyf','fib1.f'])
+
+if __name__ == "__main__":
+ from scipy_distutils.core import setup
+ setup(name = 'f2py_example',
+ description = "F2PY Users Guide examples",
+ author = "Pearu Peterson",
+ author_email = "pearu@cens.ioc.ee",
+ ext_modules = [ext1,ext2]
+ )
+# End of setup_example.py
diff --git a/numpy/f2py/docs/usersguide/spam.pyf b/numpy/f2py/docs/usersguide/spam.pyf
new file mode 100644
index 000000000..21ea18b77
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/spam.pyf
@@ -0,0 +1,19 @@
+! -*- f90 -*-
+python module spam
+ usercode '''
+ static char doc_spam_system[] = "Execute a shell command.";
+ static PyObject *spam_system(PyObject *self, PyObject *args)
+ {
+ char *command;
+ int sts;
+
+ if (!PyArg_ParseTuple(args, "s", &command))
+ return NULL;
+ sts = system(command);
+ return Py_BuildValue("i", sts);
+ }
+ '''
+ pymethoddef '''
+ {"system", spam_system, METH_VARARGS, doc_spam_system},
+ '''
+end python module spam
diff --git a/numpy/f2py/docs/usersguide/spam_session.dat b/numpy/f2py/docs/usersguide/spam_session.dat
new file mode 100644
index 000000000..7f99d13f9
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/spam_session.dat
@@ -0,0 +1,5 @@
+>>> import spam
+>>> status = spam.system('whoami')
+pearu
+>> status = spam.system('blah')
+sh: line 1: blah: command not found \ No newline at end of file
diff --git a/numpy/f2py/docs/usersguide/string.f b/numpy/f2py/docs/usersguide/string.f
new file mode 100644
index 000000000..9246f02e7
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/string.f
@@ -0,0 +1,21 @@
+C FILE: STRING.F
+ SUBROUTINE FOO(A,B,C,D)
+ CHARACTER*5 A, B
+ CHARACTER*(*) C,D
+Cf2py intent(in) a,c
+Cf2py intent(inout) b,d
+ PRINT*, "A=",A
+ PRINT*, "B=",B
+ PRINT*, "C=",C
+ PRINT*, "D=",D
+ PRINT*, "CHANGE A,B,C,D"
+ A(1:1) = 'A'
+ B(1:1) = 'B'
+ C(1:1) = 'C'
+ D(1:1) = 'D'
+ PRINT*, "A=",A
+ PRINT*, "B=",B
+ PRINT*, "C=",C
+ PRINT*, "D=",D
+ END
+C END OF FILE STRING.F
diff --git a/numpy/f2py/docs/usersguide/string_session.dat b/numpy/f2py/docs/usersguide/string_session.dat
new file mode 100644
index 000000000..64ebcb3f4
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/string_session.dat
@@ -0,0 +1,27 @@
+>>> import mystring
+>>> print mystring.foo.__doc__
+foo - Function signature:
+ foo(a,b,c,d)
+Required arguments:
+ a : input string(len=5)
+ b : in/output rank-0 array(string(len=5),'c')
+ c : input string(len=-1)
+ d : in/output rank-0 array(string(len=-1),'c')
+
+>>> import Numeric
+>>> a=Numeric.array('123')
+>>> b=Numeric.array('123')
+>>> c=Numeric.array('123')
+>>> d=Numeric.array('123')
+>>> mystring.foo(a,b,c,d)
+ A=123
+ B=123
+ C=123
+ D=123
+ CHANGE A,B,C,D
+ A=A23
+ B=B23
+ C=C23
+ D=D23
+>>> a.tostring(),b.tostring(),c.tostring(),d.tostring()
+('123', 'B23', '123', 'D23') \ No newline at end of file
diff --git a/numpy/f2py/docs/usersguide/var.pyf b/numpy/f2py/docs/usersguide/var.pyf
new file mode 100644
index 000000000..8275ff3af
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/var.pyf
@@ -0,0 +1,11 @@
+! -*- f90 -*-
+python module var
+ usercode '''
+ int BAR = 5;
+ '''
+ interface
+ usercode '''
+ PyDict_SetItemString(d,"BAR",PyInt_FromLong(BAR));
+ '''
+ end interface
+end python module
diff --git a/numpy/f2py/docs/usersguide/var_session.dat b/numpy/f2py/docs/usersguide/var_session.dat
new file mode 100644
index 000000000..fb0f798bf
--- /dev/null
+++ b/numpy/f2py/docs/usersguide/var_session.dat
@@ -0,0 +1,3 @@
+>>> import var
+>>> var.BAR
+5 \ No newline at end of file
diff --git a/numpy/f2py/f2py.1 b/numpy/f2py/f2py.1
new file mode 100644
index 000000000..3b9f054af
--- /dev/null
+++ b/numpy/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
+scipy_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.
+
+scipy_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.scipy.org
+.SH COPYRIGHT
+Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Pearu Peterson
+.SH LICENSE
+LGPL (see http://www.fsf.org)
+.SH VERSION
+2.45.241
diff --git a/numpy/f2py/f2py2e.py b/numpy/f2py/f2py2e.py
new file mode 100755
index 000000000..6230590d1
--- /dev/null
+++ b/numpy/f2py/f2py2e.py
@@ -0,0 +1,555 @@
+#!/usr/bin/env python
+"""
+
+f2py2e - Fortran to Python C/API generator. 2nd Edition.
+ See __usage__ below.
+
+Copyright 1999--2005 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@cens.ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 08:31:19 $
+Pearu Peterson
+"""
+__version__ = "$Revision: 1.90 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+import sys,os,string,pprint,shutil,types,re
+errmess=sys.stderr.write
+#outmess=sys.stdout.write
+show=pprint.pprint
+
+import crackfortran
+import rules
+import cb_rules
+import common_rules
+import auxfuncs
+import cfuncs
+import capi_maps
+import func2subr
+import f90mod_rules
+
+outmess = auxfuncs.outmess
+
+try:
+ from scipy import __core_version__ as scipy_core_version
+except ImportError:
+ scipy_distutils_version = 'N/A'
+
+__usage__ = """\
+Usage:
+
+1) To construct extension module sources:
+
+ f2py [<options>] <fortran files> [[[only:]||[skip:]] \\
+ <fortran functions> ] \\
+ [: <fortran files> ...]
+
+2) To compile fortran files and build extension modules:
+
+ f2py -c [<options>, <build_flib options>, <extra options>] <fortran files>
+
+3) To generate signature files:
+
+ f2py -h <filename.pyf> ...< same options as in (1) >
+
+Description: This program generates a Python C/API file (<modulename>module.c)
+ that contains wrappers for given fortran functions so that they
+ can be called from Python. With the -c option the corresponding
+ extension modules are built.
+
+Options:
+
+ -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.
+ <fortran functions> Names of fortran routines for which Python C/API
+ functions will be generated. Default is all that are found
+ in <fortran files>.
+ <fortran files> Paths to fortran/signature files that will be scanned for
+ <fortran functions> in order to determine their signatures.
+ skip: Ignore fortran functions that follow until `:'.
+ only: Use only fortran functions that follow until `:'.
+ : Get back to <fortran files> mode.
+
+ -m <modulename> Name of the module; f2py generates a Python/C API
+ file <modulename>module.c or extension module <modulename>.
+ Default is 'untitled'.
+
+ --[no-]lower Do [not] lower the cases in <fortran files>. By default,
+ --lower is assumed with -h key, and --no-lower without -h key.
+
+ --build-dir <dirname> All f2py generated files are created in <dirname>.
+ Default is tempfile.mktemp().
+
+ --overwrite-signature Overwrite existing signature file.
+
+ --[no-]latex-doc Create (or not) <modulename>module.tex.
+ Default is --no-latex-doc.
+ --short-latex Create 'incomplete' LaTeX document (without commands
+ \\documentclass, \\tableofcontents, and \\begin{document},
+ \\end{document}).
+
+ --[no-]rest-doc Create (or not) <modulename>module.rst.
+ Default is --no-rest-doc.
+
+ --debug-capi Create C/API code that reports the state of the wrappers
+ during runtime. Useful for debugging.
+
+ --[no-]wrap-functions Create Fortran subroutine wrappers to Fortran 77
+ functions. --wrap-functions is default because it ensures
+ maximum portability/compiler independence.
+
+ --include_paths <path1>:<path2>:... Search include files from the given
+ directories.
+
+ --help-link [..] List system resources found by system_info.py. See also
+ --link-<resource> switch below. [..] is optional list
+ of resources names. E.g. try 'f2py --help-link lapack_opt'.
+
+ --quiet Run quietly.
+ --verbose Run with extra verbosity.
+ -v Print f2py version ID and exit.
+
+
+scipy.distutils options (only effective with -c):
+
+ --fcompiler= Specify Fortran compiler type by vendor
+ --compiler= Specify C compiler type (as defined by distutils)
+
+ --help-fcompiler List available Fortran compilers and exit
+ --f77exec= Specify the path to F77 compiler
+ --f90exec= Specify the path to F90 compiler
+ --f77flags= Specify F77 compiler flags
+ --f90flags= Specify F90 compiler flags
+ --opt= Specify optimization flags
+ --arch= Specify architecture specific optimization flags
+ --noopt Compile without optimization
+ --noarch Compile without arch-dependent optimization
+ --debug Compile with debugging information
+
+Extra options (only effective with -c):
+
+ --link-<resource> Link extension module with <resource> as defined
+ by scipy.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.
+
+ -L/path/to/lib/ -l<libname>
+ -D<define> -U<name>
+ -I/path/to/include/
+ <filename>.o <filename>.so <filename>.a
+
+ Using the following macros may be required with non-gcc Fortran
+ compilers:
+ -DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN
+ -DUNDERSCORE_G77
+
+ When using -DF2PY_REPORT_ATEXIT, a performance report of F2PY
+ interface is printed out at exit (platforms: Linux).
+
+ When using -DF2PY_REPORT_ON_ARRAY_COPY=<int>, a message is
+ sent 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.
+
+Version: %s
+scipy_core Version: %s
+Requires: Python 2.3 or higher.
+License: LGPL (see http://www.fsf.org)
+Copyright 1999 - 2005 Pearu Peterson all rights reserved.
+http://cens.ioc.ee/projects/f2py2e/"""%(f2py_version, scipy_core_version)
+
+
+def scaninputline(inputline):
+ files,funcs,skipfuncs,onlyfuncs,debug=[],[],[],[],[]
+ f,f2,f3,f4,f5,f6,f7=1,0,0,0,0,0,0
+ verbose = 1
+ dolc=-1
+ dolatexdoc = 0
+ dorestdoc = 0
+ wrapfuncs = 1
+ buildpath = '.'
+ include_paths = []
+ signsfile,modulename=None,None
+ options = {'buildpath':buildpath}
+ for l in inputline:
+ if l=='': pass
+ elif l=='only:': f=0
+ elif l=='skip:': f=-1
+ elif l==':': f=1;f4=0
+ elif l[:8]=='--debug-': debug.append(l[8:])
+ elif l=='--lower': dolc=1
+ elif l=='--build-dir': f6=1
+ elif l=='--no-lower': dolc=0
+ elif l=='--quiet': verbose = 0
+ elif l=='--verbose': verbose += 1
+ elif l=='--latex-doc': dolatexdoc=1
+ elif l=='--no-latex-doc': dolatexdoc=0
+ elif l=='--rest-doc': dorestdoc=1
+ elif l=='--no-rest-doc': dorestdoc=0
+ elif l=='--wrap-functions': wrapfuncs=1
+ elif l=='--no-wrap-functions': wrapfuncs=0
+ elif l=='--short-latex': options['shortlatex']=1
+ elif l=='--overwrite-signature': options['h-overwrite']=1
+ elif l=='-h': f2=1
+ elif l=='-m': f3=1
+ elif l[:2]=='-v':
+ print f2py_version
+ sys.exit()
+ elif l=='--show-compilers':
+ f5=1
+ elif l[:8]=='-include':
+ cfuncs.outneeds['userincludes'].append(l[9:-1])
+ cfuncs.userincludes[l[9:-1]]='#include '+l[8:]
+ elif l[:15]=='--include_paths':
+ f7=1
+ elif l[0]=='-':
+ errmess('Unknown option %s\n'%`l`)
+ sys.exit()
+ elif f2: f2=0;signsfile=l
+ elif f3: f3=0;modulename=l
+ elif f6: f6=0;buildpath=l
+ elif f7: f7=0;include_paths.extend(l.split(os.pathsep))
+ elif f==1:
+ try:
+ open(l).close()
+ files.append(l)
+ except IOError,detail:
+ errmess('IOError: %s. Skipping file "%s".\n'%(str(detail),l))
+ elif f==-1: skipfuncs.append(l)
+ elif f==0: onlyfuncs.append(l)
+ if not f5 and not files and not modulename:
+ print __usage__
+ sys.exit()
+ if not os.path.isdir(buildpath):
+ if not verbose:
+ outmess('Creating build directory %s'%(buildpath))
+ os.mkdir(buildpath)
+ if signsfile:
+ signsfile = os.path.join(buildpath,signsfile)
+ if signsfile and os.path.isfile(signsfile) and not options.has_key('h-overwrite'):
+ errmess('Signature file "%s" exists!!! Use --overwrite-signature to overwrite.\n'%(signsfile))
+ sys.exit()
+
+ options['debug']=debug
+ options['verbose']=verbose
+ if dolc==-1 and not signsfile: options['do-lower']=0
+ else: options['do-lower']=dolc
+ if modulename: options['module']=modulename
+ if signsfile: options['signsfile']=signsfile
+ if onlyfuncs: options['onlyfuncs']=onlyfuncs
+ if skipfuncs: options['skipfuncs']=skipfuncs
+ options['dolatexdoc'] = dolatexdoc
+ options['dorestdoc'] = dorestdoc
+ options['wrapfuncs'] = wrapfuncs
+ options['buildpath']=buildpath
+ options['include_paths']=include_paths
+ return files,options
+
+def callcrackfortran(files,options):
+ rules.options=options
+ funcs=[]
+ crackfortran.debug=options['debug']
+ crackfortran.verbose=options['verbose']
+ if options.has_key('module'):
+ crackfortran.f77modulename=options['module']
+ if options.has_key('skipfuncs'):
+ crackfortran.skipfuncs=options['skipfuncs']
+ if options.has_key('onlyfuncs'):
+ crackfortran.onlyfuncs=options['onlyfuncs']
+ crackfortran.include_paths[:]=options['include_paths']
+ crackfortran.dolowercase=options['do-lower']
+ postlist=crackfortran.crackfortran(files)
+ if options.has_key('signsfile'):
+ outmess('Saving signatures to file "%s"\n'%(options['signsfile']))
+ pyf=crackfortran.crack2fortran(postlist)
+ if options['signsfile'][-6:]=='stdout':
+ sys.stdout.write(pyf)
+ else:
+ f=open(options['signsfile'],'w')
+ f.write(pyf)
+ f.close()
+ return postlist
+
+def buildmodules(list):
+ cfuncs.buildcfuncs()
+ outmess('Building modules...\n')
+ modules,mnames,isusedby=[],[],{}
+ for i in range(len(list)):
+ if string.find(list[i]['name'],'__user__')>=0:
+ cb_rules.buildcallbacks(list[i])
+ else:
+ if list[i].has_key('use'):
+ for u in list[i]['use'].keys():
+ if not isusedby.has_key(u): isusedby[u]=[]
+ isusedby[u].append(list[i]['name'])
+ modules.append(list[i])
+ mnames.append(list[i]['name'])
+ ret = {}
+ for i in range(len(mnames)):
+ if isusedby.has_key(mnames[i]):
+ outmess('\tSkipping module "%s" which is used by %s.\n'%(mnames[i],string.join(map(lambda s:'"%s"'%s,isusedby[mnames[i]]),',')))
+ else:
+ um=[]
+ if modules[i].has_key('use'):
+ for u in modules[i]['use'].keys():
+ if isusedby.has_key(u) and u in mnames:
+ um.append(modules[mnames.index(u)])
+ else:
+ outmess('\tModule "%s" uses nonexisting "%s" which will be ignored.\n'%(mnames[i],u))
+ ret[mnames[i]] = {}
+ dict_append(ret[mnames[i]],rules.buildmodule(modules[i],um))
+ return ret
+
+def dict_append(d_out,d_in):
+ for (k,v) in d_in.items():
+ if not d_out.has_key(k):
+ d_out[k] = []
+ if type(v) is types.ListType:
+ d_out[k] = d_out[k] + v
+ else:
+ d_out[k].append(v)
+
+def run_main(comline_list):
+ """Run f2py as if string.join(comline_list,' ') is used as a command line.
+ In case of using -h flag, return None.
+ """
+ reload(crackfortran)
+ f2pydir=os.path.dirname(os.path.abspath(cfuncs.__file__))
+ fobjhsrc = os.path.join(f2pydir,'src','fortranobject.h')
+ fobjcsrc = os.path.join(f2pydir,'src','fortranobject.c')
+ files,options=scaninputline(comline_list)
+ auxfuncs.options=options
+ postlist=callcrackfortran(files,options)
+ isusedby={}
+ for i in range(len(postlist)):
+ if postlist[i].has_key('use'):
+ for u in postlist[i]['use'].keys():
+ if not isusedby.has_key(u): isusedby[u]=[]
+ isusedby[u].append(postlist[i]['name'])
+ for i in range(len(postlist)):
+ if postlist[i]['block']=='python module' and string.find(postlist[i]['name'],'__user__')<0:
+ if isusedby.has_key(postlist[i]['name']):
+ #if not quiet:
+ outmess('Skipping Makefile build for module "%s" which is used by %s\n'%(postlist[i]['name'],string.join(map(lambda s:'"%s"'%s,isusedby[postlist[i]['name']]),',')))
+ if options.has_key('signsfile'):
+ if options['verbose']>1:
+ outmess('Stopping. Edit the signature file and then run f2py on the signature file: ')
+ outmess('%s %s\n'%(os.path.basename(sys.argv[0]),options['signsfile']))
+ return
+ for i in range(len(postlist)):
+ if postlist[i]['block']!='python module':
+ if not options.has_key('python module'):
+ errmess('Tip: If your original code is Fortran 77 then you must use -m option.\n')
+ raise TypeError,'All blocks must be module blocks but got %s'%(`postlist[i]['block']`)
+ auxfuncs.debugoptions=options['debug']
+ f90mod_rules.options=options
+ auxfuncs.wrapfuncs=options['wrapfuncs']
+
+ ret=buildmodules(postlist)
+
+ for mn in ret.keys():
+ dict_append(ret[mn],{'csrc':fobjcsrc,'h':fobjhsrc})
+ return ret
+
+def filter_files(prefix,suffix,files,remove_prefix=None):
+ """
+ Filter files by prefix and suffix.
+ """
+ filtered,rest = [],[]
+ match = re.compile(prefix+r'.*'+suffix+r'\Z').match
+ if remove_prefix:
+ ind = len(prefix)
+ else:
+ ind = 0
+ for file in map(string.strip,files):
+ if match(file): filtered.append(file[ind:])
+ else: rest.append(file)
+ return filtered,rest
+
+def get_prefix(module):
+ p = os.path.dirname(os.path.dirname(module.__file__))
+ return p
+
+def run_compile():
+ """
+ Do it all in one call!
+ """
+ import tempfile,os,shutil
+
+ i = sys.argv.index('-c')
+ del sys.argv[i]
+
+ remove_build_dir = 0
+ try: i = sys.argv.index('--build-dir')
+ except ValueError: i=None
+ if i is not None:
+ build_dir = sys.argv[i+1]
+ del sys.argv[i+1]
+ del sys.argv[i]
+ else:
+ remove_build_dir = 1
+ build_dir = os.path.join(tempfile.mktemp())
+
+ sysinfo_flags = filter(re.compile(r'[-][-]link[-]').match,sys.argv[1:])
+ sys.argv = filter(lambda a,flags=sysinfo_flags:a not in flags,sys.argv)
+ if sysinfo_flags:
+ sysinfo_flags = [f[7:] for f in sysinfo_flags]
+
+ f2py_flags = filter(re.compile(r'[-][-]((no[-]|)(wrap[-]functions|lower)|debug[-]capi|quiet)|[-]include').match,sys.argv[1:])
+ sys.argv = filter(lambda a,flags=f2py_flags:a not in flags,sys.argv)
+ f2py_flags2 = []
+ fl = 0
+ for a in sys.argv[1:]:
+ if a in ['only:','skip:']:
+ fl = 1
+ elif a==':':
+ fl = 0
+ if fl or a==':':
+ f2py_flags2.append(a)
+ if f2py_flags2 and f2py_flags2[-1]!=':':
+ f2py_flags2.append(':')
+ f2py_flags.extend(f2py_flags2)
+
+ sys.argv = filter(lambda a,flags=f2py_flags2:a not in flags,sys.argv)
+
+ flib_flags = filter(re.compile(r'[-][-]((f(90)?compiler([-]exec|)|compiler)=|help[-]compiler)').match,sys.argv[1:])
+ sys.argv = filter(lambda a,flags=flib_flags:a not in flags,sys.argv)
+ fc_flags = filter(re.compile(r'[-][-]((f(77|90)(flags|exec)|opt|arch)=|(debug|noopt|noarch|help[-]fcompiler))').match,sys.argv[1:])
+ sys.argv = filter(lambda a,flags=fc_flags:a not in flags,sys.argv)
+
+ if 1:
+ del_list = []
+ for s in flib_flags:
+ v = '--fcompiler='
+ if s[:len(v)]==v:
+ from scipy.distutils import fcompiler
+ allowed_keys = fcompiler.fcompiler_class.keys()
+ nv = ov = s[len(v):].lower()
+ if ov not in allowed_keys:
+ vmap = {} # XXX
+ try:
+ nv = vmap[ov]
+ except KeyError:
+ if ov not in vmap.values():
+ print 'Unknown vendor: "%s"' % (s[len(v):])
+ nv = ov
+ i = flib_flags.index(s)
+ flib_flags[i] = '--fcompiler=' + nv
+ continue
+ for s in del_list:
+ i = flib_flags.index(s)
+ del flib_flags[i]
+ assert len(flib_flags)<=2,`flib_flags`
+ setup_flags = filter(re.compile(r'[-][-](verbose)').match,sys.argv[1:])
+ sys.argv = filter(lambda a,flags=setup_flags:a not in flags,sys.argv)
+ if '--quiet' in f2py_flags:
+ setup_flags.append('--quiet')
+
+ modulename = 'untitled'
+ sources = sys.argv[1:]
+ if '-m' in sys.argv:
+ i = sys.argv.index('-m')
+ modulename = sys.argv[i+1]
+ del sys.argv[i+1],sys.argv[i]
+ sources = sys.argv[1:]
+ else:
+ from scipy.distutils.command.build_src import get_f2py_modulename
+ pyf_files,sources = filter_files('','[.]pyf([.]src|)',sources)
+ sources = pyf_files + sources
+ for f in pyf_files:
+ modulename = get_f2py_modulename(f)
+ if modulename:
+ break
+
+ extra_objects, sources = filter_files('','[.](o|a|so)',sources)
+ include_dirs, sources = filter_files('-I','',sources,remove_prefix=1)
+ library_dirs, sources = filter_files('-L','',sources,remove_prefix=1)
+ libraries, sources = filter_files('-l','',sources,remove_prefix=1)
+ undef_macros, sources = filter_files('-U','',sources,remove_prefix=1)
+ define_macros, sources = filter_files('-D','',sources,remove_prefix=1)
+ using_numarray = 0
+ using_numeric = 0
+ for i in range(len(define_macros)):
+ name_value = string.split(define_macros[i],'=',1)
+ if len(name_value)==1:
+ name_value.append(None)
+ if len(name_value)==2:
+ define_macros[i] = tuple(name_value)
+ else:
+ print 'Invalid use of -D:',name_value
+
+ from scipy.distutils.system_info import get_info
+
+ num_include_dir = None
+ num_info = {}
+ #import scipy
+ #n = 'scipy'
+ #p = get_prefix(scipy)
+ #from scipy.distutils.misc_util import get_scipy_include_dirs
+ #num_info = {'include_dirs': get_scipy_include_dirs()}
+
+ if num_info:
+ include_dirs.extend(num_info.get('include_dirs',[]))
+
+ from scipy.distutils.core import setup,Extension
+ ext_args = {'name':modulename,'sources':sources,
+ 'include_dirs': include_dirs,
+ 'library_dirs': library_dirs,
+ 'libraries': libraries,
+ 'define_macros': define_macros,
+ 'undef_macros': undef_macros,
+ 'extra_objects': extra_objects,
+ 'f2py_options': f2py_flags,
+ }
+
+ if sysinfo_flags:
+ from scipy.distutils.misc_util import dict_append
+ for n in sysinfo_flags:
+ i = get_info(n)
+ if not i:
+ outmess('No %s resources found in system'\
+ ' (try `f2py --help-link`)\n' % (`n`))
+ dict_append(ext_args,**i)
+
+ ext = Extension(**ext_args)
+ sys.argv = [sys.argv[0]] + setup_flags
+ sys.argv.extend(['build',
+ '--build-temp',build_dir,
+ '--build-base',build_dir,
+ '--build-platlib','.'])
+ if fc_flags:
+ sys.argv.extend(['config_fc']+fc_flags)
+ if flib_flags:
+ sys.argv.extend(['build_ext']+flib_flags)
+
+ setup(ext_modules = [ext])
+
+ if remove_build_dir and os.path.exists(build_dir):
+ outmess('Removing build directory %s\n'%(build_dir))
+ shutil.rmtree(build_dir)
+
+def main():
+ if '--help-link' in sys.argv[1:]:
+ sys.argv.remove('--help-link')
+ from scipy.distutils.system_info import show_all
+ show_all()
+ return
+ if '-c' in sys.argv[1:]:
+ run_compile()
+ else:
+ run_main(sys.argv[1:])
+
+#if __name__ == "__main__":
+# main()
+
+
+# EOF
+
diff --git a/numpy/f2py/f2py_testing.py b/numpy/f2py/f2py_testing.py
new file mode 100644
index 000000000..1126c3085
--- /dev/null
+++ b/numpy/f2py/f2py_testing.py
@@ -0,0 +1,74 @@
+
+import os,sys,re,time
+
+def cmdline():
+ m=re.compile(r'\A\d+\Z')
+ args = []
+ repeat = 1
+ for a in sys.argv[1:]:
+ if m.match(a):
+ repeat = eval(a)
+ else:
+ args.append(a)
+ f2py_opts = ' '.join(args)
+ return repeat,f2py_opts
+
+if sys.platform[:5]=='linux':
+ def jiffies(_proc_pid_stat = '/proc/%s/stat'%(os.getpid()),
+ _load_time=time.time()):
+ """ Return number of jiffies (1/100ths of a second) that this
+ process has been scheduled in user mode. See man 5 proc. """
+ try:
+ f=open(_proc_pid_stat,'r')
+ l = f.readline().split(' ')
+ f.close()
+ return int(l[13])
+ except:
+ return int(100*(time.time()-_load_time))
+
+ def memusage(_proc_pid_stat = '/proc/%s/stat'%(os.getpid())):
+ """ Return virtual memory size in bytes of the running python.
+ """
+ try:
+ f=open(_proc_pid_stat,'r')
+ l = f.readline().split(' ')
+ f.close()
+ return int(l[22])
+ except:
+ return
+else:
+ def jiffies(_load_time=time.time()):
+ """ Return number of jiffies (1/100ths of a second) that this
+ process has been scheduled in user mode. [Emulation with time.time]. """
+ return int(100*(time.time()-_load_time))
+
+ def memusage():
+ pass
+
+def run(runtest,test_functions,repeat=1):
+ l = [(t,repr(t.__doc__.split('\n')[1].strip())) for t in test_functions]
+ #l = [(t,'') for t in test_functions]
+ start_memusage = memusage()
+ diff_memusage = None
+ start_jiffies = jiffies()
+ i = 0
+ while i<repeat:
+ i += 1
+ for t,fname in l:
+ runtest(t)
+ if start_memusage is None: continue
+ if diff_memusage is None:
+ diff_memusage = memusage() - start_memusage
+ else:
+ diff_memusage2 = memusage() - start_memusage
+ if diff_memusage2!=diff_memusage:
+ print 'memory usage change at step %i:' % i,\
+ diff_memusage2-diff_memusage,\
+ fname
+ diff_memusage = diff_memusage2
+ current_memusage = memusage()
+ print 'run',repeat*len(test_functions),'tests',\
+ 'in %.2f seconds' % ((jiffies()-start_jiffies)/100.0)
+ if start_memusage:
+ print 'initial virtual memory size:',start_memusage,'bytes'
+ print 'current virtual memory size:',current_memusage,'bytes'
diff --git a/numpy/f2py/f90mod_rules.py b/numpy/f2py/f90mod_rules.py
new file mode 100644
index 000000000..9c0d54900
--- /dev/null
+++ b/numpy/f2py/f90mod_rules.py
@@ -0,0 +1,240 @@
+#!/usr/bin/env python
+"""
+
+Build F90 module support for f2py2e.
+
+Copyright 2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/02/03 19:30:23 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.27 $"[10:-1]
+
+f2py_version='See `f2py -v`'
+
+import pprint
+import sys,string,time,types,copy
+errmess=sys.stderr.write
+outmess=sys.stdout.write
+show=pprint.pprint
+
+from auxfuncs import *
+import capi_maps
+import cfuncs
+import rules
+import func2subr
+from crackfortran import undo_rmbadname, undo_rmbadname1
+
+options={}
+
+def findf90modules(m):
+ if ismodule(m): return [m]
+ if not hasbody(m): return []
+ ret = []
+ for b in m['body']:
+ if ismodule(b): ret.append(b)
+ else: ret=ret+findf90modules(b)
+ return ret
+
+fgetdims1 = """\
+ external f2pysetdata
+ logical ns
+ integer s(*),r,i,j
+ ns = .FALSE.
+ if (allocated(d)) then
+ do i=1,r
+ if ((size(d,i).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"""
+
+fgetdims2="""\
+ end if
+ if (allocated(d)) then
+ do i=1,r
+ s(i) = size(d,i)
+ end do
+ end if
+ flag = 1
+ call f2pysetdata(d,allocated(d))"""
+
+fgetdims2_sa="""\
+ end if
+ if (allocated(d)) then
+ do i=1,r
+ s(i) = size(d,i)
+ end do
+ !s(r) must be equal to len(d(1))
+ end if
+ flag = 2
+ call f2pysetdata(d,allocated(d))"""
+
+
+def buildhooks(pymod):
+ global fgetdims1,fgetdims2
+ ret = {'f90modhooks':[],'initf90modhooks':[],'body':[],
+ 'need':['F_FUNC','arrayobject.h'],
+ 'separatorsfor':{'includes0':'\n','includes':'\n'},
+ 'docs':['"Fortran 90/95 modules:\\n"'],
+ 'latexdoc':[]}
+ fhooks=['']
+ def fadd(line,s=fhooks): s[0] = '%s\n %s'%(s[0],line)
+ doc = ['']
+ def dadd(line,s=doc): s[0] = '%s\n%s'%(s[0],line)
+ for m in findf90modules(pymod):
+ sargs,fargs,efargs,modobjs,notvars,onlyvars=[],[],[],[],[m['name']],[]
+ sargsp = []
+ ifargs = []
+ mfargs = []
+ if hasbody(m):
+ for b in m['body']: notvars.append(b['name'])
+ for n in m['vars'].keys():
+ var = m['vars'][n]
+ if (n not in notvars) and (not l_or(isintent_hide,isprivate)(var)):
+ onlyvars.append(n)
+ mfargs.append(n)
+ outmess('\t\tConstructing F90 module support for "%s"...\n'%(m['name']))
+ if onlyvars:
+ outmess('\t\t Variables: %s\n'%(string.join(onlyvars)))
+ chooks=['']
+ def cadd(line,s=chooks): s[0] = '%s\n%s'%(s[0],line)
+ ihooks=['']
+ def iadd(line,s=ihooks): s[0] = '%s\n%s'%(s[0],line)
+
+ vrd=capi_maps.modsign2map(m)
+ cadd('static FortranDataDef f2py_%s_def[] = {'%(m['name']))
+ dadd('\\subsection{Fortran 90/95 module \\texttt{%s}}\n'%(m['name']))
+ if hasnote(m):
+ note = m['note']
+ if type(note) is type([]): note=string.join(note,'\n')
+ dadd(note)
+ if onlyvars:
+ dadd('\\begin{description}')
+ for n in onlyvars:
+ var = m['vars'][n]
+ modobjs.append(n)
+ ct = capi_maps.getctype(var)
+ at = capi_maps.c2capi_map[ct]
+ dm = capi_maps.getarrdims(n,var)
+ dms = string.strip(string.replace(dm['dims'],'*','-1'))
+ dms = string.strip(string.replace(dms,':','-1'))
+ if not dms: dms='-1'
+ use_fgetdims2 = fgetdims2
+ if isstringarray(var):
+ if var.has_key('charselector') and var['charselector'].has_key('len'):
+ cadd('\t{"%s",%s,{{%s,%s}},%s},'\
+ %(undo_rmbadname1(n),dm['rank'],dms,var['charselector']['len'],at))
+ use_fgetdims2 = fgetdims2_sa
+ else:
+ cadd('\t{"%s",%s,{{%s}},%s},'%(undo_rmbadname1(n),dm['rank'],dms,at))
+ else:
+ cadd('\t{"%s",%s,{{%s}},%s},'%(undo_rmbadname1(n),dm['rank'],dms,at))
+ dadd('\\item[]{{}\\verb@%s@{}}'%(capi_maps.getarrdocsign(n,var)))
+ if hasnote(var):
+ note = var['note']
+ if type(note) is type([]): note=string.join(note,'\n')
+ dadd('--- %s'%(note))
+ if isallocatable(var):
+ fargs.append('f2py_%s_getdims_%s'%(m['name'],n))
+ efargs.append(fargs[-1])
+ sargs.append('void (*%s)(int*,int*,void(*)(char*,int*),int*)'%(n))
+ sargsp.append('void (*)(int*,int*,void(*)(char*,int*),int*)')
+ iadd('\tf2py_%s_def[i_f2py++].func = %s;'%(m['name'],n))
+ fadd('subroutine %s(r,s,f2pysetdata,flag)'%(fargs[-1]))
+ fadd('use %s, only: d => %s\n'%(m['name'],undo_rmbadname1(n)))
+ fadd('integer flag\n')
+ fhooks[0]=fhooks[0]+fgetdims1
+ dms = eval('range(1,%s+1)'%(dm['rank']))
+ fadd(' allocate(d(%s))\n'%(string.join(map(lambda i:'s(%s)'%i,dms),',')))
+ fhooks[0]=fhooks[0]+use_fgetdims2
+ fadd('end subroutine %s'%(fargs[-1]))
+ else:
+ fargs.append(n)
+ sargs.append('char *%s'%(n))
+ sargsp.append('char*')
+ iadd('\tf2py_%s_def[i_f2py++].data = %s;'%(m['name'],n))
+ if onlyvars:
+ dadd('\\end{description}')
+ if hasbody(m):
+ for b in m['body']:
+ if not isroutine(b):
+ print 'Skipping',b['block'],b['name']
+ continue
+ modobjs.append('%s()'%(b['name']))
+ b['modulename'] = m['name']
+ api,wrap=rules.buildapi(b)
+ if isfunction(b):
+ fhooks[0]=fhooks[0]+wrap
+ fargs.append('f2pywrap_%s_%s'%(m['name'],b['name']))
+ #efargs.append(fargs[-1])
+ ifargs.append(func2subr.createfuncwrapper(b,signature=1))
+ else:
+ fargs.append(b['name'])
+ mfargs.append(fargs[-1])
+ #if options.has_key('--external-modroutines') and options['--external-modroutines']:
+ # outmess('\t\t\tapplying --external-modroutines for %s\n'%(b['name']))
+ # efargs.append(fargs[-1])
+ api['externroutines']=[]
+ ar=applyrules(api,vrd)
+ ar['docs']=[]
+ ar['docshort']=[]
+ ret=dictappend(ret,ar)
+ cadd('\t{"%s",-1,{{-1}},0,NULL,(void *)f2py_rout_#modulename#_%s_%s,doc_f2py_rout_#modulename#_%s_%s},'%(b['name'],m['name'],b['name'],m['name'],b['name']))
+ sargs.append('char *%s'%(b['name']))
+ sargsp.append('char *')
+ iadd('\tf2py_%s_def[i_f2py++].data = %s;'%(m['name'],b['name']))
+ cadd('\t{NULL}\n};\n')
+ iadd('}')
+ ihooks[0]='static void f2py_setup_%s(%s) {\n\tint i_f2py=0;%s'%(m['name'],string.join(sargs,','),ihooks[0])
+ if '_' in m['name']:
+ F_FUNC='F_FUNC_US'
+ else:
+ F_FUNC='F_FUNC'
+ iadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void (*)(%s));'\
+ %(F_FUNC,m['name'],string.upper(m['name']),string.join(sargsp,',')))
+ iadd('static void f2py_init_%s(void) {'%(m['name']))
+ iadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'\
+ %(F_FUNC,m['name'],string.upper(m['name']),m['name']))
+ iadd('}\n')
+ ret['f90modhooks']=ret['f90modhooks']+chooks+ihooks
+ ret['initf90modhooks']=['\tPyDict_SetItemString(d, "%s", PyFortranObject_New(f2py_%s_def,f2py_init_%s));'%(m['name'],m['name'],m['name'])]+ret['initf90modhooks']
+ fadd('')
+ fadd('subroutine f2pyinit%s(f2pysetupfunc)'%(m['name']))
+ #fadd('use %s'%(m['name']))
+ if mfargs:
+ for a in undo_rmbadname(mfargs):
+ fadd('use %s, only : %s'%(m['name'],a))
+ if ifargs:
+ fadd(string.join(['interface']+ifargs))
+ fadd('end interface')
+ fadd('external f2pysetupfunc')
+ if efargs:
+ for a in undo_rmbadname(efargs):
+ fadd('external %s'%(a))
+ fadd('call f2pysetupfunc(%s)'%(string.join(undo_rmbadname(fargs),',')))
+ fadd('end subroutine f2pyinit%s\n'%(m['name']))
+
+ dadd(string.replace(string.join(ret['latexdoc'],'\n'),r'\subsection{',r'\subsubsection{'))
+
+ ret['latexdoc']=[]
+ ret['docs'].append('"\t%s --- %s"'%(m['name'],
+ string.join(undo_rmbadname(modobjs),',')))
+
+ ret['routine_defs']=''
+ ret['doc']=[]
+ ret['docshort']=[]
+ ret['latexdoc']=doc[0]
+ if len(ret['docs'])<=1: ret['docs']=''
+ return ret,fhooks[0]
+
+
diff --git a/numpy/f2py/func2subr.py b/numpy/f2py/func2subr.py
new file mode 100644
index 000000000..4039c9996
--- /dev/null
+++ b/numpy/f2py/func2subr.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+"""
+
+Rules for building C/API module with f2py2e.
+
+Copyright 1999,2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2004/11/26 11:13:06 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.16 $"[10:-1]
+
+f2py_version='See `f2py -v`'
+
+import pprint,copy
+import sys,string,time,types,copy
+errmess=sys.stderr.write
+outmess=sys.stdout.write
+show=pprint.pprint
+
+from auxfuncs import *
+def var2fixfortran(vars,a,fa=None,f90mode=None):
+ if fa is None:
+ fa = a
+ if not vars.has_key(a):
+ show(vars)
+ outmess('var2fixfortran: No definition for argument "%s".\n'%a)
+ return ''
+ if not vars[a].has_key('typespec'):
+ show(vars[a])
+ outmess('var2fixfortran: No typespec for argument "%s".\n'%a)
+ return ''
+ vardef=vars[a]['typespec']
+ if vardef=='type' and vars[a].has_key('typename'):
+ vardef='%s(%s)'%(vardef,vars[a]['typename'])
+ selector={}
+ lk = ''
+ if vars[a].has_key('kindselector'):
+ selector=vars[a]['kindselector']
+ lk = 'kind'
+ elif vars[a].has_key('charselector'):
+ selector=vars[a]['charselector']
+ lk = 'len'
+ if selector.has_key('*'):
+ if f90mode:
+ if selector['*'] in ['*',':','(*)']:
+ vardef='%s(len=*)'%(vardef)
+ else:
+ vardef='%s(%s=%s)'%(vardef,lk,selector['*'])
+ else:
+ if selector['*'] in ['*',':']:
+ vardef='%s*(%s)'%(vardef,selector['*'])
+ else:
+ vardef='%s*%s'%(vardef,selector['*'])
+ else:
+ if selector.has_key('len'):
+ vardef='%s(len=%s'%(vardef,selector['len'])
+ if selector.has_key('kind'):
+ vardef='%s,kind=%s)'%(vardef,selector['kind'])
+ else:
+ vardef='%s)'%(vardef)
+ elif selector.has_key('kind'):
+ vardef='%s(kind=%s)'%(vardef,selector['kind'])
+
+ vardef='%s %s'%(vardef,fa)
+ if vars[a].has_key('dimension'):
+ vardef='%s(%s)'%(vardef,string.join(vars[a]['dimension'],','))
+ return vardef
+
+def createfuncwrapper(rout,signature=0):
+ assert isfunction(rout)
+ ret = ['']
+ def add(line,ret=ret):
+ ret[0] = '%s\n %s'%(ret[0],line)
+ name = rout['name']
+ fortranname = getfortranname(rout)
+ f90mode = ismoduleroutine(rout)
+ newname = '%sf2pywrap'%(name)
+ vars = rout['vars']
+ if not vars.has_key(newname):
+ vars[newname] = vars[name]
+ args = [newname]+rout['args'][1:]
+ else:
+ args = [newname]+rout['args']
+
+ l = var2fixfortran(vars,name,newname,f90mode)
+ return_char_star = 0
+ if l[:13]=='character*(*)':
+ return_char_star = 1
+ if f90mode: l = 'character(len=10)'+l[13:]
+ else: l = 'character*10'+l[13:]
+ charselect = vars[name]['charselector']
+ if charselect.get('*','')=='(*)':
+ charselect['*'] = '10'
+ if f90mode:
+ sargs = string.join(args,', ')
+ add('subroutine f2pywrap_%s_%s (%s)'%(rout['modulename'],name,sargs))
+ if not signature:
+ add('use %s, only : %s'%(rout['modulename'],fortranname))
+ else:
+ add('subroutine f2pywrap%s (%s)'%(name,string.join(args,', ')))
+ add('external %s'%(fortranname))
+ #if not return_char_star:
+ l = l + ', '+fortranname
+ args = args[1:]
+ dumped_args = []
+ for a in args:
+ if isexternal(vars[a]):
+ add('external %s'%(a))
+ dumped_args.append(a)
+ for a in args:
+ if a in dumped_args: continue
+ if isscalar(vars[a]):
+ add(var2fixfortran(vars,a,f90mode=f90mode))
+ dumped_args.append(a)
+ for a in args:
+ if a in dumped_args: continue
+ add(var2fixfortran(vars,a,f90mode=f90mode))
+
+ add(l)
+
+ if not signature:
+ if islogicalfunction(rout):
+ add('%s = .not.(.not.%s(%s))'%(newname,fortranname,string.join(args,', ')))
+ else:
+ add('%s = %s(%s)'%(newname,fortranname,string.join(args,', ')))
+ if f90mode:
+ add('end subroutine f2pywrap_%s_%s'%(rout['modulename'],name))
+ else:
+ add('end')
+ #print '**'*10
+ #print ret[0]
+ #print '**'*10
+ return ret[0]
+
+def assubr(rout):
+ if not isfunction_wrap(rout): return rout,''
+ fortranname = getfortranname(rout)
+ name = rout['name']
+ outmess('\t\tCreating wrapper for Fortran function "%s"("%s")...\n'%(name,fortranname))
+ rout = copy.copy(rout)
+ fname = name
+ rname = fname
+ if rout.has_key('result'):
+ rname = rout['result']
+ rout['vars'][fname]=rout['vars'][rname]
+ fvar = rout['vars'][fname]
+ if not isintent_out(fvar):
+ if not fvar.has_key('intent'): fvar['intent']=[]
+ fvar['intent'].append('out')
+ flag=1
+ for i in fvar['intent']:
+ if i.startswith('out='):
+ flag = 0
+ break
+ if flag:
+ fvar['intent'].append('out=%s' % (rname))
+
+ rout['args'] = [fname] + rout['args']
+ return rout,createfuncwrapper(rout)
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
new file mode 100644
index 000000000..cb2d78e65
--- /dev/null
+++ b/numpy/f2py/rules.py
@@ -0,0 +1,1345 @@
+#!/usr/bin/env python
+"""
+
+Rules for building C/API module with f2py2e.
+
+Here is a skeleton of a new wrapper function (13Dec2001):
+
+wrapper_function(args)
+ declarations
+ get_python_arguments, say, `a' and `b'
+
+ get_a_from_python
+ if (successful) {
+
+ get_b_from_python
+ if (successful) {
+
+ callfortran
+ if (succesful) {
+
+ put_a_to_python
+ if (succesful) {
+
+ put_b_to_python
+ if (succesful) {
+
+ buildvalue = ...
+
+ }
+
+ }
+
+ }
+
+ }
+ cleanup_b
+
+ }
+ cleanup_a
+
+ return buildvalue
+"""
+"""
+Copyright 1999,2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/08/30 08:58:42 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.129 $"[10:-1]
+
+import __version__
+f2py_version = __version__.version
+
+import pprint
+import sys,string,time,types,copy
+errmess=sys.stderr.write
+outmess=sys.stdout.write
+show=pprint.pprint
+
+from auxfuncs import *
+import capi_maps
+from capi_maps import *
+import cfuncs
+import common_rules
+import use_rules
+import f90mod_rules
+import func2subr
+options={}
+
+sepdict={}
+#for k in ['need_cfuncs']: sepdict[k]=','
+for k in ['decl',
+ 'frompyobj',
+ 'cleanupfrompyobj',
+ 'topyarr','method',
+ 'pyobjfrom','closepyobjfrom',
+ 'freemem',
+ 'userincludes',
+ 'includes0','includes','typedefs','typedefs_generated',
+ 'cppmacros','cfuncs','callbacks',
+ 'latexdoc',
+ 'restdoc',
+ 'routine_defs','externroutines',
+ 'initf2pywraphooks',
+ 'commonhooks','initcommonhooks',
+ 'f90modhooks','initf90modhooks']:
+ sepdict[k]='\n'
+
+#################### Rules for C/API module #################
+
+module_rules={
+ 'modulebody':"""\
+/* File: #modulename#module.c
+ * This file is auto-generated with f2py (version:#f2py_version#).
+ * f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
+ * written by Pearu Peterson <pearu@cens.ioc.ee>.
+ * See http://cens.ioc.ee/projects/f2py2e/
+ * Generation date: """+time.asctime(time.localtime(time.time()))+"""
+ * $R"""+"""evision:$
+ * $D"""+"""ate:$
+ * Do not edit this file directly unless you know what you are doing!!!
+ */
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+"""+gentitle("See f2py2e/cfuncs.py: includes")+"""
+#includes#
+#includes0#
+
+"""+gentitle("See f2py2e/rules.py: mod_rules['modulebody']")+"""
+static PyObject *#modulename#_error;
+static PyObject *#modulename#_module;
+
+"""+gentitle("See f2py2e/cfuncs.py: typedefs")+"""
+#typedefs#
+
+"""+gentitle("See f2py2e/cfuncs.py: typedefs_generated")+"""
+#typedefs_generated#
+
+"""+gentitle("See f2py2e/cfuncs.py: cppmacros")+"""
+#cppmacros#
+
+"""+gentitle("See f2py2e/cfuncs.py: cfuncs")+"""
+#cfuncs#
+
+"""+gentitle("See f2py2e/cfuncs.py: userincludes")+"""
+#userincludes#
+
+"""+gentitle("See f2py2e/capi_rules.py: usercode")+"""
+#usercode#
+
+/* See f2py2e/rules.py */
+#externroutines#
+
+"""+gentitle("See f2py2e/capi_rules.py: usercode1")+"""
+#usercode1#
+
+"""+gentitle("See f2py2e/cb_rules.py: buildcallback")+"""
+#callbacks#
+
+"""+gentitle("See f2py2e/rules.py: buildapi")+"""
+#body#
+
+"""+gentitle("See f2py2e/f90mod_rules.py: buildhooks")+"""
+#f90modhooks#
+
+"""+gentitle("See f2py2e/rules.py: module_rules['modulebody']")+"""
+
+"""+gentitle("See f2py2e/common_rules.py: buildhooks")+"""
+#commonhooks#
+
+"""+gentitle("See f2py2e/rules.py")+"""
+
+static FortranDataDef f2py_routine_defs[] = {
+#routine_defs#
+\t{NULL}
+};
+
+static PyMethodDef f2py_module_methods[] = {
+#pymethoddef#
+\t{NULL,NULL}
+};
+
+DL_EXPORT(void) init#modulename#(void) {
+\tint i;
+\tPyObject *m,*d, *s;
+\tm = #modulename#_module = Py_InitModule(\"#modulename#\", f2py_module_methods);
+\tPyFortran_Type.ob_type = &PyType_Type;
+\timport_array();
+\tif (PyErr_Occurred())
+\t\tPy_FatalError(\"can't initialize module #modulename# (failed to import scipy.base)\");
+\td = PyModule_GetDict(m);
+\ts = PyString_FromString(\"$R"""+"""evision: $\");
+\tPyDict_SetItemString(d, \"__version__\", s);
+\ts = PyString_FromString(\"This module '#modulename#' is auto-generated with f2py (version:#f2py_version#).\\nFunctions:\\n\"\n#docs#\".\");
+\tPyDict_SetItemString(d, \"__doc__\", s);
+\t#modulename#_error = PyErr_NewException (\"#modulename#.error\", NULL, NULL);
+\tPy_DECREF(s);
+\tfor(i=0;f2py_routine_defs[i].name!=NULL;i++)
+\t\tPyDict_SetItemString(d, f2py_routine_defs[i].name,PyFortranObject_NewAsAttr(&f2py_routine_defs[i]));
+#initf2pywraphooks#
+#initf90modhooks#
+#initcommonhooks#
+#interface_usercode#
+\tif (PyErr_Occurred())
+\t\tPy_FatalError(\"can't initialize module #modulename#\");
+
+#ifdef F2PY_REPORT_ATEXIT
+\ton_exit(f2py_report_on_exit,(void*)\"#modulename#\");
+#endif
+
+}
+#ifdef __cplusplus
+}
+#endif
+""",
+ 'separatorsfor':{'latexdoc':'\n\n',
+ 'restdoc':'\n\n'},
+ 'latexdoc':['\\section{Module \\texttt{#texmodulename#}}\n',
+ '#modnote#\n',
+ '#latexdoc#'],
+ 'restdoc':['Module #modulename#\n'+'='*80,
+ '\n#restdoc#']
+ }
+
+defmod_rules=[
+ {'body':'/*eof body*/',
+ 'method':'/*eof method*/',
+ 'externroutines':'/*eof externroutines*/',
+ 'routine_defs':'/*eof routine_defs*/',
+ 'initf90modhooks':'/*eof initf90modhooks*/',
+ 'initf2pywraphooks':'/*eof initf2pywraphooks*/',
+ 'initcommonhooks':'/*eof initcommonhooks*/',
+ 'latexdoc':'',
+ 'restdoc':'',
+ 'modnote':{hasnote:'#note#',l_not(hasnote):''},
+ }
+ ]
+
+routine_rules={
+ 'separatorsfor':sepdict,
+ 'body':"""
+#begintitle#
+static char doc_#apiname#[] = \"\\\nFunction signature:\\n\\\n\t#docreturn##name#(#docsignatureshort#)\\n\\\n#docstrsigns#\";
+/* #declfortranroutine# */
+static PyObject *#apiname#(const PyObject *capi_self,
+ PyObject *capi_args,
+ PyObject *capi_keywds,
+ #functype# (*f2py_func)(#callprotoargument#)) {
+\tPyObject * volatile capi_buildvalue = NULL;
+\tvolatile int f2py_success = 1;
+#decl#
+\tstatic char *capi_kwlist[] = {#kwlist##kwlistopt##kwlistxa#NULL};
+#usercode#
+#routdebugenter#
+#ifdef F2PY_REPORT_ATEXIT
+f2py_start_clock();
+#endif
+\tif (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\\
+\t\t\"#argformat#|#keyformat##xaformat#:#pyname#\",\\
+\t\tcapi_kwlist#args_capi##keys_capi##keys_xa#))\n\t\treturn NULL;
+#frompyobj#
+/*end of frompyobj*/
+#ifdef F2PY_REPORT_ATEXIT
+f2py_start_call_clock();
+#endif
+#callfortranroutine#
+if (PyErr_Occurred())
+ f2py_success = 0;
+#ifdef F2PY_REPORT_ATEXIT
+f2py_stop_call_clock();
+#endif
+/*end of callfortranroutine*/
+\t\tif (f2py_success) {
+#pyobjfrom#
+/*end of pyobjfrom*/
+\t\tCFUNCSMESS(\"Building return value.\\n\");
+\t\tcapi_buildvalue = Py_BuildValue(\"#returnformat#\"#return#);
+/*closepyobjfrom*/
+#closepyobjfrom#
+\t\t} /*if (f2py_success) after callfortranroutine*/
+/*cleanupfrompyobj*/
+#cleanupfrompyobj#
+\tif (capi_buildvalue == NULL) {
+#routdebugfailure#
+\t} else {
+#routdebugleave#
+\t}
+\tCFUNCSMESS(\"Freeing memory.\\n\");
+#freemem#
+#ifdef F2PY_REPORT_ATEXIT
+f2py_stop_clock();
+#endif
+\treturn capi_buildvalue;
+}
+#endtitle#
+""",
+ 'routine_defs':'#routine_def#',
+ 'initf2pywraphooks':'#initf2pywraphook#',
+ 'externroutines':'#declfortranroutine#',
+ 'doc':'#docreturn##name#(#docsignature#)',
+ 'docshort':'#docreturn##name#(#docsignatureshort#)',
+ 'docs':'"\t#docreturn##name#(#docsignature#)\\n"\n',
+ 'need':['arrayobject.h','CFUNCSMESS','MINMAX'],
+ 'cppmacros':{debugcapi:'#define DEBUGCFUNCS'},
+ 'latexdoc':['\\subsection{Wrapper function \\texttt{#texname#}}\n',
+ """
+\\noindent{{}\\verb@#docreturn##name#@{}}\\texttt{(#latexdocsignatureshort#)}
+#routnote#
+
+#latexdocstrsigns#
+"""],
+ 'restdoc':['Wrapped function ``#name#``\n'+'-'*80,
+
+ ]
+ }
+
+################## Rules for C/API function ##############
+
+rout_rules=[
+ { # Init
+ 'separatorsfor': {'callfortranroutine':'\n','routdebugenter':'\n','decl':'\n',
+ 'routdebugleave':'\n','routdebugfailure':'\n',
+ 'setjmpbuf':' || ',
+ 'docstrreq':'\n','docstropt':'\n','docstrout':'\n',
+ 'docstrcbs':'\n','docstrsigns':'\\n"\n"',
+ 'latexdocstrsigns':'\n',
+ 'latexdocstrreq':'\n','latexdocstropt':'\n',
+ 'latexdocstrout':'\n','latexdocstrcbs':'\n',
+ },
+ 'kwlist':'','kwlistopt':'','callfortran':'','callfortranappend':'',
+ 'docsign':'','docsignopt':'','decl':'/*decl*/',
+ 'freemem':'/*freemem*/',
+ 'docsignshort':'','docsignoptshort':'',
+ 'docstrsigns':'','latexdocstrsigns':'',
+ 'docstrreq':'Required arguments:',
+ 'docstropt':'Optional arguments:',
+ 'docstrout':'Return objects:',
+ 'docstrcbs':'Call-back functions:',
+ 'latexdocstrreq':'\\noindent Required arguments:',
+ 'latexdocstropt':'\\noindent Optional arguments:',
+ 'latexdocstrout':'\\noindent Return objects:',
+ 'latexdocstrcbs':'\\noindent Call-back functions:',
+ 'args_capi':'','keys_capi':'','functype':'',
+ 'frompyobj':'/*frompyobj*/',
+ 'cleanupfrompyobj':['/*end of cleanupfrompyobj*/'], #this list will be reversed
+ 'pyobjfrom':'/*pyobjfrom*/',
+ 'closepyobjfrom':['/*end of closepyobjfrom*/'], #this list will be reversed
+ 'topyarr':'/*topyarr*/','routdebugleave':'/*routdebugleave*/',
+ 'routdebugenter':'/*routdebugenter*/',
+ 'routdebugfailure':'/*routdebugfailure*/',
+ 'callfortranroutine':'/*callfortranroutine*/',
+ 'argformat':'','keyformat':'','need_cfuncs':'',
+ 'docreturn':'','return':'','returnformat':'','rformat':'',
+ 'kwlistxa':'','keys_xa':'','xaformat':'','docsignxa':'','docsignxashort':'',
+ 'initf2pywraphook':'',
+ 'routnote':{hasnote:'--- #note#',l_not(hasnote):''},
+ },{
+ 'apiname':'f2py_rout_#modulename#_#name#',
+ 'pyname':'#modulename#.#name#',
+ 'decl':'',
+ '_check':l_not(ismoduleroutine)
+ },{
+ 'apiname':'f2py_rout_#modulename#_#f90modulename#_#name#',
+ 'pyname':'#modulename#.#f90modulename#.#name#',
+ 'decl':'',
+ '_check':ismoduleroutine
+ },{ # Subroutine
+ 'functype':'void',
+ 'declfortranroutine':{l_and(l_not(l_or(ismoduleroutine,isintent_c)),l_not(isdummyroutine)):'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+ l_and(l_not(ismoduleroutine),isintent_c,l_not(isdummyroutine)):'extern void #fortranname#(#callprotoargument#);',
+ ismoduleroutine:'',
+ isdummyroutine:''
+ },
+ 'routine_def':{l_not(l_or(ismoduleroutine,isintent_c,isdummyroutine)):'\t{\"#name#\",-1,{{-1}},0,(char *)#F_FUNC#(#fortranname#,#FORTRANNAME#),(f2py_init_func)#apiname#,doc_#apiname#},',
+ l_and(l_not(ismoduleroutine),isintent_c,l_not(isdummyroutine)):'\t{\"#name#\",-1,{{-1}},0,(char *)#fortranname#,(f2py_init_func)#apiname#,doc_#apiname#},',
+ l_and(l_not(ismoduleroutine),isdummyroutine):'\t{\"#name#\",-1,{{-1}},0,NULL,(f2py_init_func)#apiname#,doc_#apiname#},',
+ },
+ 'need':{l_and(l_not(l_or(ismoduleroutine,isintent_c)),l_not(isdummyroutine)):'F_FUNC'},
+ 'callfortranroutine':[
+ {debugcapi:["""\tfprintf(stderr,\"debug-capi:Fortran subroutine `#fortranname#(#callfortran#)\'\\n\");"""]},
+ {hasexternals:"""\
+\t\tif (#setjmpbuf#) {
+\t\t\tf2py_success = 0;
+\t\t} else {"""},
+ {isthreadsafe:'\t\t\tPy_BEGIN_ALLOW_THREADS'},
+ {hascallstatement:'''\t\t\t\t#callstatement#;
+\t\t\t\t/*(*f2py_func)(#callfortran#);*/'''},
+ {l_not(l_or(hascallstatement,isdummyroutine)):'\t\t\t\t(*f2py_func)(#callfortran#);'},
+ {isthreadsafe:'\t\t\tPy_END_ALLOW_THREADS'},
+ {hasexternals:"""\t\t}"""}
+ ],
+ '_check':issubroutine,
+ },{ # Wrapped function
+ 'functype':'void',
+ 'declfortranroutine':{l_not(l_or(ismoduleroutine,isdummyroutine)):'extern void #F_WRAPPEDFUNC#(#name_lower#,#NAME#)(#callprotoargument#);',
+ isdummyroutine:'',
+ },
+
+ 'routine_def':{l_not(l_or(ismoduleroutine,isdummyroutine)):'\t{\"#name#\",-1,{{-1}},0,(char *)#F_WRAPPEDFUNC#(#name_lower#,#NAME#),(f2py_init_func)#apiname#,doc_#apiname#},',
+ isdummyroutine:'\t{\"#name#\",-1,{{-1}},0,NULL,(f2py_init_func)#apiname#,doc_#apiname#},',
+ },
+ 'initf2pywraphook':{l_not(l_or(ismoduleroutine,isdummyroutine)):'''
+ {
+ extern #ctype# #F_FUNC#(#name_lower#,#NAME#)(void);
+ PyObject* o = PyDict_GetItemString(d,"#name#");
+ PyObject_SetAttrString(o,"_cpointer", PyCObject_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL));
+ }
+ '''},
+ 'need':{l_not(l_or(ismoduleroutine,isdummyroutine)):['F_WRAPPEDFUNC','F_FUNC']},
+ 'callfortranroutine':[
+ {debugcapi:["""\tfprintf(stderr,\"debug-capi:Fortran subroutine `f2pywrap#name_lower#(#callfortran#)\'\\n\");"""]},
+ {hasexternals:"""\
+\tif (#setjmpbuf#) {
+\t\tf2py_success = 0;
+\t} else {"""},
+ {isthreadsafe:'\tPy_BEGIN_ALLOW_THREADS'},
+ {l_not(l_or(hascallstatement,isdummyroutine)):'\t(*f2py_func)(#callfortran#);'},
+ {hascallstatement:'\t#callstatement#;\n\t/*(*f2py_func)(#callfortran#);*/'},
+ {isthreadsafe:'\tPy_END_ALLOW_THREADS'},
+ {hasexternals:'\t}'}
+ ],
+ '_check':isfunction_wrap,
+ },{ # Function
+ 'functype':'#ctype#',
+ 'docreturn':{l_not(isintent_hide):'#rname#,'},
+ 'docstrout':'\t#pydocsignout#',
+ 'latexdocstrout':['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {hasresultnote:'--- #resultnote#'}],
+ 'callfortranroutine':[{l_and(debugcapi,isstringfunction):"""\
+#ifdef USESCOMPAQFORTRAN
+\tfprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callcompaqfortran#)\\n\");
+#else
+\tfprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\");
+#endif
+"""},
+ {l_and(debugcapi,l_not(isstringfunction)):"""\
+\tfprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\");
+"""}
+ ],
+ '_check':l_and(isfunction,l_not(isfunction_wrap))
+ },{ # Scalar function
+ 'declfortranroutine':{l_and(l_not(l_or(ismoduleroutine,isintent_c)),l_not(isdummyroutine)):'extern #ctype# #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+ l_and(l_not(ismoduleroutine),isintent_c,l_not(isdummyroutine)):'extern #ctype# #fortranname#(#callprotoargument#);',
+ isdummyroutine:''
+ },
+ 'routine_def':{l_and(l_not(l_or(ismoduleroutine,isintent_c)),l_not(isdummyroutine)):'\t{\"#name#\",-1,{{-1}},0,(char *)#F_FUNC#(#fortranname#,#FORTRANNAME#),(f2py_init_func)#apiname#,doc_#apiname#},',
+ l_and(l_not(ismoduleroutine),isintent_c,l_not(isdummyroutine)):'\t{\"#name#\",-1,{{-1}},0,(char *)#fortranname#,(f2py_init_func)#apiname#,doc_#apiname#},',
+ isdummyroutine:'\t{\"#name#\",-1,{{-1}},0,NULL,(f2py_init_func)#apiname#,doc_#apiname#},',
+ },
+ 'decl':[{iscomplexfunction_warn:'\t#ctype# #name#_return_value={0,0};',
+ l_not(iscomplexfunction):'\t#ctype# #name#_return_value=0;'},
+ {iscomplexfunction:'\tPyObject *#name#_return_value_capi = Py_None;'}
+ ],
+ 'callfortranroutine':[
+ {hasexternals:"""\
+\tif (#setjmpbuf#) {
+\t\tf2py_success = 0;
+\t} else {"""},
+ {isthreadsafe:'\tPy_BEGIN_ALLOW_THREADS'},
+ {hascallstatement:'''\t#callstatement#;
+/*\t#name#_return_value = (*f2py_func)(#callfortran#);*/
+'''},
+ {l_not(l_or(hascallstatement,isdummyroutine)):'\t#name#_return_value = (*f2py_func)(#callfortran#);'},
+ {isthreadsafe:'\tPy_END_ALLOW_THREADS'},
+ {hasexternals:'\t}'},
+ {l_and(debugcapi,iscomplexfunction):'\tfprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value.r,#name#_return_value.i);'},
+ {l_and(debugcapi,l_not(iscomplexfunction)):'\tfprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value);'}],
+ 'pyobjfrom':{iscomplexfunction:'\t#name#_return_value_capi = pyobj_from_#ctype#1(#name#_return_value);'},
+ 'need':[{l_not(isdummyroutine):'F_FUNC'},
+ {iscomplexfunction:'pyobj_from_#ctype#1'},
+ {islong_longfunction:'long_long'},
+ {islong_doublefunction:'long_double'}],
+ 'returnformat':{l_not(isintent_hide):'#rformat#'},
+ 'return':{iscomplexfunction:',#name#_return_value_capi',
+ l_not(l_or(iscomplexfunction,isintent_hide)):',#name#_return_value'},
+ '_check':l_and(isfunction,l_not(isstringfunction),l_not(isfunction_wrap))
+ },{ # String function # in use for --no-wrap
+ 'declfortranroutine':'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+ 'routine_def':{l_not(l_or(ismoduleroutine,isintent_c)):
+# '\t{\"#name#\",-1,{{-1}},0,(char *)F_FUNC(#fortranname#,#FORTRANNAME#),(void *)#apiname#,doc_#apiname#},',
+ '\t{\"#name#\",-1,{{-1}},0,(char *)#F_FUNC#(#fortranname#,#FORTRANNAME#),(f2py_init_func)#apiname#,doc_#apiname#},',
+ l_and(l_not(ismoduleroutine),isintent_c):
+# '\t{\"#name#\",-1,{{-1}},0,(char *)#fortranname#,(void *)#apiname#,doc_#apiname#},'
+ '\t{\"#name#\",-1,{{-1}},0,(char *)#fortranname#,(f2py_init_func)#apiname#,doc_#apiname#},'
+ },
+ 'decl':['\t#ctype# #name#_return_value = NULL;',
+ '\tint #name#_return_value_len = 0;'],
+ 'callfortran':'#name#_return_value,#name#_return_value_len,',
+ 'callfortranroutine':['\t#name#_return_value_len = #rlength#;',
+ '\tif ((#name#_return_value = (string)malloc(sizeof(char)*(#name#_return_value_len+1))) == NULL) {',
+ '\t\tPyErr_SetString(PyExc_MemoryError, \"out of memory\");',
+ '\t\tf2py_success = 0;',
+ '\t} else {',
+ "\t\t(#name#_return_value)[#name#_return_value_len] = '\\0';",
+ '\t}',
+ '\tif (f2py_success) {',
+ {hasexternals:"""\
+\t\tif (#setjmpbuf#) {
+\t\t\tf2py_success = 0;
+\t\t} else {"""},
+ {isthreadsafe:'\t\tPy_BEGIN_ALLOW_THREADS'},
+ """\
+#ifdef USESCOMPAQFORTRAN
+\t\t(*f2py_func)(#callcompaqfortran#);
+#else
+\t\t(*f2py_func)(#callfortran#);
+#endif
+""",
+ {isthreadsafe:'\t\tPy_END_ALLOW_THREADS'},
+ {hasexternals:'\t\t}'},
+ {debugcapi:'\t\tfprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value_len,#name#_return_value);'},
+ '\t} /* if (f2py_success) after (string)malloc */',
+ ],
+ 'returnformat':'#rformat#',
+ 'return':',#name#_return_value',
+ 'freemem':'\tSTRINGFREE(#name#_return_value);',
+ 'need':['F_FUNC','#ctype#','STRINGFREE'],
+ '_check':l_and(isstringfunction,l_not(isfunction_wrap)) # ???obsolete
+ },
+ { # Debugging
+ 'routdebugenter':'\tfprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#(#docsignature#)\\n");',
+ 'routdebugleave':'\tfprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: successful.\\n");',
+ 'routdebugfailure':'\tfprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: failure.\\n");',
+ '_check':debugcapi
+ }
+ ]
+
+################ Rules for arguments ##################
+
+typedef_need_dict = {islong_long:'long_long',
+ islong_double:'long_double',
+ islong_complex:'complex_long_double',
+ isunsigned_char:'unsigned_char',
+ isunsigned_short:'unsigned_short',
+ isunsigned:'unsigned',
+ isunsigned_long_long:'unsigned_long_long'}
+
+aux_rules=[
+ {
+ 'separatorsfor':sepdict
+ },
+ { # Common
+ 'frompyobj':['\t/* Processing auxiliary variable #varname# */',
+ {debugcapi:'\tfprintf(stderr,"#vardebuginfo#\\n");'},],
+ 'cleanupfrompyobj':'\t/* End of cleaning variable #varname# */',
+ 'need':typedef_need_dict,
+ },
+# Scalars (not complex)
+ { # Common
+ 'decl':'\t#ctype# #varname# = 0;',
+ 'need':{hasinitvalue:'math.h'},
+ 'frompyobj':{hasinitvalue:'\t#varname# = #init#;'},
+ '_check':l_and(isscalar,l_not(iscomplex)),
+ },
+ {
+ 'return':',#varname#',
+ 'docstrout':'\t#pydocsignout#',
+ 'docreturn':'#outvarname#,',
+ 'returnformat':'#varrformat#',
+ '_check':l_and(isscalar,l_not(iscomplex),isintent_out),
+ },
+# Complex scalars
+ { # Common
+ 'decl':'\t#ctype# #varname#;',
+ 'frompyobj': {hasinitvalue:'\t#varname#.r = #init.r#, #varname#.i = #init.i#;'},
+ '_check':iscomplex
+ },
+# String
+ { # Common
+ 'decl':['\t#ctype# #varname# = NULL;',
+ '\tint slen(#varname#);',
+ ],
+ 'need':['len..'],
+ '_check':isstring
+ },
+# Array
+ { # Common
+ 'decl':['\t#ctype# *#varname# = NULL;',
+ '\tintp #varname#_Dims[#rank#] = {#rank*[-1]#};',
+ '\tconst int #varname#_Rank = #rank#;',
+ ],
+ 'need':['len..',{hasinitvalue:'forcomb'},{hasinitvalue:'CFUNCSMESS'}],
+ '_check':isarray
+ },
+# Scalararray
+ { # Common
+ '_check':l_and(isarray,l_not(iscomplexarray))
+ },{ # Not hidden
+ '_check':l_and(isarray,l_not(iscomplexarray),isintent_nothide)
+ },
+# Integer*1 array
+ {'need':'#ctype#',
+ '_check':isint1array,
+ '_depend':''
+ },
+# Integer*-1 array
+ {'need':'#ctype#',
+ '_check':isunsigned_chararray,
+ '_depend':''
+ },
+# Integer*-2 array
+ {'need':'#ctype#',
+ '_check':isunsigned_shortarray,
+ '_depend':''
+ },
+# Integer*-8 array
+ {'need':'#ctype#',
+ '_check':isunsigned_long_longarray,
+ '_depend':''
+ },
+# Complexarray
+ {'need':'#ctype#',
+ '_check':iscomplexarray,
+ '_depend':''
+ },
+# Stringarray
+ {
+ 'callfortranappend':{isarrayofstrings:'flen(#varname#),'},
+ 'need':'string',
+ '_check':isstringarray
+ }
+ ]
+
+arg_rules=[
+ {
+ 'separatorsfor':sepdict
+ },
+ { # Common
+ 'frompyobj':['\t/* Processing variable #varname# */',
+ {debugcapi:'\tfprintf(stderr,"#vardebuginfo#\\n");'},],
+ 'cleanupfrompyobj':'\t/* End of cleaning variable #varname# */',
+ '_depend':'',
+ 'need':typedef_need_dict,
+ },
+# Doc signatures
+ {
+ 'docstropt':{l_and(isoptional,isintent_nothide):'\t#pydocsign#'},
+ 'docstrreq':{l_and(isrequired,isintent_nothide):'\t#pydocsign#'},
+ 'docstrout':{isintent_out:'\t#pydocsignout#'},
+ 'latexdocstropt':{l_and(isoptional,isintent_nothide):['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote:'--- #note#'}]},
+ 'latexdocstrreq':{l_and(isrequired,isintent_nothide):['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote:'--- #note#'}]},
+ 'latexdocstrout':{isintent_out:['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {l_and(hasnote,isintent_hide):'--- #note#',
+ l_and(hasnote,isintent_nothide):'--- See above.'}]},
+ 'depend':''
+ },
+# Required/Optional arguments
+ {
+ 'kwlist':'"#varname#",',
+ 'docsign':'#varname#,',
+ '_check':l_and(isintent_nothide,l_not(isoptional))
+ },
+ {
+ 'kwlistopt':'"#varname#",',
+ 'docsignopt':'#varname#=#showinit#,',
+ 'docsignoptshort':'#varname#,',
+ '_check':l_and(isintent_nothide,isoptional)
+ },
+# Docstring/BuildValue
+ {
+ 'docreturn':'#outvarname#,',
+ 'returnformat':'#varrformat#',
+ '_check':isintent_out
+ },
+# Externals (call-back functions)
+ { # Common
+ 'docsignxa':{isintent_nothide:'#varname#_extra_args=(),'},
+ 'docsignxashort':{isintent_nothide:'#varname#_extra_args,'},
+ 'docstropt':{isintent_nothide:'\t#varname#_extra_args := () input tuple'},
+ 'docstrcbs':'#cbdocstr#',
+ 'latexdocstrcbs':'\\item[] #cblatexdocstr#',
+ 'latexdocstropt':{isintent_nothide:'\\item[]{{}\\verb@#varname#_extra_args := () input tuple@{}} --- Extra arguments for call-back function {{}\\verb@#varname#@{}}.'},
+ 'decl':['\tPyObject *#varname#_capi = Py_None;',
+ '\tPyTupleObject *#varname#_xa_capi = NULL;',
+ '\tPyTupleObject *#varname#_args_capi = NULL;',
+ '\tint #varname#_nofargs_capi = 0;',
+ {l_not(isintent_callback):'\t#cbname#_typedef #varname#_cptr;'}
+ ],
+ 'kwlistxa':{isintent_nothide:'"#varname#_extra_args",'},
+ 'argformat':{isrequired:'O'},
+ 'keyformat':{isoptional:'O'},
+ 'xaformat':{isintent_nothide:'O!'},
+ 'args_capi':{isrequired:',&#varname#_capi'},
+ 'keys_capi':{isoptional:',&#varname#_capi'},
+ 'keys_xa':',&PyTuple_Type,&#varname#_xa_capi',
+ 'setjmpbuf':'(setjmp(#cbname#_jmpbuf))',
+ 'callfortran':{l_not(isintent_callback):'#varname#_cptr,'},
+ 'need':['#cbname#','setjmp.h'],
+ '_check':isexternal
+ },
+ {
+ 'frompyobj':[{l_not(isintent_callback):"""\
+if(PyCObject_Check(#varname#_capi)) {
+ #varname#_cptr = PyCObject_AsVoidPtr(#varname#_capi);
+} else {
+ #varname#_cptr = #cbname#;
+}
+"""},{isintent_callback:"""\
+if (#varname#_capi==Py_None) {
+ #varname#_capi = PyObject_GetAttrString(#modulename#_module,\"#varname#\");
+ if (#varname#_capi) {
+ if (#varname#_xa_capi==NULL) {
+ if (PyObject_HasAttrString(#modulename#_module,\"#varname#_extra_args\")) {
+ PyObject* capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#varname#_extra_args\");
+ if (capi_tmp)
+ #varname#_xa_capi = (PyTupleObject *)PySequence_Tuple(capi_tmp);
+ else
+ #varname#_xa_capi = (PyTupleObject *)Py_BuildValue(\"()\");
+ if (#varname#_xa_capi==NULL) {
+ PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#varname#_extra_args to tuple.\\n\");
+ return NULL;
+ }
+ }
+ }
+ }
+ if (#varname#_capi==NULL) {
+ PyErr_SetString(#modulename#_error,\"Callback #varname# not defined (as an argument or module #modulename# attribute).\\n\");
+ return NULL;
+ }
+}
+"""},
+## {l_not(isintent_callback):"""\
+## if (#varname#_capi==Py_None) {
+## printf(\"hoi\\n\");
+## }
+## """},
+"""\
+\t#varname#_nofargs_capi = #cbname#_nofargs;
+\tif (create_cb_arglist(#varname#_capi,#varname#_xa_capi,#maxnofargs#,#nofoptargs#,&#cbname#_nofargs,&#varname#_args_capi,\"failed in processing argument list for call-back #varname#.\")) {
+\t\tjmp_buf #varname#_jmpbuf;""",
+{debugcapi:["""\
+\t\tfprintf(stderr,\"debug-capi:Assuming %d arguments; at most #maxnofargs#(-#nofoptargs#) is expected.\\n\",#cbname#_nofargs);
+\t\tCFUNCSMESSPY(\"for #varname#=\",#cbname#_capi);""",
+{l_not(isintent_callback):"""\t\tfprintf(stderr,\"#vardebugshowvalue# (call-back in C).\\n\",#cbname#);"""}]},
+ """\
+\t\tCFUNCSMESS(\"Saving jmpbuf for `#varname#`.\\n\");
+\t\tSWAP(#varname#_capi,#cbname#_capi,PyObject);
+\t\tSWAP(#varname#_args_capi,#cbname#_args_capi,PyTupleObject);
+\t\tmemcpy(&#varname#_jmpbuf,&#cbname#_jmpbuf,sizeof(jmp_buf));""",
+ ],
+'cleanupfrompyobj':
+"""\
+\t\tCFUNCSMESS(\"Restoring jmpbuf for `#varname#`.\\n\");
+\t\t#cbname#_capi = #varname#_capi;
+\t\tPy_DECREF(#cbname#_args_capi);
+\t\t#cbname#_args_capi = #varname#_args_capi;
+\t\t#cbname#_nofargs = #varname#_nofargs_capi;
+\t\tmemcpy(&#cbname#_jmpbuf,&#varname#_jmpbuf,sizeof(jmp_buf));
+\t}""",
+ 'need':['SWAP','create_cb_arglist'],
+ '_check':isexternal,
+ '_depend':''
+ },
+# Scalars (not complex)
+ { # Common
+ 'decl':'\t#ctype# #varname# = 0;',
+ 'pyobjfrom':{debugcapi:'\tfprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'},
+ 'callfortran':{isintent_c:'#varname#,',l_not(isintent_c):'&#varname#,'},
+ 'return':{isintent_out:',#varname#'},
+ '_check':l_and(isscalar,l_not(iscomplex))
+ },{
+ 'need':{hasinitvalue:'math.h'},
+ '_check':l_and(isscalar,l_not(iscomplex)),
+ #'_depend':''
+ },{ # Not hidden
+ 'decl':'\tPyObject *#varname#_capi = Py_None;',
+ 'argformat':{isrequired:'O'},
+ 'keyformat':{isoptional:'O'},
+ 'args_capi':{isrequired:',&#varname#_capi'},
+ 'keys_capi':{isoptional:',&#varname#_capi'},
+ 'pyobjfrom':{isintent_inout:"""\
+\tf2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#);
+\tif (f2py_success) {"""},
+ 'closepyobjfrom':{isintent_inout:"\t} /*if (f2py_success) of #varname# pyobjfrom*/"},
+ 'need':{isintent_inout:'try_pyarr_from_#ctype#'},
+ '_check':l_and(isscalar,l_not(iscomplex),isintent_nothide)
+ },{
+ 'frompyobj':[
+# hasinitvalue...
+# if pyobj is None:
+# varname = init
+# else
+# from_pyobj(varname)
+#
+# isoptional and noinitvalue...
+# if pyobj is not None:
+# from_pyobj(varname)
+# else:
+# varname is uninitialized
+#
+# ...
+# from_pyobj(varname)
+#
+ {hasinitvalue:'\tif (#varname#_capi == Py_None) #varname# = #init#; else',
+ '_depend':''},
+ {l_and(isoptional,l_not(hasinitvalue)):'\tif (#varname#_capi != Py_None)',
+ '_depend':''},
+ {l_not(islogical):'''\
+\t\tf2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#");
+\tif (f2py_success) {'''},
+ {islogical:'''\
+\t\t#varname# = (#ctype#)PyObject_IsTrue(#varname#_capi);
+\t\tf2py_success = 1;
+\tif (f2py_success) {'''},
+ ],
+ 'cleanupfrompyobj':'\t} /*if (f2py_success) of #varname#*/',
+ 'need':{l_not(islogical):'#ctype#_from_pyobj'},
+ '_check':l_and(isscalar,l_not(iscomplex),isintent_nothide),
+ '_depend':''
+# },{ # Hidden
+# '_check':l_and(isscalar,l_not(iscomplex),isintent_hide)
+ },{ # Hidden
+ 'frompyobj':{hasinitvalue:'\t#varname# = #init#;'},
+ 'need':typedef_need_dict,
+ '_check':l_and(isscalar,l_not(iscomplex),isintent_hide),
+ '_depend':''
+ },{ # Common
+ 'frompyobj':{debugcapi:'\tfprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'},
+ '_check':l_and(isscalar,l_not(iscomplex)),
+ '_depend':''
+ },
+# Complex scalars
+ { # Common
+ 'decl':'\t#ctype# #varname#;',
+ 'callfortran':{isintent_c:'#varname#,',l_not(isintent_c):'&#varname#,'},
+ 'pyobjfrom':{debugcapi:'\tfprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'},
+ 'return':{isintent_out:',#varname#_capi'},
+ '_check':iscomplex
+ },{ # Not hidden
+ 'decl':'\tPyObject *#varname#_capi = Py_None;',
+ 'argformat':{isrequired:'O'},
+ 'keyformat':{isoptional:'O'},
+ 'args_capi':{isrequired:',&#varname#_capi'},
+ 'keys_capi':{isoptional:',&#varname#_capi'},
+ 'need':{isintent_inout:'try_pyarr_from_#ctype#'},
+ 'pyobjfrom':{isintent_inout:"""\
+\t\tf2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#);
+\t\tif (f2py_success) {"""},
+ 'closepyobjfrom':{isintent_inout:"\t\t} /*if (f2py_success) of #varname# pyobjfrom*/"},
+ '_check':l_and(iscomplex,isintent_nothide)
+ },{
+ 'frompyobj':[{hasinitvalue:'\tif (#varname#_capi==Py_None) {#varname#.r = #init.r#, #varname#.i = #init.i#;} else'},
+ {l_and(isoptional,l_not(hasinitvalue)):'\tif (#varname#_capi != Py_None)'},
+# '\t\tf2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#ctype#_from_pyobj failed in converting #nth# `#varname#\' of #pyname# to C #ctype#\\n");'
+ '\t\tf2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#");'
+ '\n\tif (f2py_success) {'],
+ 'cleanupfrompyobj':'\t} /*if (f2py_success) of #varname# frompyobj*/',
+ 'need':['#ctype#_from_pyobj'],
+ '_check':l_and(iscomplex,isintent_nothide),
+ '_depend':''
+ },{ # Hidden
+ 'decl':{isintent_out:'\tPyObject *#varname#_capi = Py_None;'},
+ '_check':l_and(iscomplex,isintent_hide)
+ },{
+ 'frompyobj': {hasinitvalue:'\t#varname#.r = #init.r#, #varname#.i = #init.i#;'},
+ '_check':l_and(iscomplex,isintent_hide),
+ '_depend':''
+ },{ # Common
+ 'pyobjfrom':{isintent_out:'\t#varname#_capi = pyobj_from_#ctype#1(#varname#);'},
+ 'need':['pyobj_from_#ctype#1'],
+ '_check':iscomplex
+ },{
+ 'frompyobj':{debugcapi:'\tfprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'},
+ '_check':iscomplex,
+ '_depend':''
+ },
+# String
+ { # Common
+ 'decl':['\t#ctype# #varname# = NULL;',
+ '\tint slen(#varname#);',
+ '\tPyObject *#varname#_capi = Py_None;'],
+ 'callfortran':'#varname#,',
+ 'callfortranappend':'slen(#varname#),',
+ 'pyobjfrom':{debugcapi:'\tfprintf(stderr,"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'},
+# 'freemem':'\tSTRINGFREE(#varname#);',
+ 'return':{isintent_out:',#varname#'},
+ 'need':['len..'],#'STRINGFREE'],
+ '_check':isstring
+ },{ # Common
+ 'frompyobj':"""\
+\tslen(#varname#) = #length#;
+\tf2py_success = #ctype#_from_pyobj(&#varname#,&slen(#varname#),#init#,#varname#_capi,\"#ctype#_from_pyobj failed in converting #nth# `#varname#\' of #pyname# to C #ctype#\");
+\tif (f2py_success) {""",
+ 'cleanupfrompyobj':"""\
+\t\tSTRINGFREE(#varname#);
+\t} /*if (f2py_success) of #varname#*/""",
+ 'need':['#ctype#_from_pyobj','len..','STRINGFREE'],
+ '_check':isstring,
+ '_depend':''
+ },{ # Not hidden
+ 'argformat':{isrequired:'O'},
+ 'keyformat':{isoptional:'O'},
+ 'args_capi':{isrequired:',&#varname#_capi'},
+ 'keys_capi':{isoptional:',&#varname#_capi'},
+ 'pyobjfrom':{isintent_inout:'''\
+\tf2py_success = try_pyarr_from_#ctype#(#varname#_capi,#varname#);
+\tif (f2py_success) {'''},
+ 'closepyobjfrom':{isintent_inout:'\t} /*if (f2py_success) of #varname# pyobjfrom*/'},
+ 'need':{isintent_inout:'try_pyarr_from_#ctype#'},
+ '_check':l_and(isstring,isintent_nothide)
+ },{ # Hidden
+ '_check':l_and(isstring,isintent_hide)
+ },{
+ 'frompyobj':{debugcapi:'\tfprintf(stderr,"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'},
+ '_check':isstring,
+ '_depend':''
+ },
+# Array
+ { # Common
+ 'decl':['\t#ctype# *#varname# = NULL;',
+ '\tintp #varname#_Dims[#rank#] = {#rank*[-1]#};',
+ '\tconst int #varname#_Rank = #rank#;',
+ '\tPyArrayObject *capi_#varname#_tmp = NULL;',
+ '\tint capi_#varname#_intent = 0;',
+ ],
+ 'callfortran':'#varname#,',
+ 'return':{isintent_out:',capi_#varname#_tmp'},
+ 'need':'len..',
+ '_check':isarray
+ },{ # intent(overwrite) array
+ 'decl':'\tint capi_overwrite_#varname# = 1;',
+ 'kwlistxa':'"overwrite_#varname#",',
+ 'xaformat':'i',
+ 'keys_xa':',&capi_overwrite_#varname#',
+ 'docsignxa':'overwrite_#varname#=1,',
+ 'docsignxashort':'overwrite_#varname#,',
+ 'docstropt':'\toverwrite_#varname# := 1 input int',
+ '_check':l_and(isarray,isintent_overwrite),
+ },{
+ 'frompyobj':'\tcapi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);',
+ '_check':l_and(isarray,isintent_overwrite),
+ '_depend':'',
+ },
+ { # intent(copy) array
+ 'decl':'\tint capi_overwrite_#varname# = 0;',
+ 'kwlistxa':'"overwrite_#varname#",',
+ 'xaformat':'i',
+ 'keys_xa':',&capi_overwrite_#varname#',
+ 'docsignxa':'overwrite_#varname#=0,',
+ 'docsignxashort':'overwrite_#varname#,',
+ 'docstropt':'\toverwrite_#varname# := 0 input int',
+ '_check':l_and(isarray,isintent_copy),
+ },{
+ 'frompyobj':'\tcapi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);',
+ '_check':l_and(isarray,isintent_copy),
+ '_depend':'',
+ },{
+ 'need':[{hasinitvalue:'forcomb'},{hasinitvalue:'CFUNCSMESS'}],
+ '_check':isarray,
+ '_depend':''
+ },{ # Not hidden
+ 'decl':'\tPyObject *#varname#_capi = Py_None;',
+ 'argformat':{isrequired:'O'},
+ 'keyformat':{isoptional:'O'},
+ 'args_capi':{isrequired:',&#varname#_capi'},
+ 'keys_capi':{isoptional:',&#varname#_capi'},
+# 'pyobjfrom':{isintent_inout:"""\
+# /* Partly because of the following hack, intent(inout) is depreciated,
+# Use intent(in,out) instead.
+
+# \tif ((#varname#_capi != Py_None) && PyArray_Check(#varname#_capi) \\
+# \t\t&& (#varname#_capi != (PyObject *)capi_#varname#_tmp)) {
+# \t\tif (((PyArrayObject *)#varname#_capi)->nd != capi_#varname#_tmp->nd) {
+# \t\t\tif (#varname#_capi != capi_#varname#_tmp->base)
+# \t\t\t\tcopy_ND_array((PyArrayObject *)capi_#varname#_tmp->base,(PyArrayObject *)#varname#_capi);
+# \t\t} else
+# \t\t\tcopy_ND_array(capi_#varname#_tmp,(PyArrayObject *)#varname#_capi);
+# \t}
+# */
+# """},
+# 'need':{isintent_inout:'copy_ND_array'},
+ '_check':l_and(isarray,isintent_nothide)
+ },{
+ 'frompyobj':['\t#setdims#;',
+ '\tcapi_#varname#_intent |= #intent#;',
+ {isintent_hide:'\tcapi_#varname#_tmp = array_from_pyobj(#atype#,#varname#_Dims,#varname#_Rank,capi_#varname#_intent,Py_None);'},
+ {isintent_nothide:'\tcapi_#varname#_tmp = array_from_pyobj(#atype#,#varname#_Dims,#varname#_Rank,capi_#varname#_intent,#varname#_capi);'},
+ """\
+\tif (capi_#varname#_tmp == NULL) {
+\t\tif (!PyErr_Occurred())
+\t\t\tPyErr_SetString(#modulename#_error,\"failed in converting #nth# `#varname#\' of #pyname# to C/Fortran array\" );
+\t} else {
+\t\t#varname# = (#ctype# *)(capi_#varname#_tmp->data);
+""",
+{hasinitvalue:[
+ {isintent_nothide:'\tif (#varname#_capi == Py_None) {'},
+ {isintent_hide:'\t{'},
+ {iscomplexarray:'\t\t#ctype# capi_c;'},
+ """\
+\t\tint *_i,capi_i=0;
+\t\tCFUNCSMESS(\"#name#: Initializing #varname#=#init#\\n\");
+\t\tif (initforcomb(capi_#varname#_tmp->dimensions,capi_#varname#_tmp->nd,1)) {
+\t\t\twhile ((_i = nextforcomb()))
+\t\t\t\t#varname#[capi_i++] = #init#; /* fortran way */
+\t\t} else {
+\t\t\tif (!PyErr_Occurred())
+\t\t\t\tPyErr_SetString(#modulename#_error,\"Initialization of #nth# #varname# failed (initforcomb).\");
+\t\t\tf2py_success = 0;
+\t\t}
+\t}
+\tif (f2py_success) {"""]},
+ ],
+ 'cleanupfrompyobj':[ # note that this list will be reversed
+ '\t} /*if (capi_#varname#_tmp == NULL) ... else of #varname#*/',
+ {l_not(l_or(isintent_out,isintent_hide)):"""\
+\tif((PyObject *)capi_#varname#_tmp!=#varname#_capi) {
+\t\tPy_XDECREF(capi_#varname#_tmp); }"""},
+ {l_and(isintent_hide,l_not(isintent_out)):"""\t\tPy_XDECREF(capi_#varname#_tmp);"""},
+ {hasinitvalue:'\t} /*if (f2py_success) of #varname# init*/'},
+ ],
+ '_check':isarray,
+ '_depend':''
+ },
+# { # Hidden
+# 'freemem':{l_not(isintent_out):'\tPy_XDECREF(capi_#varname#_tmp);'},
+# '_check':l_and(isarray,isintent_hide)
+# },
+# Scalararray
+ { # Common
+ '_check':l_and(isarray,l_not(iscomplexarray))
+ },{ # Not hidden
+ '_check':l_and(isarray,l_not(iscomplexarray),isintent_nothide)
+ },
+# Integer*1 array
+ {'need':'#ctype#',
+ '_check':isint1array,
+ '_depend':''
+ },
+# Integer*-1 array
+ {'need':'#ctype#',
+ '_check':isunsigned_chararray,
+ '_depend':''
+ },
+# Integer*-2 array
+ {'need':'#ctype#',
+ '_check':isunsigned_shortarray,
+ '_depend':''
+ },
+# Integer*-8 array
+ {'need':'#ctype#',
+ '_check':isunsigned_long_longarray,
+ '_depend':''
+ },
+# Complexarray
+ {'need':'#ctype#',
+ '_check':iscomplexarray,
+ '_depend':''
+ },
+# Stringarray
+ {
+ 'callfortranappend':{isarrayofstrings:'flen(#varname#),'},
+ 'need':'string',
+ '_check':isstringarray
+ }
+ ]
+
+################# Rules for checking ###############
+
+check_rules=[
+ {
+ 'frompyobj':{debugcapi:'\tfprintf(stderr,\"debug-capi:Checking `#check#\'\\n\");'},
+ 'need':'len..'
+ },{
+ 'frompyobj':'\tCHECKSCALAR(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {',
+ 'cleanupfrompyobj':'\t} /*CHECKSCALAR(#check#)*/',
+ 'need':'CHECKSCALAR',
+ '_check':l_and(isscalar,l_not(iscomplex)),
+ '_break':''
+ },{
+ 'frompyobj':'\tCHECKSTRING(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {',
+ 'cleanupfrompyobj':'\t} /*CHECKSTRING(#check#)*/',
+ 'need':'CHECKSTRING',
+ '_check':isstring,
+ '_break':''
+ },{
+ 'need':'CHECKARRAY',
+ 'frompyobj':'\tCHECKARRAY(#check#,\"#check#\",\"#nth# #varname#\") {',
+ 'cleanupfrompyobj':'\t} /*CHECKARRAY(#check#)*/',
+ '_check':isarray,
+ '_break':''
+ },{
+ 'need':'CHECKGENERIC',
+ 'frompyobj':'\tCHECKGENERIC(#check#,\"#check#\",\"#nth# #varname#\") {',
+ 'cleanupfrompyobj':'\t} /*CHECKGENERIC(#check#)*/',
+ }
+]
+
+########## Applying the rules. No need to modify what follows #############
+
+#################### Build C/API module #######################
+
+def buildmodule(m,um):
+ """
+ Return
+ """
+ global f2py_version,options
+ outmess('\tBuilding module "%s"...\n'%(m['name']))
+ ret = {}
+ mod_rules=defmod_rules[:]
+ vrd=modsign2map(m)
+ rd=dictappend({'f2py_version':f2py_version},vrd)
+ funcwrappers = []
+ funcwrappers2 = [] # F90 codes
+ for n in m['interfaced']:
+ nb=None
+ for bi in m['body']:
+ if not bi['block']=='interface':
+ errmess('buildmodule: Expected interface block. Skipping.\n')
+ continue
+ for b in bi['body']:
+ if b['name']==n: nb=b;break
+
+ if not nb:
+ errmess('buildmodule: Could not found the body of interfaced routine "%s". Skipping.\n'%(n))
+ continue
+ nb_list = [nb]
+ if nb.has_key('entry'):
+ for k,a in nb['entry'].items():
+ nb1 = copy.deepcopy(nb)
+ del nb1['entry']
+ nb1['name'] = k
+ nb1['args'] = a
+ nb_list.append(nb1)
+ for nb in nb_list:
+ api,wrap=buildapi(nb)
+ if wrap:
+ if ismoduleroutine(nb):
+ funcwrappers2.append(wrap)
+ else:
+ funcwrappers.append(wrap)
+ ar=applyrules(api,vrd)
+ rd=dictappend(rd,ar)
+
+ # Construct COMMON block support
+ cr,wrap = common_rules.buildhooks(m)
+ if wrap:
+ funcwrappers.append(wrap)
+ ar=applyrules(cr,vrd)
+ rd=dictappend(rd,ar)
+
+ # Construct F90 module support
+ mr,wrap = f90mod_rules.buildhooks(m)
+ if wrap:
+ funcwrappers2.append(wrap)
+ ar=applyrules(mr,vrd)
+ rd=dictappend(rd,ar)
+
+ for u in um:
+ ar=use_rules.buildusevars(u,m['use'][u['name']])
+ rd=dictappend(rd,ar)
+
+ needs=cfuncs.get_needs()
+ code={}
+ for n in needs.keys():
+ code[n]=[]
+ for k in needs[n]:
+ c=''
+ if cfuncs.includes0.has_key(k): c=cfuncs.includes0[k]
+ elif cfuncs.includes.has_key(k): c=cfuncs.includes[k]
+ elif cfuncs.userincludes.has_key(k): c=cfuncs.userincludes[k]
+ elif cfuncs.typedefs.has_key(k): c=cfuncs.typedefs[k]
+ elif cfuncs.typedefs_generated.has_key(k):
+ c=cfuncs.typedefs_generated[k]
+ elif cfuncs.cppmacros.has_key(k): c=cfuncs.cppmacros[k]
+ elif cfuncs.cfuncs.has_key(k): c=cfuncs.cfuncs[k]
+ elif cfuncs.callbacks.has_key(k): c=cfuncs.callbacks[k]
+ elif cfuncs.f90modhooks.has_key(k): c=cfuncs.f90modhooks[k]
+ elif cfuncs.commonhooks.has_key(k): c=cfuncs.commonhooks[k]
+ else: errmess('buildmodule: unknown need %s.\n'%(`k`));continue
+ code[n].append(c)
+ mod_rules.append(code)
+ for r in mod_rules:
+ if (r.has_key('_check') and r['_check'](m)) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,m)
+ rd=dictappend(rd,ar)
+ ar=applyrules(module_rules,rd)
+
+ fn = os.path.join(options['buildpath'],vrd['modulename']+'module.c')
+ ret['csrc'] = fn
+ f=open(fn,'w')
+ f.write(string.replace(ar['modulebody'],'\t',2*' '))
+ f.close()
+ outmess('\tWrote C/API module "%s" to file "%s/%smodule.c"\n'%(m['name'],options['buildpath'],vrd['modulename']))
+
+ if options['dorestdoc']:
+ fn = os.path.join(options['buildpath'],vrd['modulename']+'module.rest')
+ f=open(fn,'w')
+ f.write('.. -*- rest -*-\n')
+ f.write(string.join(ar['restdoc'],'\n'))
+ f.close()
+ outmess('\tReST Documentation is saved to file "%s/%smodule.rest"\n'%(options['buildpath'],vrd['modulename']))
+ if options['dolatexdoc']:
+ fn = os.path.join(options['buildpath'],vrd['modulename']+'module.tex')
+ ret['ltx'] = fn
+ f=open(fn,'w')
+ f.write('%% This file is auto-generated with f2py (version:%s)\n'%(f2py_version))
+ if not options.has_key('shortlatex'):
+ f.write('\\documentclass{article}\n\\usepackage{a4wide}\n\\begin{document}\n\\tableofcontents\n\n')
+ f.write(string.join(ar['latexdoc'],'\n'))
+ if not options.has_key('shortlatex'):
+ f.write('\\end{document}')
+ f.close()
+ outmess('\tDocumentation is saved to file "%s/%smodule.tex"\n'%(options['buildpath'],vrd['modulename']))
+ if funcwrappers:
+ wn = os.path.join(options['buildpath'],'%s-f2pywrappers.f'%(vrd['modulename']))
+ ret['fsrc'] = wn
+ f=open(wn,'w')
+ f.write('C -*- fortran -*-\n')
+ f.write('C This file is autogenerated with f2py (version:%s)\n'%(f2py_version))
+ f.write('C It contains Fortran 77 wrappers to fortran functions.\n')
+ lines = []
+ for l in string.split(string.join(funcwrappers,'\n\n')+'\n','\n'):
+ if l and l[0]==' ':
+ while len(l)>=66:
+ lines.append(l[:66]+'\n &')
+ l = l[66:]
+ lines.append(l+'\n')
+ else: lines.append(l+'\n')
+ lines = string.join(lines,'').replace('\n &\n','\n')
+ f.write(lines)
+ f.close()
+ outmess('\tFortran 77 wrappers are saved to "%s"\n'%(wn))
+ if funcwrappers2:
+ wn = os.path.join(options['buildpath'],'%s-f2pywrappers2.f90'%(vrd['modulename']))
+ ret['fsrc'] = wn
+ f=open(wn,'w')
+ f.write('! -*- f90 -*-\n')
+ f.write('! This file is autogenerated with f2py (version:%s)\n'%(f2py_version))
+ f.write('! It contains Fortran 90 wrappers to fortran functions.\n')
+ lines = []
+ for l in string.split(string.join(funcwrappers2,'\n\n')+'\n','\n'):
+ if len(l)>72 and l[0]==' ':
+ lines.append(l[:72]+'&\n &')
+ l = l[72:]
+ while len(l)>66:
+ lines.append(l[:66]+'&\n &')
+ l = l[66:]
+ lines.append(l+'\n')
+ else: lines.append(l+'\n')
+ lines = string.join(lines,'').replace('\n &\n','\n')
+ f.write(lines)
+ f.close()
+ outmess('\tFortran 90 wrappers are saved to "%s"\n'%(wn))
+ return ret
+
+################## Build C/API function #############
+
+stnd={1:'st',2:'nd',3:'rd',4:'th',5:'th',6:'th',7:'th',8:'th',9:'th',0:'th'}
+def buildapi(rout):
+ rout,wrap = func2subr.assubr(rout)
+ args,depargs=getargs2(rout)
+ capi_maps.depargs=depargs
+ var=rout['vars']
+ auxvars = [a for a in var.keys() if isintent_aux(var[a])]
+
+ if ismoduleroutine(rout):
+ outmess('\t\t\tConstructing wrapper function "%s.%s"...\n'%(rout['modulename'],rout['name']))
+ else:
+ outmess('\t\tConstructing wrapper function "%s"...\n'%(rout['name']))
+ # Routine
+ vrd=routsign2map(rout)
+ rd=dictappend({},vrd)
+ for r in rout_rules:
+ if (r.has_key('_check') and r['_check'](rout)) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,rout)
+ rd=dictappend(rd,ar)
+
+ # Args
+ nth,nthk=0,0
+ savevrd={}
+ for a in args:
+ vrd=sign2map(a,var[a])
+ if isintent_aux(var[a]):
+ _rules = aux_rules
+ else:
+ _rules = arg_rules
+ if not isintent_hide(var[a]):
+ if not isoptional(var[a]):
+ nth=nth+1
+ vrd['nth']=`nth`+stnd[nth%10]+' argument'
+ else:
+ nthk=nthk+1
+ vrd['nth']=`nthk`+stnd[nthk%10]+' keyword'
+ else: vrd['nth']='hidden'
+ savevrd[a]=vrd
+ for r in _rules:
+ if r.has_key('_depend'): continue
+ if (r.has_key('_check') and r['_check'](var[a])) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,var[a])
+ rd=dictappend(rd,ar)
+ if r.has_key('_break'): break
+ for a in depargs:
+ if isintent_aux(var[a]):
+ _rules = aux_rules
+ else:
+ _rules = arg_rules
+ vrd=savevrd[a]
+ for r in _rules:
+ if not r.has_key('_depend'): continue
+ if (r.has_key('_check') and r['_check'](var[a])) or (not r.has_key('_check')):
+ ar=applyrules(r,vrd,var[a])
+ rd=dictappend(rd,ar)
+ if r.has_key('_break'): break
+ if var[a].has_key('check'):
+ for c in var[a]['check']:
+ vrd['check']=c
+ ar=applyrules(check_rules,vrd,var[a])
+ rd=dictappend(rd,ar)
+ if type(rd['cleanupfrompyobj']) is types.ListType:
+ rd['cleanupfrompyobj'].reverse()
+ if type(rd['closepyobjfrom']) is types.ListType:
+ rd['closepyobjfrom'].reverse()
+ rd['docsignature']=stripcomma(replace('#docsign##docsignopt##docsignxa#',
+ {'docsign':rd['docsign'],
+ 'docsignopt':rd['docsignopt'],
+ 'docsignxa':rd['docsignxa']}))
+ optargs=stripcomma(replace('#docsignopt##docsignxa#',
+ {'docsignxa':rd['docsignxashort'],
+ 'docsignopt':rd['docsignoptshort']}
+ ))
+ if optargs=='':
+ rd['docsignatureshort']=stripcomma(replace('#docsign#',{'docsign':rd['docsign']}))
+ else:
+ rd['docsignatureshort']=replace('#docsign#[#docsignopt#]',
+ {'docsign':rd['docsign'],
+ 'docsignopt':optargs,
+ })
+ rd['latexdocsignatureshort']=string.replace(rd['docsignatureshort'],'_','\\_')
+ rd['latexdocsignatureshort']=string.replace(rd['latexdocsignatureshort'],',',', ')
+ cfs=stripcomma(replace('#callfortran##callfortranappend#',{'callfortran':rd['callfortran'],'callfortranappend':rd['callfortranappend']}))
+ if len(rd['callfortranappend'])>1:
+ rd['callcompaqfortran']=stripcomma(replace('#callfortran# 0,#callfortranappend#',{'callfortran':rd['callfortran'],'callfortranappend':rd['callfortranappend']}))
+ else:
+ rd['callcompaqfortran']=cfs
+ rd['callfortran']=cfs
+ if type(rd['docreturn'])==types.ListType:
+ rd['docreturn']=stripcomma(replace('#docreturn#',{'docreturn':rd['docreturn']}))+' = '
+ rd['docstrsigns']=[]
+ rd['latexdocstrsigns']=[]
+ for k in ['docstrreq','docstropt','docstrout','docstrcbs']:
+ if rd.has_key(k) and type(rd[k])==types.ListType:
+ rd['docstrsigns']=rd['docstrsigns']+rd[k]
+ k='latex'+k
+ if rd.has_key(k) and type(rd[k])==types.ListType:
+ rd['latexdocstrsigns']=rd['latexdocstrsigns']+rd[k][0:1]+\
+ ['\\begin{description}']+rd[k][1:]+\
+ ['\\end{description}']
+ ar=applyrules(routine_rules,rd)
+ if ismoduleroutine(rout):
+ outmess('\t\t\t %s\n'%(ar['docshort']))
+ else:
+ outmess('\t\t %s\n'%(ar['docshort']))
+ return ar,wrap
+
+
+#################### EOF rules.py #######################
diff --git a/numpy/f2py/setup.cfg b/numpy/f2py/setup.cfg
new file mode 100644
index 000000000..14669544c
--- /dev/null
+++ b/numpy/f2py/setup.cfg
@@ -0,0 +1,3 @@
+[bdist_rpm]
+doc_files = docs/
+ tests/ \ No newline at end of file
diff --git a/numpy/f2py/setup.py b/numpy/f2py/setup.py
new file mode 100755
index 000000000..2616ccbd5
--- /dev/null
+++ b/numpy/f2py/setup.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+"""
+setup.py for installing F2PY
+
+Usage:
+ python setup.py install
+
+Copyright 2001-2005 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@cens.ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Revision: 1.32 $
+$Date: 2005/01/30 17:22:14 $
+Pearu Peterson
+"""
+
+__version__ = "$Id: setup.py,v 1.32 2005/01/30 17:22:14 pearu Exp $"
+
+import os
+import sys
+from distutils.dep_util import newer
+from scipy.distutils.core import setup
+from scipy.distutils.misc_util import Configuration
+
+from __version__ import version
+
+def configuration(parent_package='',top_path=None):
+ config = Configuration('f2py', parent_package, top_path)
+
+ config.add_data_dir('docs')
+
+ config.add_data_files('src/fortranobject.c',
+ 'src/fortranobject.h',
+ 'f2py.1'
+ )
+
+ config.make_svn_version_py()
+
+ def generate_f2py_py(build_dir):
+ f2py_exe = 'f2py'+os.path.basename(sys.executable)[6:]
+ if f2py_exe[-4:]=='.exe':
+ f2py_exe = f2py_exe[:-4] + '.py'
+ if 'bdist_wininst' in sys.argv and f2py_exe[-3:] != '.py':
+ f2py_exe = f2py_exe + '.py'
+ target = os.path.join(build_dir,f2py_exe)
+ if newer(__file__,target):
+ print 'Creating',target
+ f = open(target,'w')
+ f.write('''\
+#!/usr/bin/env %s
+# See http://cens.ioc.ee/projects/f2py2e/
+import os
+os.environ["NO_SCIPY_IMPORT"]="f2py"
+import scipy.f2py as f2py
+f2py.main()
+'''%(os.path.basename(sys.executable)))
+ f.close()
+ return target
+
+ config.add_scripts(generate_f2py_py)
+
+ print 'F2PY Version',config.get_version()
+
+ return config
+
+if __name__ == "__main__":
+
+ config = configuration(top_path='')
+ version = config.get_version()
+ print 'F2PY Version',version
+ config = config.todict()
+
+ if sys.version[:3]>='2.3':
+ config['download_url'] = "http://cens.ioc.ee/projects/f2py2e/2.x"\
+ "/F2PY-2-latest.tar.gz"
+ config['classifiers'] = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Science/Research',
+ 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: C',
+ 'Programming Language :: Fortran',
+ 'Programming Language :: Python',
+ 'Topic :: Scientific/Engineering',
+ 'Topic :: Software Development :: Code Generators',
+ ]
+ setup(version=version,
+ description = "F2PY - Fortran to Python Interface Generaton",
+ author = "Pearu Peterson",
+ author_email = "pearu@cens.ioc.ee",
+ maintainer = "Pearu Peterson",
+ maintainer_email = "pearu@cens.ioc.ee",
+ license = "LGPL",
+ platforms = "Unix, Windows (mingw|cygwin), Mac OSX",
+ long_description = """\
+The Fortran to Python Interface Generator, or F2PY for short, is a
+command line tool (f2py) for generating Python C/API modules for
+wrapping Fortran 77/90/95 subroutines, accessing common blocks from
+Python, and calling Python functions from Fortran (call-backs).
+Interfacing subroutines/data from Fortran 90/95 modules is supported.""",
+ url = "http://cens.ioc.ee/projects/f2py2e/",
+ keywords = ['Fortran','f2py'],
+ **config)
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
new file mode 100644
index 000000000..d5da43a88
--- /dev/null
+++ b/numpy/f2py/src/fortranobject.c
@@ -0,0 +1,756 @@
+#define FORTRANOBJECT_C
+#include "fortranobject.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ This file implements: FortranObject, array_from_pyobj, copy_ND_array
+
+ Author: Pearu Peterson <pearu@cens.ioc.ee>
+ $Revision: 1.52 $
+ $Date: 2005/07/11 07:44:20 $
+*/
+
+/************************* FortranObject *******************************/
+
+typedef PyObject *(*fortranfunc)(PyObject *,PyObject *,PyObject *,void *);
+
+PyObject *
+PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) {
+ int i;
+ PyFortranObject *fp = NULL;
+ PyObject *v = NULL;
+ if (init!=NULL) /* Initialize F90 module objects */
+ (*(init))();
+ if ((fp = PyObject_New(PyFortranObject, &PyFortran_Type))==NULL) return NULL;
+ if ((fp->dict = PyDict_New())==NULL) return NULL;
+ fp->len = 0;
+ while (defs[fp->len].name != NULL) fp->len++;
+ if (fp->len == 0) goto fail;
+ fp->defs = defs;
+ for (i=0;i<fp->len;i++)
+ if (fp->defs[i].rank == -1) { /* Is Fortran routine */
+ v = PyFortranObject_NewAsAttr(&(fp->defs[i]));
+ if (v==NULL) return NULL;
+ PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
+ } else
+ if ((fp->defs[i].data)!=NULL) { /* Is Fortran variable or array (not allocatable) */
+ v = PyArray_New(&PyArray_Type, fp->defs[i].rank, fp->defs[i].dims.d,
+ fp->defs[i].type, NULL, fp->defs[i].data, 0, FARRAY_FLAGS,
+ NULL);
+ if (v==NULL) return NULL;
+ PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
+ }
+ Py_XDECREF(v);
+ return (PyObject *)fp;
+ fail:
+ Py_XDECREF(v);
+ return NULL;
+}
+
+PyObject *
+PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module routines */
+ PyFortranObject *fp = NULL;
+ fp = PyObject_New(PyFortranObject, &PyFortran_Type);
+ if (fp == NULL) return NULL;
+ if ((fp->dict = PyDict_New())==NULL) return NULL;
+ fp->len = 1;
+ fp->defs = defs;
+ return (PyObject *)fp;
+}
+
+/* Fortran methods */
+
+static void
+fortran_dealloc(PyFortranObject *fp) {
+ Py_XDECREF(fp->dict);
+ PyMem_Del(fp);
+}
+
+
+static PyMethodDef fortran_methods[] = {
+ {NULL, NULL} /* sentinel */
+};
+
+
+static PyObject *
+fortran_doc (FortranDataDef def) {
+ char *p;
+ PyObject *s = NULL;
+ int i;
+ unsigned size=100;
+ if (def.doc!=NULL)
+ size += strlen(def.doc);
+ p = (char*)malloc (size);
+ if (sprintf(p,"%s - ",def.name)==0) goto fail;
+ if (def.rank==-1) {
+ if (def.doc==NULL) {
+ if (sprintf(p,"%sno docs available",p)==0)
+ goto fail;
+ } else {
+ if (sprintf(p,"%s%s",p,def.doc)==0)
+ goto fail;
+ }
+ } else {
+ PyArray_Descr *d = PyArray_DescrFromType(def.type);
+ if (sprintf(p,"%s'%c'-",p,d->type)==0) goto fail;
+ if (def.data==NULL) {
+ if (sprintf(p,"%sarray(%" INTP_FMT,p,def.dims.d[0])==0) goto fail;
+ for(i=1;i<def.rank;++i)
+ if (sprintf(p,"%s,%" INTP_FMT,p,def.dims.d[i])==0) goto fail;
+ if (sprintf(p,"%s), not allocated",p)==0) goto fail;
+ } else {
+ if (def.rank>0) {
+ if (sprintf(p,"%sarray(%"INTP_FMT,p,def.dims.d[0])==0) goto fail;
+ for(i=1;i<def.rank;i++)
+ if (sprintf(p,"%s,%" INTP_FMT,p,def.dims.d[i])==0) goto fail;
+ if (sprintf(p,"%s)",p)==0) goto fail;
+ } else {
+ if (sprintf(p,"%sscalar",p)==0) goto fail;
+ }
+ }
+ }
+ if (sprintf(p,"%s\n",p)==0) goto fail;
+ if (strlen(p)>size) {
+ fprintf(stderr,"fortranobject.c:fortran_doc:len(p)=%zd>%d(size): too long doc string required, increase size\n",strlen(p),size);
+ goto fail;
+ }
+ s = PyString_FromString(p);
+ fail:
+ free(p);
+ return s;
+}
+
+static FortranDataDef *save_def; /* save pointer of an allocatable array */
+static void set_data(char *d,intp *f) { /* callback from Fortran */
+ if (*f) /* In fortran f=allocated(d) */
+ save_def->data = d;
+ else
+ save_def->data = NULL;
+ /* printf("set_data: d=%p,f=%d\n",d,*f); */
+}
+
+static PyObject *
+fortran_getattr(PyFortranObject *fp, char *name) {
+ int i,j,k,flag;
+ if (fp->dict != NULL) {
+ PyObject *v = PyDict_GetItemString(fp->dict, name);
+ if (v != NULL) {
+ Py_INCREF(v);
+ return v;
+ }
+ }
+ for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
+ if (j==0)
+ if (fp->defs[i].rank!=-1) { /* F90 allocatable array */
+ if (fp->defs[i].func==NULL) return NULL;
+ for(k=0;k<fp->defs[i].rank;++k)
+ fp->defs[i].dims.d[k]=-1;
+ save_def = &fp->defs[i];
+ (*(fp->defs[i].func))(&fp->defs[i].rank,fp->defs[i].dims.d,set_data,&flag);
+ if (flag==2)
+ k = fp->defs[i].rank + 1;
+ else
+ k = fp->defs[i].rank;
+ if (fp->defs[i].data !=NULL) { /* array is allocated */
+ PyObject *v = PyArray_New(&PyArray_Type, k, fp->defs[i].dims.d,
+ fp->defs[i].type, NULL, fp->defs[i].data, 0, FARRAY_FLAGS,
+ NULL);
+ if (v==NULL) return NULL;
+ /* Py_INCREF(v); */
+ return v;
+ } else { /* array is not allocated */
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ }
+ if (strcmp(name,"__dict__")==0) {
+ Py_INCREF(fp->dict);
+ return fp->dict;
+ }
+ if (strcmp(name,"__doc__")==0) {
+ PyObject *s = PyString_FromString("");
+ for (i=0;i<fp->len;i++)
+ PyString_ConcatAndDel(&s,fortran_doc(fp->defs[i]));
+ if (PyDict_SetItemString(fp->dict, name, s))
+ return NULL;
+ return s;
+ }
+ if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
+ PyObject *cobj = PyCObject_FromVoidPtr((void *)(fp->defs[0].data),NULL);
+ if (PyDict_SetItemString(fp->dict, name, cobj))
+ return NULL;
+ return cobj;
+ }
+ return Py_FindMethod(fortran_methods, (PyObject *)fp, name);
+}
+
+static int
+fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
+ int i,j,flag;
+ PyArrayObject *arr = NULL;
+ for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
+ if (j==0) {
+ if (fp->defs[i].rank==-1) {
+ PyErr_SetString(PyExc_AttributeError,"over-writing fortran routine");
+ return -1;
+ }
+ if (fp->defs[i].func!=NULL) { /* is allocatable array */
+ intp dims[F2PY_MAX_DIMS];
+ int k;
+ save_def = &fp->defs[i];
+ if (v!=Py_None) { /* set new value (reallocate if needed --
+ see f2py generated code for more
+ details ) */
+ for(k=0;k<fp->defs[i].rank;k++) dims[k]=-1;
+ if ((arr = array_from_pyobj(fp->defs[i].type,dims,fp->defs[i].rank,F2PY_INTENT_IN,v))==NULL)
+ return -1;
+ (*(fp->defs[i].func))(&fp->defs[i].rank,arr->dimensions,set_data,&flag);
+ } else { /* deallocate */
+ for(k=0;k<fp->defs[i].rank;k++) dims[k]=0;
+ (*(fp->defs[i].func))(&fp->defs[i].rank,dims,set_data,&flag);
+ for(k=0;k<fp->defs[i].rank;k++) dims[k]=-1;
+ }
+ memcpy(fp->defs[i].dims.d,dims,fp->defs[i].rank*sizeof(intp));
+ } else { /* not allocatable array */
+ if ((arr = array_from_pyobj(fp->defs[i].type,fp->defs[i].dims.d,fp->defs[i].rank,F2PY_INTENT_IN,v))==NULL)
+ return -1;
+ }
+ if (fp->defs[i].data!=NULL) { /* copy Python object to Fortran array */
+ intp s = PyArray_MultiplyList(fp->defs[i].dims.d,arr->nd);
+ if (s==-1)
+ s = PyArray_MultiplyList(arr->dimensions,arr->nd);
+ if (s<0 ||
+ (memcpy(fp->defs[i].data,arr->data,s*PyArray_ITEMSIZE(arr)))==NULL) {
+ if ((PyObject*)arr!=v) {
+ Py_DECREF(arr);
+ }
+ return -1;
+ }
+ if ((PyObject*)arr!=v) {
+ Py_DECREF(arr);
+ }
+ } else return (fp->defs[i].func==NULL?-1:0);
+ return 0; /* succesful */
+ }
+ if (fp->dict == NULL) {
+ fp->dict = PyDict_New();
+ if (fp->dict == NULL)
+ return -1;
+ }
+ if (v == NULL) {
+ int rv = PyDict_DelItemString(fp->dict, name);
+ if (rv < 0)
+ PyErr_SetString(PyExc_AttributeError,"delete non-existing fortran attribute");
+ return rv;
+ }
+ else
+ return PyDict_SetItemString(fp->dict, name, v);
+}
+
+static PyObject*
+fortran_call(PyFortranObject *fp, PyObject *arg, PyObject *kw) {
+ int i = 0;
+ /* printf("fortran call
+ name=%s,func=%p,data=%p,%p\n",fp->defs[i].name,
+ fp->defs[i].func,fp->defs[i].data,&fp->defs[i].data); */
+ if (fp->defs[i].rank==-1) {/* is Fortran routine */
+ if ((fp->defs[i].func==NULL)) {
+ PyErr_Format(PyExc_RuntimeError, "no function to call");
+ return NULL;
+ }
+ else if (fp->defs[i].data==NULL)
+ /* dummy routine */
+ return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp,arg,kw,NULL);
+ else
+ return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp,arg,kw,
+ (void *)fp->defs[i].data);
+ }
+ PyErr_Format(PyExc_TypeError, "this fortran object is not callable");
+ return NULL;
+}
+
+
+PyTypeObject PyFortran_Type = {
+ PyObject_HEAD_INIT(0)
+ 0, /*ob_size*/
+ "fortran", /*tp_name*/
+ sizeof(PyFortranObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)fortran_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc)fortran_getattr, /*tp_getattr*/
+ (setattrfunc)fortran_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ (ternaryfunc)fortran_call, /*tp_call*/
+};
+
+/************************* f2py_report_atexit *******************************/
+
+#ifdef F2PY_REPORT_ATEXIT
+static int passed_time = 0;
+static int passed_counter = 0;
+static int passed_call_time = 0;
+static struct timeb start_time;
+static struct timeb stop_time;
+static struct timeb start_call_time;
+static struct timeb stop_call_time;
+static int cb_passed_time = 0;
+static int cb_passed_counter = 0;
+static int cb_passed_call_time = 0;
+static struct timeb cb_start_time;
+static struct timeb cb_stop_time;
+static struct timeb cb_start_call_time;
+static struct timeb cb_stop_call_time;
+
+extern void f2py_start_clock(void) { ftime(&start_time); }
+extern
+void f2py_start_call_clock(void) {
+ f2py_stop_clock();
+ ftime(&start_call_time);
+}
+extern
+void f2py_stop_clock(void) {
+ ftime(&stop_time);
+ passed_time += 1000*(stop_time.time - start_time.time);
+ passed_time += stop_time.millitm - start_time.millitm;
+}
+extern
+void f2py_stop_call_clock(void) {
+ ftime(&stop_call_time);
+ passed_call_time += 1000*(stop_call_time.time - start_call_time.time);
+ passed_call_time += stop_call_time.millitm - start_call_time.millitm;
+ passed_counter += 1;
+ f2py_start_clock();
+}
+
+extern void f2py_cb_start_clock(void) { ftime(&cb_start_time); }
+extern
+void f2py_cb_start_call_clock(void) {
+ f2py_cb_stop_clock();
+ ftime(&cb_start_call_time);
+}
+extern
+void f2py_cb_stop_clock(void) {
+ ftime(&cb_stop_time);
+ cb_passed_time += 1000*(cb_stop_time.time - cb_start_time.time);
+ cb_passed_time += cb_stop_time.millitm - cb_start_time.millitm;
+}
+extern
+void f2py_cb_stop_call_clock(void) {
+ ftime(&cb_stop_call_time);
+ cb_passed_call_time += 1000*(cb_stop_call_time.time - cb_start_call_time.time);
+ cb_passed_call_time += cb_stop_call_time.millitm - cb_start_call_time.millitm;
+ cb_passed_counter += 1;
+ f2py_cb_start_clock();
+}
+
+static int f2py_report_on_exit_been_here = 0;
+extern
+void f2py_report_on_exit(int exit_flag,void *name) {
+ if (f2py_report_on_exit_been_here) {
+ fprintf(stderr," %s\n",(char*)name);
+ return;
+ }
+ f2py_report_on_exit_been_here = 1;
+ fprintf(stderr," /-----------------------\\\n");
+ fprintf(stderr," < F2PY performance report >\n");
+ fprintf(stderr," \\-----------------------/\n");
+ fprintf(stderr,"Overall time spent in ...\n");
+ fprintf(stderr,"(a) wrapped (Fortran/C) functions : %8d msec\n",
+ passed_call_time);
+ fprintf(stderr,"(b) f2py interface, %6d calls : %8d msec\n",
+ passed_counter,passed_time);
+ fprintf(stderr,"(c) call-back (Python) functions : %8d msec\n",
+ cb_passed_call_time);
+ fprintf(stderr,"(d) f2py call-back interface, %6d calls : %8d msec\n",
+ cb_passed_counter,cb_passed_time);
+
+ fprintf(stderr,"(e) wrapped (Fortran/C) functions (acctual) : %8d msec\n\n",
+ passed_call_time-cb_passed_call_time-cb_passed_time);
+ fprintf(stderr,"Use -DF2PY_REPORT_ATEXIT_DISABLE to disable this message.\n");
+ fprintf(stderr,"Exit status: %d\n",exit_flag);
+ fprintf(stderr,"Modules : %s\n",(char*)name);
+}
+#endif
+
+/********************** report on array copy ****************************/
+
+#ifdef F2PY_REPORT_ON_ARRAY_COPY
+static void f2py_report_on_array_copy(PyArrayObject* arr) {
+ const long arr_size = PyArray_Size((PyObject *)arr);
+ if (arr_size>F2PY_REPORT_ON_ARRAY_COPY) {
+ fprintf(stderr,"copied an array: size=%ld, elsize=%d\n",
+ arr_size, PyArray_ITEMSIZE(arr));
+ }
+}
+static void f2py_report_on_array_copy_fromany(void) {
+ fprintf(stderr,"created an array from object\n");
+}
+
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR f2py_report_on_array_copy((PyArrayObject *)arr)
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY f2py_report_on_array_copy_fromany()
+#else
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY
+#endif
+
+
+/************************* array_from_obj *******************************/
+
+/*
+ * 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: fortranobject.c,v 1.52 2005/07/11 07:44:20 pearu Exp $
+ */
+
+static int
+count_nonpos(const int rank,
+ const intp *dims) {
+ int i=0,r=0;
+ while (i<rank) {
+ if (dims[i] <= 0) ++r;
+ ++i;
+ }
+ return r;
+}
+
+static int check_and_fix_dimensions(const PyArrayObject* arr,
+ const int rank,
+ intp *dims);
+
+#ifdef DEBUG_COPY_ND_ARRAY
+void dump_attrs(const PyArrayObject* arr) {
+ int rank = arr->nd;
+ intp size = PyArray_Size((PyObject *)arr);
+ int i;
+ printf("\trank = %d, flags = %d, size = %" INTP_FMT "\n",
+ rank,arr->flags,size);
+ printf("\tstrides = [");
+ for(i=0;i<rank;++i) {
+ printf("%3" INTP_FMT,arr->strides[i]);
+ }
+ printf("]\n\t dimensions = [");
+ for(i=0;i<rank;++i) {
+ printf("%3" INTP_FMT, arr->dimensions[i]);
+ }
+ printf("]\n");
+}
+#endif
+
+#define SWAPTYPE(a,b,t) {t c; c = (a); (a) = (b); (b) = c; }
+
+static int swap_arrays(PyArrayObject* arr1, PyArrayObject* arr2) {
+ SWAPTYPE(arr1->data,arr2->data,char*);
+ SWAPTYPE(arr1->nd,arr2->nd,int);
+ SWAPTYPE(arr1->dimensions,arr2->dimensions,intp*);
+ SWAPTYPE(arr1->strides,arr2->strides,intp*);
+ SWAPTYPE(arr1->base,arr2->base,PyObject*);
+ SWAPTYPE(arr1->descr,arr2->descr,PyArray_Descr*);
+ SWAPTYPE(arr1->flags,arr2->flags,int);
+ /* SWAPTYPE(arr1->weakreflist,arr2->weakreflist,PyObject*); */
+ return 0;
+}
+
+#define ARRAY_ISCOMPATIBLE(arr,type_num) \
+( (PyArray_ISINTEGER(arr) && PyTypeNum_ISINTEGER(type_num)) \
+ ||(PyArray_ISFLOAT(arr) && PyTypeNum_ISFLOAT(type_num)) \
+ ||(PyArray_ISCOMPLEX(arr) && PyTypeNum_ISCOMPLEX(type_num)) \
+)
+
+extern
+PyArrayObject* array_from_pyobj(const int type_num,
+ intp *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).
+
+ Note on intent(cache,out,..)
+ ---------------------
+ Don't expect correct data when returning intent(cache) array.
+
+ */
+ char mess[200];
+ PyArrayObject *arr = NULL;
+ PyArray_Descr *descr = PyArray_DescrFromType(type_num);
+
+ if ((intent & F2PY_INTENT_HIDE)
+ || ((intent & F2PY_INTENT_CACHE) && (obj==Py_None))
+ || ((intent & F2PY_OPTIONAL) && (obj==Py_None))
+ ) {
+ /* intent(cache), optional, intent(hide) */
+ if (count_nonpos(rank,dims)) {
+ int i;
+ sprintf(mess,"failed to create intent(cache|hide)|optional array"
+ "-- must have defined dimensions but got (");
+ for(i=0;i<rank;++i)
+ sprintf(mess+strlen(mess),"%" INTP_FMT ",",dims[i]);
+ sprintf(mess+strlen(mess),")");
+ PyErr_SetString(PyExc_ValueError,mess);
+ return NULL;
+ }
+ arr = (PyArrayObject *)
+ PyArray_New(&PyArray_Type, rank, dims, type_num,
+ NULL,NULL,0,
+ !(intent&F2PY_INTENT_C),
+ NULL);
+ if (!(intent & F2PY_INTENT_CACHE))
+ PyArray_FILLWBYTE(arr, 0);
+ return arr;
+ }
+
+ if (PyArray_Check(obj)) {
+ arr = (PyArrayObject *)obj;
+
+ if (intent & F2PY_INTENT_CACHE) {
+ /* intent(cache) */
+ if (PyArray_ISONESEGMENT(obj)
+ && PyArray_ITEMSIZE((PyArrayObject *)obj)>=descr->elsize) {
+ 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;
+ }
+ sprintf(mess,"failed to initialize intent(cache) array");
+ if (!PyArray_ISONESEGMENT(obj))
+ sprintf(mess+strlen(mess)," -- input must be in one segment");
+ if (PyArray_ITEMSIZE(arr)<descr->elsize)
+ sprintf(mess+strlen(mess)," -- expected at least elsize=%d but got %d",
+ descr->elsize,PyArray_ITEMSIZE(arr)
+ );
+ PyErr_SetString(PyExc_ValueError,mess);
+ return NULL;
+ }
+
+ /* here we have always intent(in) or intent(inout) or intent(inplace) */
+
+ if (check_and_fix_dimensions(arr,rank,dims))
+ return NULL; /*XXX: set exception */
+
+ if ((! (intent & F2PY_INTENT_COPY))
+ && PyArray_ITEMSIZE(arr)==descr->elsize
+ && ARRAY_ISCOMPATIBLE(arr,type_num)
+ ) {
+ if ((intent & F2PY_INTENT_C)?PyArray_ISCARRAY(arr):PyArray_ISFARRAY(arr)) {
+ if ((intent & F2PY_INTENT_OUT)) {
+ Py_INCREF(arr);
+ }
+ /* Returning input array */
+ return arr;
+ }
+ }
+
+ if (intent & F2PY_INTENT_INOUT) {
+ sprintf(mess,"failed to initialize intent(inout) array");
+ if ((intent & F2PY_INTENT_C) && !PyArray_ISCARRAY(arr))
+ sprintf(mess+strlen(mess)," -- input not contiguous");
+ if (!(intent & F2PY_INTENT_C) && !PyArray_ISFARRAY(arr))
+ sprintf(mess+strlen(mess)," -- input not fortran contiguous");
+ if (PyArray_ITEMSIZE(arr)!=descr->elsize)
+ sprintf(mess+strlen(mess)," -- expected elsize=%d but got %d",
+ descr->elsize,
+ PyArray_ITEMSIZE(arr)
+ );
+ if (!(ARRAY_ISCOMPATIBLE(arr,type_num)))
+ sprintf(mess+strlen(mess)," -- input '%c' not compatible to '%c'",
+ arr->descr->type,descr->type);
+ PyErr_SetString(PyExc_ValueError,mess);
+ return NULL;
+ }
+
+ /* here we have always intent(in) or intent(inplace) */
+
+ {
+ PyArrayObject *retarr = (PyArrayObject *) \
+ PyArray_New(&PyArray_Type, arr->nd, arr->dimensions, type_num,
+ NULL,NULL,0,
+ !(intent&F2PY_INTENT_C),
+ NULL);
+ if (retarr==NULL)
+ return NULL;
+ F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
+ if (PyArray_CopyInto(retarr, arr)) {
+ Py_DECREF(retarr);
+ return NULL;
+ }
+ if (intent & F2PY_INTENT_INPLACE) {
+ if (swap_arrays(arr,retarr))
+ return NULL; /* XXX: set exception */
+ Py_XDECREF(retarr);
+ if (intent & F2PY_INTENT_OUT)
+ Py_INCREF(arr);
+ } else {
+ arr = retarr;
+ }
+ }
+ return arr;
+ }
+
+ if ((intent & F2PY_INTENT_INOUT)
+ || (intent & F2PY_INTENT_INPLACE)
+ || (intent & F2PY_INTENT_CACHE)) {
+ sprintf(mess,"failed to initialize intent(inout|inplace|cache) array"
+ " -- input must be array but got %s",
+ PyString_AsString(PyObject_Str(PyObject_Type(obj)))
+ );
+ PyErr_SetString(PyExc_TypeError,mess);
+ return NULL;
+ }
+
+ {
+ F2PY_REPORT_ON_ARRAY_COPY_FROMANY;
+ arr = (PyArrayObject *) \
+ PyArray_FromAny(obj,PyArray_DescrFromType(type_num), 0,0,
+ ((intent & F2PY_INTENT_C)?CARRAY_FLAGS:FARRAY_FLAGS) \
+ | FORCECAST );
+ if (arr==NULL)
+ return NULL;
+ if (check_and_fix_dimensions(arr,rank,dims))
+ return NULL; /*XXX: set exception */
+ return arr;
+ }
+
+}
+
+ /*****************************************/
+ /* Helper functions for array_from_pyobj */
+ /*****************************************/
+
+static
+int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,intp *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 intp arr_size = (arr->nd)?PyArray_Size((PyObject *)arr):1;
+
+ if (rank > arr->nd) { /* [1,2] -> [[1],[2]]; 1 -> [[1]] */
+ intp 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 %" INTP_FMT
+ " but got %" INTP_FMT "\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 %" INTP_FMT
+ " 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=%" INTP_FMT
+ ", arr_size=%" INTP_FMT " (maybe too many free"
+ " indices)\n", new_size,arr_size);
+ return 1;
+ }
+ } else { /* [[1,2]] -> [[1],[2]] */
+ int i,j;
+ intp d;
+ int effrank;
+ intp size;
+ for (i=0,effrank=0;i<arr->nd;++i)
+ if (arr->dimensions[i]>1) ++effrank;
+ if (dims[rank-1]>=0)
+ if (effrank>rank) {
+ fprintf(stderr,"too many axes: %d (effrank=%d), expected rank=%d\n",
+ arr->nd,effrank,rank);
+ return 1;
+ }
+ for (i=0,j=0;i<rank;++i) {
+ while (j<arr->nd && arr->dimensions[j]<2) ++j;
+ if (j>=arr->nd) d = 1;
+ else d = arr->dimensions[j++];
+ if (dims[i]>=0) {
+ if (d>1 && d!=dims[i]) {
+ fprintf(stderr,"%d-th dimension must be fixed to %" INTP_FMT
+ " but got %" INTP_FMT " (real index=%d)\n",
+ i,dims[i],d,j-1);
+ return 1;
+ }
+ if (!dims[i]) dims[i] = 1;
+ } else
+ dims[i] = d;
+ }
+ for (i=rank;i<arr->nd;++i) { /* [[1,2],[3,4]] -> [1,2,3,4] */
+ while (j<arr->nd && arr->dimensions[j]<2) ++j;
+ if (j>=arr->nd) d = 1;
+ else d = arr->dimensions[j++];
+ dims[rank-1] *= d;
+ }
+ for (i=0,size=1;i<rank;++i) size *= dims[i];
+ if (size != arr_size) {
+ fprintf(stderr,"confused: size=%" INTP_FMT ", arr_size=%" INTP_FMT
+ ", rank=%d, effrank=%d, arr.nd=%d, dims=[",
+ size,arr_size,rank,effrank,arr->nd);
+ for (i=0;i<rank;++i) fprintf(stderr," %" INTP_FMT,dims[i]);
+ fprintf(stderr," ], arr.dims=[");
+ for (i=0;i<arr->nd;++i) fprintf(stderr," %" INTP_FMT,arr->dimensions[i]);
+ fprintf(stderr," ]\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* End of file: array_from_pyobj.c */
+
+/************************* copy_ND_array *******************************/
+
+extern
+int copy_ND_array(const PyArrayObject *arr, PyArrayObject *out)
+{
+ F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
+ return PyArray_CopyInto(out, (PyArrayObject *)arr);
+}
+
+#ifdef __cplusplus
+}
+#endif
+/************************* EOF fortranobject.c *******************************/
diff --git a/numpy/f2py/src/fortranobject.h b/numpy/f2py/src/fortranobject.h
new file mode 100644
index 000000000..680e6690e
--- /dev/null
+++ b/numpy/f2py/src/fortranobject.h
@@ -0,0 +1,123 @@
+#ifndef Py_FORTRANOBJECT_H
+#define Py_FORTRANOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "Python.h"
+
+#ifdef FORTRANOBJECT_C
+#define NO_IMPORT_ARRAY
+#endif
+#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API
+#include "scipy/arrayobject.h"
+
+ /*
+#ifdef F2PY_REPORT_ATEXIT_DISABLE
+#undef F2PY_REPORT_ATEXIT
+#else
+
+#ifndef __FreeBSD__
+#ifndef __WIN32__
+#ifndef __APPLE__
+#define F2PY_REPORT_ATEXIT
+#endif
+#endif
+#endif
+
+#endif
+ */
+
+#ifdef F2PY_REPORT_ATEXIT
+#include <sys/timeb.h>
+ extern void f2py_start_clock(void);
+ extern void f2py_stop_clock(void);
+ extern void f2py_start_call_clock(void);
+ extern void f2py_stop_call_clock(void);
+ extern void f2py_cb_start_clock(void);
+ extern void f2py_cb_stop_clock(void);
+ extern void f2py_cb_start_call_clock(void);
+ extern void f2py_cb_stop_call_clock(void);
+ extern void f2py_report_on_exit(int,void*);
+#endif
+
+#ifdef DMALLOC
+#include "dmalloc.h"
+#endif
+
+/* Fortran object interface */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+PyFortranObject represents various Fortran objects:
+Fortran (module) routines, COMMON blocks, module data.
+
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+*/
+
+#define F2PY_MAX_DIMS 40
+
+typedef void (*f2py_set_data_func)(char*,intp*);
+typedef void (*f2py_void_func)(void);
+typedef void (*f2py_init_func)(int*,intp*,f2py_set_data_func,int*);
+
+ /*typedef void* (*f2py_c_func)(void*,...);*/
+
+typedef void *(*f2pycfunc)(void);
+
+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 {intp d[F2PY_MAX_DIMS];} dims; /* dimensions of the array, || not used */
+ int type; /* PyArray_<type> || not used */
+ char *data; /* pointer to array || Fortran routine */
+ f2py_init_func 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;
+
+typedef struct {
+ PyObject_HEAD
+ int len; /* Number of attributes */
+ FortranDataDef *defs; /* An array of FortranDataDef's */
+ PyObject *dict; /* Fortran object attribute dictionary */
+} PyFortranObject;
+
+#define PyFortran_Check(op) ((op)->ob_type == &PyFortran_Type)
+#define PyFortran_Check1(op) (0==strcmp((op)->ob_type->tp_name,"fortran"))
+
+ extern PyTypeObject PyFortran_Type;
+ extern PyObject * PyFortranObject_New(FortranDataDef* defs, f2py_void_func init);
+ extern PyObject * PyFortranObject_NewAsAttr(FortranDataDef* defs);
+
+#define ISCONTIGUOUS(m) ((m)->flags & CONTIGUOUS)
+#define F2PY_INTENT_IN 1
+#define F2PY_INTENT_INOUT 2
+#define F2PY_INTENT_OUT 4
+#define F2PY_INTENT_HIDE 8
+#define F2PY_INTENT_CACHE 16
+#define F2PY_INTENT_COPY 32
+#define F2PY_INTENT_C 64
+#define F2PY_OPTIONAL 128
+#define F2PY_INTENT_INPLACE 256
+
+ extern PyArrayObject* array_from_pyobj(const int type_num,
+ intp *dims,
+ const int rank,
+ const int intent,
+ PyObject *obj);
+ extern int copy_ND_array(const PyArrayObject *in, PyArrayObject *out);
+
+#ifdef DEBUG_COPY_ND_ARRAY
+ extern void dump_attrs(const PyArrayObject* arr);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_FORTRANOBJECT_H */
diff --git a/numpy/f2py/src/test/Makefile b/numpy/f2py/src/test/Makefile
new file mode 100644
index 000000000..0f8869f72
--- /dev/null
+++ b/numpy/f2py/src/test/Makefile
@@ -0,0 +1,96 @@
+# -*- makefile -*-
+# File: Makefile-foo
+# Usage:
+# make -f Makefile-foo [MODE=opt|debug]
+# Notes:
+# 1) You must use GNU make; try `gmake ..' if `make' fails.
+# 2) This file is auto-generated with f2py (version 2.264).
+# f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
+# written by Pearu Peterson <pearu@ioc.ee>.
+# See http://cens.ioc.ee/projects/f2py2e/
+# Generation date: Wed Sep 13 16:22:55 2000
+# $Revision: 1.2 $
+# $Date: 2000/09/17 16:10:27 $
+
+# Recommendation notes produced by f2py2e/buildmakefile.py:
+# ***
+
+PYINC = -I/numeric/include/python1.5/Numeric -I/numeric/include/python1.5
+INCLUDES = -I..
+LIBS = -L$(shell gcc -v 2>&1 | grep specs | sed -e 's/Reading specs from //g' | sed -e 's/\/specs//g') -lg2c
+LIBS=-L$$ABSOFT/lib -lfio -lf77math -lf90math
+LIBS=-L/numeric/bin -lvast90 -L/usr/lib/gcc-lib/i586-mandrake-linux/2.95.2 -lg2c
+
+# Wrapper generator:
+F2PY = /home/pearu/bin/f2py-cvs
+
+# Fortran compiler: Absoft f95
+FC = f95
+FC = f90
+FOPT =
+FDEBUG =
+FFLAGS = -B108 -YCFRL=1 -YCOM_NAMES=LCS -YCOM_PFX -YCOM_SFX=_ -YEXT_PFX -YEXT_NAMES=LCS
+FFLAGS =
+# C compiler: cc ('gcc 2.x.x' 2.95.2)
+CC = cc
+COPT =
+CDEBUG =
+CFLAGS = -fpic
+
+# Linker: ld ('GNU ld' 2.9.5)
+LD = ld
+LDFLAGS = -shared -s
+SO = .so
+
+ifeq '$(MODE)' 'debug'
+FFLAGS += $(FDEBUG)
+CFLAGS += $(CDEBUG)
+endif
+ifeq '$(MODE)' 'opt'
+FFLAGS += $(FOPT)
+CFLAGS += $(COPT)
+endif
+FFLAGS += $(INCLUDES)
+CFLAGS += $(PYINC) $(INCLUDES)
+
+SRCC = ../fortranobject.c
+SRCF = mod.f90 bar.f foo90.f90 wrap.f
+SRCS = $(SRCC) $(SRCF)
+OBJC = $(filter %.o,$(SRCC:.c=.o) $(SRCC:.cc=.o) $(SRCC:.C=.o))
+OBJF = $(filter %.o,$(SRCF:.f90=.o) $(SRCF:.f=.o) $(SRCF:.F=.o) $(SRCF:.for=.o))
+OBJS = $(OBJC) $(OBJF)
+
+INSTALLNAME = f2py2e-apps
+INSTALLDIRECTORY = /numeric/lib/python1.5/site-packages/$(INSTALLNAME)
+INSTALLDIR = install -d -c
+INSTALLEXEC = install -m 755 -c
+
+all: foo
+
+foo: foomodule$(SO)
+foomodule$(SO) : foomodule.o $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $< $(OBJS) $(LIBS)
+
+foomodule.o: foomodule.c
+
+
+$(OBJS) : $(SRCS)
+%.o : %.f ; $(FC) -c $(FFLAGS) $<
+%.o : %.f90 ; $(FC) -c $(FFLAGS) $<
+
+test: foomodule$(SO)
+ python -c 'import foo;print foo.__doc__'
+install: foomodule$(SO)
+ $(INSTALLDIR) $(INSTALLDIRECTORY)
+ $(INSTALLEXEC) foomodule$(SO) $(INSTALLDIRECTORY)
+ cd $(INSTALLDIRECTORY) && echo "$(INSTALLNAME)" > ../$(INSTALLNAME).pth
+
+.PHONY: clean distclean debug test install foo
+debug:
+ echo "OBJS=$(OBJS)"
+ echo "SRCS=$(SRCS)"
+clean:
+ $(RM) *.o *.mod core foomodule.{dvi,log} $(OBJS)
+distclean: clean
+ $(RM) *.so *.sl foomodule.{tex,so}
+ $(RM) .f2py_get_compiler_*
diff --git a/numpy/f2py/src/test/bar.f b/numpy/f2py/src/test/bar.f
new file mode 100644
index 000000000..5354ceaf9
--- /dev/null
+++ b/numpy/f2py/src/test/bar.f
@@ -0,0 +1,11 @@
+ subroutine bar()
+ integer a
+ real*8 b,c(3)
+ common /foodata/ a,b,c
+ a = 4
+ b = 6.7
+ c(2) = 3.0
+ write(*,*) "bar:a=",a
+ write(*,*) "bar:b=",b
+ write(*,*) "bar:c=",c
+ end
diff --git a/numpy/f2py/src/test/foo.f b/numpy/f2py/src/test/foo.f
new file mode 100644
index 000000000..5354ceaf9
--- /dev/null
+++ b/numpy/f2py/src/test/foo.f
@@ -0,0 +1,11 @@
+ subroutine bar()
+ integer a
+ real*8 b,c(3)
+ common /foodata/ a,b,c
+ a = 4
+ b = 6.7
+ c(2) = 3.0
+ write(*,*) "bar:a=",a
+ write(*,*) "bar:b=",b
+ write(*,*) "bar:c=",c
+ end
diff --git a/numpy/f2py/src/test/foo90.f90 b/numpy/f2py/src/test/foo90.f90
new file mode 100644
index 000000000..dbca7e95b
--- /dev/null
+++ b/numpy/f2py/src/test/foo90.f90
@@ -0,0 +1,13 @@
+subroutine foo()
+ integer a
+ real*8 b,c(3)
+ common /foodata/ a,b,c
+ print*, " F: in foo"
+ a = 5
+ b = 6.3
+ c(2) = 9.1
+end subroutine foo
+
+
+
+
diff --git a/numpy/f2py/src/test/foomodule.c b/numpy/f2py/src/test/foomodule.c
new file mode 100644
index 000000000..0a954676e
--- /dev/null
+++ b/numpy/f2py/src/test/foomodule.c
@@ -0,0 +1,143 @@
+/* File: foomodule.c
+ * Example of FortranObject usage. See also wrap.f foo.f foo90.f90.
+ * Author: Pearu Peterson <pearu@ioc.ee>.
+ * http://cens.ioc.ee/projects/f2py2e/
+ * $Revision: 1.2 $
+ * $Date: 2000/09/17 16:10:27 $
+ */
+#ifdef __CPLUSPLUS__
+extern "C" {
+#endif
+
+#include "Python.h"
+#include "fortranobject.h"
+
+static PyObject *foo_error;
+
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F
+#else
+#define F_FUNC(f,F) f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F##_
+#else
+#define F_FUNC(f,F) f##_
+#endif
+#endif
+
+ /************* foo_bar *************/
+ static char doc_foo_bar[] = "\
+Function signature:\n\
+ bar()\n\
+";
+ static PyObject *foo_bar(PyObject *capi_self, PyObject *capi_args,
+ PyObject *capi_keywds, void (*f2py_func)()) {
+ PyObject *capi_buildvalue = NULL;
+ static char *capi_kwlist[] = {NULL};
+ if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\
+ "|:foo.bar",\
+ capi_kwlist))
+ goto capi_fail;
+ (*f2py_func)();
+ capi_buildvalue = Py_BuildValue("");
+ capi_fail:
+ return capi_buildvalue;
+ }
+ /************ mod_init **************/
+ static PyObject *mod_init(PyObject *capi_self, PyObject *capi_args,
+ PyObject *capi_keywds, void (*f2py_func)()) {
+ PyObject *capi_buildvalue = NULL;
+ static char *capi_kwlist[] = {NULL};
+ if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\
+ "|:mod.init",\
+ capi_kwlist))
+ goto capi_fail;
+ (*f2py_func)();
+ capi_buildvalue = Py_BuildValue("");
+ capi_fail:
+ return capi_buildvalue;
+ }
+
+ /* F90 module */
+ static FortranDataDef f2py_mod_def[] = {
+ {"a",0, {}, PyArray_INT},
+ {"b",0, {}, PyArray_DOUBLE},
+ {"c",1, {3}, PyArray_DOUBLE},
+ {"d",1, {-1}, PyArray_DOUBLE},
+ {"init",-1,{},0,NULL,(void *)mod_init},
+ {NULL}
+ };
+ static void f2py_setup_mod(char *a,char *b,char *c,void (*d)(),char *init) {
+ f2py_mod_def[0].data = a;
+ f2py_mod_def[1].data = b;
+ f2py_mod_def[2].data = c;
+ f2py_mod_def[3].func = d;
+ f2py_mod_def[4].data = init;
+ }
+ extern void F_FUNC(f2pyinitmod,F2PYINITMOD)();
+ static void f2py_init_mod() {
+ F_FUNC(f2pyinitmod,F2PYINITMOD)(f2py_setup_mod);
+ }
+
+ /* COMMON block */
+ static FortranDataDef f2py_foodata_def[] = {
+ {"a",0, {}, PyArray_INT},
+ {"b",0, {}, PyArray_DOUBLE},
+ {"c",1, {3}, PyArray_DOUBLE},
+ {NULL}
+ };
+ static void f2py_setup_foodata(char *a,char *b,char *c) {
+ f2py_foodata_def[0].data = a;
+ f2py_foodata_def[1].data = b;
+ f2py_foodata_def[2].data = c;
+ }
+ extern void F_FUNC(f2pyinitfoodata,F2PYINITFOODATA)();
+ static void f2py_init_foodata() {
+ F_FUNC(f2pyinitfoodata,F2PYINITFOODATA)(f2py_setup_foodata);
+ }
+
+ /* Fortran routines (needs no initialization/setup function) */
+ extern void F_FUNC(bar,BAR)();
+ extern void F_FUNC(foo,FOO)();
+ static FortranDataDef f2py_routines_def[] = {
+ {"bar",-1, {}, 0, (char *)F_FUNC(bar,BAR),(void *)foo_bar,doc_foo_bar},
+ {"foo",-1, {}, 0, (char *)F_FUNC(foo,FOO),(void *)foo_bar,doc_foo_bar},
+ {NULL}
+ };
+
+static PyMethodDef foo_module_methods[] = {
+/*eof method*/
+ {NULL,NULL}
+};
+
+void initfoo() {
+ int i;
+ PyObject *m, *d, *s;
+ PyTypeObject *t;
+ PyObject *f;
+ import_array();
+
+ m = Py_InitModule("foo", foo_module_methods);
+
+ d = PyModule_GetDict(m);
+ s = PyString_FromString("This module 'foo' demonstrates the usage of fortranobject.");
+ PyDict_SetItemString(d, "__doc__", s);
+
+ /* Fortran objects: */
+ PyDict_SetItemString(d, "mod", PyFortranObject_New(f2py_mod_def,f2py_init_mod));
+ PyDict_SetItemString(d, "foodata", PyFortranObject_New(f2py_foodata_def,f2py_init_foodata));
+ for(i=0;f2py_routines_def[i].name!=NULL;i++)
+ PyDict_SetItemString(d, f2py_routines_def[i].name,
+ PyFortranObject_NewAsAttr(&f2py_routines_def[i]));
+
+ Py_DECREF(s);
+
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module foo");
+}
+#ifdef __CPLUSCPLUS__
+}
+#endif
diff --git a/numpy/f2py/src/test/wrap.f b/numpy/f2py/src/test/wrap.f
new file mode 100644
index 000000000..9414eb9f6
--- /dev/null
+++ b/numpy/f2py/src/test/wrap.f
@@ -0,0 +1,70 @@
+ subroutine f2py_mod_get_dims(f2py_r,f2py_s,f2py_set,f2py_n)
+ use mod
+ external f2py_set
+ logical f2py_ns
+ integer f2py_s(*),f2py_r,f2py_i,f2py_j
+ character*(*) f2py_n
+ if ("d".eq.f2py_n) then
+ f2py_ns = .FALSE.
+ if (allocated(d)) then
+ do f2py_i=1,f2py_r
+ if ((size(d,f2py_r-f2py_i+1).ne.f2py_s(f2py_i)).and.
+ c (f2py_s(f2py_i).ge.0)) then
+ f2py_ns = .TRUE.
+ end if
+ end do
+ if (f2py_ns) then
+ deallocate(d)
+ end if
+ end if
+ if (.not.allocated(d)) then
+ allocate(d(f2py_s(1)))
+ end if
+ if (allocated(d)) then
+ do f2py_i=1,f2py_r
+ f2py_s(f2py_i) = size(d,f2py_r-f2py_i+1)
+ end do
+ call f2py_set(d)
+ end if
+ end if
+ end subroutine f2py_mod_get_dims
+ subroutine f2py_mod_get_dims_d(r,s,set_data)
+ use mod, only: d => d
+ external set_data
+ 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 set_data(d,allocated(d))
+ end subroutine f2py_mod_get_dims_d
+
+ subroutine f2pyinitmod(setupfunc)
+ use mod
+ external setupfunc,f2py_mod_get_dims_d,init
+ call setupfunc(a,b,c,f2py_mod_get_dims_d,init)
+ end subroutine f2pyinitmod
+
+ subroutine f2pyinitfoodata(setupfunc)
+ external setupfunc
+ integer a
+ real*8 b,c(3)
+ common /foodata/ a,b,c
+ call setupfunc(a,b,c)
+ end subroutine f2pyinitfoodata
diff --git a/numpy/f2py/tests/array_from_pyobj/__init__.py b/numpy/f2py/tests/array_from_pyobj/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/numpy/f2py/tests/array_from_pyobj/__init__.py
diff --git a/numpy/f2py/tests/array_from_pyobj/setup.py b/numpy/f2py/tests/array_from_pyobj/setup.py
new file mode 100644
index 000000000..ff7ff8cfc
--- /dev/null
+++ b/numpy/f2py/tests/array_from_pyobj/setup.py
@@ -0,0 +1,26 @@
+
+import os
+def configuration(parent_name='',top_path=None):
+ from scipy.distutils.misc_util import Configuration
+
+ config = Configuration('array_from_pyobj',parent_name,top_path)
+ #import scipy.f2py as f2py
+ #f2pydir=os.path.dirname(os.path.abspath(f2py.__file__))
+ f2pydir=os.path.join(config.local_path,'..','..')
+ fobjhsrc = os.path.join(f2pydir,'src','fortranobject.h')
+ fobjcsrc = os.path.join(f2pydir,'src','fortranobject.c')
+ config.add_extension('wrap',
+ sources = ['wrapmodule.c',fobjcsrc],
+ include_dirs = [os.path.dirname(fobjhsrc)],
+ depends = [fobjhsrc,fobjcsrc],
+ define_macros = [('DEBUG_COPY_ND_ARRAY',1),
+ #('F2PY_REPORT_ON_ARRAY_COPY',1),
+ #('F2PY_REPORT_ATEXIT',1)
+ ]
+ )
+
+ return config
+
+if __name__ == "__main__":
+ from scipy.distutils.core import setup
+ setup(**configuration(top_path='').todict())
diff --git a/numpy/f2py/tests/array_from_pyobj/tests/test_array_from_pyobj.py b/numpy/f2py/tests/array_from_pyobj/tests/test_array_from_pyobj.py
new file mode 100644
index 000000000..309ad03f6
--- /dev/null
+++ b/numpy/f2py/tests/array_from_pyobj/tests/test_array_from_pyobj.py
@@ -0,0 +1,512 @@
+import unittest
+import sys
+import copy
+
+from scipy.test.testing import *
+from scipy.base import array, typeinfo, alltrue, ndarray, asarray, can_cast,zeros
+set_package_path()
+from array_from_pyobj import wrap
+del sys.path[0]
+
+def flags_info(arr):
+ flags = wrap.array_attrs(arr)[6]
+ return flags2names(flags)
+
+def flags2names(flags):
+ info = []
+ for flagname in ['CONTIGUOUS','FORTRAN','OWNDATA','ENSURECOPY',
+ 'ENSUREARRAY','ALIGNED','NOTSWAPPED','WRITEABLE',
+ 'UPDATEIFCOPY','BEHAVED_FLAGS','BEHAVED_FLAGS_RO',
+ 'CARRAY_FLAGS','FARRAY_FLAGS'
+ ]:
+ if abs(flags) & getattr(wrap,flagname):
+ info.append(flagname)
+ return info
+
+class Intent:
+ def __init__(self,intent_list=[]):
+ self.intent_list = intent_list[:]
+ flags = 0
+ for i in intent_list:
+ if i=='optional':
+ flags |= wrap.F2PY_OPTIONAL
+ else:
+ flags |= getattr(wrap,'F2PY_INTENT_'+i.upper())
+ self.flags = flags
+ def __getattr__(self,name):
+ name = name.lower()
+ if name=='in_': name='in'
+ return self.__class__(self.intent_list+[name])
+ def __str__(self):
+ return 'intent(%s)' % (','.join(self.intent_list))
+ def __repr__(self):
+ return 'Intent(%r)' % (self.intent_list)
+ def is_intent(self,*names):
+ for name in names:
+ if name not in self.intent_list:
+ return False
+ return True
+ def is_intent_exact(self,*names):
+ return len(self.intent_list)==len(names) and self.is_intent(*names)
+
+intent = Intent()
+
+class Type(object):
+
+ _type_names = ['BOOL','BYTE','UBYTE','SHORT','USHORT','INT','UINT',
+ 'LONG','ULONG','LONGLONG','ULONGLONG',
+ 'FLOAT','DOUBLE','LONGDOUBLE','CFLOAT','CDOUBLE',
+ 'CLONGDOUBLE']
+ _type_cache = {}
+
+ _cast_dict = {'BOOL':['BOOL']}
+ _cast_dict['BYTE'] = _cast_dict['BOOL'] + ['BYTE']
+ _cast_dict['UBYTE'] = _cast_dict['BOOL'] + ['UBYTE']
+ _cast_dict['BYTE'] = ['BYTE']
+ _cast_dict['UBYTE'] = ['UBYTE']
+ _cast_dict['SHORT'] = _cast_dict['BYTE'] + ['UBYTE','SHORT']
+ _cast_dict['USHORT'] = _cast_dict['UBYTE'] + ['BYTE','USHORT']
+ _cast_dict['INT'] = _cast_dict['SHORT'] + ['USHORT','INT']
+ _cast_dict['UINT'] = _cast_dict['USHORT'] + ['SHORT','UINT']
+
+ _cast_dict['LONG'] = _cast_dict['INT'] + ['LONG']
+ _cast_dict['ULONG'] = _cast_dict['UINT'] + ['ULONG']
+
+ _cast_dict['LONGLONG'] = _cast_dict['LONG'] + ['LONGLONG']
+ _cast_dict['ULONGLONG'] = _cast_dict['ULONG'] + ['ULONGLONG']
+
+ _cast_dict['FLOAT'] = _cast_dict['SHORT'] + ['USHORT','FLOAT']
+ _cast_dict['DOUBLE'] = _cast_dict['INT'] + ['UINT','FLOAT','DOUBLE']
+ _cast_dict['LONGDOUBLE'] = _cast_dict['LONG'] + ['ULONG','FLOAT','DOUBLE','LONGDOUBLE']
+
+ _cast_dict['CFLOAT'] = _cast_dict['FLOAT'] + ['CFLOAT']
+ _cast_dict['CDOUBLE'] = _cast_dict['DOUBLE'] + ['CFLOAT','CDOUBLE']
+ _cast_dict['CLONGDOUBLE'] = _cast_dict['LONGDOUBLE'] + ['CFLOAT','CDOUBLE','CLONGDOUBLE']
+
+
+ def __new__(cls,name):
+ if isinstance(name,type):
+ dtype = name
+ name = None
+ for n,i in typeinfo.items():
+ if isinstance(i,tuple) and dtype is i[-1]:
+ name = n
+ break
+ obj = cls._type_cache.get(name.upper(),None)
+ if obj is not None:
+ return obj
+ obj = object.__new__(cls)
+ obj._init(name)
+ cls._type_cache[name.upper()] = obj
+ return obj
+
+ def _init(self,name):
+ self.NAME = name.upper()
+ self.type_num = getattr(wrap,'PyArray_'+self.NAME)
+ assert_equal(self.type_num,typeinfo[self.NAME][1])
+ self.dtype = typeinfo[self.NAME][-1]
+ self.elsize = typeinfo[self.NAME][2] / 8
+ self.dtypechar = typeinfo[self.NAME][0]
+
+ def cast_types(self):
+ return map(self.__class__,self._cast_dict[self.NAME])
+
+ def all_types(self):
+ return map(self.__class__,self._type_names)
+
+ def smaller_types(self):
+ bits = typeinfo[self.NAME][3]
+ types = []
+ for name in self._type_names:
+ if typeinfo[name][3]<bits:
+ types.append(Type(name))
+ return types
+
+ def equal_types(self):
+ bits = typeinfo[self.NAME][3]
+ types = []
+ for name in self._type_names:
+ if name==self.NAME: continue
+ if typeinfo[name][3]==bits:
+ types.append(Type(name))
+ return types
+
+ def larger_types(self):
+ bits = typeinfo[self.NAME][3]
+ types = []
+ for name in self._type_names:
+ if typeinfo[name][3]>bits:
+ types.append(Type(name))
+ return types
+
+class Array:
+ def __init__(self,typ,dims,intent,obj):
+ self.type = typ
+ self.dims = dims
+ self.intent = intent
+ self.obj_copy = copy.deepcopy(obj)
+ self.obj = obj
+
+ # arr.dtypechar may be different from typ.dtypechar
+ self.arr = wrap.call(typ.type_num,dims,intent.flags,obj)
+
+ self.arr_attr = wrap.array_attrs(self.arr)
+
+ if len(dims)>1:
+ if self.intent.is_intent('c'):
+ assert intent.flags & wrap.F2PY_INTENT_C
+ assert not self.arr.flags['FORTRAN'],`self.arr.flags,obj.flags`
+ assert self.arr.flags['CONTIGUOUS']
+ assert not self.arr_attr[6] & wrap.FORTRAN
+ else:
+ assert not intent.flags & wrap.F2PY_INTENT_C
+ assert self.arr.flags['FORTRAN']
+ assert not self.arr.flags['CONTIGUOUS']
+ assert self.arr_attr[6] & wrap.FORTRAN
+
+ if obj is None:
+ self.pyarr = None
+ self.pyarr_attr = None
+ return
+
+ if intent.is_intent('cache'):
+ assert isinstance(obj,ndarray),`type(obj)`
+ self.pyarr = array(obj).reshape(*dims)
+
+ else:
+ self.pyarr = array(array(obj,
+ dtype = typ.dtypechar).reshape(*dims),
+ fortran=not self.intent.is_intent('c'))
+ assert self.pyarr.dtypechar==typ.dtypechar,\
+ `self.pyarr.dtypechar,typ.dtypechar`
+ assert self.pyarr.flags['OWNDATA']
+ self.pyarr_attr = wrap.array_attrs(self.pyarr)
+
+ if len(dims)>1:
+ if self.intent.is_intent('c'):
+ assert not self.pyarr.flags['FORTRAN']
+ assert self.pyarr.flags['CONTIGUOUS']
+ assert not self.pyarr_attr[6] & wrap.FORTRAN
+ else:
+ assert self.pyarr.flags['FORTRAN']
+ assert not self.pyarr.flags['CONTIGUOUS']
+ assert self.pyarr_attr[6] & wrap.FORTRAN
+
+
+ assert self.arr_attr[1]==self.pyarr_attr[1] # nd
+ assert self.arr_attr[2]==self.pyarr_attr[2] # dimensions
+ if self.arr_attr[1]<=1:
+ assert self.arr_attr[3]==self.pyarr_attr[3],\
+ `self.arr_attr[3],self.pyarr_attr[3],self.arr.tostring(),self.pyarr.tostring()` # strides
+ assert self.arr_attr[5][-2:]==self.pyarr_attr[5][-2:],\
+ `self.arr_attr[5],self.pyarr_attr[5]` # descr
+ assert self.arr_attr[6]==self.pyarr_attr[6],\
+ `self.arr_attr[6],self.pyarr_attr[6],flags2names(0*self.arr_attr[6]-self.pyarr_attr[6]),flags2names(self.arr_attr[6]),intent` # flags
+
+ if intent.is_intent('cache'):
+ assert self.arr_attr[5][3]>=self.type.elsize,\
+ `self.arr_attr[5][3],self.type.elsize`
+ else:
+ assert self.arr_attr[5][3]==self.type.elsize,\
+ `self.arr_attr[5][3],self.type.elsize`
+ assert self.arr_equal(self.pyarr,self.arr)
+
+ if isinstance(self.obj,ndarray):
+ if typ.elsize==Type(obj.dtype).elsize:
+ if not intent.is_intent('copy') and self.arr_attr[1]<=1:
+ assert self.has_shared_memory()
+
+ def arr_equal(self,arr1,arr2):
+ if arr1.shape != arr2.shape:
+ return False
+ return alltrue(arr1==arr2)
+
+ def __str__(self):
+ return str(self.arr)
+
+ def has_shared_memory(self):
+ """Check that created array shares data with input array.
+ """
+ if self.obj is self.arr:
+ return True
+ if not isinstance(self.obj,ndarray):
+ return False
+ obj_attr = wrap.array_attrs(self.obj)
+ return obj_attr[0]==self.arr_attr[0]
+
+##################################################
+
+class test_intent(unittest.TestCase):
+ def check_in_out(self):
+ assert_equal(str(intent.in_.out),'intent(in,out)')
+ assert intent.in_.c.is_intent('c')
+ assert not intent.in_.c.is_intent_exact('c')
+ assert intent.in_.c.is_intent_exact('c','in')
+ assert intent.in_.c.is_intent_exact('in','c')
+ assert not intent.in_.is_intent('c')
+
+class _test_shared_memory:
+ num2seq = [1,2]
+ num23seq = [[1,2,3],[4,5,6]]
+ def check_in_from_2seq(self):
+ a = self.array([2],intent.in_,self.num2seq)
+ assert not a.has_shared_memory()
+
+ def check_in_from_2casttype(self):
+ for t in self.type.cast_types():
+ obj = array(self.num2seq,dtype=t.dtype)
+ a = self.array([len(self.num2seq)],intent.in_,obj)
+ if t.elsize==self.type.elsize:
+ assert a.has_shared_memory(),`self.type.dtype,t.dtype`
+ else:
+ assert not a.has_shared_memory(),`t.dtype`
+
+ def check_inout_2seq(self):
+ obj = array(self.num2seq,dtype=self.type.dtype)
+ a = self.array([len(self.num2seq)],intent.inout,obj)
+ assert a.has_shared_memory()
+
+ try:
+ a = self.array([2],intent.in_.inout,self.num2seq)
+ except TypeError,msg:
+ if not str(msg).startswith('failed to initialize intent(inout|inplace|cache) array'):
+ raise
+ else:
+ raise SystemError,'intent(inout) should have failed on sequence'
+
+ def check_f_inout_23seq(self):
+ obj = array(self.num23seq,dtype=self.type.dtype,fortran=1)
+ shape = (len(self.num23seq),len(self.num23seq[0]))
+ a = self.array(shape,intent.in_.inout,obj)
+ assert a.has_shared_memory()
+
+ obj = array(self.num23seq,dtype=self.type.dtype,fortran=0)
+ shape = (len(self.num23seq),len(self.num23seq[0]))
+ try:
+ a = self.array(shape,intent.in_.inout,obj)
+ except ValueError,msg:
+ if not str(msg).startswith('failed to initialize intent(inout) array'):
+ raise
+ else:
+ raise SystemError,'intent(inout) should have failed on improper array'
+
+ def check_c_inout_23seq(self):
+ obj = array(self.num23seq,dtype=self.type.dtype)
+ shape = (len(self.num23seq),len(self.num23seq[0]))
+ a = self.array(shape,intent.in_.c.inout,obj)
+ assert a.has_shared_memory()
+
+ def check_in_copy_from_2casttype(self):
+ for t in self.type.cast_types():
+ obj = array(self.num2seq,dtype=t.dtype)
+ a = self.array([len(self.num2seq)],intent.in_.copy,obj)
+ assert not a.has_shared_memory(),`t.dtype`
+
+ def check_c_in_from_23seq(self):
+ a = self.array([len(self.num23seq),len(self.num23seq[0])],
+ intent.in_,self.num23seq)
+ assert not a.has_shared_memory()
+
+ def check_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = array(self.num23seq,dtype=t.dtype)
+ a = self.array([len(self.num23seq),len(self.num23seq[0])],
+ intent.in_,obj)
+ assert not a.has_shared_memory(),`t.dtype`
+
+ def check_f_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = array(self.num23seq,dtype=t.dtype,fortran=1)
+ a = self.array([len(self.num23seq),len(self.num23seq[0])],
+ intent.in_,obj)
+ if t.elsize==self.type.elsize:
+ assert a.has_shared_memory(),`t.dtype`
+ else:
+ assert not a.has_shared_memory(),`t.dtype`
+
+ def check_c_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = array(self.num23seq,dtype=t.dtype)
+ a = self.array([len(self.num23seq),len(self.num23seq[0])],
+ intent.in_.c,obj)
+ if t.elsize==self.type.elsize:
+ assert a.has_shared_memory(),`t.dtype`
+ else:
+ assert not a.has_shared_memory(),`t.dtype`
+
+ def check_f_copy_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = array(self.num23seq,dtype=t.dtype,fortran=1)
+ a = self.array([len(self.num23seq),len(self.num23seq[0])],
+ intent.in_.copy,obj)
+ assert not a.has_shared_memory(),`t.dtype`
+
+ def check_c_copy_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = array(self.num23seq,dtype=t.dtype)
+ a = self.array([len(self.num23seq),len(self.num23seq[0])],
+ intent.in_.c.copy,obj)
+ assert not a.has_shared_memory(),`t.dtype`
+
+ def check_in_cache_from_2casttype(self):
+ for t in self.type.all_types():
+ if t.elsize != self.type.elsize:
+ continue
+ obj = array(self.num2seq,dtype=t.dtype)
+ shape = (len(self.num2seq),)
+ a = self.array(shape,intent.in_.c.cache,obj)
+ assert a.has_shared_memory(),`t.dtype`
+
+ a = self.array(shape,intent.in_.cache,obj)
+ assert a.has_shared_memory(),`t.dtype`
+
+ obj = array(self.num2seq,dtype=t.dtype,fortran=1)
+ a = self.array(shape,intent.in_.c.cache,obj)
+ assert a.has_shared_memory(),`t.dtype`
+
+ a = self.array(shape,intent.in_.cache,obj)
+ assert a.has_shared_memory(),`t.dtype`
+
+ try:
+ a = self.array(shape,intent.in_.cache,obj[::-1])
+ except ValueError,msg:
+ if not str(msg).startswith('failed to initialize intent(cache) array'):
+ raise
+ else:
+ raise SystemError,'intent(cache) should have failed on multisegmented array'
+ def check_in_cache_from_2casttype_failure(self):
+ for t in self.type.all_types():
+ if t.elsize >= self.type.elsize:
+ continue
+ obj = array(self.num2seq,dtype=t.dtype)
+ shape = (len(self.num2seq),)
+ try:
+ a = self.array(shape,intent.in_.cache,obj)
+ except ValueError,msg:
+ if not str(msg).startswith('failed to initialize intent(cache) array'):
+ raise
+ else:
+ raise SystemError,'intent(cache) should have failed on smaller array'
+
+ def check_cache_hidden(self):
+ shape = (2,)
+ a = self.array(shape,intent.cache.hide,None)
+ assert a.arr.shape==shape
+
+ shape = (2,3)
+ a = self.array(shape,intent.cache.hide,None)
+ assert a.arr.shape==shape
+
+ shape = (-1,3)
+ try:
+ a = self.array(shape,intent.cache.hide,None)
+ except ValueError,msg:
+ if not str(msg).startswith('failed to create intent(cache|hide)|optional array'):
+ raise
+ else:
+ raise SystemError,'intent(cache) should have failed on undefined dimensions'
+
+ def check_hidden(self):
+ shape = (2,)
+ a = self.array(shape,intent.hide,None)
+ assert a.arr.shape==shape
+ assert a.arr_equal(a.arr,zeros(shape,dtype=self.type.dtype))
+
+ shape = (2,3)
+ a = self.array(shape,intent.hide,None)
+ assert a.arr.shape==shape
+ assert a.arr_equal(a.arr,zeros(shape,dtype=self.type.dtype))
+ assert a.arr.flags['FORTRAN'] and not a.arr.flags['CONTIGUOUS']
+
+ shape = (2,3)
+ a = self.array(shape,intent.c.hide,None)
+ assert a.arr.shape==shape
+ assert a.arr_equal(a.arr,zeros(shape,dtype=self.type.dtype))
+ assert not a.arr.flags['FORTRAN'] and a.arr.flags['CONTIGUOUS']
+
+ shape = (-1,3)
+ try:
+ a = self.array(shape,intent.hide,None)
+ except ValueError,msg:
+ if not str(msg).startswith('failed to create intent(cache|hide)|optional array'):
+ raise
+ else:
+ raise SystemError,'intent(hide) should have failed on undefined dimensions'
+
+ def check_optional_none(self):
+ shape = (2,)
+ a = self.array(shape,intent.optional,None)
+ assert a.arr.shape==shape
+ assert a.arr_equal(a.arr,zeros(shape,dtype=self.type.dtype))
+
+ shape = (2,3)
+ a = self.array(shape,intent.optional,None)
+ assert a.arr.shape==shape
+ assert a.arr_equal(a.arr,zeros(shape,dtype=self.type.dtype))
+ assert a.arr.flags['FORTRAN'] and not a.arr.flags['CONTIGUOUS']
+
+ shape = (2,3)
+ a = self.array(shape,intent.c.optional,None)
+ assert a.arr.shape==shape
+ assert a.arr_equal(a.arr,zeros(shape,dtype=self.type.dtype))
+ assert not a.arr.flags['FORTRAN'] and a.arr.flags['CONTIGUOUS']
+
+ def check_optional_from_2seq(self):
+ obj = self.num2seq
+ shape = (len(obj),)
+ a = self.array(shape,intent.optional,obj)
+ assert a.arr.shape==shape
+ assert not a.has_shared_memory()
+
+ def check_optional_from_23seq(self):
+ obj = self.num23seq
+ shape = (len(obj),len(obj[0]))
+ a = self.array(shape,intent.optional,obj)
+ assert a.arr.shape==shape
+ assert not a.has_shared_memory()
+
+ a = self.array(shape,intent.optional.c,obj)
+ assert a.arr.shape==shape
+ assert not a.has_shared_memory()
+
+ def check_inplace(self):
+ obj = array(self.num23seq,dtype=self.type.dtype)
+ assert not obj.flags['FORTRAN'] and obj.flags['CONTIGUOUS']
+ shape = obj.shape
+ a = self.array(shape,intent.inplace,obj)
+ assert obj[1][2]==a.arr[1][2],`obj,a.arr`
+ a.arr[1][2]=54
+ assert obj[1][2]==a.arr[1][2]==array(54,dtype=self.type.dtype),`obj,a.arr`
+ assert a.arr is obj
+ assert obj.flags['FORTRAN'] # obj attributes are changed inplace!
+ assert not obj.flags['CONTIGUOUS']
+
+ def check_inplace_from_casttype(self):
+ for t in self.type.cast_types():
+ if t is self.type:
+ continue
+ obj = array(self.num23seq,dtype=t.dtype)
+ assert obj.dtype==t.dtype
+ assert obj.dtype is not self.type.dtype
+ assert not obj.flags['FORTRAN'] and obj.flags['CONTIGUOUS']
+ shape = obj.shape
+ a = self.array(shape,intent.inplace,obj)
+ assert obj[1][2]==a.arr[1][2],`obj,a.arr`
+ a.arr[1][2]=54
+ assert obj[1][2]==a.arr[1][2]==array(54,dtype=self.type.dtype),`obj,a.arr`
+ assert a.arr is obj
+ assert obj.flags['FORTRAN'] # obj attributes are changed inplace!
+ assert not obj.flags['CONTIGUOUS']
+ assert obj.dtype is self.type.dtype # obj type is changed inplace!
+
+for t in Type._type_names:
+ exec '''\
+class test_%s_gen(unittest.TestCase,
+ _test_shared_memory
+ ):
+ type = Type(%r)
+ array = lambda self,dims,intent,obj: Array(Type(%r),dims,intent,obj)
+''' % (t,t,t)
+
+if __name__ == "__main__":
+ ScipyTest().run()
diff --git a/numpy/f2py/tests/array_from_pyobj/wrapmodule.c b/numpy/f2py/tests/array_from_pyobj/wrapmodule.c
new file mode 100644
index 000000000..0d9e41f1c
--- /dev/null
+++ b/numpy/f2py/tests/array_from_pyobj/wrapmodule.c
@@ -0,0 +1,194 @@
+/* File: wrapmodule.c
+ * This file is auto-generated with f2py (version:2_1330).
+ * Hand edited by Pearu.
+ * f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
+ * written by Pearu Peterson <pearu@cens.ioc.ee>.
+ * See http://cens.ioc.ee/projects/f2py2e/
+ * Generation date: Fri Oct 21 22:41:12 2005
+ * $Revision:$
+ * $Date:$
+ * Do not edit this file directly unless you know what you are doing!!!
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************** See f2py2e/cfuncs.py: includes ***********************/
+#include "Python.h"
+#include "fortranobject.h"
+#include <math.h>
+
+static PyObject *wrap_error;
+static PyObject *wrap_module;
+
+/************************************ call ************************************/
+static char doc_f2py_rout_wrap_call[] = "\
+Function signature:\n\
+ arr = call(type_num,dims,intent,obj)\n\
+Required arguments:\n"
+" type_num : input int\n"
+" dims : input int-sequence\n"
+" intent : input int\n"
+" obj : input python object\n"
+"Return objects:\n"
+" arr : array";
+static PyObject *f2py_rout_wrap_call(PyObject *capi_self,
+ PyObject *capi_args) {
+ PyObject * volatile capi_buildvalue = NULL;
+ int type_num = 0;
+ intp *dims = NULL;
+ PyObject *dims_capi = Py_None;
+ int rank = 0;
+ int intent = 0;
+ PyArrayObject *capi_arr_tmp = NULL;
+ PyObject *arr_capi = Py_None;
+ int i;
+
+ if (!PyArg_ParseTuple(capi_args,"iOiO|:wrap.call",\
+ &type_num,&dims_capi,&intent,&arr_capi))
+ return NULL;
+ rank = PySequence_Length(dims_capi);
+ dims = malloc(rank*sizeof(intp));
+ for (i=0;i<rank;++i)
+ dims[i] = (intp)PyInt_AsLong(PySequence_GetItem(dims_capi,i));
+
+ capi_arr_tmp = array_from_pyobj(type_num,dims,rank,intent|F2PY_INTENT_OUT,arr_capi);
+ if (capi_arr_tmp == NULL)
+ return NULL;
+ capi_buildvalue = Py_BuildValue("N",capi_arr_tmp);
+ free(dims);
+ return capi_buildvalue;
+}
+
+static char doc_f2py_rout_wrap_attrs[] = "\
+Function signature:\n\
+ arr = array_attrs(arr)\n\
+Required arguments:\n"
+" arr : input array object\n"
+"Return objects:\n"
+" data : data address in hex\n"
+" nd : int\n"
+" dimensions : tuple\n"
+" strides : tuple\n"
+" base : python object\n"
+" (kind,type,type_num,elsize,alignment) : 4-tuple\n"
+" flags : int\n"
+" itemsize : int\n"
+;
+static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self,
+ PyObject *capi_args) {
+ PyObject *arr_capi = Py_None;
+ PyArrayObject *arr = NULL;
+ PyObject *dimensions = NULL;
+ PyObject *strides = NULL;
+ char s[100];
+ int i;
+ memset(s,0,100*sizeof(char));
+ if (!PyArg_ParseTuple(capi_args,"O!|:wrap.attrs",
+ &PyArray_Type,&arr_capi))
+ return NULL;
+ arr = (PyArrayObject *)arr_capi;
+ sprintf(s,"%p",arr->data);
+ dimensions = PyTuple_New(arr->nd);
+ strides = PyTuple_New(arr->nd);
+ for (i=0;i<arr->nd;++i) {
+ PyTuple_SetItem(dimensions,i,PyInt_FromLong(arr->dimensions[i]));
+ PyTuple_SetItem(strides,i,PyInt_FromLong(arr->strides[i]));
+ }
+ return Py_BuildValue("siOOO(cciii)ii",s,arr->nd,
+ dimensions,strides,
+ (arr->base==NULL?Py_None:arr->base),
+ arr->descr->kind,
+ arr->descr->type,
+ arr->descr->type_num,
+ arr->descr->elsize,
+ arr->descr->alignment,
+ arr->flags,
+ arr->itemsize);
+}
+
+static PyMethodDef f2py_module_methods[] = {
+
+ {"call",f2py_rout_wrap_call,METH_VARARGS,doc_f2py_rout_wrap_call},
+ {"array_attrs",f2py_rout_wrap_attrs,METH_VARARGS,doc_f2py_rout_wrap_attrs},
+ {NULL,NULL}
+};
+
+DL_EXPORT(void) initwrap(void) {
+ PyObject *m,*d, *s;
+ m = wrap_module = Py_InitModule("wrap", f2py_module_methods);
+ PyFortran_Type.ob_type = &PyType_Type;
+ import_array();
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module wrap (failed to import scipy.base)");
+ d = PyModule_GetDict(m);
+ s = PyString_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n"
+" arr = call(type_num,dims,intent,obj)\n"
+".");
+ PyDict_SetItemString(d, "__doc__", s);
+ wrap_error = PyErr_NewException ("wrap.error", NULL, NULL);
+ Py_DECREF(s);
+ PyDict_SetItemString(d, "F2PY_INTENT_IN", PyInt_FromLong(F2PY_INTENT_IN));
+ PyDict_SetItemString(d, "F2PY_INTENT_INOUT", PyInt_FromLong(F2PY_INTENT_INOUT));
+ PyDict_SetItemString(d, "F2PY_INTENT_OUT", PyInt_FromLong(F2PY_INTENT_OUT));
+ PyDict_SetItemString(d, "F2PY_INTENT_HIDE", PyInt_FromLong(F2PY_INTENT_HIDE));
+ PyDict_SetItemString(d, "F2PY_INTENT_CACHE", PyInt_FromLong(F2PY_INTENT_CACHE));
+ PyDict_SetItemString(d, "F2PY_INTENT_COPY", PyInt_FromLong(F2PY_INTENT_COPY));
+ PyDict_SetItemString(d, "F2PY_INTENT_C", PyInt_FromLong(F2PY_INTENT_C));
+ PyDict_SetItemString(d, "F2PY_OPTIONAL", PyInt_FromLong(F2PY_OPTIONAL));
+ PyDict_SetItemString(d, "F2PY_INTENT_INPLACE", PyInt_FromLong(F2PY_INTENT_INPLACE));
+ PyDict_SetItemString(d, "PyArray_BOOL", PyInt_FromLong(PyArray_BOOL));
+ PyDict_SetItemString(d, "PyArray_BYTE", PyInt_FromLong(PyArray_BYTE));
+ PyDict_SetItemString(d, "PyArray_UBYTE", PyInt_FromLong(PyArray_UBYTE));
+ PyDict_SetItemString(d, "PyArray_SHORT", PyInt_FromLong(PyArray_SHORT));
+ PyDict_SetItemString(d, "PyArray_USHORT", PyInt_FromLong(PyArray_USHORT));
+ PyDict_SetItemString(d, "PyArray_INT", PyInt_FromLong(PyArray_INT));
+ PyDict_SetItemString(d, "PyArray_UINT", PyInt_FromLong(PyArray_UINT));
+ PyDict_SetItemString(d, "PyArray_INTP", PyInt_FromLong(PyArray_INTP));
+ PyDict_SetItemString(d, "PyArray_UINTP", PyInt_FromLong(PyArray_UINTP));
+ PyDict_SetItemString(d, "PyArray_LONG", PyInt_FromLong(PyArray_LONG));
+ PyDict_SetItemString(d, "PyArray_ULONG", PyInt_FromLong(PyArray_ULONG));
+ PyDict_SetItemString(d, "PyArray_LONGLONG", PyInt_FromLong(PyArray_LONGLONG));
+ PyDict_SetItemString(d, "PyArray_ULONGLONG", PyInt_FromLong(PyArray_ULONGLONG));
+ PyDict_SetItemString(d, "PyArray_FLOAT", PyInt_FromLong(PyArray_FLOAT));
+ PyDict_SetItemString(d, "PyArray_DOUBLE", PyInt_FromLong(PyArray_DOUBLE));
+ PyDict_SetItemString(d, "PyArray_LONGDOUBLE", PyInt_FromLong(PyArray_LONGDOUBLE));
+ PyDict_SetItemString(d, "PyArray_CFLOAT", PyInt_FromLong(PyArray_CFLOAT));
+ PyDict_SetItemString(d, "PyArray_CDOUBLE", PyInt_FromLong(PyArray_CDOUBLE));
+ PyDict_SetItemString(d, "PyArray_CLONGDOUBLE", PyInt_FromLong(PyArray_CLONGDOUBLE));
+ PyDict_SetItemString(d, "PyArray_OBJECT", PyInt_FromLong(PyArray_OBJECT));
+ PyDict_SetItemString(d, "PyArray_STRING", PyInt_FromLong(PyArray_STRING));
+ PyDict_SetItemString(d, "PyArray_UNICODE", PyInt_FromLong(PyArray_UNICODE));
+ PyDict_SetItemString(d, "PyArray_VOID", PyInt_FromLong(PyArray_VOID));
+ PyDict_SetItemString(d, "PyArray_NTYPES", PyInt_FromLong(PyArray_NTYPES));
+ PyDict_SetItemString(d, "PyArray_NOTYPE", PyInt_FromLong(PyArray_NOTYPE));
+ PyDict_SetItemString(d, "PyArray_UDERDEF", PyInt_FromLong(PyArray_USERDEF));
+
+ PyDict_SetItemString(d, "CONTIGUOUS", PyInt_FromLong(CONTIGUOUS));
+ PyDict_SetItemString(d, "FORTRAN", PyInt_FromLong(FORTRAN));
+ PyDict_SetItemString(d, "OWNDATA", PyInt_FromLong(OWNDATA));
+ PyDict_SetItemString(d, "ENSURECOPY", PyInt_FromLong(ENSURECOPY));
+ PyDict_SetItemString(d, "ENSUREARRAY", PyInt_FromLong(ENSUREARRAY));
+ PyDict_SetItemString(d, "ALIGNED", PyInt_FromLong(ALIGNED));
+ PyDict_SetItemString(d, "NOTSWAPPED", PyInt_FromLong(NOTSWAPPED));
+ PyDict_SetItemString(d, "WRITEABLE", PyInt_FromLong(WRITEABLE));
+ PyDict_SetItemString(d, "UPDATEIFCOPY", PyInt_FromLong(UPDATEIFCOPY));
+
+ PyDict_SetItemString(d, "BEHAVED_FLAGS", PyInt_FromLong(BEHAVED_FLAGS));
+ PyDict_SetItemString(d, "BEHAVED_FLAGS_RO", PyInt_FromLong(BEHAVED_FLAGS_RO));
+ PyDict_SetItemString(d, "CARRAY_FLAGS", PyInt_FromLong(CARRAY_FLAGS));
+ PyDict_SetItemString(d, "FARRAY_FLAGS", PyInt_FromLong(FARRAY_FLAGS));
+ PyDict_SetItemString(d, "DEFAULT_FLAGS", PyInt_FromLong(DEFAULT_FLAGS));
+ PyDict_SetItemString(d, "UPDATE_ALL_FLAGS", PyInt_FromLong(UPDATE_ALL_FLAGS));
+
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module wrap");
+
+#ifdef F2PY_REPORT_ATEXIT
+ on_exit(f2py_report_on_exit,(void*)"array_from_pyobj.wrap.call");
+#endif
+
+}
+#ifdef __cplusplus
+}
+#endif
diff --git a/numpy/f2py/tests/c/return_real.py b/numpy/f2py/tests/c/return_real.py
new file mode 100644
index 000000000..7d35b28cf
--- /dev/null
+++ b/numpy/f2py/tests/c/return_real.py
@@ -0,0 +1,108 @@
+__usage__ = """
+Run:
+ python return_real.py [<f2py options>]
+Examples:
+ python return_real.py --fcompiler=Gnu --no-wrap-functions
+ python return_real.py --quiet
+"""
+
+
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import c_ext_return_real
+ except ImportError:
+ assert not f2py2e.compile('''\
+python module c_ext_return_real
+usercode \'\'\'
+float t4(float value) { return value; }
+void s4(float *t4, float value) { *t4 = value; }
+double t8(double value) { return value; }
+void s8(double *t8, double value) { *t8 = value; }
+\'\'\'
+interface
+ function t4(value)
+ real*4 intent(c) :: t4,value
+ end
+ function t8(value)
+ real*8 intent(c) :: t8,value
+ end
+ subroutine s4(t4,value)
+ intent(c) s4
+ real*4 intent(out) :: t4
+ real*4 intent(c) :: value
+ end
+ subroutine s8(t8,value)
+ intent(c) s8
+ real*8 intent(out) :: t8
+ real*8 intent(c) :: value
+ end
+end interface
+end python module c_ext_return_real
+''','c_ext_return_real',f2py_opts,source_fn='c_ret_real.pyf')
+
+ from c_ext_return_real import t4,t8,s4,s8
+ test_functions = [t4,t8,s4,s8]
+ return test_functions
+
+def runtest(t):
+ import sys
+ if t.__doc__.split()[0] in ['t0','t4','s0','s4']:
+ err = 1e-5
+ else:
+ err = 0.0
+ assert abs(t(234)-234.0)<=err
+ assert abs(t(234.6)-234.6)<=err
+ assert abs(t(234l)-234.0)<=err
+ if sys.version[:3]<'2.3':
+ assert abs(t(234.6+3j)-234.6)<=err
+ assert abs(t('234')-234)<=err
+ assert abs(t('234.6')-234.6)<=err
+ assert abs(t(-234)+234)<=err
+ assert abs(t([234])-234)<=err
+ assert abs(t((234,))-234.)<=err
+ assert abs(t(array(234))-234.)<=err
+ assert abs(t(array([234]))-234.)<=err
+ assert abs(t(array([[234]]))-234.)<=err
+ assert abs(t(array([234],'1'))+22)<=err
+ assert abs(t(array([234],'s'))-234.)<=err
+ assert abs(t(array([234],'i'))-234.)<=err
+ assert abs(t(array([234],'l'))-234.)<=err
+ assert abs(t(array([234],'b'))-234.)<=err
+ assert abs(t(array([234],'f'))-234.)<=err
+ assert abs(t(array([234],'d'))-234.)<=err
+ if sys.version[:3]<'2.3':
+ assert abs(t(array([234+3j],'F'))-234.)<=err
+ assert abs(t(array([234],'D'))-234.)<=err
+ if t.__doc__.split()[0] in ['t0','t4','s0','s4']:
+ assert t(1e200)==t(1e300) # inf
+
+ try: raise RuntimeError,`t(array([234],'c'))`
+ except ValueError: pass
+ try: raise RuntimeError,`t('abc')`
+ except ValueError: pass
+
+ try: raise RuntimeError,`t([])`
+ except IndexError: pass
+ try: raise RuntimeError,`t(())`
+ except IndexError: pass
+
+ try: raise RuntimeError,`t(t)`
+ except TypeError: pass
+ try: raise RuntimeError,`t({})`
+ except TypeError: pass
+
+ try:
+ try: raise RuntimeError,`t(10l**400)`
+ except OverflowError: pass
+ except RuntimeError:
+ r = t(10l**400); assert `r` in ['inf','Infinity'],`r`
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/f77/callback.py b/numpy/f2py/tests/f77/callback.py
new file mode 100644
index 000000000..672504bc7
--- /dev/null
+++ b/numpy/f2py/tests/f77/callback.py
@@ -0,0 +1,99 @@
+
+__usage__ = """
+Run:
+ python callback.py [<f2py options>]
+Examples:
+ python callback.py --fcompiler=Gnu --no-wrap-functions
+ python callback.py --quiet
+"""
+
+import f2py2e
+import math
+import sys
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import f77_ext_callback
+ except ImportError:
+ assert not f2py2e.compile('''\
+ subroutine t(fun,a)
+ integer a
+cf2py intent(out) a
+ external fun
+ call fun(a)
+ end
+
+ subroutine func(a)
+cf2py intent(in,out) a
+ integer a
+ a = a + 11
+ end
+
+ subroutine func0(a)
+cf2py intent(out) a
+ integer a
+ a = 11
+ end
+
+ subroutine t2(a)
+cf2py intent(callback) fun
+ integer a
+cf2py intent(out) a
+ external fun
+ call fun(a)
+ end
+
+''','f77_ext_callback',f2py_opts,source_fn='f77_callback.f')
+
+ from f77_ext_callback import t,t2
+ test_functions = [t,t2]
+ return test_functions
+
+def runtest(t):
+ r = t(lambda : 4)
+ assert r==4,`r`
+ r = t(lambda a:5,fun_extra_args=(6,))
+ assert r==5,`r`
+ r = t(lambda a:a,fun_extra_args=(6,))
+ assert r==6,`r`
+ r = t(lambda a:5+a,fun_extra_args=(7,))
+ assert r==12,`r`
+ if sys.version[:3]>='2.3':
+ r = t(lambda a:math.degrees(a),fun_extra_args=(math.pi,))
+ assert r==180,`r`
+ r = t(math.degrees,fun_extra_args=(math.pi,))
+ assert r==180,`r`
+ from f77_ext_callback import func,func0
+ r = t(func,fun_extra_args=(6,))
+ assert r==17,`r`
+ r = t(func0)
+ assert r==11,`r`
+ r = t(func0._cpointer)
+ assert r==11,`r`
+ class A:
+ def __call__(self):
+ return 7
+ def mth(self):
+ return 9
+ a = A()
+ r = t(a)
+ assert r==7,`r`
+ r = t(a.mth)
+ assert r==9,`r`
+
+if __name__=='__main__':
+ #import libwadpy
+ status = 1
+ try:
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
+ status = 0
+ finally:
+ if status:
+ print '*'*20
+ print 'Running f2py2e.diagnose'
+ import f2py2e.diagnose
+ f2py2e.diagnose.run()
diff --git a/numpy/f2py/tests/f77/return_character.py b/numpy/f2py/tests/f77/return_character.py
new file mode 100644
index 000000000..3361c11f5
--- /dev/null
+++ b/numpy/f2py/tests/f77/return_character.py
@@ -0,0 +1,100 @@
+
+__usage__ = """
+Run:
+ python return_character.py [<f2py options>]
+Examples:
+ python return_character.py --fcompiler=Gnu --no-wrap-functions
+ python return_character.py --quiet
+"""
+
+import sys
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import f77_ext_return_character
+ except ImportError:
+ assert not f2py2e.compile('''\
+ function t0(value)
+ character value
+ character t0
+ t0 = value
+ end
+ function t1(value)
+ character*1 value
+ character*1 t1
+ t1 = value
+ end
+ function t5(value)
+ character*5 value
+ character*5 t5
+ t5 = value
+ end
+ function ts(value)
+ character*(*) value
+ character*(*) ts
+ ts = value
+ end
+
+ subroutine s0(t0,value)
+ character value
+ character t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s1(t1,value)
+ character*1 value
+ character*1 t1
+cf2py intent(out) t1
+ t1 = value
+ end
+ subroutine s5(t5,value)
+ character*5 value
+ character*5 t5
+cf2py intent(out) t5
+ t5 = value
+ end
+ subroutine ss(ts,value)
+ character*(*) value
+ character*10 ts
+cf2py intent(out) ts
+ ts = value
+ end
+''','f77_ext_return_character',f2py_opts,source_fn='f77_ret_char.f')
+
+ from f77_ext_return_character import t0,t1,t5,s0,s1,s5,ss
+ test_functions = [t0,t1,t5,s0,s1,s5,ss]
+ if sys.platform!='win32': # this is acctually compiler dependent case
+ from f77_ext_return_character import ts
+ test_functions.append(ts)
+
+ return test_functions
+
+def runtest(t):
+ tname = t.__doc__.split()[0]
+ if tname in ['t0','t1','s0','s1']:
+ assert t(23)=='2'
+ r = t('ab');assert r=='a',`r`
+ r = t(array('ab'));assert r=='a',`r`
+ r = t(array(77,'1'));assert r=='M',`r`
+ try: raise RuntimeError,`t(array([77,87]))`
+ except ValueError: pass
+ try: raise RuntimeError,`t(array(77))`
+ except ValueError: pass
+ elif tname in ['ts','ss']:
+ assert t(23)=='23 ',`t(23)`
+ assert t('123456789abcdef')=='123456789a'
+ elif tname in ['t5','s5']:
+ assert t(23)=='23 ',`t(23)`
+ assert t('ab')=='ab ',`t('ab')`
+ assert t('123456789abcdef')=='12345'
+ else:
+ raise NotImplementedError
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/f77/return_complex.py b/numpy/f2py/tests/f77/return_complex.py
new file mode 100644
index 000000000..39743a9f6
--- /dev/null
+++ b/numpy/f2py/tests/f77/return_complex.py
@@ -0,0 +1,125 @@
+__usage__ = """
+Run:
+ python return_complex.py [<f2py options>]
+Examples:
+ python return_complex.py --fcompiler=Gnu --no-wrap-functions
+ python return_complex.py --quiet
+"""
+
+
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import f77_ext_return_complex
+ except ImportError:
+ assert not f2py2e.compile('''\
+ function t0(value)
+ complex value
+ complex t0
+ t0 = value
+ end
+ function t8(value)
+ complex*8 value
+ complex*8 t8
+ t8 = value
+ end
+ function t16(value)
+ complex*16 value
+ complex*16 t16
+ t16 = value
+ end
+ function td(value)
+ double complex value
+ double complex td
+ td = value
+ end
+
+ subroutine s0(t0,value)
+ complex value
+ complex t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s8(t8,value)
+ complex*8 value
+ complex*8 t8
+cf2py intent(out) t8
+ t8 = value
+ end
+ subroutine s16(t16,value)
+ complex*16 value
+ complex*16 t16
+cf2py intent(out) t16
+ t16 = value
+ end
+ subroutine sd(td,value)
+ double complex value
+ double complex td
+cf2py intent(out) td
+ td = value
+ end
+''','f77_ext_return_complex',f2py_opts)
+
+ from f77_ext_return_complex import t0,t8,t16,td,s0,s8,s16,sd
+ test_functions = [t0,t8,t16,td,s0,s8,s16,sd]
+ return test_functions
+
+
+def runtest(t):
+ tname = t.__doc__.split()[0]
+ if tname in ['t0','t8','s0','s8']:
+ err = 1e-5
+ else:
+ err = 0.0
+ assert abs(t(234j)-234.0j)<=err
+ assert abs(t(234.6)-234.6)<=err
+ assert abs(t(234l)-234.0)<=err
+ assert abs(t(234.6+3j)-(234.6+3j))<=err
+ #assert abs(t('234')-234.)<=err
+ #assert abs(t('234.6')-234.6)<=err
+ assert abs(t(-234)+234.)<=err
+ assert abs(t([234])-234.)<=err
+ assert abs(t((234,))-234.)<=err
+ assert abs(t(array(234))-234.)<=err
+ assert abs(t(array(23+4j,'F'))-(23+4j))<=err
+ assert abs(t(array([234]))-234.)<=err
+ assert abs(t(array([[234]]))-234.)<=err
+ assert abs(t(array([234],'1'))+22.)<=err
+ assert abs(t(array([234],'s'))-234.)<=err
+ assert abs(t(array([234],'i'))-234.)<=err
+ assert abs(t(array([234],'l'))-234.)<=err
+ assert abs(t(array([234],'b'))-234.)<=err
+ assert abs(t(array([234],'f'))-234.)<=err
+ assert abs(t(array([234],'d'))-234.)<=err
+ assert abs(t(array([234+3j],'F'))-(234+3j))<=err
+ assert abs(t(array([234],'D'))-234.)<=err
+
+ try: raise RuntimeError,`t(array([234],'c'))`
+ except TypeError: pass
+ try: raise RuntimeError,`t('abc')`
+ except TypeError: pass
+
+ try: raise RuntimeError,`t([])`
+ except IndexError: pass
+ try: raise RuntimeError,`t(())`
+ except IndexError: pass
+
+ try: raise RuntimeError,`t(t)`
+ except TypeError: pass
+ try: raise RuntimeError,`t({})`
+ except TypeError: pass
+
+ try:
+ try: raise RuntimeError,`t(10l**400)`
+ except OverflowError: pass
+ except RuntimeError:
+ r = t(10l**400); assert `r` in ['(inf+0j)','(Infinity+0j)'],`r`
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/f77/return_integer.py b/numpy/f2py/tests/f77/return_integer.py
new file mode 100644
index 000000000..f50ab52da
--- /dev/null
+++ b/numpy/f2py/tests/f77/return_integer.py
@@ -0,0 +1,148 @@
+
+__usage__ = """
+Run:
+ python return_integer.py [<f2py options>]
+Examples:
+ python return_integer.py --fcompiler=Gnu --no-wrap-functions
+ python return_integer.py --quiet
+"""
+
+import scipy.f2py as f2py2e
+from scipy.base import array
+
+def build(f2py_opts):
+ try:
+ import f77_ext_return_integer
+ except ImportError:
+ assert not f2py2e.compile('''\
+ function t0(value)
+ integer value
+ integer t0
+ t0 = value
+ end
+ function t1(value)
+ integer*1 value
+ integer*1 t1
+ t1 = value
+ end
+ function t2(value)
+ integer*2 value
+ integer*2 t2
+ t2 = value
+ end
+ function t4(value)
+ integer*4 value
+ integer*4 t4
+ t4 = value
+ end
+ function t8(value)
+ integer*8 value
+ integer*8 t8
+ t8 = value
+ end
+
+ subroutine s0(t0,value)
+ integer value
+ integer t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s1(t1,value)
+ integer*1 value
+ integer*1 t1
+cf2py intent(out) t1
+ t1 = value
+ end
+ subroutine s2(t2,value)
+ integer*2 value
+ integer*2 t2
+cf2py intent(out) t2
+ t2 = value
+ end
+ subroutine s4(t4,value)
+ integer*4 value
+ integer*4 t4
+cf2py intent(out) t4
+ t4 = value
+ end
+ subroutine s8(t8,value)
+ integer*8 value
+ integer*8 t8
+cf2py intent(out) t8
+ t8 = value
+ end
+
+''','f77_ext_return_integer',f2py_opts,source_fn='f77_ret_int.f')
+
+ from f77_ext_return_integer import t0,t1,t2,t4,t8,s0,s1,s2,s4,s8
+ test_functions = [t0,t1,t2,t4,t8,s0,s1,s2,s4,s8]
+ return test_functions
+
+def runtest(t):
+ import sys
+ assert t(123)==123,`t(123)`
+ assert t(123.6)==123
+ assert t(123l)==123
+ if sys.version[:3]<'2.3':
+ assert t(123.6+3j)==123
+ assert t('123')==123
+ assert t(-123)==-123
+ assert t([123])==123
+ assert t((123,))==123
+ assert t(array(123))==123
+ assert t(array([123]))==123
+ assert t(array([[123]]))==123
+ assert t(array([123],'b'))==123
+ assert t(array([123],'h'))==123
+ assert t(array([123],'i'))==123
+ assert t(array([123],'l'))==123
+ assert t(array([123],'B'))==123
+ assert t(array([123],'f'))==123
+ assert t(array([123],'d'))==123
+ if sys.version[:3]<'2.3':
+ assert t(array([123+3j],'F'))==123
+ assert t(array([123],'D'))==123
+
+
+ try: raise RuntimeError,`t(array([123],'c'))`
+ except ValueError: pass
+ try: raise RuntimeError,`t('abc')`
+ except ValueError: pass
+
+ try: raise RuntimeError,`t([])`
+ except IndexError: pass
+ try: raise RuntimeError,`t(())`
+ except IndexError: pass
+
+ try: raise RuntimeError,`t(t)`
+ except TypeError: pass
+ try: raise RuntimeError,`t({})`
+ except TypeError: pass
+
+ if t.__doc__.split()[0] in ['t8','s8']:
+ try: raise RuntimeError,`t(100000000000000000000000l)`
+ except OverflowError: pass
+ try: raise RuntimeError,`t(10000000011111111111111.23)`
+ except OverflowError: pass
+ else:
+ if sys.version[:3]<'2.3':
+ try: raise RuntimeError,`t(10000000000000l)`
+ except OverflowError: pass
+ try: raise RuntimeError,`t(10000000000.23)`
+ except OverflowError: pass
+
+if __name__=='__main__':
+ #import libwadpy
+ status = 1
+ try:
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
+ status = 0
+ finally:
+ if status:
+ print '*'*20
+ print 'Running f2py2e.diagnose'
+ import scipy.f2py.diagnose as diagnose
+ #diagnose.run()
diff --git a/numpy/f2py/tests/f77/return_logical.py b/numpy/f2py/tests/f77/return_logical.py
new file mode 100644
index 000000000..e252e03a6
--- /dev/null
+++ b/numpy/f2py/tests/f77/return_logical.py
@@ -0,0 +1,135 @@
+
+__usage__ = """
+Run:
+ python return_logical.py [<f2py options>]
+Examples:
+ python return_logical.py --fcompiler=Gnu --no-wrap-functions
+ python return_logical.py --quiet
+"""
+
+import f2py2e
+from Numeric import array
+try: True
+except NameError:
+ True = 1
+ False = 0
+
+def build(f2py_opts):
+ try:
+ import f77_ext_return_logical
+ except ImportError:
+ assert not f2py2e.compile('''\
+ function t0(value)
+ logical value
+ logical t0
+ t0 = value
+ end
+ function t1(value)
+ logical*1 value
+ logical*1 t1
+ t1 = value
+ end
+ function t2(value)
+ logical*2 value
+ logical*2 t2
+ t2 = value
+ end
+ function t4(value)
+ logical*4 value
+ logical*4 t4
+ t4 = value
+ end
+c function t8(value)
+c logical*8 value
+c logical*8 t8
+c t8 = value
+c end
+
+ subroutine s0(t0,value)
+ logical value
+ logical t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s1(t1,value)
+ logical*1 value
+ logical*1 t1
+cf2py intent(out) t1
+ t1 = value
+ end
+ subroutine s2(t2,value)
+ logical*2 value
+ logical*2 t2
+cf2py intent(out) t2
+ t2 = value
+ end
+ subroutine s4(t4,value)
+ logical*4 value
+ logical*4 t4
+cf2py intent(out) t4
+ t4 = value
+ end
+c subroutine s8(t8,value)
+c logical*8 value
+c logical*8 t8
+cf2py intent(out) t8
+c t8 = value
+c end
+''','f77_ext_return_logical',f2py_opts)
+
+ #from f77_ext_return_logical import t0,t1,t2,t4,t8,s0,s1,s2,s4,s8
+ #test_functions = [t0,t1,t2,t4,t8,s0,s1,s2,s4,s8]
+ from f77_ext_return_logical import t0,t1,t2,t4,s0,s1,s2,s4
+ test_functions = [t0,t1,t2,t4,s0,s1,s2,s4]
+ return test_functions
+
+def runtest(t):
+ assert t(True)==1,`t(True)`
+ assert t(False)==0,`t(False)`
+ assert t(0)==0
+ assert t(None)==0
+ assert t(0.0)==0
+ assert t(0j)==0
+ assert t(1j)==1
+ assert t(234)==1
+ assert t(234.6)==1
+ assert t(234l)==1
+ assert t(234.6+3j)==1
+ assert t('234')==1
+ assert t('aaa')==1
+ assert t('')==0
+ assert t([])==0
+ assert t(())==0
+ assert t({})==0
+ assert t(t)==1
+ assert t(-234)==1
+ assert t(10l**100)==1
+ assert t([234])==1
+ assert t((234,))==1
+ assert t(array(234))==1
+ assert t(array([234]))==1
+ assert t(array([[234]]))==1
+ assert t(array([234],'1'))==1
+ assert t(array([234],'s'))==1
+ assert t(array([234],'i'))==1
+ assert t(array([234],'l'))==1
+ assert t(array([234],'b'))==1
+ assert t(array([234],'f'))==1
+ assert t(array([234],'d'))==1
+ assert t(array([234+3j],'F'))==1
+ assert t(array([234],'D'))==1
+ assert t(array(0))==0
+ assert t(array([0]))==0
+ assert t(array([[0]]))==0
+ assert t(array([0j]))==0
+ assert t(array([1]))==1
+ assert t(array([0,0]))==0
+ assert t(array([0,1]))==1 #XXX: is this expected?
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
+
diff --git a/numpy/f2py/tests/f77/return_real.py b/numpy/f2py/tests/f77/return_real.py
new file mode 100644
index 000000000..37f97a06d
--- /dev/null
+++ b/numpy/f2py/tests/f77/return_real.py
@@ -0,0 +1,127 @@
+__usage__ = """
+Run:
+ python return_real.py [<f2py options>]
+Examples:
+ python return_real.py --fcompiler=Gnu --no-wrap-functions
+ python return_real.py --quiet
+"""
+
+
+import scipy.f2py as f2py2e
+from scipy.base import array
+
+def build(f2py_opts):
+ try:
+ import f77_ext_return_real
+ except ImportError:
+ assert not f2py2e.compile('''\
+ function t0(value)
+ real value
+ real t0
+ t0 = value
+ end
+ function t4(value)
+ real*4 value
+ real*4 t4
+ t4 = value
+ end
+ function t8(value)
+ real*8 value
+ real*8 t8
+ t8 = value
+ end
+ function td(value)
+ double precision value
+ double precision td
+ td = value
+ end
+
+ subroutine s0(t0,value)
+ real value
+ real t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s4(t4,value)
+ real*4 value
+ real*4 t4
+cf2py intent(out) t4
+ t4 = value
+ end
+ subroutine s8(t8,value)
+ real*8 value
+ real*8 t8
+cf2py intent(out) t8
+ t8 = value
+ end
+ subroutine sd(td,value)
+ double precision value
+ double precision td
+cf2py intent(out) td
+ td = value
+ end
+''','f77_ext_return_real',f2py_opts,source_fn='f77_ret_real.f')
+
+ from f77_ext_return_real import t0,t4,t8,td,s0,s4,s8,sd
+ test_functions = [t0,t4,t8,td,s0,s4,s8,sd]
+ return test_functions
+
+def runtest(t):
+ import sys
+ if t.__doc__.split()[0] in ['t0','t4','s0','s4']:
+ err = 1e-5
+ else:
+ err = 0.0
+ assert abs(t(234)-234.0)<=err
+ assert abs(t(234.6)-234.6)<=err
+ assert abs(t(234l)-234.0)<=err
+ if sys.version[:3]<'2.3':
+ assert abs(t(234.6+3j)-234.6)<=err
+ assert abs(t('234')-234)<=err
+ assert abs(t('234.6')-234.6)<=err
+ assert abs(t(-234)+234)<=err
+ assert abs(t([234])-234)<=err
+ assert abs(t((234,))-234.)<=err
+ assert abs(t(array(234))-234.)<=err
+ assert abs(t(array([234]))-234.)<=err
+ assert abs(t(array([[234]]))-234.)<=err
+ assert abs(t(array([234],'b'))+22)<=err
+ assert abs(t(array([234],'h'))-234.)<=err
+ assert abs(t(array([234],'i'))-234.)<=err
+ assert abs(t(array([234],'l'))-234.)<=err
+ assert abs(t(array([234],'B'))-234.)<=err
+ assert abs(t(array([234],'f'))-234.)<=err
+ assert abs(t(array([234],'d'))-234.)<=err
+ if sys.version[:3]<'2.3':
+ assert abs(t(array([234+3j],'F'))-234.)<=err
+ assert abs(t(array([234],'D'))-234.)<=err
+ if t.__doc__.split()[0] in ['t0','t4','s0','s4']:
+ assert t(1e200)==t(1e300) # inf
+
+ try: raise RuntimeError,`t(array([234],'c'))`
+ except ValueError: pass
+ try: raise RuntimeError,`t('abc')`
+ except ValueError: pass
+
+ try: raise RuntimeError,`t([])`
+ except IndexError: pass
+ try: raise RuntimeError,`t(())`
+ except IndexError: pass
+
+ try: raise RuntimeError,`t(t)`
+ except TypeError: pass
+ try: raise RuntimeError,`t({})`
+ except TypeError: pass
+
+ try:
+ try: raise RuntimeError,`t(10l**400)`
+ except OverflowError: pass
+ except RuntimeError:
+ r = t(10l**400); assert `r` in ['inf','Infinity'],`r`
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/f90/return_character.py b/numpy/f2py/tests/f90/return_character.py
new file mode 100644
index 000000000..0bd7be701
--- /dev/null
+++ b/numpy/f2py/tests/f90/return_character.py
@@ -0,0 +1,100 @@
+
+__usage__ = """
+Run:
+ python return_character.py [<f2py options>]
+Examples:
+ python return_character.py --fcompiler=Gnu --no-wrap-functions
+ python return_character.py --quiet
+"""
+
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import f90_ext_return_character
+ except ImportError:
+ assert not f2py2e.compile('''\
+module f90_return_char
+ contains
+ function t0(value)
+ character :: value
+ character :: t0
+ t0 = value
+ end function t0
+ function t1(value)
+ character(len=1) :: value
+ character(len=1) :: t1
+ t1 = value
+ end function t1
+ function t5(value)
+ character(len=5) :: value
+ character(len=5) :: t5
+ t5 = value
+ end function t5
+ function ts(value)
+ character(len=*) :: value
+ character(len=10) :: ts
+ ts = value
+ end function ts
+
+ subroutine s0(t0,value)
+ character :: value
+ character :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s1(t1,value)
+ character(len=1) :: value
+ character(len=1) :: t1
+!f2py intent(out) t1
+ t1 = value
+ end subroutine s1
+ subroutine s5(t5,value)
+ character(len=5) :: value
+ character(len=5) :: t5
+!f2py intent(out) t5
+ t5 = value
+ end subroutine s5
+ subroutine ss(ts,value)
+ character(len=*) :: value
+ character(len=10) :: ts
+!f2py intent(out) ts
+ ts = value
+ end subroutine ss
+end module f90_return_char
+''','f90_ext_return_character',f2py_opts,source_fn='f90_ret_char.f90')
+
+ from f90_ext_return_character import f90_return_char as m
+ test_functions = [m.t0,m.t1,m.t5,m.ts,m.s0,m.s1,m.s5,m.ss]
+ return test_functions
+
+
+def runtest(t):
+ tname = t.__doc__.split()[0]
+ if tname in ['t0','t1','s0','s1']:
+ assert t(23)=='2'
+ r = t('ab');assert r=='a',`r`
+ r = t(array('ab'));assert r=='a',`r`
+ r = t(array(77,'1'));assert r=='M',`r`
+ try: raise RuntimeError,`t(array([77,87]))`
+ except ValueError: pass
+ try: raise RuntimeError,`t(array(77))`
+ except ValueError: pass
+ elif tname in ['ts','ss']:
+ assert t(23)=='23 ',`t(23)`
+ assert t('123456789abcdef')=='123456789a',`t('123456789abcdef')`
+ elif tname in ['t5','s5']:
+ assert t(23)=='23 '
+ assert t('ab')=='ab '
+ assert t('123456789abcdef')=='12345'
+ else:
+ raise NotImplementedError
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
+
diff --git a/numpy/f2py/tests/f90/return_complex.py b/numpy/f2py/tests/f90/return_complex.py
new file mode 100644
index 000000000..36d8707fc
--- /dev/null
+++ b/numpy/f2py/tests/f90/return_complex.py
@@ -0,0 +1,127 @@
+__usage__ = """
+Run:
+ python return_complex.py [<f2py options>]
+Examples:
+ python return_complex.py --quiet
+"""
+
+
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import f90_ext_return_complex
+ except ImportError:
+ assert not f2py2e.compile('''\
+module f90_return_complex
+ contains
+ function t0(value)
+ complex :: value
+ complex :: t0
+ t0 = value
+ end function t0
+ function t8(value)
+ complex(kind=4) :: value
+ complex(kind=4) :: t8
+ t8 = value
+ end function t8
+ function t16(value)
+ complex(kind=8) :: value
+ complex(kind=8) :: t16
+ t16 = value
+ end function t16
+ function td(value)
+ double complex :: value
+ double complex :: td
+ td = value
+ end function td
+
+ subroutine s0(t0,value)
+ complex :: value
+ complex :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s8(t8,value)
+ complex(kind=4) :: value
+ complex(kind=4) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+ subroutine s16(t16,value)
+ complex(kind=8) :: value
+ complex(kind=8) :: t16
+!f2py intent(out) t16
+ t16 = value
+ end subroutine s16
+ subroutine sd(td,value)
+ double complex :: value
+ double complex :: td
+!f2py intent(out) td
+ td = value
+ end subroutine sd
+end module f90_return_complex
+''','f90_ext_return_complex',f2py_opts,source_fn='f90_ret_cmlx.f90')
+
+ from f90_ext_return_complex import f90_return_complex as m
+ test_functions = [m.t0,m.t8,m.t16,m.td,m.s0,m.s8,m.s16,m.sd]
+ return test_functions
+
+
+def runtest(t):
+ tname = t.__doc__.split()[0]
+ if tname in ['t0','t8','s0','s8']:
+ err = 1e-5
+ else:
+ err = 0.0
+ #assert abs(t(234j)-234.0j)<=err
+ assert abs(t(234.6)-234.6)<=err
+ assert abs(t(234l)-234.0)<=err
+ assert abs(t(234.6+3j)-(234.6+3j))<=err
+ #assert abs(t('234')-234.)<=err
+ #assert abs(t('234.6')-234.6)<=err
+ assert abs(t(-234)+234.)<=err
+ assert abs(t([234])-234.)<=err
+ assert abs(t((234,))-234.)<=err
+ assert abs(t(array(234))-234.)<=err
+ assert abs(t(array(23+4j,'F'))-(23+4j))<=err
+ assert abs(t(array([234]))-234.)<=err
+ assert abs(t(array([[234]]))-234.)<=err
+ assert abs(t(array([234],'1'))+22.)<=err
+ assert abs(t(array([234],'s'))-234.)<=err
+ assert abs(t(array([234],'i'))-234.)<=err
+ assert abs(t(array([234],'l'))-234.)<=err
+ assert abs(t(array([234],'b'))-234.)<=err
+ assert abs(t(array([234],'f'))-234.)<=err
+ assert abs(t(array([234],'d'))-234.)<=err
+ assert abs(t(array([234+3j],'F'))-(234+3j))<=err
+ assert abs(t(array([234],'D'))-234.)<=err
+
+ try: raise RuntimeError,`t(array([234],'c'))`
+ except TypeError: pass
+ try: raise RuntimeError,`t('abc')`
+ except TypeError: pass
+
+ try: raise RuntimeError,`t([])`
+ except IndexError: pass
+ try: raise RuntimeError,`t(())`
+ except IndexError: pass
+
+ try: raise RuntimeError,`t(t)`
+ except TypeError: pass
+ try: raise RuntimeError,`t({})`
+ except TypeError: pass
+
+ try:
+ try: raise RuntimeError,`t(10l**400)`
+ except OverflowError: pass
+ except RuntimeError:
+ r = t(10l**400); assert `r` in ['(inf+0j)','(Infinity+0j)'],`r`
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/f90/return_integer.py b/numpy/f2py/tests/f90/return_integer.py
new file mode 100644
index 000000000..635252ce9
--- /dev/null
+++ b/numpy/f2py/tests/f90/return_integer.py
@@ -0,0 +1,152 @@
+
+# XXX: investigate cases that are disabled under win32
+#
+
+__usage__ = """
+Run:
+ python return_integer.py [<f2py options>]
+Examples:
+ python return_integer.py --quiet
+"""
+
+import sys
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import f90_ext_return_integer
+ except ImportError:
+ assert not f2py2e.compile('''\
+module f90_return_integer
+ contains
+ function t0(value)
+ integer :: value
+ integer :: t0
+ t0 = value
+ end function t0
+ function t1(value)
+ integer(kind=1) :: value
+ integer(kind=1) :: t1
+ t1 = value
+ end function t1
+ function t2(value)
+ integer(kind=2) :: value
+ integer(kind=2) :: t2
+ t2 = value
+ end function t2
+ function t4(value)
+ integer(kind=4) :: value
+ integer(kind=4) :: t4
+ t4 = value
+ end function t4
+ function t8(value)
+ integer(kind=8) :: value
+ integer(kind=8) :: t8
+ t8 = value
+ end function t8
+
+ subroutine s0(t0,value)
+ integer :: value
+ integer :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s1(t1,value)
+ integer(kind=1) :: value
+ integer(kind=1) :: t1
+!f2py intent(out) t1
+ t1 = value
+ end subroutine s1
+ subroutine s2(t2,value)
+ integer(kind=2) :: value
+ integer(kind=2) :: t2
+!f2py intent(out) t2
+ t2 = value
+ end subroutine s2
+ subroutine s4(t4,value)
+ integer(kind=4) :: value
+ integer(kind=4) :: t4
+!f2py intent(out) t4
+ t4 = value
+ end subroutine s4
+ subroutine s8(t8,value)
+ integer(kind=8) :: value
+ integer(kind=8) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+end module f90_return_integer
+''','f90_ext_return_integer',f2py_opts,source_fn='f90_ret_int.f90')
+
+ from f90_ext_return_integer import f90_return_integer as m
+ test_functions = [m.t0,m.t1,m.t2,m.t4,m.t8,m.s0,m.s1,m.s2,m.s4,m.s8]
+ return test_functions
+
+def runtest(t):
+ tname = t.__doc__.split()[0]
+ assert t(123)==123
+ assert t(123.6)==123
+ assert t(123l)==123
+ if sys.version[:3]<='2.2':
+ assert t(123.6+3j)==123
+ assert t('123')==123
+ assert t(-123)==-123
+ assert t([123])==123
+ assert t((123,))==123
+ assert t(array(123))==123
+ assert t(array([123]))==123
+ assert t(array([[123]]))==123
+ assert t(array([123],'1'))==123
+ assert t(array([123],'s'))==123
+ assert t(array([123],'i'))==123
+ assert t(array([123],'l'))==123
+ assert t(array([123],'b'))==123
+ assert t(array([123],'f'))==123
+ assert t(array([123],'d'))==123
+ if sys.version[:3]<='2.2':
+ assert t(array([123+3j],'F'))==123
+ assert t(array([123],'D'))==123
+
+ try: raise RuntimeError,`t(array([123],'c'))`
+ except ValueError: pass
+ try: raise RuntimeError,`t('abc')`
+ except ValueError: pass
+
+ try: raise RuntimeError,`t([])`
+ except IndexError: pass
+ try: raise RuntimeError,`t(())`
+ except IndexError: pass
+
+ try: raise RuntimeError,`t(t)`
+ except TypeError: pass
+ try: raise RuntimeError,`t({})`
+ except TypeError: pass
+
+ if tname in ['t8','s8']:
+ try: raise RuntimeError,`t(100000000000000000000000l)`
+ except OverflowError: pass
+ try: raise RuntimeError,`t(10000000011111111111111.23)`
+ except OverflowError: pass
+ else:
+ if sys.version[:3]<='2.2':
+ try: raise RuntimeError,`t(10000000000000l)`
+ except OverflowError: pass
+ try: raise RuntimeError,`t(10000000000.23)`
+ except OverflowError: pass
+
+if __name__=='__main__':
+ #import libwadpy
+ status = 1
+ try:
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
+ status = 0
+ finally:
+ if status:
+ print '*'*20
+ print 'Running f2py2e.diagnose'
+ import f2py2e.diagnose
+ f2py2e.diagnose.run()
diff --git a/numpy/f2py/tests/f90/return_logical.py b/numpy/f2py/tests/f90/return_logical.py
new file mode 100644
index 000000000..c9479edaf
--- /dev/null
+++ b/numpy/f2py/tests/f90/return_logical.py
@@ -0,0 +1,138 @@
+
+__usage__ = """
+Run:
+ python return_logical.py [<f2py options>]
+Examples:
+ python return_logical.py --quiet
+"""
+
+import f2py2e
+from Numeric import array
+
+try: True
+except NameError:
+ True = 1
+ False = 0
+
+def build(f2py_opts):
+ try:
+ import f90_ext_return_logical
+ except ImportError:
+ assert not f2py2e.compile('''\
+module f90_return_logical
+ contains
+ function t0(value)
+ logical :: value
+ logical :: t0
+ t0 = value
+ end function t0
+ function t1(value)
+ logical(kind=1) :: value
+ logical(kind=1) :: t1
+ t1 = value
+ end function t1
+ function t2(value)
+ logical(kind=2) :: value
+ logical(kind=2) :: t2
+ t2 = value
+ end function t2
+ function t4(value)
+ logical(kind=4) :: value
+ logical(kind=4) :: t4
+ t4 = value
+ end function t4
+ function t8(value)
+ logical(kind=8) :: value
+ logical(kind=8) :: t8
+ t8 = value
+ end function t8
+
+ subroutine s0(t0,value)
+ logical :: value
+ logical :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s1(t1,value)
+ logical(kind=1) :: value
+ logical(kind=1) :: t1
+!f2py intent(out) t1
+ t1 = value
+ end subroutine s1
+ subroutine s2(t2,value)
+ logical(kind=2) :: value
+ logical(kind=2) :: t2
+!f2py intent(out) t2
+ t2 = value
+ end subroutine s2
+ subroutine s4(t4,value)
+ logical(kind=4) :: value
+ logical(kind=4) :: t4
+!f2py intent(out) t4
+ t4 = value
+ end subroutine s4
+ subroutine s8(t8,value)
+ logical(kind=8) :: value
+ logical(kind=8) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+end module f90_return_logical
+''','f90_ext_return_logical',f2py_opts,source_fn='f90_ret_log.f90')
+
+ from f90_ext_return_logical import f90_return_logical as m
+ test_functions = [m.t0,m.t1,m.t2,m.t4,m.t8,m.s0,m.s1,m.s2,m.s4,m.s8]
+ return test_functions
+
+
+
+
+def runtest(t):
+ assert t(True)==1,`t(True)`
+ assert t(False)==0,`t(False)`
+ assert t(0)==0
+ assert t(None)==0
+ assert t(0.0)==0
+ assert t(0j)==0
+ assert t(1j)==1
+ assert t(234)==1
+ assert t(234.6)==1
+ assert t(234l)==1
+ assert t(234.6+3j)==1
+ assert t('234')==1
+ assert t('aaa')==1
+ assert t('')==0
+ assert t([])==0
+ assert t(())==0
+ assert t({})==0
+ assert t(t)==1
+ assert t(-234)==1
+ assert t(10l**100)==1
+ assert t([234])==1
+ assert t((234,))==1
+ assert t(array(234))==1
+ assert t(array([234]))==1
+ assert t(array([[234]]))==1
+ assert t(array([234],'1'))==1
+ assert t(array([234],'s'))==1
+ assert t(array([234],'i'))==1
+ assert t(array([234],'l'))==1
+ assert t(array([234],'b'))==1
+ assert t(array([234],'f'))==1
+ assert t(array([234],'d'))==1
+ assert t(array([234+3j],'F'))==1
+ assert t(array([234],'D'))==1
+ assert t(array(0))==0
+ assert t(array([0]))==0
+ assert t(array([[0]]))==0
+ assert t(array([0j]))==0
+ assert t(array([1]))==1
+ assert t(array([0,0]))==0
+ assert t(array([0,1]))==1 #XXX: is this expected?
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/f90/return_real.py b/numpy/f2py/tests/f90/return_real.py
new file mode 100644
index 000000000..263e28165
--- /dev/null
+++ b/numpy/f2py/tests/f90/return_real.py
@@ -0,0 +1,129 @@
+__usage__ = """
+Run:
+ python return_real.py [<f2py options>]
+Examples:
+ python return_real.py --quiet
+"""
+
+import sys
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import f90_ext_return_real
+ except ImportError:
+ assert not f2py2e.compile('''\
+module f90_return_real
+ contains
+ function t0(value)
+ real :: value
+ real :: t0
+ t0 = value
+ end function t0
+ function t4(value)
+ real(kind=4) :: value
+ real(kind=4) :: t4
+ t4 = value
+ end function t4
+ function t8(value)
+ real(kind=8) :: value
+ real(kind=8) :: t8
+ t8 = value
+ end function t8
+ function td(value)
+ double precision :: value
+ double precision :: td
+ td = value
+ end function td
+
+ subroutine s0(t0,value)
+ real :: value
+ real :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s4(t4,value)
+ real(kind=4) :: value
+ real(kind=4) :: t4
+!f2py intent(out) t4
+ t4 = value
+ end subroutine s4
+ subroutine s8(t8,value)
+ real(kind=8) :: value
+ real(kind=8) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+ subroutine sd(td,value)
+ double precision :: value
+ double precision :: td
+!f2py intent(out) td
+ td = value
+ end subroutine sd
+end module f90_return_real
+''','f90_ext_return_real',f2py_opts,source_fn='f90_ret_real.f90')
+
+ from f90_ext_return_real import f90_return_real as m
+ test_functions = [m.t0,m.t4,m.t8,m.td,m.s0,m.s4,m.s8,m.sd]
+ return test_functions
+
+def runtest(t):
+ tname = t.__doc__.split()[0]
+ if tname in ['t0','t4','s0','s4']:
+ err = 1e-5
+ else:
+ err = 0.0
+ assert abs(t(234)-234.0)<=err
+ assert abs(t(234.6)-234.6)<=err
+ assert abs(t(234l)-234.0)<=err
+ if sys.version[:3]<='2.2':
+ assert abs(t(234.6+3j)-234.6)<=err,`t(234.6+3j)`
+ assert abs(t('234')-234)<=err
+ assert abs(t('234.6')-234.6)<=err
+ assert abs(t(-234)+234)<=err
+ assert abs(t([234])-234)<=err
+ assert abs(t((234,))-234.)<=err
+ assert abs(t(array(234))-234.)<=err
+ assert abs(t(array([234]))-234.)<=err
+ assert abs(t(array([[234]]))-234.)<=err
+ assert abs(t(array([234],'1'))+22)<=err
+ assert abs(t(array([234],'s'))-234.)<=err
+ assert abs(t(array([234],'i'))-234.)<=err
+ assert abs(t(array([234],'l'))-234.)<=err
+ assert abs(t(array([234],'b'))-234.)<=err
+ assert abs(t(array([234],'f'))-234.)<=err
+ assert abs(t(array([234],'d'))-234.)<=err
+ if sys.version[:3]<='2.2':
+ assert abs(t(array([234+3j],'F'))-234.)<=err,`t(array([234+3j],'F'))`
+ assert abs(t(array([234],'D'))-234.)<=err,`t(array([234],'D'))`
+ if tname in ['t0','t4','s0','s4']:
+ assert t(1e200)==t(1e300) # inf
+
+ try: raise RuntimeError,`t(array([234],'c'))`
+ except ValueError: pass
+ try: raise RuntimeError,`t('abc')`
+ except ValueError: pass
+
+ try: raise RuntimeError,`t([])`
+ except IndexError: pass
+ try: raise RuntimeError,`t(())`
+ except IndexError: pass
+
+ try: raise RuntimeError,`t(t)`
+ except TypeError: pass
+ try: raise RuntimeError,`t({})`
+ except TypeError: pass
+
+ try:
+ try: raise RuntimeError,`t(10l**400)`
+ except OverflowError: pass
+ except RuntimeError:
+ r = t(10l**400); assert `r` in ['inf','Infinity'],`r`
+
+if __name__=='__main__':
+ #import libwadpy
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/mixed/foo.f b/numpy/f2py/tests/mixed/foo.f
new file mode 100644
index 000000000..c34742578
--- /dev/null
+++ b/numpy/f2py/tests/mixed/foo.f
@@ -0,0 +1,5 @@
+ subroutine bar11(a)
+cf2py intent(out) a
+ integer a
+ a = 11
+ end
diff --git a/numpy/f2py/tests/mixed/foo_fixed.f90 b/numpy/f2py/tests/mixed/foo_fixed.f90
new file mode 100644
index 000000000..7543a6acb
--- /dev/null
+++ b/numpy/f2py/tests/mixed/foo_fixed.f90
@@ -0,0 +1,8 @@
+ module foo_fixed
+ contains
+ subroutine bar12(a)
+!f2py intent(out) a
+ integer a
+ a = 12
+ end subroutine bar12
+ end module foo_fixed
diff --git a/numpy/f2py/tests/mixed/foo_free.f90 b/numpy/f2py/tests/mixed/foo_free.f90
new file mode 100644
index 000000000..c1b641f13
--- /dev/null
+++ b/numpy/f2py/tests/mixed/foo_free.f90
@@ -0,0 +1,8 @@
+module foo_free
+contains
+ subroutine bar13(a)
+ !f2py intent(out) a
+ integer a
+ a = 13
+ end subroutine bar13
+end module foo_free
diff --git a/numpy/f2py/tests/mixed/run.py b/numpy/f2py/tests/mixed/run.py
new file mode 100644
index 000000000..6f4b7d444
--- /dev/null
+++ b/numpy/f2py/tests/mixed/run.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+__usage__ = """
+Run:
+ python run.py [<f2py options>]
+Examples:
+ python run.py --quiet
+"""
+
+import os
+import sys
+import string
+import f2py2e
+from Numeric import array
+
+def build(f2py_opts):
+ try:
+ import mixed_f77_f90
+ except:
+ d,b=os.path.split(sys.argv[0])
+ files = ['foo.f','foo_fixed.f90','foo_free.f90']
+ files = [os.path.join(d,f) for f in files]
+ files = string.join(files)
+ args = ' -c -m mixed_f77_f90 %s %s'%(files,f2py_opts)
+ c = '%s -c "import f2py2e;f2py2e.main()" %s' %(sys.executable,args)
+ s = os.system(c)
+ assert not s
+ from mixed_f77_f90 import bar11
+ test_functions = [bar11]
+ from mixed_f77_f90 import foo_fixed as m
+ test_functions.append(m.bar12)
+ from mixed_f77_f90 import foo_free as m
+ test_functions.append(m.bar13)
+ return test_functions
+
+def runtest(t):
+ tname = t.__doc__.split()[0]
+ if tname=='bar11':
+ assert t()==11
+ elif tname=='bar12':
+ assert t()==12
+ elif tname=='bar13':
+ assert t()==13
+ else:
+ raise NotImplementedError
+
+if __name__=='__main__':
+ repeat,f2py_opts = f2py2e.f2py_testing.cmdline()
+ test_functions = build(f2py_opts)
+ f2py2e.f2py_testing.run(runtest,test_functions,repeat)
+ print 'ok'
diff --git a/numpy/f2py/tests/run_all.py b/numpy/f2py/tests/run_all.py
new file mode 100755
index 000000000..016e68c29
--- /dev/null
+++ b/numpy/f2py/tests/run_all.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+
+import os,sys
+
+opts = sys.argv[1:]
+if not opts:
+ opts = ['10','--quiet']
+
+NUMARRAY = "-DNUMARRAY" in sys.argv
+
+test_f77_files = [\
+ 'f77/return_integer.py',
+ 'f77/return_logical.py',
+ 'f77/return_real.py',
+ 'f77/return_complex.py',
+ 'f77/callback.py',
+ ]
+
+if not NUMARRAY: # no support for character yet in numarray
+ test_f77_files.append('f77/return_character.py')
+
+test_f90_files = [\
+ 'f90/return_integer.py',
+ 'f90/return_logical.py',
+ 'f90/return_real.py',
+ 'f90/return_complex.py',
+ 'f90/return_character.py',
+ 'mixed/run.py',
+ ]
+
+test_files = test_f77_files
+
+if NUMARRAY:
+ print >>sys.stderr,"NOTE: f2py for numarray does not support"\
+ " f90 or character arrays."
+else:
+ test_files += test_f90_files
+
+py_path = os.environ.get('PYTHONPATH')
+if py_path is None:
+ py_path = '.'
+else:
+ py_path = os.pathsep.join(['.',py_path])
+os.environ['PYTHONPATH'] = py_path
+
+for f in test_files:
+ print "**********************************************"
+ ff = os.path.join(sys.path[0],f)
+ args = [sys.executable,ff]+opts
+ print "Running",' '.join(args)
+ status = os.spawnve(os.P_WAIT,sys.executable,args,os.environ)
+ if status:
+ print 'TEST FAILURE (status=%s)' % (status)
+ if f=='f90/return_integer.py':
+ sys.exit()
diff --git a/numpy/f2py/use_rules.py b/numpy/f2py/use_rules.py
new file mode 100644
index 000000000..8affcbe41
--- /dev/null
+++ b/numpy/f2py/use_rules.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+"""
+
+Build 'use others module data' mechanism for f2py2e.
+
+Unfinished.
+
+Copyright 2000 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 LGPL. See http://www.fsf.org
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2000/09/10 12:35:43 $
+Pearu Peterson
+"""
+
+__version__ = "$Revision: 1.3 $"[10:-1]
+
+f2py_version='See `f2py -v`'
+
+import pprint
+import sys,string,time,types,copy
+errmess=sys.stderr.write
+outmess=sys.stdout.write
+show=pprint.pprint
+
+from auxfuncs import *
+import capi_maps
+import cfuncs
+##############
+
+usemodule_rules={
+ 'body':"""
+#begintitle#
+static char doc_#apiname#[] = \"\\\nVariable wrapper signature:\\n\\
+\t #name# = get_#name#()\\n\\
+Arguments:\\n\\
+#docstr#\";
+extern F_MODFUNC(#usemodulename#,#USEMODULENAME#,#realname#,#REALNAME#);
+static PyObject *#apiname#(PyObject *capi_self, PyObject *capi_args) {
+/*#decl#*/
+\tif (!PyArg_ParseTuple(capi_args, \"\")) goto capi_fail;
+printf(\"c: %d\\n\",F_MODFUNC(#usemodulename#,#USEMODULENAME#,#realname#,#REALNAME#));
+\treturn Py_BuildValue(\"\");
+capi_fail:
+\treturn NULL;
+}
+""",
+ 'method':'\t{\"get_#name#\",#apiname#,METH_VARARGS|METH_KEYWORDS,doc_#apiname#},',
+ 'need':['F_MODFUNC']
+ }
+
+################
+
+def buildusevars(m,r):
+ ret={}
+ outmess('\t\tBuilding use variable hooks for module "%s" (feature only for F90/F95)...\n'%(m['name']))
+ varsmap={}
+ revmap={}
+ if r.has_key('map'):
+ for k in r['map'].keys():
+ if revmap.has_key(r['map'][k]):
+ outmess('\t\t\tVariable "%s<=%s" is already mapped by "%s". Skipping.\n'%(r['map'][k],k,revmap[r['map'][k]]))
+ else:
+ revmap[r['map'][k]]=k
+ if r.has_key('only') and r['only']:
+ for v in r['map'].keys():
+ if m['vars'].has_key(r['map'][v]):
+
+ if revmap[r['map'][v]]==v:
+ varsmap[v]=r['map'][v]
+ else:
+ outmess('\t\t\tIgnoring map "%s=>%s". See above.\n'%(v,r['map'][v]))
+ else:
+ outmess('\t\t\tNo definition for variable "%s=>%s". Skipping.\n'%(v,r['map'][v]))
+ else:
+ for v in m['vars'].keys():
+ if revmap.has_key(v):
+ varsmap[v]=revmap[v]
+ else:
+ varsmap[v]=v
+ for v in varsmap.keys():
+ ret=dictappend(ret,buildusevar(v,varsmap[v],m['vars'],m['name']))
+ return ret
+def buildusevar(name,realname,vars,usemodulename):
+ outmess('\t\t\tConstructing wrapper function for variable "%s=>%s"...\n'%(name,realname))
+ ret={}
+ vrd={'name':name,
+ 'realname':realname,
+ 'REALNAME':string.upper(realname),
+ 'usemodulename':usemodulename,
+ 'USEMODULENAME':string.upper(usemodulename),
+ 'texname':string.replace(name,'_','\\_'),
+ 'begintitle':gentitle('%s=>%s'%(name,realname)),
+ 'endtitle':gentitle('end of %s=>%s'%(name,realname)),
+ 'apiname':'#modulename#_use_%s_from_%s'%(realname,usemodulename)
+ }
+ nummap={0:'Ro',1:'Ri',2:'Rii',3:'Riii',4:'Riv',5:'Rv',6:'Rvi',7:'Rvii',8:'Rviii',9:'Rix'}
+ vrd['texnamename']=name
+ for i in nummap.keys():
+ vrd['texnamename']=string.replace(vrd['texnamename'],`i`,nummap[i])
+ if hasnote(vars[realname]): vrd['note']=vars[realname]['note']
+ rd=dictappend({},vrd)
+ var=vars[realname]
+
+ print name,realname,vars[realname]
+ ret=applyrules(usemodule_rules,rd)
+ return ret
+
+
+
+
+
+