开发者

How to arrange elements of vector in Fortran?

开发者 https://www.devze.com 2022-12-15 16:55 出处:网络
I have two p*n arrays, y and ymiss. y contains real numbers and NA\'s. ymiss contains 1\'s and 0\'s, so that if y(i,j)==NA, ymiss(i,j)==0, and 1 otherwise. I also have 1*n array ydim which tells how m

I have two p*n arrays, y and ymiss. y contains real numbers and NA's. ymiss contains 1's and 0's, so that if y(i,j)==NA, ymiss(i,j)==0, and 1 otherwise. I also have 1*n array ydim which tells how many real numbers there is at y(1:p,n), so ydim has values 0 to p

In R programming language, I can do following:

if(ydim!=p && ydim开发者_如何学JAVA!=0)  
  y(1:ydim(t), t) = y(ymiss(,t), t)

That code arranges all real numbers of y(,t) in like this

first there's for example y(,t) = (3,1,NA,6,2,NA) after the code it's y(,t) = (3,1,6,2,2,NA)

Now I will only need those first 1:ydim(t), so it doesn't matter what those rest are.

The question is, how can I do something like that in Fortran?

Thanks,

Jouni


The "where statement" and the "merge" intrinsic function are powerful, operating on selected positions in arrays, but they don't move items to the front of an array. With old-fashioned code with explicit indexing (could be packaged into a function) e.g.:

k=1
do i=1, n
   if (ymiss (i) == 1) then
      y(k) = y(i)
      k = k + 1
   end if
end do

What you want could be done with array intrinsics using the "pack" intrinsic. Convert ymiss into a logical array: 0 --> .false., 1 --> .true.. Then use code like (tested without the second index):

y(1:ydim(t), t) = pack (y (:,t), ymiss (:,t))


Edit to add example code, showing use of Fortran intrinsics "where", "count" and "pack". "where" alone can't solve the problem, but "pack" can. I used "< -90" as NaN for this example. The step "y (ydim+1:LEN) = -99.0" isn't required by the OP, who doesn't need to use these elements.

program test1

integer, parameter :: LEN = 6
real, dimension (1:LEN) :: y = [3.0, 1.0, -99.0, 6.0, 2.0, -99.0 ]
real, dimension (1:LEN) :: y2
logical, dimension (1:LEN) :: ymiss
integer :: ydim

y2 = y
write (*, '(/ "The input array:" / 6(F6.1) )' )  y

where (y < -90.0)
   ymiss = .false.
elsewhere
   ymiss = .true.
end where

ydim = count (ymiss)

where (ymiss) y2 = y
write (*, '(/ "Masking with where does not rearrange:" / 6(F6.1) )' )  y2

y (1:ydim) = pack (y, ymiss)
y (ydim+1:LEN) = -99.0
write (*, '(/ "After using pack, and ""erasing"" the end:" / 6(F6.1) )' )  y


stop

end program test1

Output is:

The input array: 3.0 1.0 -99.0 6.0 2.0 -99.0

Masking with where does not rearrange: 3.0 1.0 -99.0 6.0 2.0 -99.0

After using pack, and "erasing" the end: 3.0 1.0 6.0 2.0 -99.0 -99.0


In Fortran you can't store na in an array of real numbers, you can only store real numbers. So you'll probably want to replace na's with some value not likely to be present in your data: huge() might be suitable. 2D arrays are no problem at all for Fortan. You might want to use a 2D array of logicals to replace ymiss rather than a 2D array of 1s and 0s.

There is no simple, intrinsic to achieve what you want, you'd need to write a function. However, a more Fortran way of doing things would be to use the array of logicals as a mask for the operations you want to carry out.

So, here's some fragmentary Fortran code, not tested:

! Declarations
real(8), dimension(m,n) :: y, ynew
logical, dimension(m,n) :: ymiss

! Executable
where (ymiss) ynew = func(y)  ! here func() is whatever your function is
0

精彩评论

暂无评论...
验证码 换一张
取 消