如何简化这个Fortran功能?

时间:2014-12-07 13:05:38

标签: function fortran

我有以下代码来计算连续性的数量 来自第一个的逻辑。我想简化这个功能。有 我一直在想,或许我可以用某种方式使用递归,但现在却相当 当然。这可能吗?

Function count_present              & 
  (                                 &
    p1, p2, p3, p4, p5, p6, p7, p8  &
  )                                 &
    Result (n)

Logical, Intent (in) :: p1
Logical, Intent (in), Optional :: p2, p3, p4, p5, p6, p7, p8 

Integer :: n

n = 0

If (Present (p8)) Then

  If      (p8) Then; n = 8
  Else If (p7) Then; n = 7
  Else If (p6) Then; n = 6
  Else If (p5) Then; n = 5
  Else If (p4) Then; n = 4
  Else If (p3) Then; n = 3
  Else If (p2) Then; n = 2
  Else If (p1) Then; n = 1
  End If

Else If (Present (p7)) Then

  If      (p7) Then; n = 7
  Else If (p6) Then; n = 6
  Else If (p5) Then; n = 5
  Else If (p4) Then; n = 4
  Else If (p3) Then; n = 3
  Else If (p2) Then; n = 2
  Else If (p1) Then; n = 1
  End If

Else If (Present (p6)) Then

  If      (p6) Then; n = 6
  Else If (p5) Then; n = 5
  Else If (p4) Then; n = 4
  Else If (p3) Then; n = 3
  Else If (p2) Then; n = 2
  Else If (p1) Then; n = 1
  End If

Else If (Present (p5)) Then

  If      (p5) Then; n = 5
  Else If (p4) Then; n = 4
  Else If (p3) Then; n = 3
  Else If (p2) Then; n = 2
  Else If (p1) Then; n = 1
  End If

Else If (Present (p4)) Then

  If      (p4) Then; n = 4
  Else If (p3) Then; n = 3
  Else If (p2) Then; n = 2
  Else If (p1) Then; n = 1
  End If

Else If (Present (p3)) Then

  If      (p3) Then; n = 3
  Else If (p2) Then; n = 2
  Else If (p1) Then; n = 1
  End If

Else If (Present (p2)) Then

  If      (p2) Then; n = 2
  Else If (p1) Then; n = 1
  End If

Else

  If (p1) n = 1

End If

End Function count_present

2 个答案:

答案 0 :(得分:1)

这是一个使用merge和一个简单循环(没有递归)的小解决方案:

module test_mod
  interface merge
    module procedure custom_merge
  end interface

contains

! Use custom merge as TSOURCE might not be present
elemental function custom_merge( TSOURCE, FSOURCE, MASK ) result(res)
  implicit none
  logical,intent(in),optional :: TSOURCE
  logical,intent(in)          :: FSOURCE
  logical,intent(in)          :: MASK
  logical                     :: res

  if ( MASK ) then
    if ( present(TSOURCE) ) then
      res = TSOURCE
    else
      res = .false.
    endif
  else
    res = FSOURCE
  endif
end function

function count_present ( p1, p2, p3, p4, p5, p6, p7, p8  ) result(n)
  implicit none
  logical,intent (in)           :: p1
  logical,intent (in),optional  :: p2, p3, p4, p5, p6, p7, p8 
  integer                       :: n
  logical                       :: arr(1:8)
  integer                       :: i

  arr(1) = p1
  arr(2) = merge( p2, .false., present(p2) )
  arr(3) = merge( p3, .false., present(p3) )
  arr(4) = merge( p4, .false., present(p4) )
  arr(5) = merge( p5, .false., present(p5) )
  arr(6) = merge( p6, .false., present(p6) )
  arr(7) = merge( p7, .false., present(p7) )
  arr(8) = merge( p8, .false., present(p8) )

  n = 0
  do i=1,size(arr)
    if ( arr(i) ) n = i
  enddo
end function
end module

program test_prog
  use test_mod
  implicit none

  print *,count_present(.true., p3=.true., p4=.false.)
end program

答案 1 :(得分:1)

可以使用递归来编写它。注意

count_present(p_1, p_2, ..., p_n, p_{n+1})

返回值count_present(p_1, p_2, ..., p_n),除非所有p_1,...,p_{n+1}都存在且.TRUE.。在后一种情况下,结果为n+1。如果count_present(p_1)1,则p_1会返回.TRUE.,否则会返回0

recursive function count_present(p1, p2, p3, p4, p5, p6, p7, p8) result (res)
  logical, intent(in) :: p1, p2, p3, p4, p5, p6, p7, p8
  optional p2, p3, p4, p5, p6, p7, p8
  integer res

  if (PRESENT(p8)) then
    res = count_present(p1, p2, p3, p4, p5, p6, p7)
    if (res.eq.7.and.p8) res = res+1
  else if (PRESENT(p7)) then
    res = count_present(p1, p2, p3, p4, p5, p6)
    if (res.eq.6.and.p7) res = res+1
  else if (PRESENT(p6)) then
    res = count_present(p1, p2, p3, p4, p5)
    if (res.eq.5.and.p6) res = res+1
  else if (PRESENT(p5)) then
    res = count_present(p1, p2, p3, p4)
    if (res.eq.4.and.p5) res = res+1
  else if (PRESENT(p4)) then
    res = count_present(p1, p2, p3)
    if (res.eq.3.and.p4) res = res+1
  else if (PRESENT(p3)) then
    res = count_present(p1, p2)
    if (res.eq.2.and.p3) res = res+1
  else if (PRESENT(p2)) then
    res = count_present(p1)
    if (res.eq.1.and.p2) res = res+1
  else
    res = COUNT([p1])
  end if
end function count_present

这是个好主意吗?嗯,这是另一个问题。