Re: Examples of FORALL and nested FORALL
  Home FAQ Contact Sign in
comp.lang.fortran only
 
Advanced search
POPULAR GROUPS

more...

 Up
Re: Examples of FORALL and nested FORALL         

Group: comp.lang.fortran · Group Profile
Author: Tom Micevski
Date: Jan 19, 2007 19:49

Tom Micevski wrote:
> Steven G. Kargl wrote:
>> Anyone have code that uses FORALL and nested FORALLs that
>> they may be willing to permit the gfortran developers to use
>> in testing a bug fix and then optimization work?
>
> give me a few days (or so) and i'll try to email you something.
>
> note, though, i don't think that i'm doing anything too complex with my
> FORALLs (simple/masked assignments, user-defined pure functions) ---
> hopefully they'll still be useful.

here is my promised test program. i've just stripped down an old
program (but you could strip even more away, eg. data statements and
write statements). hope it's helpful.

in case the code gets wrapped by my news program, i've also uploaded it
here:
http://www.mytempdir.com/1176091

tom

program forall_test_flike
implicit none
integer, parameter :: rk = selected_real_kind(p=10,r=100) ! double precision
! test data (0.0 = missing data)
real(rk), parameter :: q1(30) = (/
34.1,45.1,38.5,60.9,75.4,71.6,365.7,93.1,49.0,98.2,516.9,&

51.6,361.1,75.5,0.0,26.7,30.4,29.7,49.0,45.9,50.0,18.5,73.4,26.1,92.4,71.0,48.0,0.0,1216.3,0.0
/)
real(rk), parameter :: q2(30) = (/
169.2,469.9,305.7,566.1,317.0,492.5,150.0,795.4,764.3,1372.9,&

3366.0,62.2,418.9,261.8,158.5,345.3,8516.7,206.6,71.3,42.5,210.9,0.0,0.0,0.0,0.0,0.0,670.3,712.6,178.6,748.3
/)
real(rk), parameter :: q3(30) = (/
353.8,0.0,2135.5,0.0,3677.0,2123.0,1631.0,3693.7,1826.6,1852.4,&

146.6,433.4,614.3,393.5,54.8,1073.4,1368.6,1492.5,155.6,361.5,1616.8,182.8,259.3,570.6,1302.4,1301.8,0.0,0.0,0.0,0.0
/)
real(rk), parameter :: q4(30) = (/
38.4,12.7,12.4,39.1,175.3,0.0,0.0,0.0,0.0,0.0,&

0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,101.1,16.2,59.5,366.4,0.0
/)
real(rk), parameter :: q5(30) = (/ 0.0,0.0,0.0,0.0,0.0,0.3,0.6,1.2,0.9,4.5,&

4.3,5.6,1.5,1.6,2.4,3.0,1.6,4.4,10.1,2.1,3.9,4.4,2.4,0.7,3.1,3.2,1.6,1.8,5.0,3.2
/)
real(rk), parameter :: q6(30) = (/
1372.9,279.9,202.4,40416.9,7522.6,2533.5,3304.0,1231.3,1390.4,12536.6,&
3639.8,448.7,478.4,180.2,164.2,229.3,2123.0,965.3,27416.5,49.0,&
76.4,571.5,925.6,468.8,348.2,5412.3,3632.3,942.6,1006.5,335.2 /)
real(rk), parameter :: q7(30) = (/ 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,&

0.0,22.9,53.4,44.5,14.4,36.6,216.5,34.0,25.0,33.0,8.5,10.7,25.1,0.0,0.0,4.5,44.0,0.0,0.0,0.0
/)
real(rk) :: q(30,7) = reshape( (/q1,q2,q3,q4,q5,q6,q7/), (/30,7/) )
! vars
integer :: npos_min = 15
real(rk) :: zero = 0.0_rk, miss = -999.0_rk
integer :: nsite, nyear, i, j
integer, allocatable :: npos(:)
real(rk), allocatable :: mn(:), sd(:)
character*20, allocatable :: text(:)
! start program
nyear = size(q, dim=1)
nsite = size(q, dim=2)
! mark/flag missing data (2 versions [1 using forall])
where (q <= zero .and. q > miss) q = miss - 10.0
forall (i=1:nsite, j=1:nyear, q(j,i) <= zero .and. q(j,i) > miss)
q(j,i) = miss - 10.0
end forall
do i=1,nyear
write(*,'(999f8.1)') (real(q(i,j)), j=1,nsite)
enddo
! count no. of positive values (2 versions [1 using forall])
allocate (npos(nsite))
npos = count(q > zero, dim=1)
write(*,*) npos
forall (i=1:nsite) npos(i) = count(q(:,i) > miss)
write(*,*) npos
! calc mead/sd (outer forall [with mask] calling pure subroutines [1
with inner forall])
allocate (mn(nsite), sd(nsite))
mn = zero; sd = zero
forall (i=1:nsite, npos(i) >= npos_min)
mn(i) = getmean (x=pack(q(:,i), q(:,i) > miss))
sd(i) = getsd (x=pack(q(:,i), q(:,i) > miss), m=mn(i))
end forall
write(*,*) real(mn)
write(*,*) real(sd)
! now just add a string-based forall
allocate (text(nsite))
forall (i=1:nsite) text(i) = 'site='//number_string(i)
write(*,*) text
continue
stop
contains
! ======================================================
pure function getmean (x)
IMPLICIT NONE
REAL(rk), INTENT(IN) :: x(:)
REAL(rk) :: getmean
real(rk) :: nr
nr = real(size(x),rk)
getmean = sum(x)/nr
end function getmean
! ======================================================
pure function getsd (x, m)
IMPLICIT NONE
REAL(rk), INTENT(IN) :: x(:), m
REAL(rk) :: getsd
INTEGER :: i
real(rk) :: nr1, resid(size(x))
nr1 = real(size(x)+1,rk)
forall (i=1:size(x)) resid(i) = x(i) - m
getsd = dot_product(resid,resid)/nr1
getsd = sqrt(getsd)
end function getsd
! ======================================================
pure function number_string (int)
implicit none
integer, intent(in) :: int
character(len=20) :: number_string
write(number_string,'(i0)') int
END function number_string

end program forall_test_flike
no comments
diggit! del.icio.us! reddit!