f90wrap
f90wrap copied to clipboard
f90wrap always chooses single precision Fortran function from interface with single and double precision routines
Dear James,
this really bugs me because it was a requirement here that all routines exist in a single and in a double precision version. The test code is:
module itestit
implicit none
private
public :: testit
interface testit
module procedure testit_dp, testit_sp
end interface testit
integer, parameter :: sp = kind(1.0)
integer, parameter :: dp = kind(1.0d0)
contains
function testit_dp(x)
implicit none
real(dp), dimension(:), intent(in) :: x
real(dp) :: testit_dp
testit_dp = sum(2.0_dp * x)
end function testit_dp
function testit_sp(x)
implicit none
real(sp), dimension(:), intent(in) :: x
real(sp) :: testit_sp
testit_sp = sum(1.0_sp * x)
end function testit_sp
end module itestit
Here, the single precision version sums the input numbers and the double precision version gives double the outcome. So the two calls in Python should give 45 and 90:
from __future__ import division, absolute_import, print_function
import numpy as np
import test
a = np.arange(10, dtype=np.float32)
print(test.itestit.testit(a))
a = np.arange(10, dtype=np.float64)
print(test.itestit.testit(a))
But it returns 45 in both cases. I was thinking that changing the order in the interface or in the file might change, which module procedure it takes, but it always returns 45, i.e. it takes the single precision version.
Kind regards Matthias
You can choose the type mapping in the file kind_map
. I am not quite sure if this will solve your question. You can check one of the examples.
Dear Caoxiang,
thanks for the feedback. You are correct. I normally have always the following kind map:
# file: kind_map { 'real': {'': 'float', '4': 'float', 'sp': 'float', '8': 'double', 'dp': 'double', '16': 'long_double', 'qp': 'long_double'}, 'complex' : {'': 'complex_float', '4': 'complex_float', 'sp': 'complex_float', 'spc': 'complex_float', '8': 'complex_double', 'dp': 'complex_double', 'dpc': 'complex_double', '16': 'complex_long_double', 'qp': 'complex_long_double', 'qpc': 'complex_long_double'}, 'integer' : {'': 'int', 'i1': 'signed_char', 'i2': 'short', '4': 'int', 'i4': 'int', '8': 'long_long', 'i8': 'long_long'}, }
I then wrap with:
f90wrap -m itest -P -k kind_map main.f90 -v
This gives the file f90wrap_mai.f90: ` ! Module itestit defined in file main.f90
subroutine f90wrap_testit_dp(ret_testit_dp, x, n0) use itestit, only: testit implicit none
real(8), intent(out) :: ret_testit_dp
real(8), intent(in), dimension(n0) :: x
integer :: n0
!f2py intent(hide), depend(x) :: n0 = shape(x,0)
ret_testit_dp = testit(x=x)
end subroutine f90wrap_testit_dp
subroutine f90wrap_testit_sp(ret_testit_sp, x, n0) use itestit, only: testit implicit none
real(4), intent(out) :: ret_testit_sp
real(4), intent(in), dimension(n0) :: x
integer :: n0
!f2py intent(hide), depend(x) :: n0 = shape(x,0)
ret_testit_sp = testit(x=x)
end subroutine f90wrap_testit_sp
! End of module itestit defined in file main.f90 `
If I leave out the kind_map from the call to f90wrap, the numbers '8' in the function f90wrap_testit_dp
are '4', which is wrong.
Now the example gives 90 in case of 32 or 64 bit:
`
a = np.arange(10, dtype=np.float32)
print(itest.itestit.testit(a))
a = np.arange(10, dtype=np.float64) print(itest.itestit.testit(a)) ` That means it chooses the first routine of the interface no matter what.
I try to attach a very small zip file with the full example including the makefile.
Kind regards Matthias issue107_problem_choosing_the_right_precision.zip