2016-12-31 64 views
1

如果我打算將一個布爾型的NumPy數組與f2py一起傳遞給Fortran變量,應該如何輸入?我已嘗試integer*1logical*1,但這些都表明數組已被複制。傳遞布爾數組而不用`f2py`複製?

例如,如果我編譯文件,foo.f95,包含:

subroutine foo(x, n) 
    logical*1 x(n) 
    !f2py intent(in) x 
    !f2py intent(hide), depend(x) :: n=shape(x,0) 
    ... 
end subroutine 

f2py -c -m foo foo.f90 -DF2PY_REPORT_ON_ARRAY_COPY=1和運行是這樣的:

import numpy as np 
import foo 
x = np.random.randn(100) < 0 
foo.foo(x) 

它打印

copied an array: size=100, elsize=1 

我得到的如果我將logical*1更改爲,結果相同。什麼是Fortran文件中布爾數組的適當類型,以便數組不被複制?

請注意,由於陣列是1D,因此這不是存儲器連續性的問題 - foo.foo(np.asfortranarray(x))會打印相同的副本消息。

+0

[This fortran 95 guide](http://northstar-www.dartmouth.edu/doc/solaris-forte/manuals/fortran/user_guide/C_f95.html)說邏輯* 1是一個字節的邏輯類型。使用'邏輯'給出相同的信息。 –

+0

那麼,這個人不是一個標準的文件。 francescalus是對的,'*'語法只是字符類型的標準。但可能它不會改變太多。 –

回答

2

從一些實驗(*)看來,Python/f2py認爲np.int8logical*1兼容,而np.boolnp.bool8不是由於某些原因。插入print *, "(fort) x = ", x成foo.f90後,我們得到:

>>> foo.foo(np.array([ True, False, False ], dtype=np.bool)) 
copied an array: size=3, elsize=1 
(fort) x = T F F 
>>> foo.foo(np.array([ False, True, False ], dtype=np.bool8)) 
copied an array: size=3, elsize=1 
(fort) x = F T F 
>>> foo.foo(np.array([ False, False, True ], dtype=np.int8)) # no copy 
(fort) x = F F T 

由於TrueFalse被簡單地映射到1和0,使用在Python端的int8陣列可以是方便。


(*)一些實驗

在這裏,我改變了f2py意圖註釋inout,看看我們是否可以從Fortran語言方面修改數組。

foo.f90:

subroutine foo(x, n) 
    use iso_c_binding 
    implicit none 
    integer n 
    logical*1 x(n) 
    ! logical x(n) 
    ! logical(c_bool) x(n) 

    !f2py intent(inout) x 
    !f2py intent(hide), depend(x) :: n=shape(x,0) 

    print *, "(fort) x = ", x 
    print *, "(fort) sizeof(x(1)) = ", sizeof(x(1)) 
    print *, "(fort) resetting x(:) to true" 
    x(:) = .true. 
end subroutine 

test.py:

import numpy as np 
import foo 

for T in [ np.bool, np.bool8, 
      np.int, np.int8, np.int32, np.int64, 
      np.uint, np.uint8, np.uint32, np.uint64, 
      np.dtype('b'), np.dtype('int8'), np.dtype('int32') ]: 

    print("-------------------------") 
    print("dtype =", T) 

    x = np.array([ True, False, True ], dtype=T) 
    print("input x =", x) 

    try: 
     foo.foo(x) 
     print("output x =", x) 
    except: 
     print("failed") 

結果與logical*1

------------------------- 
dtype = <class 'bool'> 
input x = [ True False True] 
failed 
------------------------- 
dtype = <class 'numpy.bool_'> 
input x = [ True False True] 
failed 
------------------------- 
dtype = <class 'int'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.int8'> 
input x = [1 0 1] 
(fort) x = T F T 
(fort) sizeof(x(1)) =      1 
(fort) resetting x(:) to true 
output x = [1 1 1] 
------------------------- 
dtype = <class 'numpy.int32'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.int64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint8'> 
input x = [1 0 1] 
(fort) x = T F T 
(fort) sizeof(x(1)) =      1 
(fort) resetting x(:) to true 
output x = [1 1 1] 
------------------------- 
dtype = <class 'numpy.uint32'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = int8 
input x = [1 0 1] 
(fort) x = T F T 
(fort) sizeof(x(1)) =      1 
(fort) resetting x(:) to true 
output x = [1 1 1] 
------------------------- 
dtype = int8 
input x = [1 0 1] 
(fort) x = T F T 
(fort) sizeof(x(1)) =      1 
(fort) resetting x(:) to true 
output x = [1 1 1] 
------------------------- 
dtype = int32 
input x = [1 0 1] 
failed 

結果與logical(默認的那種):

------------------------- 
dtype = <class 'bool'> 
input x = [ True False True] 
failed 
------------------------- 
dtype = <class 'numpy.bool_'> 
input x = [ True False True] 
failed 
------------------------- 
dtype = <class 'int'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.int8'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.int32'> 
input x = [1 0 1] 
(fort) x = T F T 
(fort) sizeof(x(1)) =      4 
(fort) resetting x(:) to true 
output x = [1 1 1] 
------------------------- 
dtype = <class 'numpy.int64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint8'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint32'> 
input x = [1 0 1] 
(fort) x = T F T 
(fort) sizeof(x(1)) =      4 
(fort) resetting x(:) to true 
output x = [1 1 1] 
------------------------- 
dtype = <class 'numpy.uint64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = int8 
input x = [1 0 1] 
failed 
------------------------- 
dtype = int8 
input x = [1 0 1] 
failed 
------------------------- 
dtype = int32 
input x = [1 0 1] 
(fort) x = T F T 
(fort) sizeof(x(1)) =      4 
(fort) resetting x(:) to true 
output x = [1 1 1] 

結果與logical(c_bool)(通過ISO_C_BINDING):

------------------------- 
dtype = <class 'bool'> 
input x = [ True False True] 
failed 
------------------------- 
dtype = <class 'numpy.bool_'> 
input x = [ True False True] 
failed 
------------------------- 
dtype = <class 'int'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.int8'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.int32'> 
input x = [1 0 1] 
(fort) x = T F F 
(fort) sizeof(x(1)) =      1 
(fort) resetting x(:) to true 
output x = [65793  0  1] 
------------------------- 
dtype = <class 'numpy.int64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint8'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = <class 'numpy.uint32'> 
input x = [1 0 1] 
(fort) x = T F F 
(fort) sizeof(x(1)) =      1 
(fort) resetting x(:) to true 
output x = [65793  0  1] 
------------------------- 
dtype = <class 'numpy.uint64'> 
input x = [1 0 1] 
failed 
------------------------- 
dtype = int8 
input x = [1 0 1] 
failed 
------------------------- 
dtype = int8 
input x = [1 0 1] 
failed 
------------------------- 
dtype = int32 
input x = [1 0 1] 
(fort) x = T F F 
(fort) sizeof(x(1)) =      1 
(fort) resetting x(:) to true 
output x = [65793  0  1] 

出於某種原因,這最後logical(c_bool)不符合上述使用工作...(f2py似乎認爲logical(c_bool)爲4個字節,而gfortran對待它作爲1個字節,所以有些不一致......)

+0

嗯。我認爲我只會在兩端使用'int'類型! –