dynamic array

Skif
07-21-2008, 10:52 AM
hello,
I fail to have a arrey arr() where the dimension is not defined, but it must grow
recalling the old values

ex.
STEP 1
dimension is 1, and
arr(1)= 12
STEP 2
dimension is 2, and
arr(1)= 12
arr(2)= 5
STEP 3
dimension is 3, and
arr(1)= 12
arr(2)= 5
arr(3)= 15
STEP 4
...
...
STEP n
dimension is n, and
arr(1)= 12
arr(2)= 5
....
arr(n)= 144

thanks to all :D

davekw7x
07-21-2008, 11:55 PM
...but it must grow...

Given a dynamically allocated array, x, with size = n, containing values x(1), x(2), ... , x(n).

Suppose we want to "resize" the array x to have size n+1, keeping the old values, and then store a new value in x(n+1).

If that's it, then consider:

Suppose we have defined allocatable arrays a and temp. We have allocated storage size n for a and have stored n values in a(1), a(2), a(3), ... , a(n)

Then, to make it "grow," wouldn't you simply do something like:

1. Allocate storage for temp, with size n.

2. Copy x(1), x(2), ... , x(n) to temp(1), temp(2), ... , temp(n).

3. Deallocate the storage for x.

4. Allocate storage for x with size n+1.

5. Copy temp(1), temp(2), ... , temp(n) to x(1), x(2), ... , x(n).

6. Store the new value in x(n+1).

7. Deallocate the storage for temp.

Or am I missing something?

Regards,

Dave

Skif
07-22-2008, 12:48 AM
yes your comment is correct but:
if I do a subroutine where add my array, I can't define a allocatable vector
because the vector is already allocate

es
program main
...
...
integer, allocatable, dimension( : ) :: pippo
...
...
allocate(pippo(1)) !Pippo is allocate
...
...
...
...
end

!in the sub ADD_MAT I pass "pippo" but this vector is already allocate
!when I declare the array "matrix" in the ADD_MAT, I can not declare
!allocatable, and if I not declare a vector allocatable I can not
!vary its dimension

!external
integer :: newDimension
integer :: oldDimension
!#####
integer, allocatable, dimension( : ) :: matrix !this line is uncorrect
!#####
!
!internal
integer, allocatable, dimension( : ) :: copyMatrix
!
allocate(copyMatrix(oldDimension))
copyMatrix = matrix
deallocate (matrix)
allocate(matrix(newDimension))
matrix = copyMatrix
return
end subroutine

thanks :eek:

davekw7x
07-22-2008, 10:13 AM
yes your comment is correct but:
if I do a subroutine where add my array,...

Well, for some reason you didn't impart this little tidbit in your original post.

The procedure is the same (copy old values into a temporary array then deallocate and allocate the array with a larger size and copy the original values into the newly allocated storage space of the original array).

Since we aren't allowed to use dynamically allocated arrays as formal parameters in subroutines, we can fake it with a module. (The variables will be "global" to all parts of the program that use this module.) This gives us a way to de-allocate and re-allocate without needing subroutine parameters.

Here's an example showing a 1-D array of integers (compiled with GNU gfortran).

!****
!
! Since we can't use an allocatable array as an argument
! to a function or a subroutine, we create a module that
! allows this functionality.
!
!****
MODULE DynamicIntegerArray
INTEGER IArraySize
INTEGER, DIMENSION(:), ALLOCATABLE :: Iarray
END MODULE DynamicIntegerArray

!****
! The program calls a subroutine ResizeIarray to
! increase the size of a dynamically allocated array
! by one and retain all of its previous contents
!****
PROGRAM TestDynamicAllocationFunctionArguments
USE DynamicIntegerArray

IMPLICIT NONE

INTERFACE
SUBROUTINE ResizeIArray
END SUBROUTINE ResizeIArray
END INTERFACE

INTERFACE
SUBROUTINE DeallocIArray
END SUBROUTINE DeallocIArray
END INTERFACE

INTEGER :: ix
INTEGER :: i

IArraySize = 0 ! Initialize dynamic array

DO i=1,5
WRITE(*,'(A)', ADVANCE = 'NO') "Enter an integer: "
CALL ResizeIArray
Iarray(i) = ix
WRITE(*,'("Stored ", I0, " in Iarray(", I0, ")"/)') ix, i
END DO
DO i=1,5
WRITE(*, '("ix(",I0,") = ", I0)') i, Iarray(i)
END DO

CALL DeallocIArray

END PROGRAM TestDynamicAllocationFunctionArguments

!****
!
! Increase the size of the dynamically allocated array
! by one. Keep all of the old values, and store a
! value of zero in the new element
!
!****
SUBROUTINE ResizeIArray
USE DynamicIntegerArray

IMPLICIT NONE

INTEGER, DIMENSION(:), ALLOCATABLE :: Temp

INTEGER :: AllocateStatus
INTEGER :: i

IF (IArraySize < 0) STOP "*** IArraySize < 0 ***"

IF (IArraySize == 0) THEN
IArraySize = 1
ALLOCATE(Iarray(1),STAT = AllocateStatus)
IF (AllocateStatus /= 0) STOP "*** 1: Allocate failed ***"
ELSE
ALLOCATE(Temp(IArraySize), STAT = AllocateStatus)
IF (AllocateStatus /= 0) STOP "*** 2: Allocate failed ***"

DO i=1,IArraySize
Temp(i) = Iarray(i)
END DO

CALL DeallocIArray

IArraySize = SIZE(Temp) + 1

ALLOCATE(Iarray(IArraySize), STAT = AllocateStatus )
IF (AllocateStatus /= 0) STOP "*** 3: Allocate failed ***"

DO i=1,SIZE(Temp)
Iarray(i) = Temp(i)
END DO

END IF

! The following is not really necessary but I don't like
! any uninitialized stuff anywhere
Iarray(IArraySize) = 0

END SUBROUTINE ResizeIArray

!****
! Subroutine to deallocate the storage for the dynamically
! allocated array in the DynamicIntegerArray module
!****

SUBROUTINE DeallocIArray
USE DynamicIntegerArray

IMPLICIT NONE

INTEGER :: DeAllocateStatus

IF (ALLOCATED(Iarray)) THEN
DEALLOCATE(Iarray, STAT = DeAllocateStatus)
IF (DeAllocateStatus /= 0) &
STOP "*** Trouble deallocating ***"
END IF;

IArraySize = 0

END SUBROUTINE DeallocIArray

Here's a run:

Enter an integer: 42
Stored 42 in Iarray(1)

Enter an integer: 965
Stored 965 in Iarray(2)

Enter an integer: 31
Stored 31 in Iarray(3)

Enter an integer: 12345678
Stored 12345678 in Iarray(4)

Enter an integer: -33
Stored -33 in Iarray(5)

ix(1) = 42
ix(2) = 965
ix(3) = 31
ix(4) = 12345678
ix(5) = -33

Skif
07-26-2008, 03:43 PM
oooo FANTASTIC :D

is perfect thanks