Search code examples
fortranprogramming-languages

Counterpart of stencil update in other languages


What I find really interesting is Fortrans's capability of stencil updates: instead of looping

t2 = v(1)
do i=2, n-1
    t1   = v(i)
    v(i) = 0.5 * (t2 + v(i+1))
    t2   = t1
enddo

one can use a one-liner, without an explicit loop

v(2:n-1) = 0.5 * (v(1:n-2) + v(3:n))

(For this, and other examples see this slideshow)

I haven't anything similar in any other programming language. Is there any other language which supports a similar syntax?


Solution

  • It may be interesting to check the wiki page for Array programming, which says

    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...

    and also pages for array slicing and a list of array languages. So, several languages seem to have a similar syntax (which goes back to as old as ALGOL68 ?!)

    Here are some examples (there may be mistakes so please check by yourself..):

    Fortran :

    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.]
    

    Julia:

    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]
    

    Chapel:

    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
    

    (please see wiki pages etc for other languages).

    I think the array notation such as : or .. is very convenient, but it can give unexpected results (if not used properly, e.g., the meaning of indices, or a possible overlap of LHS/RHS) or cause run-time overhead (because of temporary arrays), depending on cases. So please take care when actually using it...