The HPF/F90 program...
integer n
parameter(n = 8)
real u(n, n)
!hpf$ distribute u (block, block) onto p
!hpf$ processors p (2, 2)
integer i, j
integer iter
do i = 1, n
do j = 1, n
if(i == 1 .or. i == n .or. j == 1 .or. j == n) then
u(i, j) = 1.0
else
u(i, j) = 0.0
endif
enddo
enddo
do iter = 1, 5
u(2 : n - 1, 2 : n - 1) = &
0.25 * (u(2 : n - 1, 1 : n - 2) + u(2 : n - 1, 3 : n) + &
u(1 : n - 2, 2 : n - 1) + u(3 : n, 2 : n - 1))
enddo
end
could be translated as...
final integer n = 8 ;
Procs p = new Procs(2, 2) ;
Range x = new Range(n, BLK, p.dim(0)) ;
Range y = new Range(n, BLK, p.dim(1)) ;
ArrayFloat u = new ArrayFloat(x, y) ;
ArrayInt mask = new ArrayInt(x, y) ;
mask = x.gt(0).and(x.lt(n - 1)).and(y.gt(0)).and(y.lt(n - 1)) ;
u.where(mask, 0.0, 1.0) ;
ArrayFloat tmp1 = new ArrayFloat(x, y) ;
ArrayFloat tmp2 = new ArrayFloat(x, y) ;
ArrayFloat tmp3 = new ArrayFloat(x, y) ;
ArrayFloat tmp4 = new ArrayFloat(x, y) ;
for(int iter = 1 ; iter <= 5 ; iter++) {
tmp1.shift(u, -1, 0) ;
tmp2.shift(u, 1, 0) ;
tmp4.shift(u, -1, 1) ;
tmp3.shift(u, 1, 1) ;
u.where(mask, tmp1.plus(tmp2).plus(tmp3).plus(tmp4).
times(0.25)) ;
// where(mask) u = 0.25 * (tmp1 + tmp2 + tmp3 + tmp4)
}
This assumes that the arithmetic members on arrays include boolean
arithmetic, and that two variants of masked assignment (where) are
provided (one with two arguments corresponds to F90 simple WHERE;
one with three arguments corresponds to F90 WHERE/ELSEWHERE).
Variation: the where operation in the loop could be replaced
by use of sections...
Range i = x.sub(1, n - 2) ; // subrange 1 : n - 2
Range j = y.sub(1, n - 2) ; // subrange 1 : n - 2
...
u.sect(i, j).assign(tmp1.sect(i, j).plus(tmp2.sect(i, j)).
plus(tmp3.sect(i, j)).plus(tmp4.sect(i, j)).
times(0.25)) ;
// u(2 : n - 1, 2 : n - 1) = 0.25 *
// (tmp1(2 : n - 1, 2 : n - 1) +
// tmp2(2 : n - 1, 2 : n - 1) +
// tmp3(2 : n - 1, 2 : n - 1) +
// tmp4(2 : n - 1, 2 : n - 1))
Variation: the shift operations could be replaced by remap
operations...
ArrayFloat tmp1 = new ArrayFloat(i, j) ;
ArrayFloat tmp2 = new ArrayFloat(i, j) ;
ArrayFloat tmp3 = new ArrayFloat(i, j) ;
ArrayFloat tmp4 = new ArrayFloat(i, j) ;
...
tmp1.remap(u.sect(x.sub(2, n - 1), j)) ;
tmp2.remap(u.sect(x.sub(0, n - 3), j)) ;
tmp3.remap(u.sect(i, y.sub(2, n - 1))) ;
tmp4.remap(u.sect(i, y.sub(0, n - 3))) ;
// tmp3 = u(1 : n - 2, 2 : n - 1)
// tmp2 = u(0 : n - 3, 1 : n - 2)
// tmp1 = u(2 : n - 1, 1 : n - 2)
// tmp4 = u(1 : n - 2, 0 : n - 3)
u.sect(i, j).assign(tmp1.plus(tmp2).plus(tmp3).plus(tmp4).
times(0.25)) ;
// u(2 : n - 1, 2 : n - 1) = 0.25 *
// (tmp1 + tmp2 + tmp3 + tmp4)
This corresponds more directly to the original Fortran which uses
arithmetic on array sections, rather than shift operations.