Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Pass one dimensional array to function which may resize it

MWind2
New Contributor III
297 Views

How to declare a one dimensional array that can be passed to a function, and in function it is resized and returned. I was trying to adapt an example in docs for MOVE_ALLOC:

program fmalloc
    ! This program uses MOVE_ALLOC to make an allocated array X bigger and
    ! keep the old values of X in the variable X. Only one copy of the old values
    ! of X is needed.
    implicit none
    
    ! Variables
        integer :: I, N = 2
        real, allocatable :: X(:), Y(:)
    ! Body of fmalloc
        allocate (X(N), Y(2*N))         ! Y is twice as big as X
        X = (/(I,I=1,N)/)       ! put "old values" into X
        Y = -1                  ! put different "old values" into Y
        print *, ' allocated of X is ', allocated (X)
        print *, ' allocated of Y is ', allocated (Y)
        print *, ' old X is ', X
        print *, ' old Y is ', Y
        Y (1:N) = X             ! copy all of X into the first half of Y
                                ! this is the only copying of values required
        print *, ' new Y is ', Y
        call move_alloc (Y, X)  ! X is now twice as big as it was, Y is
                                ! deallocated, the values were not copied from Y to X
        print *, ' allocated of X is ', allocated (X)
        print *, ' allocated of Y is ', allocated (Y)
        print *, ' new X is ', X
        !faX(X) not implemented
        !print *, ' new X is ', X
    end program fmalloc

 

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
297 Views

No, this is the classic method of performing this task.

View solution in original post

0 Kudos
7 Replies
MWind2
New Contributor III
297 Views

Something that seems OK:


 

!****************************************************************************
!
!  PROGRAM: fmalloc
!
!  PURPOSE:  Entry point for the console application.
!
!****************************************************************************
    module farray 
    contains
    subroutine faX(aX)
    real, allocatable, intent(inout) :: aX(:)
    integer:: aisize
    integer :: I
    integer :: aishape(1)
    
    real, allocatable :: aY(:)
    !
    aishape=SHAPE(aX)
    !N=aishape(1)
    aisize=SIZE(aX)
    allocate (aY(2*aisize))         ! Y is twice as big as X
        !X = (/(I,I=1,N)/)       ! put "old values" into X
        aY = -2                  ! put different "old values" into Y
        print *, ' allocated of aX is ', allocated (aX)
        print *, ' allocated of aY is ', allocated (aY)
        print *, ' old aX is ', aX
        print *, ' old aY is ', aY
        aY (1:aisize) = aX             ! copy all of X into the first half of Y
                                ! this is the only copying of values required
        print *, ' new aY is ', aY
        call move_alloc (aY, aX)  ! X is now twice as big as it was, Y is
                                ! deallocated, the values were not copied from Y to X
        print *, ' allocated of aX is ', allocated (aX)
        print *, ' allocated of aY is ', allocated (aY)
        print *, ' new aX is ', aX
        aisize=SIZE(aX)
    
    end subroutine  faX
    end module farray
    !
    program fmalloc
    use farray
    ! This program uses MOVE_ALLOC to make an allocated array X bigger and
    ! keep the old values of X in the variable X. Only one copy of the old values
    ! of X is needed.
    implicit none
    
    ! Variables
        integer :: I
        integer :: N = 2
        real, allocatable :: X(:), Y(:)
    ! Body of fmalloc
        allocate (X(N), Y(2*N))         ! Y is twice as big as X
        X = (/(I,I=1,N)/)       ! put "old values" into X
        Y = -1                  ! put different "old values" into Y
        print *, ' allocated of X is ', allocated (X)
        print *, ' allocated of Y is ', allocated (Y)
        print *, ' old X is ', X
        print *, ' old Y is ', Y
        Y (1:N) = X             ! copy all of X into the first half of Y
                                ! this is the only copying of values required
        print *, ' new Y is ', Y
        call move_alloc (Y, X)  ! X is now twice as big as it was, Y is
                                ! deallocated, the values were not copied from Y to X
        print *, ' allocated of X is ', allocated (X)
        print *, ' allocated of Y is ', allocated (Y)
        print *, ' new X is ', X
        call faX(X)
        print *, ' new X is ', X
    end program fmalloc

 

0 Kudos
MWind2
New Contributor III
297 Views

Previous no check for rank1, 

In c++ the idea was like:

#include "pch.h"
#include <iostream>
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define AITEST (0x20)
int resize(int** ppai, int ilen, double drsz) {
	int* pai = *ppai;
	int icopy;
	int iret = (int)(double(ilen) * drsz);
	int* aitemp = new int[iret];
	if (iret > ilen)icopy = ilen;
	else icopy = ilen;
	for (int i = 0; i < icopy; i++) *(aitemp+i) = *(pai+i);
	if (icopy < iret)for (int i = icopy; i < iret; i++) *(aitemp + i) = i;
	int* pai_old = pai;
	*ppai = aitemp;
	delete[] pai_old;
	return iret;
}
int main(int argc, char *argv[]){
	int iaisz=AITEST;
	int* ai0 = new int[iaisz];
	for (int i = 0; i < iaisz; i++)  *(ai0+i) = i;
	iaisz = resize(&ai0, iaisz, 1.5);
	delete[] ai0;
	bool bLeak_= _CrtDumpMemoryLeaks();
	return 0;
}

:

0 Kudos
Steve_Lionel
Honored Contributor III
297 Views

Do you have a question? You use of MOVE_ALLOC here is the classic use case.

0 Kudos
MWind2
New Contributor III
297 Views

I was looking for review, as in "there is a better way" or how this does something wrong.   

0 Kudos
Steve_Lionel
Honored Contributor III
298 Views

No, this is the classic method of performing this task.

0 Kudos
jimdempseyatthecove
Honored Contributor III
297 Views

mwindham,

In your code example in #2, you should be aware that the extended portion of the move-alloc'd array is uninitialized. IOW do not consider these values 0.0 or an arbitrary value that is not a signaling NaN. If this is a potential issue then you will have to initialize these cells to your preference value (which, if you desire, may hold a value you select as never been used such as a subnormal, or TINY or HUGE).

Jim Dempsey

0 Kudos
MWind2
New Contributor III
297 Views

Thanks for noting initialization omission.

0 Kudos
Reply