gfortran - Why does this Fortran module interface give different results depending on how many of its functions are used? -


i have written module contains interface called 'push' pushes values onto allocatable arrays. want have generic behavior can add new function given type 'push' interface needed. problem amount of functions given interface grows, strange behavior of push interface.

code module (push_array.f90):

module push_array   implicit none   ! usage:   ! array = push(array,val)   interface push      module procedure push_scalar_int_onto_rank1_int      module procedure push_scalar_int2_onto_rank1_int2      module procedure push_rank1_int_onto_rank2_int      module procedure push_rank1_real8_onto_rank2_real8   end interface push  contains   function push_scalar_int_onto_rank1_int (array,val) result (new_array)     integer,intent(in),allocatable :: array(:)     integer,intent(in) :: val     integer,allocatable :: new_array(:)     integer :: length     if (allocated(array))        length = size(array) + 1     else        length = 1     end if     allocate(new_array(size(array) + 1))     if (allocated(array)) new_array(:) = array(:)     new_array(length) = val     return   end function push_scalar_int_onto_rank1_int    function push_scalar_int2_onto_rank1_int2 (array,val) result (new_array)     integer(2),intent(in),allocatable :: array(:)     integer(2),intent(in) :: val     integer(2),allocatable :: new_array(:)     integer :: length     if (allocated(array))        length = size(array) + 1     else        length = 1     end if     allocate(new_array(size(array) + 1))     if (allocated(array)) new_array(:) = array(:)     new_array(length) = val     return   end function push_scalar_int2_onto_rank1_int2    function push_rank1_int_onto_rank2_int (array,val) result (new_array)     integer,intent(in),allocatable :: array(:,:)     integer,intent(in) :: val(:)     integer,allocatable :: new_array(:,:)     integer :: length     if (allocated(array))        length = size(array,2) + 1     else        length = 1     end if     allocate(new_array(1:size(val),length))     if (allocated(array)) new_array(1:size(val),:) = array(1:size(val),:)     new_array(1:size(val),length) = val     return   end function push_rank1_int_onto_rank2_int      function push_rank1_real8_onto_rank2_real8 (array,val) result (new_array)     real(8),intent(in),allocatable :: array(:,:)     real(8),intent(in) :: val(:)     real(8),allocatable :: new_array(:,:)     integer :: length     if (allocated(array))        length = size(array,2) + 1     else        length = 1     end if     allocate(new_array(1:size(val),length))     if (allocated(array)) new_array(1:size(val),:) = array(1:size(val),:)     new_array(1:size(val),length) = val     return   end function push_rank1_real8_onto_rank2_real8  end module push_array 

test code (test_push_array.f90):

program main   use push_array, only: push   implicit none   integer,allocatable :: a(:)   integer(2),allocatable :: b(:)   integer,allocatable :: c(:,:)   real(8),allocatable :: d(:,:)   integer :: xp(3)   real(8) :: xp8(3)   integer ::   integer(2) :: j   ! test scalar integer can pushed onto rank1 integer array   i=1,100      = push(a,i)   end   print *, a(1),a(100)    ! test scalar integer(2) can pushed onto rank1 integer(2) array   j=1,100      b = push(b,j)   end   print *, b(1),b(100)    ! test rank1 integer can pushed onto rank2 integer   i=1,100      xp = [i,i+1,i+2]      c = push(c,xp)   end   print *, c(1:3,1),c(1:3,100)    ! test rank1 real(8) can pushed onto rank2 real(8)   i=1,100      xp8 = [i + 0.001,i + 0.002, + 0.003]      d = push(d,xp8)   end   print *, d(:,1),d(:,100)  end program main 

make output show compiler flags:

$ make gfortran -g -o2 -c push_array.f90 gfortran -g -o2 -o main test_push_array.f90 push_array.o 

my compiler version:

$ gfortran --version gnu fortran (gcc) 4.8.2 copyright (c) 2013 free software foundation, inc. 

my system:

$ uname -a darwin darthan 12.5.0 darwin kernel version 12.5.0: sun sep 29 13:33:47 pdt 2013; root:xnu-2050.48.12~1/release_x86_64 x86_64 

if run test code given, goes infinite loop , system memory exhausted. tried trace test case in gdb setting breakpoint push onto in first loop,but gdb unable step module function.

if comment first test loop pushed onto a, here results:

$ ./main       1    100            1           2           3         100         101         102    1.0010000467300415        1.0019999742507935        1.0030000209808350        100.00099945068359        100.00199890136719        100.00299835205078      

these expected.

if comment out second loop push j onto b, here results:

$ ./main            1         100            1           2           3         100         101         102    1.0010000467300415        1.0019999742507935        1.0030000209808350        100.00099945068359        100.00199890136719        100.00299835205078      

once again, expected.

things start getting strange when comment out third loop push xp onto c:

$ ./main            1           0       1      0    1.0010000467300415        1.0019999742507935        1.0030000209808350        100.00099945068359        100.00199890136719        100.00299835205078      

the pattern continues when comment out fourth loop push xp8 onto d:

$ ./main            1           0       1      0            1           2           3         100         101         102 

my questions:

  1. why main test program go infinite loop when try use 4 functions defined in push interface in same program?

  2. in case comment out third , fourth loops , why results a(100) , b(100) both equal 0?

any feedback appreciated...thanks!

edit:

the 2 functions needed changed given below

  function push_scalar_int_onto_rank1_int (array,val) result (new_array)     integer,intent(in),allocatable :: array(:)     integer,intent(in) :: val     integer,allocatable :: new_array(:)     integer :: length     if (allocated(array))        length = size(array) + 1     else        length = 1     end if     allocate(new_array(length)) ! changed     if (allocated(array)) new_array(:) = array(:)     new_array(length) = val     return   end function push_scalar_int_onto_rank1_int    function push_scalar_int2_onto_rank1_int2 (array,val) result (new_array)     integer(2),intent(in),allocatable :: array(:)     integer(2),intent(in) :: val     integer(2),allocatable :: new_array(:)     integer :: length     if (allocated(array))        length = size(array) + 1     else        length = 1     end if     allocate(new_array(length)) ! changed     if (allocated(array)) new_array(:) = array(:)     new_array(length) = val     return   end function push_scalar_int2_onto_rank1_int2 

you allocate statement in of function bodies references size of array argument. if array argument not allocated, reference invalid.

earlier in procedure test allocation status , set variable named length - perhaps meant use that.

(for clarity - perhaps @ allocate statement in push_scalar_int_onto_rank1_int function.)


Comments

Popular posts from this blog

php - SPIP: From Tag directly to an article -

jquery - isAjaxRequest always return false -

ruby on rails - In a controller spec, how to find a specific tag in the generated view? -