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 + CHARACTER variables + TRANSFER

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
Kenneth_Smith



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

PostPosted: Fri Apr 28, 2023 12:29 am    Post subject: Allocate on assignment + CHARACTER variables + TRANSFER Reply with quote

I think there is an issue with the new Fortran 2003 Allocate on assignment for CHARACTER variables, when the array is defined by the result of the TRANSFER intrinsic.

Having never used TRANSFER before this evening it's definitely not a critical issue of me. Just experimenting after getting a little bit further into one of the (now old) text books by Metcalf and Reid.
Code:
program t
implicit none
character(len=1), allocatable :: info(:)
integer                       :: lengthData
real                          :: r = 5.0
real                          :: x = -999.0

!
! This works in FTN95
!
  info=['A','B','C']                    ! Allocate on assignment works in this case
  print*, 'Info = ', info
  deallocate(info)
  print*
                                        ! Now use TRANSFER intrinsic
                                       
  print*, 'Value of R is  ', r          ! 1. Print value of R
  lengthData = size(transfer(r, info))  ! 2. Find size of required character array
  allocate(info(lengthData))            ! 3. Allocate array
  info = transfer(r, info)              ! 4. Do transfer R to array
  print*, 'Size of array  ',size(info)  ! 5. Print size of array
  print*, 'Info string is ',info        ! 6. Print array
  x = transfer(info,r)                  ! 7. Do transfer array to X
  print*, 'Value of X is  ', x          ! 8. Print value of X
  deallocate(info)
  print*
!
! This alternative fails in FTN95 where steps 2, 3 and 4 are done
! in a single line of code
!
  x = -999.0
  print*, 'Value of R is  ', r          ! 1. Print value of R
  info = transfer(r,info)               !    Access violation occurs here ###
  print*, 'Size of array  ',size(info)  ! 5. Print size of array
  print*, 'Info string is ',info        ! 6. Print array
  x = transfer(info,r)                  ! 7. Do transfer array to X
  print*, 'Value of X is  ', x          ! 8. Print value of X
  deallocate(info)
end program t
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


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

PostPosted: Fri Apr 28, 2023 7:51 am    Post subject: Reply with quote

Ken

Thanks for the feedback.

This sample code does not produce sensible results when compiled with gFortran or iFort so I am guessing that there is something wrong with it.

I am not that familiar with the TRANSFER function and at first sight I don't understand what is intended.
Back to top
View user's profile Send private message AIM Address
Kenneth_Smith



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

PostPosted: Fri Apr 28, 2023 11:46 am    Post subject: Reply with quote

Thanks Paul,

I have set myself the task of investigating parts of the language which I never used before, and I may be going a bit of course here.

The code should be equivalent to the single line X=R, which is achieved in the first part of the example with FTN95. Basically R is TRANSFERed to the character array INFO, and then TRANSFERed from INFO to X.

The printed output for INFO is meaningless. I cannot figure out how to print the bit pattern for the elements of INFO to the terminal, as in:
Code:
character(len=1) :: a(3) = ['A','B','C']
print'(3B8)', a(1), a(2), a(3)
end


Should this not return: 1000001 1000010 1000011 ?

Binary 1000001 = 65 in decimal, IACHAR('A') = 65

Perhaps the use of the B format code to characters is a recent addition to the language, or an extension in gFortran?

PS Sometime later I asked myself another "what happens if" question:

Code:
program p
integer, parameter :: sp = kind(1.0), dp=kind(1.d0)
real(sp)    :: rs = 1.0
real(dp)    :: rd = 1.d0
complex(sp) :: cs =cmplx(1.0,0.0)
complex(dp) :: cd =cmplx(1.d0,0.d0,kind=dp)
print'(A,B32)' , 'rs',rs
print'(A,B64)' , 'rd',rd
print'(A,2B32)', 'cs',cs
print'(A,2B64)', 'dc',cd
end program p


This is valid in gFortran.
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


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

PostPosted: Fri Apr 28, 2023 2:39 pm    Post subject: Reply with quote

Ken

When I see

lengthData = size(transfer(r, info))

I ask what is transfer(r, info)? r is REAL and contains the floating point representation of the single precision 5.0. The result has the same bit pattern as this but with the type changed to that of info. But then info is a 1-dimensional CHARACTER array of unknown length.

Is this meaningful and what its intended?
Back to top
View user's profile Send private message AIM Address
Kenneth_Smith



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

PostPosted: Fri Apr 28, 2023 4:36 pm    Post subject: Reply with quote

