Recursive function (with allocatable inside)
- From: relaxmike <michael.baudin@xxxxxxxxx>
- Date: Wed, 14 May 2008 03:18:35 -0700 (PDT)
Hi,
I continue to experiment some bugs while using derived-types
based on allocatable arrays. So I worked to reduce the problem and
the following is a small source code which contains a recursive
function
which returns a derived-type, which contains an allocatable array.
It tries to compute a tree, for which each node has 3 leaves.
Several versions of the code are possible, depending on the following
parameters:
- the level of recursive calls (I tried 1 and 2 levels),
- use allocatable or pointer arrays,
- use a subroutine or a function (yes, I tried that !).
With 1 level of recursion, the tree has 12 leaves, and with
2 levels, the tree has 39 leaves (the root is not counted).
I tried 3 compilers : Intel Fortran 8, gfortran and g95.
By making these parameters vary, I generated a family of bug,
which could be called a bug farm ...
module mymodule
implicit none
type, public :: t_dt
! Or : integer , dimension (:), pointer :: array
integer , dimension (:), allocatable :: array
end type t_dt
integer :: currentid = 0
contains
! Or : recursive subroutine mysub ( level , stufflist )
recursive function myfunc ( level ) result ( stufflist )
integer , intent(in) :: level
type ( t_dt ) :: stufflist
type ( t_dt ) :: stufflist_copy
type ( t_dt ) :: stufflist_sublevel
integer , parameter :: maxchild = 3
integer :: myindex
integer :: current_size
integer :: newsize
integer :: sublevelsize
!
! Compute the current direct children
!
allocate ( stufflist % array ( maxchild ) )
do myindex = 1 , maxchild
currentid = currentid + 1
stufflist % array ( myindex ) = currentid
enddo
! Or : if ( level == 2 ) then
if ( level == 1 ) then
return
endif
!
! Loop over the children
!
do myindex = 1 , maxchild
!
! Compute the children from sub-levels
!
stufflist_sublevel = myfunc ( level + 1 )
!
! Append the children of sub-levels to the current list
!
current_size = size ( stufflist % array )
allocate ( stufflist_copy % array ( current_size ) )
stufflist_copy % array = stufflist % array
deallocate ( stufflist % array )
sublevelsize = size ( stufflist_sublevel % array )
newsize = current_size + sublevelsize
allocate ( stufflist % array ( newsize ) )
stufflist % array ( 1 : current_size ) = stufflist_copy % array
( 1 : current_size )
stufflist % array ( current_size + 1 : newsize ) =
stufflist_sublevel % array ( 1 : sublevelsize )
deallocate ( stufflist_copy % array )
deallocate ( stufflist_sublevel % array )
enddo
end function myfunc
end module mymodule
program test1
use mymodule
implicit none
type ( t_dt ) :: stufflist
integer :: myindex
integer :: arraysize
stufflist = myfunc ( 0 )
arraysize = size ( stufflist % array )
do myindex = 1 , arraysize
write(12,*) "[", myindex , "]" , stufflist % array ( myindex )
enddo
end program test1
These are the version of the compilers I used :
Intel Fortran :
(recursivefunc_withdt) 73 % ifort -h
Intel(R) Fortran Compiler for 32-bit applications, Version 8.0 Build
20031017Z Package ID: w_fc_p_8.0.034
Copyright (C) 1985-2003 Intel Corporation. All rights reserved.
(recursivefunc_withdt) 73 % g95 -v
Using built-in specs.
Target:
Configured with: /src/G95/gcc-4.0-20060302/configure --with-gcc --with-
gnu-ld --with-ld=/mingw/bin/ld --with-gnu-as --with-as=/mingw/bin/as --
host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --
disable-nls --enable-languages=c --disable-win32-registry --disable-
shared --without-x --disable-libmudflap --disable-libssp
Thread model: win32
gcc version 4.0.3 (g95 0.91!) May 3 2007
gfortran :
(recursivefunc_withdt) 74 % gfortran -v
Using built-in specs.
Target: i586-pc-mingw32
Configured with: ../trunk/configure --prefix=/mingw --enable-
languages=c,fortran --with-gmp=/home/FX/local --with-ld=/mingw/bin/ld
--with-as=/mingw/bin/as --disable-werror --enable-bootstrap --enable-
threads --disable-nls --build=i586-pc-mingw32 --enable-libgomp --
disable-shared
Thread model: win32
gcc version 4.4.0 20080312 (experimental) [trunk revision 133139]
(GCC)
This is a sample result with gfortran and 2 levels :
(recursivefunc_withdt) 58 % gfortran test4.f90 -o test4.exe
(recursivefunc_withdt) 59 % test4.exe
[ 1 ] 1
[ 2 ] 2
[ 3 ] 3
[ 4 ] 4
[ 5 ] 5
[ 6 ] 6
[ 7 ] 7
[ 8 ] 8
[ 9 ] 9
[ 10 ] 10
[ 11 ] 11
[ 12 ] 12
[ 13 ] 13
[ 14 ] 14
[ 15 ] 15
[ 16 ] 16
[ 17 ] 17
[ 18 ] 18
[ 19 ] 19
[ 20 ] 20
[ 21 ] 21
[ 22 ] 22
[ 23 ] 23
[ 24 ] 24
[ 25 ] 25
[ 26 ] 26
[ 27 ] 27
[ 28 ] 28
[ 29 ] 29
[ 30 ] 30
[ 31 ] 31
[ 32 ] 32
[ 33 ] 33
[ 34 ] 34
[ 35 ] 35
[ 36 ] 36
[ 37 ] 37
[ 38 ] 38
[ 39 ] 39
These are the results I got, depending on the source code.
test2 : function, allocatable, level 1
gfortran : OK
Intel Fortran : OK
test3 : function, allocatable, level 2
gfortran : OK
Intel Fortran : FALSE
g95 : OK
test4 : function, pointer, level 2
gfortran : OK
Intel Fortran : Exception
g95 : OK
test5 : subroutine, allocatable, level 2
gfortran : child killed: segmentation violation
Intel Fortran : OK !
g95 : OK
I was not really surprised to find out that gfortran had some
problems, because I have allready reported a bug for gfortran :
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35959
which has been fixed several week ago.
So I will try the same code with the next release of gfortran.
What was more surprising to me is that Intel Fortran works
in that particular case with recursive subroutines and
not with recursive functions.
Another thing which is strange to me is that the allocatable
version runs with wrong results, whereas the pointer
version fails with a runtime exception.
This is an abstract of the call stack when Intel Fortran
fails with 2 levels, pointer array and function :
...>_for_deallocate>free>_free_dbg > _CrtIsValidHeapPointer
This is the wrong result for the Intel Fortran compiler,
2 levels, allocatable array and function :
[ 1 ] 1
[ 2 ] 2
[ 3 ] 3
[ 4 ] 13
[ 5 ] 14
[ 6 ] 15
[ 7 ] 13
[ 8 ] 14
[ 9 ] 15
[ 10 ] 25
[ 11 ] 26
[ 12 ] 27
[ 13 ] 25
[ 14 ] 26
[ 15 ] 27
[ 16 ] 37
[ 17 ] 38
[ 18 ] 39
[ 19 ] 37
[ 20 ] 38
[ 21 ] 39
I looked at the release notes for the Intel Fortran Compilers (8, 9,
10), but
I did not find any comments on that particular problem.
It is difficult for me to find a practical conclusion for this.
Should I update my Intel compiler for the 10. release ?
Should I use subroutines instead of functions : stupid conclusion,
but would solve the problem !
Regards,
Michaël
.
- Follow-Ups:
- Re: Recursive function (with allocatable inside)
- From: James Van Buskirk
- Re: Recursive function (with allocatable inside)
- From: Michael Metcalf
- Re: Recursive function (with allocatable inside)
- Prev by Date: Re: Derived types and allocatable
- Next by Date: Re: How to distinguish between numerical data and alphanumeric title
- Previous by thread: Bitwise logical functions in gfortran
- Next by thread: Re: Recursive function (with allocatable inside)
- Index(es):
Relevant Pages
|
|