Hello again,
Several days ago I posted a question about generic reallocation of arrays of polymorphic elements, which was answered by Steve Lionel. But when switching to the compilation options which are actually used in our software, I found another problem.
At first glance, this is not directly related to polymorphism. However, I am unable to create a smaller program that shows the same problems so that may have something to do with it.
Here is the same program that I submitted last time (with Steve’s change), with one addition : I set the first three elements of the measurement array before resizing the array, and print the three elements after the resizing is done.
Depending on the compilation options, the result is OK or not.
module measurements_management
! Measurements types
!-------------------
type :: generic_measurement
end type generic_measurement
type, extends(generic_measurement) :: measurement_as_reals
real :: real_measurement
end type measurement_as_reals
type, extends(generic_measurement) :: measurement_as_integers
integer :: int_measurement
end type measurement_as_integers
! Generic management of measurement arrays
! ----------------------------------------
type measurements_buffer
integer :: nb_used = 0
class(generic_measurement), allocatable, dimension(:) :: tab_measurements
contains
procedure :: init => buffer_init
procedure :: realloc => buffer_realloc
end type measurements_buffer
contains
! create a buffer containing an array with a selected measurement type
! the measurement array has an initial dimension of 50 elements
subroutine buffer_init(this, measurement)
class(measurements_buffer), intent(inout) :: this
class(generic_measurement) :: measurement
allocate(this%tab_measurements(50), mold=measurement)
end subroutine buffer_init
! for an existing buffer created for a specific measurement type,
! reallocate the measurements array, adding 100 empty elements and
! copying the existing elements
subroutine buffer_realloc(this)
class(measurements_buffer), intent(inout), target :: this
!.. Local variables ..
integer :: current_size
class(generic_measurement), allocatable, dimension(:), target :: tab_tmp
current_size = size(this%tab_measurements)
write(*,*) 'current size=', current_size
tab_tmp = reshape(this%tab_measurements,[current_size+100],this%tab_measurements)
write(*,*) 'tab_tmp size after copy = ',size(tab_tmp)
call move_alloc(tab_tmp, this%tab_measurements)
end subroutine buffer_realloc
end module measurements_management
! example with a buffer of integer measurements
program polymorphic_realloc
use measurements_management
implicit none
type(measurements_buffer), target :: buffer_of_integer_measurements
type(measurement_as_integers) :: measurement_int
class(generic_measurement), pointer :: ptr_measurement
integer :: i
! init buffer
call buffer_of_integer_measurements%init(measurement_int)
! fill buffer
do i=1,3
ptr_measurement => buffer_of_integer_measurements%tab_measurements(i)
select type (ptr_measurement)
class is (measurement_as_integers)
ptr_measurement%int_measurement = 10*i
end select
end do
! extend buffer
call buffer_of_integer_measurements%realloc()
do i=1,3
ptr_measurement => buffer_of_integer_measurements%tab_measurements(i)
select type (ptr_measurement)
class is (measurement_as_integers)
write (*,*) i, ' =>', ptr_measurement%int_measurement
end select
end do
end program polymorphic_realloc
which should display :
current size= 50
tab_tmp size after copy = 150
1 => 10
2 => 20
3 => 30
This is ok with the following options :
ifort -i8
ifort -qmkl
ifort -i4 -qmkl
but not with :
ifort -i8 -qmkl
as shown below :
current size= 50
tab_tmp size after copy = 150
1 => 139883383696650
2 => 20
3 => 139883383696670
Unfortunately, this is the option combination that we are using. Contrary to the example above, we are using a lot of BLAS95 ans LAPACK95 routines in our real software.
I have also tried :
ifort -i8 -qmkl-ilp64
to force the ILP64 back-end of mkl, to no avail.
Strangely (or not) ifx -i8 -mkl gives the correct result.
Also, when I change the code to :
type, extends(generic_measurement) :: measurement_as_integers
integer*4 :: int_measurement
end type measurement_as_integers
Then all combinations are ok. But this means changing a lot of things in our code.
Thanks for any help,
Franck