------- Comment #5 from David dot Duffy at qimr dot edu dot au  2007-04-14 
01:09 -------
Subject: Re:  Array size declaration depended on order of
 declaration of variable containing size 

You wrote:

> as parameter is not allowed in a type specification and using a simple
>   type ped_data
>     integer :: maxsiz = 5
>   end type ped_data
> does also not work:
>   integer, dimension(dataset%maxsiz) :: nobs
>                     1
> Error: Variable 'dataset' cannot appear in the expression at (1)
> or in words of NAG f95:
>   DATASET is not permitted in a specification expression


and tobi at gcc dot gnu dot org wrote:

> 
> 
> ------- Comment #2 from tobi at gcc dot gnu dot org  2007-04-13 15:22 -------
> (In reply to comment #0)
>> GNU Fortran (GCC) 4.3.0 20070412 (experimental)
>> Linux 2.4.20-20030701 #2 SMP
>>
>>   use ped_class
>>   type (ped_data) :: dataset
>>   integer, dimension(dataset%maxsiz) :: nobs
>> 
>> works but
>>
>>   use ped_class
>>   integer, dimension(dataset%maxsiz) :: nobs
>>   type (ped_data) :: dataset
>> 
>> doesn't.
> 
> If I understand you correctly, what you're trying to do is invalid.  You may
> only reference previously declared objects in data object declarations.  In
> your second example dataset is referenced before it is declared.
> 
> Please provide a complete testcase, and if the problem is indeed the order of
> declarations please tell us where you think I'm wrong.
>

Hi.

Please find a cutdown example attached.  In this form, it compiles successfully
with gfortran, ifort and g95.  If line 251 is commented out and line 256
uncommented, only g95 compiles it successfully.

Since dataset, nobs and relid are all subroutine arguments, it seems
plausible to me that the order of declaration should be irrelevant, even
though it require more work by the compiler.  I haven't looked at the Fortran
Standard (and probably couldn't work out what it was saying anyway ;)) to see
if there is a defined behaviour.

Cheers,

David Duffy.
!
! Output stream
!
module outstream
  integer :: outstr
end module outstream
!
! One big pedigree data structure
! Updating size requires copying entire structure
! (hopefully maintaining contiguous storage)
!
module idstring_widths
  integer, parameter :: ped_width = 20
  integer, parameter :: id_width = 12
end module idstring_widths
module ped_class
  use idstring_widths
  type ped_data
    integer :: nped   ! number of pedigrees
    integer :: nact   ! number of active pedigrees
    integer :: maxsiz ! size of largest pedigree
    integer :: nobs   ! number of records
    integer :: numloc ! number of columns of locus data
! pedigree level data
    character (len=ped_width), dimension(:), allocatable :: pedigree
    integer, dimension(:), allocatable :: num
    integer, dimension(:), allocatable :: nfound
    integer, dimension(:), allocatable :: actset
! individual level data
    integer, dimension(:), allocatable :: iped
    character (len=id_width), dimension(:), allocatable :: id
    integer, dimension(:), allocatable :: fa
    integer, dimension(:), allocatable :: mo
    integer, dimension(:), allocatable :: sex
    double precision, dimension(:,:), allocatable :: locus
! useful work arrays -- usually referring to locus being currently analysed
    logical, dimension(:), allocatable :: untyped
  end type ped_data

contains
!
! allocate pedigree data
!
  subroutine setup_peds(nped, nobs, numloc, dataset)
    integer :: nobs, nped, numloc
    type (ped_data) :: dataset
    dataset%nped = nped
    dataset%nact = nped
    dataset%maxsiz = 0
    dataset%nobs = nobs
    dataset%numloc = numloc
    allocate(dataset%pedigree(nped))
    allocate(dataset%num(0:nped))
    allocate(dataset%nfound(nped))
    allocate(dataset%actset(nped))
    dataset%num(0)=0

    allocate(dataset%iped(nobs))
    allocate(dataset%id(nobs))
    allocate(dataset%fa(nobs))
    allocate(dataset%mo(nobs))
    allocate(dataset%sex(nobs))
    allocate(dataset%locus(nobs, numloc))
    allocate(dataset%untyped(nobs))
  end subroutine setup_peds
!
! copy pedigree data
!
  subroutine copy_peds(set1, set2)
    type (ped_data) :: set1, set2
    integer :: i
    set2%nped = set1%nped
    set2%nact = set1%nact
    set2%maxsiz = set1%maxsiz
    set2%nobs = set1%nobs
    set2%numloc = set1%numloc
    do i=0, set1%nped
      set2%num(i)      = set1%num(i)     
    end do
    do i=1, set1%nped
      set2%pedigree(i) = set1%pedigree(i)
      set2%nfound(i)   = set1%nfound(i)  
      set2%actset(i)   = set1%actset(i)  
    end do
    do i=1, set1%nobs
      set2%iped(i) = set1%iped(i) 
      set2%id(i) = set1%id(i) 
      set2%fa(i) = set1%fa(i) 
      set2%mo(i) = set1%mo(i)
      set2%sex(i) = set1%sex(i)
      set2%locus(i, 1:set1%numloc) =  set1%locus(i, 1:set1%numloc)
    end do
  end subroutine copy_peds
!
! deallocate pedigree structure arrays
!
  subroutine cleanup_peds(dataset)
    type (ped_data) :: dataset
    if (allocated(dataset%locus)) then
      deallocate(dataset%pedigree)
      deallocate(dataset%num)
      deallocate(dataset%nfound)
      deallocate(dataset%actset)

      deallocate(dataset%iped)
      deallocate(dataset%id)
      deallocate(dataset%fa)
      deallocate(dataset%mo)
      deallocate(dataset%sex)
      deallocate(dataset%locus)
      deallocate(dataset%untyped)
    end if
    dataset%nped=0
    dataset%nact=0
    dataset%maxsiz=0
    dataset%nobs=0
    dataset%numloc=0
  end subroutine cleanup_peds
end module ped_class
program tester
  use outstream
  use ped_class
  type (ped_data) :: work   
  integer :: MISS=-9999
  outstr=6
  call setup_peds(1, 4, 1, work)
  work%maxsiz=4
  work%pedigree(1)='Test'
  work%num(1)=4
  work%nfound(1)=2
  work%actset(1)=2
  work%iped=1
  work%id(1)='1'
  work%id(2)='2'
  work%id(3)='3'
  work%id(4)='4'
  work%fa=MISS
  work%mo=MISS
  work%fa(3)=1
  work%mo(3)=2
  work%fa(4)=1
  work%mo(4)=2
  work%sex=1
  work%locus=1.0d0
  call getrelval('sib', 'mea', 'test', 4, 1, MISS, work, 0)
  call cleanup_peds(work)
end program tester
!
! Get values for trait in relatives
!
subroutine getrelval(relate, summary, locnam, loctyp, trait,  &
                     sumval, dataset, plevel)
  use outstream
  use ped_class  
  implicit none
  character (len=3), intent(in) :: relate, summary
  character (len=10), intent(in) :: locnam
  integer, intent(in) :: loctyp
  integer, intent(in) :: trait, sumval
  type (ped_data) :: dataset
  integer, intent(in) :: plevel
!
  integer, parameter :: MISS=-9999, MAXREC=20
! trait values in relatives
  integer, dimension(dataset%maxsiz) :: nobs
  integer, dimension(dataset%maxsiz, MAXREC) :: relid
  integer :: currf, currm, i, idx, j, k, nsibs, num, pedoffset, ped, pos,  &
             reltyp, totobs
  character (len=1) :: ch
  character (len=6), dimension(13) :: relnam = (/  'All      ',  &
    'Offspring', 'Son      ', 'Daughter ',  &
    'Parent   ', 'Father   ', 'Mother   ',  &
    'Sibling  ', 'Brother  ', 'Sister   ',  &
    'Spouse   ', 'Husband  ', 'Wife     ' /)

  reltyp=1
  if (relate=='sib') then
    reltyp=8
  end if
  if (plevel >= 0) then
    write(outstr, '(/3a/a)') 'Pedigree       ID         Rel   Summary (',
summary, ')',  &
                            '------------ ------------ ---
--------------------'
  end if
  totobs=0
! Siblings
  if (reltyp==8 .or. reltyp==9 .or. reltyp==10) then
    do ped=1, dataset%nped
    if (dataset%actset(ped) > 0) then
      pedoffset=dataset%num(ped-1)+dataset%nfound(ped)
      num=dataset%num(ped)-dataset%num(ped-1)
      do k=1, num
        nobs(k)=-1
      end do
      nobs((dataset%nfound(ped)+1):num)=0
      currf=MISS
      currm=MISS
      idx=num
      i=dataset%num(ped)
      do while (i > pedoffset)
        currf=dataset%fa(i)
        currm=dataset%mo(i)
        nsibs=0
        pos=i-1
        do while (dataset%fa(pos)==currf .and. dataset%mo(pos)==currm)
          nsibs=nsibs+1
          pos=pos-1
        end do
        do j=pos+1, i
          if (reltyp==8 .or. (reltyp==9 .and. dataset%sex(j)==1) .or.  &
                             (reltyp==10 .and. dataset%sex(j)==2)) then
            if (dataset%locus(j,trait) /= MISS .and. nobs(idx) < MAXREC) then
              nobs(idx)=nobs(idx)+1
              relid(idx, nobs(idx))=j
            end if
          end if
        end do
        do j=idx-nsibs, idx-1
          nobs(j)=nobs(idx)
          do k=1, nobs(idx)
            relid(j,k)=relid(idx,k)
          end do
        end do
        i=pos
        idx=idx-nsibs-1
      end do
      call prirelval(relnam(reltyp), summary, trait, loctyp, ped, nobs, relid, 
&
                     sumval, totobs, dataset, plevel)
    end if
    end do
  end if
  if (plevel <= 0 .and. totobs>=30) then
    write(outstr, '(a)') '...'
  end if
  write(outstr, '(/a,i6,a)')  &
    'Processed', totobs, ' trait values from relatives.'
end subroutine getrelval
!
! Output values for each eligible persion
! 
subroutine prirelval(relate, summary, trait, loctyp, ped,  &
                     nobs, relid, sumval, totobs, dataset, plevel)
  use outstream
  use ped_class  
  implicit none
  integer, parameter :: MAXREC=20
  character (len=3), intent(in) :: relate
  character (len=3), intent(in) :: summary
  integer, intent(in) :: trait, loctyp
  integer, intent(in) :: ped
! FROM HERE
  type (ped_data) :: dataset 
! trait values in relatives
  integer, dimension(dataset%maxsiz) :: nobs
  integer, dimension(dataset%maxsiz, MAXREC) :: relid
! TO HERE
! type (ped_data) :: dataset
  integer, intent(in) :: sumval
  integer, intent(inout) :: totobs
  integer, intent(in) :: plevel
!
  integer, parameter :: MISS=-9999
  integer :: i, idx, j, n, pedoffset
  double precision :: res
  character (len=1) :: ch
! functions
!
! Detailed output
!
  pedoffset=dataset%num(ped-1)
  if (summary=='sum' .or. summary=='mea') then
    idx=0
    do i=pedoffset+1, dataset%num(ped)
      idx=idx+1
      res=MISS
      if (nobs(idx) > 0) then
        totobs=totobs+1
        res=0.0d0
        do j=1, nobs(idx)
          res=res+dataset%locus(relid(idx,j),trait)
        end do
        if (loctyp==4) res=res-dfloat(nobs(idx))
        if (summary=='mea') res=res/dfloat(nobs(idx))
        if (plevel>0 .or. (plevel==0 .and. totobs<30)) then
          write(outstr, '(a12,1x,a12,1x,a3,1x,f16.4)')  &
             dataset%pedigree(ped), dataset%id(i), relate, res
        end if
      else if (nobs(idx) == 0 .and.  &
               (plevel>0 .or. (plevel==0 .and. totobs<30))) then
        write(outstr, '(a12,1x,a12,1x,a3,12x,a)')  &
          dataset%pedigree(ped), dataset%id(i), relate, 'x'
      end if
      if (sumval /= MISS) dataset%locus(i, sumval)=res
    end do
  end if
end subroutine prirelval
!  
! binary trait as character
!  
subroutine wraff(value, ch, typ)
  double precision, intent(in) :: value
  character (len=1), intent(out) :: ch
  integer, intent(in) :: typ
  character (len=1), dimension(6), parameter :: let=(/'x','n','y','?','U','A'/)
  ch=let(1+3*(typ-1))
  if (value == 1.0d0) then
    ch=let(2+3*(typ-1))
  else if (value == 2.0d0) then
    ch=let(3+3*(typ-1))
  end if
end subroutine wraff


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31560

Reply via email to