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:
why main test program go infinite loop when try use 4 functions defined in push interface in same program?
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
Post a Comment