其他语言模板更新的对应物
Counterpart of stencil update in other languages
我发现真正有趣的是 Fortrans 的模板更新功能:而不是循环
t2 = v(1)
do i=2, n-1
t1 = v(i)
v(i) = 0.5 * (t2 + v(i+1))
t2 = t1
enddo
可以使用单行,无需显式循环
v(2:n-1) = 0.5 * (v(1:n-2) + v(3:n))
(有关此示例和其他示例,请参见 this slideshow)
我在任何其他编程语言中都没有类似的东西。是否有任何其他语言支持类似的语法?
查看 Array programming 的 wiki 页面可能会很有趣,上面写着
Modern programming languages that support array programming are commonly used in scientific and engineering settings; these include Fortran 90, Mata, MATLAB, Analytica, TK Solver (as lists), Octave, R, Cilk Plus, Julia, and the NumPy extension to Python...
还有 array slicing and a list of array languages 的页面。因此,几种语言似乎具有相似的语法(可以追溯到 ALGOL68 时代?!)
举例如下(可能有错误,请自行核对..):
语言:
program main
implicit none
real, allocatable :: v(:)
integer i, n
n = 8
v = [( real(i)**2, i=1,n )]
print *, "v = ", v
v(2:n-1) = 0.5 * ( v(1:n-2) + v(3:n) )
print *, "v = ", v
end
$ gfortran test.f90 && ./a.out
v = 1.00000000 4.00000000 9.00000000 16.0000000 25.0000000 36.0000000 49.0000000 64.0000000
v = 1.00000000 5.00000000 10.0000000 17.0000000 26.0000000 37.0000000 50.0000000 64.0000000
Python:
import numpy as np
n = 8
v = np.array( [ float(i+1)**2 for i in range( n ) ] )
print( "v = ", v )
v[1:n-1] = 0.5 * ( v[0:n-2] + v[2:n] )
print( "v = ", v )
$ python3 test.py
v = [ 1. 4. 9. 16. 25. 36. 49. 64.]
v = [ 1. 5. 10. 17. 26. 37. 50. 64.]
茱莉亚:
n = 8
v = Float64[ i^2 for i = 1 : n ]
println( "v = ", v )
v[2:n-1] = 0.5 * ( v[1:n-2] + v[3:n] )
println( "v = ", v )
$ julia test.jl
v = [1.0,4.0,9.0,16.0,25.0,36.0,49.0,64.0]
v = [1.0,5.0,10.0,17.0,26.0,37.0,50.0,64.0]
礼拜堂:
var n = 8;
var v = ( for i in 1..n do (i:real)**2 );
writeln( "v = ", v );
var vtmp = 0.5 * ( v[1..n-2] + v[3..n] );
v[2..n-1] = vtmp;
writeln( "v = ", v );
$ chpl test.chpl && ./a.out
v = 1.0 4.0 9.0 16.0 25.0 36.0 49.0 64.0
v = 1.0 5.0 10.0 17.0 26.0 37.0 50.0 64.0
(请查看其他语言的 wiki 页面等)。
我觉得:
或..
这样的数组表示法很方便,但是会给出意想不到的结果(如果使用不当,例如,索引的含义,或者可能的重叠LHS/RHS) 或导致 run-time 开销(因为临时数组),视情况而定。所以实际使用的时候请注意...
我发现真正有趣的是 Fortrans 的模板更新功能:而不是循环
t2 = v(1)
do i=2, n-1
t1 = v(i)
v(i) = 0.5 * (t2 + v(i+1))
t2 = t1
enddo
可以使用单行,无需显式循环
v(2:n-1) = 0.5 * (v(1:n-2) + v(3:n))
(有关此示例和其他示例,请参见 this slideshow)
我在任何其他编程语言中都没有类似的东西。是否有任何其他语言支持类似的语法?
查看 Array programming 的 wiki 页面可能会很有趣,上面写着
Modern programming languages that support array programming are commonly used in scientific and engineering settings; these include Fortran 90, Mata, MATLAB, Analytica, TK Solver (as lists), Octave, R, Cilk Plus, Julia, and the NumPy extension to Python...
还有 array slicing and a list of array languages 的页面。因此,几种语言似乎具有相似的语法(可以追溯到 ALGOL68 时代?!)
举例如下(可能有错误,请自行核对..):
语言:
program main
implicit none
real, allocatable :: v(:)
integer i, n
n = 8
v = [( real(i)**2, i=1,n )]
print *, "v = ", v
v(2:n-1) = 0.5 * ( v(1:n-2) + v(3:n) )
print *, "v = ", v
end
$ gfortran test.f90 && ./a.out
v = 1.00000000 4.00000000 9.00000000 16.0000000 25.0000000 36.0000000 49.0000000 64.0000000
v = 1.00000000 5.00000000 10.0000000 17.0000000 26.0000000 37.0000000 50.0000000 64.0000000
Python:
import numpy as np
n = 8
v = np.array( [ float(i+1)**2 for i in range( n ) ] )
print( "v = ", v )
v[1:n-1] = 0.5 * ( v[0:n-2] + v[2:n] )
print( "v = ", v )
$ python3 test.py
v = [ 1. 4. 9. 16. 25. 36. 49. 64.]
v = [ 1. 5. 10. 17. 26. 37. 50. 64.]
茱莉亚:
n = 8
v = Float64[ i^2 for i = 1 : n ]
println( "v = ", v )
v[2:n-1] = 0.5 * ( v[1:n-2] + v[3:n] )
println( "v = ", v )
$ julia test.jl
v = [1.0,4.0,9.0,16.0,25.0,36.0,49.0,64.0]
v = [1.0,5.0,10.0,17.0,26.0,37.0,50.0,64.0]
礼拜堂:
var n = 8;
var v = ( for i in 1..n do (i:real)**2 );
writeln( "v = ", v );
var vtmp = 0.5 * ( v[1..n-2] + v[3..n] );
v[2..n-1] = vtmp;
writeln( "v = ", v );
$ chpl test.chpl && ./a.out
v = 1.0 4.0 9.0 16.0 25.0 36.0 49.0 64.0
v = 1.0 5.0 10.0 17.0 26.0 37.0 50.0 64.0
(请查看其他语言的 wiki 页面等)。
我觉得:
或..
这样的数组表示法很方便,但是会给出意想不到的结果(如果使用不当,例如,索引的含义,或者可能的重叠LHS/RHS) 或导致 run-time 开销(因为临时数组),视情况而定。所以实际使用的时候请注意...