How should Fortran variables be typed if I intend to pass them a boolean, NumPy array with f2py
? I have tried both integer*1
and logical*1
, but these both indicate that the array is copied.
For example, if I compile the file, foo.f95
, containing:
subroutine foo(x, n)
logical*1 x(n)
!f2py intent(in) x
!f2py intent(hide), depend(x) :: n=shape(x,0)
...
end subroutine
with f2py -c -m foo foo.f90 -DF2PY_REPORT_ON_ARRAY_COPY=1
and run something like:
import numpy as np
import foo
x = np.random.randn(100) < 0
foo.foo(x)
it prints
copied an array: size=100, elsize=1
I get the same result if I change logical*1
to integer*1
. What is the proper type for the boolean array in the Fortran file, so that the array is not copied?
Note that this is not a problem of memory contiguity since the arrays are 1D -- foo.foo(np.asfortranarray(x))
prints the same copy message.
From some experiments(*), it seems that Python/f2py treats
np.int8
as compatible withlogical*1
, whilenp.bool
ornp.bool8
not for some reason. After insertingprint *, "(fort) x = ", x
into foo.f90, we get:Because
True
andFalse
are simply mapped to 1 and 0, using anint8
array on the Python side may be convenient.(*) Some experiments
Here, I changed the f2py intent comment to
inout
to see whether we can modify the array from the Fortran side.foo.f90:
test.py:
Results with
logical*1
:Results with
logical
(default kind):Results with
logical(c_bool)
(via iso_c_binding):For some reason, this last
logical(c_bool)
does not work with the above usage... (f2py seems to considerlogical(c_bool)
as 4 bytes, while gfortran treats it as 1 byte, so something is inconsistent...)