在IPython笔记本中使用fortranmagic排序数组:没有返回值
我得说,我根本不是一个Fortran程序员。我通常只用Python和C++,不过有时候同事们写了一些很棒的Fortran函数,如果能在我的Python代码中用上,那效率会更高。我正准备通过IPython的魔法函数尝试一下f2py模块。
为了做一个简单的测试,我有一个冒泡排序的实现,我想在原地对一个Python列表进行排序(我把它转换成了一个按照Fortran风格在内存中排列的numpy数组;我想这样会比用Python列表更高效,对吧?)
不过,这个函数没有返回值(None
),我在想我哪里出错了!?
安装和加载fortranmagic(使用f2py)的命令:
%install_ext https://raw.github.com/mgaitan/fortran_magic/master/fortranmagic.py
%load_ext fortranmagic
Fortran的冒泡排序代码:
%%fortran
SUBROUTINE fortran_bubblesort(a)
REAL, INTENT(in out), DIMENSION(:) :: a
REAL :: temp
INTEGER :: i, j
LOGICAL :: swapped = .TRUE.
DO j = SIZE(a)-1, 1, -1
swapped = .FALSE.
DO i = 1, j
IF (a(i) > a(i+1)) THEN
temp = a(i)
a(i) = a(i+1)
a(i+1) = temp
swapped = .TRUE.
END IF
END DO
IF (.NOT. swapped) EXIT
END DO
END SUBROUTINE fortran_bubblesort
执行结果:
x = np.asfortranarray([3,2,1])
y = fortran_bubblesort(x)
print(x, y)
结果:
[3 2 1] None
========
为了测试一般情况下是否能返回一个值,我运行了以下代码,结果很好:
%%fortran
SUBROUTINE fortran_sum(x, y, z)
REAL, INTENT(in) :: x,y
REAL, INTENT(out) :: z
z = x + y
END SUBROUTINE fortran_sum
执行:
fortran_sum(3, 4)
返回:
7.0
2 个回答
0
我把问题中的原始Fortran代码搞定了,只需要把两个"REAL"的语句换成"REAL(kind=8)"的语句。这样一来,Fortran的变量就和Python的变量对上了。
另外,为了让程序能正常运行,避免输出"None",我建议加上以下几行(注意我把整数输入改成了浮点数,以确保匹配正确):
import numpy as np
x = np.asfortranarray([3.,0., 2.,1.])
print(x)
fortran_bubblesort(x)
print(x)
执行结果:
[ 3. 0. 2. 1.]
[ 0. 1. 2. 3.]
我还加了数字零,让它看起来更像Python的风格;-)
0
你遇到的问题跟数组的维度有关。看起来这个子程序是从一个模块中提取出来的,因为它使用了一个假定形状的虚拟数组 a
。这就需要一个明确的接口,而我不太清楚 f2py
是怎么处理这个的。我之前只用过 f2py
来处理假定大小的虚拟数组,这个它处理得很好。下面是代码:
SUBROUTINE fortran_bubblesort(a,n)
INTEGER, INTENT(in) :: n
REAL, INTENT(in out), DIMENSION(n) :: a
REAL :: temp
INTEGER :: i, j
LOGICAL :: swapped = .TRUE.
DO j = SIZE(a)-1, 1, -1
swapped = .FALSE.
DO i = 1, j
IF (a(i) > a(i+1)) THEN
temp = a(i)
a(i) = a(i+1)
a(i+1) = temp
swapped = .TRUE.
END IF
END DO
IF (.NOT. swapped) EXIT
END DO
END SUBROUTINE fortran_bubblesort
在这种情况下,f2py
会注意到 n
只是数组的维度,它会把这个参数变成 Python 函数中的一个可选参数。