soccer jersey forums.silverfrost.com :: View topic - Allocate on assignment to grow an array.
forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Allocate on assignment to grow an array.
Goto page Previous  1, 2
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8011
Location: Salford, UK

PostPosted: Fri Jan 26, 2024 4:47 pm    Post subject: Reply with quote

Ken

It fails for me so I have added it to the list.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8011
Location: Salford, UK

PostPosted: Fri Jan 26, 2024 6:39 pm    Post subject: Reply with quote

This runs correctly:

Code:
real, allocatable :: a(:)
integer n, i
n = 10
a = [ (real(i),i=1,n) ]
print*, allocated(a)
print*, a
end
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8011
Location: Salford, UK

PostPosted: Sat Jan 27, 2024 9:02 am    Post subject: Reply with quote

FTN95 has been fixed for the next release so that this will work...

Code:
real, allocatable :: a(:)
integer n, i
n = 10
a = [ (i,i=1,n) ]
print*, allocated(a)
end
Back to top
View user's profile Send private message AIM Address
Kenneth_Smith



Joined: 18 May 2012
Posts: 709
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Sat Jan 27, 2024 9:51 am    Post subject: Reply with quote

Thanks Paul, I think that will fix John's issue.
Back to top
View user's profile Send private message Visit poster's website
JohnCampbell



Joined: 16 Feb 2006
Posts: 2580
Location: Sydney

PostPosted: Sat Jan 27, 2024 2:17 pm    Post subject: Reply with quote

Thanks Paul for finding the source of the error.
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2580
Location: Sydney

PostPosted: Sun Jan 28, 2024 10:03 am    Post subject: Reply with quote

Expanding on my "Saturday devilry" and including a variant of Ken's suggestion of MOVE_ALLOC, the following code example does not compile with updated FTN95 Ver 9.00.
Code:
  subroutine auto_alloc ( a, nn )     ! using auto-allocate

!  extend vector A by nn using auto-allocate

    real, allocatable, intent(inout) :: a(:)
    integer, intent(in) :: nn
    real, allocatable :: extra(:)
    real, allocatable :: copy(:)
    integer na

!    allocate ( extra(nn) )
    extra = [ (0.0, i=1,nn) ]
    if ( allocated (a) ) then
       na = size(a)
       call move_alloc ( a, copy )
       a = [ copy, extra ]
    else
       na = 0
       a = extra
    end if
    write (*,fmt='(a,i0,a,i0)') 'Auto-Extend A from ',na,' to ',na+nn

  end subroutine auto_alloc


But using " a = [ a, extra ]" does compile.

Would the use of MOVE_ALLOC be a more conservative approach, when available ?
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8011
Location: Salford, UK

PostPosted: Sun Jan 28, 2024 11:12 am    Post subject: Reply with quote

John

At the moment the FTN95 implementation of MOVE_ALLOC does not allow for this construction. Hopefully it can be fixed fairly soon.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8011
Location: Salford, UK

PostPosted: Tue Jan 30, 2024 4:54 pm    Post subject: Reply with quote

This failure with MOVE_ALLOC has now been fixed for the next release of FTN95.
Back to top
View user's profile Send private message AIM Address
JohnCampbell



Joined: 16 Feb 2006
Posts: 2580
Location: Sydney

PostPosted: Wed Jan 31, 2024 1:25 am    Post subject: Reply with quote

Thanks Paul and Ken for this thread.

The following are 3 alternatives for extending a vector size by nn, using either:
* FTN95+ but no auto allocate
* using auto allocate, but making a copy first
* using auto allocate, allowing compiler to manage copy

I am not sure which is best. If hidden in a library, the first is the most conservative approach ?
Code:
program extend
  use iso_fortran_env
  implicit none
  real, allocatable :: a(:)
  integer i

  write (*,*) compiler_version ()

  do i = 1, 5
    select case ( mod(i,3) )
      case (0)
        call extend_alloc_auto ( a, 5000 )
      case (1)
        call extend_alloc_move ( a, 500 )
      case (2)
        call extend_alloc_no_auto ( a, 500 )
    end select
    print*, size(a), a(size(a))
  end do

contains

  subroutine extend_alloc_no_auto ( a, nn )     ! with no auto-allocate

!  extend vector A by nn without auto-allocate
 
    real, allocatable, intent(inout) :: a(:)
    integer, intent(in) :: nn
    real, allocatable :: copy(:)
    integer na

    if ( allocated (a) ) then
       na = size(a)
       allocate ( copy(na) )
       copy = a
       deallocate ( a )
       allocate ( a(na+nn) )
       a(1:na)  = copy
       a(na+1:) = 0
       deallocate ( copy )
    else
       allocate ( a(nn) )
       a = 0
    end if
    write (*,*) 'extend_alloc_no_auto', size(a)

  end subroutine extend_alloc_no_auto

  subroutine extend_alloc_move ( a, nn )     ! using move_alloc

!  extend vector A by nn using auto-allocate

    integer, intent(in) :: nn
    real, allocatable, intent(inout) :: a(:)
    real, allocatable :: extra(:)
    real, allocatable :: copy(:)

!    allocate ( extra(nn) )
    extra = [ (0.0, i=1,nn) ]
    if ( allocated (a) ) then
       call move_alloc ( a, copy )
       a = [ copy, extra ]
    else
       a = extra
    end if
    write (*,*) 'extend_alloc_move', size(a)

  end subroutine extend_alloc_move

  subroutine extend_alloc_auto ( a, nn )     ! using auto-allocate

!  extend vector A by nn using auto-allocate

    real, allocatable, intent(inout) :: a(:)
    integer, intent(in) :: nn
    real, allocatable :: extra(:)
    real, allocatable :: copy(:)

    extra = [ (0.0, i=1,nn) ]
    if ( allocated (a) ) then
       a = [ a, extra ]
    else
       a = extra
    end if
    write (*,*) 'extend_alloc_auto', size(a)

  end subroutine extend_alloc_auto

end program extend
Back to top
View user's profile Send private message
Kenneth_Smith



Joined: 18 May 2012
Posts: 709
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Wed Jan 31, 2024 1:54 pm    Post subject: Reply with quote

John,

It gets interesting if the lower bound of the source array is not 1. Hopefully this example illustrates this particular devilry.
Code:
real, allocatable :: a(:), b(:), c(:), d(:)

allocate(a(-10:-8))

! Assign some data so checkmate does not complain
a = [1,2,3]

print*, lbound(a)                ! -10

! No array constructor
b = a
print*, lbound(b)                ! -10

! With array constructor []
c = [a]                         
print*, lbound(c)                ! 1

! With move_alloc
call move_alloc(a,d)
print*, lbound(d)               ! -10

end
Back to top
View user's profile Send private message Visit poster's website
JohnCampbell



Joined: 16 Feb 2006
Posts: 2580
Location: Sydney

PostPosted: Fri Feb 02, 2024 3:27 am    Post subject: Reply with quote

Hi Ken,

Thanks for highlighting an added complexity of changing the lower bound of an allocatable array !

Not something I want to address ( as I find Fortran's support of non-default lower bounds to be unfriendly )

John
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group