Hy all,
As a test case before writing something bigger, I'm trying to write a little
Fortran module to compute the average of a array in these 4 cases:
avg2d_float, avg2d_double
avg3d_float, avg3d_double
I want this module to be callable from both Fortran and Python, using f2py.
4 Fortran functions have to be written, and a generic Fortran function 'avg'
overloads its.
The Fortran module 'stat.f90' (containing the functions), a Fortran program
'stat_example.f90' and a Python script 'stat_example.py' are at the end of
the email.
(everything works fine: the compilation, f2py, the execution in Python and
in Fortran.)
My questions are:
- Assumed shape array are not supported by f2py. However, it is much more
handy to write in Fortran 'avg(array)' than 'avg(array,n1,n2,n3)'. Would it
be possible to supported it by modifying the signature files?
- Is there a way to avoid to write by hand the 'avg' Python function (in
example_stat.py) ?
- Isn't there no way to declare private the functions: avg2d_float,
avg2d_double, avg3d_float,avg3d_double? It's embarassing its are visible
from stat_example.f90.
Uncommenting the lines in the top of the file stat.f90:
!private
!public:: avg
and running:
f2py -m f90stat -c stat.f90
give the error:
use stat, only : avg2d_float
Error: Symbol 'avg2d_float' referenced at (1) not found in module 'stat'
Thanks for any suggestion,
David
* to create the Fortran executable:
gfortran -c stat.f90
gfortran -c stat_example.f90
gfortran -o stat_example.x stat.o stat_example.o
* to create the Python module:
f2py -m f90stat -c stat.f90
* The Fortran module is:
"""
!file stat.f90
module stat
implicit none
!private
!public:: avg
interface avg
module procedure avg2d_float, avg2d_double, avg3d_float, avg3d_double
end interface
contains
function avg2d_float(array,n1,n2) result(average)
implicit none
real(kind=4):: average
integer:: n1,n2
real(kind=4),dimension(n1,n2),intent(in):: array
average = sum(array)
average = average / n1
average = average / n2
end function avg2d_float
function avg2d_double(array,n1,n2) result(average)
implicit none
real(kind=8):: average
integer:: n1,n2
real(kind=8),dimension(n1,n2),intent(in):: array
average = sum(array)
average = average / n1
average = average / n2
end function avg2d_double
function avg3d_float(array,n1,n2,n3) result(average)
implicit none
real(kind=4):: average
integer:: n1,n2,n3
real(kind=4),dimension(n1,n2,n3),intent(in):: array
average = sum(array)
average = average / n1
average = average / n2
average = average / n3
end function avg3d_float
function avg3d_double(array,n1,n2,n3) result(average)
implicit none
real(kind=8):: average
integer:: n1,n2,n3
real(kind=8),dimension(n1,n2,n3),intent(in):: array
average = sum(array)
average = average / n1
average = average / n2
average = average / n3
end function avg3d_double
end module stat
"""
* The Fortran program is:
"""
!file: stat_example.f90
program stat_example
use stat
implicit none
integer,parameter:: n1=10,n2=10,n3=10
real(kind=4),dimension(n1,n2):: array2d_float
real(kind=8),dimension(n1,n2):: array2d_double
real(kind=4),dimension(n1,n2,n3):: array3d_float
real(kind=8),dimension(n1,n2,n3):: array3d_double
array2d_float = 4.
array2d_double = 4.
array3d_float = 4.
array3d_double = 4.
write(*,*) avg(array2d_float,n1,n2)
write(*,*) avg(array2d_double,n1,n2)
write(*,*) avg(array3d_float,n1,n2,n3)
write(*,*) avg(array3d_double,n1,n2,n3)
write(*,*) avg2d_float(array2d_float,n1,n2)
end program stat_example
"""
* The Python script is:
"""
#!/usr/bin/env python
#file stat_example.py
import numpy as np
import f90stat
def avg(a):
if a.ndim == 2:
if a.dtype == 'float32':
return f90stat.stat.avg2d_float(a)
elif a.dtype == 'float64' :
return f90stat.stat.avg2d_double(a)
else:
raise ValueError, 'dtype = %r unsupported.' % (a.dtype)
elif a.ndim == 3:
if a.dtype == 'float32':
return f90stat.stat.avg3d_float(a)
elif a.dtype == 'float64' :
return f90stat.stat.avg3d_double(a)
else:
raise ValueError, 'dtype = %r unsupported.' % (a.dtype)
else:
raise ValueError, 'ndim = %r unsupported.' % (a.ndim)
if __name__ == '__main__':
a = np.arange(6.)
a = a.reshape(2,3)
print avg(a)
"""