wahorger
Joined: 13 Oct 2014 Posts: 1226 Location: Morrison, CO, USA
|
Posted: Tue Apr 27, 2021 6:44 pm Post subject: Using PACK |
|
|
First off, this is NOT a bug report or a request for action!
I like using PACK(). It is an easy, understandable way to select data from arrays and reorganize the data.
It is an easy way, in well-defined lists, to select an item and move it to the top of the list. I was doing that with file extents (for get_filtered_file@() usage. Since I cannot select a specific file specification to match an already defined file, I am re-organizing the list, matching the file extent of the file to the list of potential file extents.
As an example, if my file choices are *.txt, *.dat, and *.*, and the file ends in .dat, I will reorder the sequence to be *.dat, *.txt, and *.*.
There are two methods shown in the sample code below. Method 1 just PACK()'s the data using what I term as a "direct memory move". The second method generates a vector of indices, then moves the data. Method 1 yields different results from Method 2 (Method 2 is correct). I am posting this to give a "heads up". As always, moving data onto itself is risky, regardless of the technique used. It is especially problematic when you cannot control the moves (i.e. relying on the compiler writer to do it the way you might want).
Code: | program main
character*5:: fspec(3)
integer:: i
fspec(1) = '*.txt'; fspec(2)= '*.dat'; fspec(3) = '*.*'
call reorder1(fspec,3,'*.dat')
do i=1,3 ; print *,'Spec=',fspec(i) ; end do
fspec(1) = '*.txt'; fspec(2)= '*.dat'; fspec(3) = '*.*'
call reorder2(fspec,3,'*.dat')
do i=1,3 ; print *,'Spec=',fspec(i) ; end do
end
subroutine reorder1(fspec,nf,first)
integer:: nf
character*(*):: fspec(nf),first
character*(len(fspec(1))):: spec(1)
integer :: i, n_index(nf)
! make sure the integer array is properly built
do i=1,nf ; n_index(i) = i ; end do
print *,'Reorder 1: Move the data directly'
print *,'Index to move to the top =',pack(n_index,fspec.eq.first)
print *,' Indices to keep below =',pack(n_index,fspec.ne.first)
! this does not compile unless you specify spec as a vector
spec(1:1) = fspec(pack(n_index,fspec.eq.first))
fspec(2:nf) = pack(fspec,fspec.ne.first)
fspec(1) = spec(1)
return
end
subroutine reorder2(fspec,nf,first)
integer:: nf
character*(*):: fspec(nf),first
character*(len(fspec(1))):: spec(1)
integer :: i, n_index(nf)
! make sure the integer array is properly built
do i=1,nf ; n_index(i) = i ; end do
print *,'Reorder 2: Use integer vector to move data'
print *,'Index to move to the top =',pack(n_index,fspec.eq.first)
print *,' Indices to keep below =',pack(n_index,fspec.ne.first)
! this does not compile unless you specify spec as a vector
spec(1:1) = fspec(pack(n_index,fspec.eq.first))
fspec(2:nf) = fspec(pack(n_index,fspec.ne.first))
fspec(1) = spec(1)
return
end
|
Results:
Quote: |
Reorder 1: Move the data directly
Index to move to the top = 2
Indices to keep below = 1 3
Spec=*.dat
Spec=*.dat
Spec=*.*
Reorder 2: Use integer vector to move data
Index to move to the top = 2
Indices to keep below = 1 3
Spec=*.dat
Spec=*.txt
Spec=*.* |
|
|