问题
I am wanting to mask a Fortran array. Here's the way I am currently doing it...
where (my_array <=15.0)
mask_array = 1
elsewhere
mask_array = 0
end where
So then I get my masked array with:
masked = my_array * mask_array
Is there a more concise way to do this?
回答1:
Use the MERGE intrinsic function:
masked = my_array * merge(1,0,my_array<=15.0)
回答2:
Or, sticking with where
,
masked = 0
where (my_array <=15.0) masked = my_array
I expect that there are differences, in speed and memory consumption, between the use of where
and the use of merge
but off the top of my head I don't know what they are.
回答3:
There are two different approaches already given here: one retaining where and one using merge. In the first, High Performance Mark mentions that there may be differences in speed and memory use (think about temporary arrays). I'll point out another potential consideration (without making a value judgment).
subroutine work_with_masked_where(my_array)
real, intent(in) :: my_array(:)
real, allocatable :: masked(:)
allocate(masked(SIZE(my_array)), source=0.)
where (my_array <=15.0) masked = my_array
! ...
end subroutine
subroutine work_with_masked_merge(my_array)
real, intent(in) :: my_array(:)
real, allocatable :: masked(:)
masked = MERGE(my_array, 0., my_array<=15.)
! ...
end subroutine
That is, the merge
solution can use automatic allocation. Of course, there are times when one doesn't want this (such as when working with lots of my_array
s of the same size: there are often overheads when checking array sizes in these cases): use masked(:) = MERGE(...)
after handling the allocation (which may be relevant even for the question code).
来源:https://stackoverflow.com/questions/28637105/better-way-to-mask-a-fortran-array