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

Re-size array within a subroutine

sang186
Beginner
1,428 Views

I am trying to implement a push_back routine as below. 

SUBROUTINE push_back(array, val)
    INTEGER,DIMENSION(:), ALLOCATABLE :: tmp_arr
    INTEGER, DIMENSION(:) :: array
    INTEGER val
    ALLOCATE(tmp_arr(0 : SIZE(array)))
    tmp_arr(0:(SIZE(array)-1))=array
    tmp_arr(SIZE(array)) = val
    DEALLOCATE(array)
    ALLOCATE(array(0:SIZE(tmp_arr)-1))
    CALL move_alloc(tmp_arr, array)
END SUBROUTINE push_back 

On resizing an allocatable array (declared ALLOCATABLE in the calling subroutine) , I get the following compile errors

  • error #6724: An allocate/deallocate object must have the ALLOCATABLE or POINTER attribute. [ARRAY]
  • error #8195: The argument to the MOVE_ALLOC intrinsic subroutine shall be an allocatable object. [MOVE_ALLOC]

I want the resize to work such that the data that is passed is not lost. However, by making array ALLOCATABLE within the subroutine , I would lose the existing data.
Any help with this would be great. 

0 Kudos
1 Solution
mecej4
Honored Contributor III
1,428 Views
Merely declaring an argument array to be ALLOCATABLE does not change its allocation status or contents. The following program works fine [fortran] program tpush IMPLICIT NONE INTEGER, DIMENSION(:), ALLOCATABLE :: ivec INTEGER :: val=4 ALLOCATE(ivec(3)) ivec=(/1,2,3/) call push_back(ivec, val) write(*,'(10I4)')ivec contains SUBROUTINE push_back(array, val) INTEGER,DIMENSION(:), ALLOCATABLE :: tmp_arr INTEGER, DIMENSION(:),ALLOCATABLE :: array INTEGER val ALLOCATE(tmp_arr(0 : SIZE(array))) tmp_arr(0:(SIZE(array)-1))=array tmp_arr(SIZE(array)) = val DEALLOCATE(array) ALLOCATE(array(0:SIZE(tmp_arr)-1)) CALL move_alloc(tmp_arr, array) END SUBROUTINE push_back END PROGRAM tpush [/fortran] The program prints out [bash] 1 2 3 4[/bash] [Complaints re ISDN forum software: (i) The program source code above appears single-spaced in edit mode, but appears mostly double spaced in browse mode; (ii) It is confusing when the OP replies to other people's responses and there are no response numbers to provide information on which response is being replied to .]

View solution in original post

0 Kudos
7 Replies
Les_Neilson
Valued Contributor II
1,428 Views
INTEGER, DIMENSION(:), ALLOCATABLE :: array you forgot to tell the compiler that "array" was also allocatable. Les
0 Kudos
A__Valle
Beginner
1,428 Views
Is this something that you want to reach? SUBROUTINE UTIL_ADDTO_ARRAYint2Allocarray(ToBeAdded,IntegerArray) !{ ! This subroutine adds a single value to the end of an integer array. IMPLICIT NONE !** HEADER VARIABLES/ARGUMENTS INTEGER, INTENT(IN) ::ToBeAdded INTEGER, ALLOCATABLE ::IntegerArray(:) !***************************************************************************** !** LOCAL VARIABLES INTEGER ::NewSize INTEGER ::OldSize INTEGER, ALLOCATABLE ::CopyArray(:) !************************************************************************* IF (allocated(IntegerArray)) THEN OldSize=size(IntegerArray) NewSize = OldSize + 1 ALLOCATE(CopyArray(NewSize)) CALL MOVE_ALLOC(CopyArray, IntegerArray) IntegerArray(NewSize) = ToBeAdded ELSE ALLOCATE(IntegerArray(1)) IntegerArray(1)=ToBeAdded ENDIF ENDSUBROUTINE UTIL_ADDTO_ARRAYint2Allocarray !} Making the array allocatable within the subroutine does not lose your data. regards, Dirk
0 Kudos
sang186
Beginner
1,428 Views
On making array 'ALLOCATABLE ' with INTEGER, DIMENSION(:), ALLOCATABLE :: array I would lose its existing allocation and its data and I would like to retain that.
0 Kudos
sang186
Beginner
1,428 Views
Sorry, It was my bad. I had overlooked the allocation of the array with a zero index in the calling function . It works now. @Les & @Dirk - Thank you very much for the inputs. Sangeetha
0 Kudos
sang186
Beginner
1,428 Views
It was totally my bad. Thank you very much, mecej4.
0 Kudos
mecej4
Honored Contributor III
1,429 Views
Merely declaring an argument array to be ALLOCATABLE does not change its allocation status or contents. The following program works fine [fortran] program tpush IMPLICIT NONE INTEGER, DIMENSION(:), ALLOCATABLE :: ivec INTEGER :: val=4 ALLOCATE(ivec(3)) ivec=(/1,2,3/) call push_back(ivec, val) write(*,'(10I4)')ivec contains SUBROUTINE push_back(array, val) INTEGER,DIMENSION(:), ALLOCATABLE :: tmp_arr INTEGER, DIMENSION(:),ALLOCATABLE :: array INTEGER val ALLOCATE(tmp_arr(0 : SIZE(array))) tmp_arr(0:(SIZE(array)-1))=array tmp_arr(SIZE(array)) = val DEALLOCATE(array) ALLOCATE(array(0:SIZE(tmp_arr)-1)) CALL move_alloc(tmp_arr, array) END SUBROUTINE push_back END PROGRAM tpush [/fortran] The program prints out [bash] 1 2 3 4[/bash] [Complaints re ISDN forum software: (i) The program source code above appears single-spaced in edit mode, but appears mostly double spaced in browse mode; (ii) It is confusing when the OP replies to other people's responses and there are no response numbers to provide information on which response is being replied to .]
0 Kudos
Les_Neilson
Valued Contributor II
1,428 Views
That's ok - we all make mistakes. Glad it now works Les
0 Kudos
Reply