Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
The Intel sign-in experience has changed to support enhanced security controls. If you sign in, click here for more information.

Pass one dimensional array to function which may resize it

MWind2
New Contributor III
185 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
Black Belt Retired Employee
185 Views

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

View solution in original post

7 Replies
MWind2
New Contributor III
185 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

 

MWind2
New Contributor III
185 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;
}

:

Steve_Lionel
Black Belt Retired Employee
185 Views

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

MWind2
New Contributor III
185 Views

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

Steve_Lionel
Black Belt Retired Employee
186 Views

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

jimdempseyatthecove
Black Belt
185 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

MWind2
New Contributor III
185 Views

Thanks for noting initialization omission.

Reply