Paul, firstly apologies for taking up your time.

TRANSFER (SOURCE, MOLD [, SIZE])

According to Metcalf:

“ …. when SIZE is absent, the result is scalar if MOLD is scalar, and it is of rank one and size just sufficient to hold all of SOURCE if MOLD is array-valued.”

The draft Fortran 95 standard says:

“If MOLD is array valued and SIZE is absent, the result is array valued and of rank one. Its size is as small as possible such that its physical representation is not shorter than that of SOURCE

I think these two extracts both have the same meaning, and imply that lengthData = size(transfer(r, info)) is a valid Fortran construction.

The form: lengthData = size(transfer(r, info)) also appears in this discussion of a generic linked list module implemented in Fortran 95:

https://jblevins.org/research/generic-list.pdf

In this case MOLD is integer, but the type of MOLD does not matter for the purpose of storing a collection of bits.

However, even with info defined as integer(kind=1), (which is probably more logical and fixes the problem printing the bit pattern), the allocate on assignment still fails.
Code:
program t2
implicit none
integer(kind=1), allocatable :: info(:)
integer                      :: lengthData,i
real                         :: r = 5.0
real                         :: x = -999.0

  print*, 'Value of R is  ', r          ! 1. Print value of R
  lengthData = size(transfer(r, info))  ! 2. Find size of required character array
  allocate(info(lengthData))            ! 3. Allocate array
  info = transfer(r, info)              ! 4. Do transfer R to array
  print*, 'Size of array  ',size(info)  ! 5. Print size of array
  do i = 1, lengthData                  ! 6. Print array
    print'(B8)', info(i)
  end do 
  x = transfer(info,r)                  ! 7. Do transfer array to X
  print*, 'Value of X is  ', x          ! 8. Print value of X
  deallocate(info)
  print*
 
  print*, 'Value of R is  ', r                   ! 1. Print value of R
  info = transfer(r,info)                        ! 2, 3, 4
  print*, 'Size of array  ',size(info)           ! 5. Print size of array
  print*, 'Info string (bit pattern) is '        ! 6. Print array
  do i = 1, size(info)
    print'(B8)', info(i)
  end do
  x = transfer(info,r)                           ! 7. Do transfer array to X
  print*, 'Value of X is  ', x                   ! 8. Print value of X
  deallocate(info)
end program t2


Enjoy the weekend and don’t worry about the TRANSFER intrinsic, the dearth of information google finds on this subject tells me its little used.
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


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

PostPosted: Fri Apr 28, 2023 8:21 pm    Post subject: Reply with quote

Ken

I am beginning to understand what is expected. The C language has sizeof and Fortran 2008 has C_SIZEOF and this could provide a simpler approach.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


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

PostPosted: Sat Apr 29, 2023 7:56 am    Post subject: Reply with quote

Here is a sample that illustrates the concept...

Code:
program main
use iso_c_binding
integer,parameter::k=selected_int_kind(2)
integer(k),allocatable::info(:)
integer(k)::v
integer::r = 16+256+1024
isize = c_sizeof(r)/c_sizeof(v)
print*, k, isize
allocate(info(isize))
info = transfer(r, info)
write(*,"(z6)") r
print*, "=============="
do i=isize,1,-1
  write(*, "(z6)") info(i)
end do 
end program main


On this basis it might be relatively easy to get FTN95 to do the "allocate on assignment" for the TRANSFER function.
Back to top
View user's profile Send private message AIM Address
Kenneth_Smith



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

PostPosted: Sun Apr 30, 2023 12:16 pm    Post subject: Reply with quote

Paul,

Thanks for the sample program, it took me some time to understand the code.

My main concern here was to highlight that the new feature i.e. allocate on assignment failed with TRANSFER.

As there is an easy alternative work around (find the required SIZE and ALLOCATE before TRANSFER), and the probability of another user finding this particular issue must be relatively low, perhaps this fix should be deferred to a low position on the wish list i.e. one for when available time/resources permit. In other words, nice to have but not a priority.

Enjoy what remains of the long bank holiday weekend.
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


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

PostPosted: Tue May 30, 2023 2:06 pm    Post subject: Reply with quote

FTN95 has now been extended for the next release so that it will handle this "allocate on assignment" (AOA) for the TRANSFER intrinsic.

Note that, by default, FTN95 does not do AOA when the associated variable is explicitly ALLOCATEd (in the current subprogram) prior to the assignment.

This provides some protection against the impact of AOA on existing code.

So the explicit ALLOCATE in the above code will prevent the following AOA.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
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