【问题标题】:Fortran macro function for literal string?用于文字字符串的 Fortran 宏函数?
【发布时间】:2015-07-20 18:21:02
【问题描述】:

我需要对各种数据类型名称进行一系列子例程调用。例如:

print*, 'Now giving information about Matrix1'
call mysub(Matrix1, size(Matrix1,1), size(Matrix1,2))
print*, 'About to do function on Matrix1'
call dofunction(Matrix1)
print*, 'Matrix1 is a nice matrix! Huzzah!'

print*, 'Now giving information about Matrix2'
call mysub(Matrix2, size(Matrix2,1), size(Matrix2,2))
print*, 'About to do function on Matrix2'
call dofunction(Matrix2)
print*, 'Matrix2 is a nice matrix! Huzzah!'

print*, 'Now giving information about OtherMat'
call mysub(OtherMat, size(OtherMat,1), size(OtherMat,2))
print*, 'About to do function on OtherMat'
call dofunction(OtherMat)
print*, 'OtherMat is a nice matrix! Huzzah!'

并且我想定义一个宏,它将采用#define 值,以便我可以包装这个调用序列。比如定义一个宏mymacro,我希望能够简单的调用

mymacro(Matrix1)
mymacro(Matrix2)
mymacro(OtherMat)

完成同样的事情。这可能吗?

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 我试过用谷歌搜索如何做到这一点,但一无所获:)

标签: macros fortran


【解决方案1】:

我花了一段时间才为gfortran 工作,因为它不支持#expr

这个想法是使用; 将多个命令放在一行中。当然,这需要禁用通常的行限制。使用gfortran,这是由-ffree-line-length-0 实现的。

然后,gfortran 的预处理器使用"x" 而不是#s(就像所有其他编译器一样)。 结果如下:它正在处理ifortgfortran

#ifdef __GFORTRAN__

#define mymacro(x) print *, "Now giving information about ", "x" ; \
                   call mysub( x, size(x,1), size(x,2) ) ; \
                   print *, "About to do function on ", "x"; \
                   call dofunction(x) ; \
                   print *, "x"," is a nice matrix! Huzzah!"

#else

#define mymacro(x) print *, "Now giving information about ", #x ; \
                   call mysub( x, size(x,1), size(x,2) ) ; \
                   print *, "About to do function on ", #x; \
                   call dofunction(x) ; \
                   print *, #x," is a nice matrix! Huzzah!"

#endif

program main

implicit none
integer :: i(2,2)

i = 123

mymacro(i)

contains

subroutine mysub(ii, N, M)
  integer,intent(in) :: ii(:,:), N, M
  print *,'in mysub:', ii(1,1)
end subroutine

subroutine dofunction(ii)
  integer,intent(in) :: ii(:,:)
  print *,'in dofunction:', ii(1,1)
end subroutine
end program main

【讨论】:

    【解决方案2】:

    这样写一个子程序怎么样:

    subroutine mymacro(matrix, matrixName)
        ! declare matrix, precision should be declare somewhere as a constant
        real(precision), dimension(:,:) :: matrix
        character(*), intent(in) :: matrixname
    
        print*, 'Now giving information about '//matrixname
        call mysub(matrix, size(matrix,1), size(matrix,2))
        print*, 'About to do function on '//matrixname
        call dofunction(matrix)
        print*, matrixname//' is a nice matrix! Huzzah!'
    end subroutine mymacro
    

    它不会完全为您获取矩阵的名称,但足够接近。

    mymacro(matrix)
    

    变成

    call mymacro(matrix,'matrix')
    

    不是很不同,你不觉得吗?

    【讨论】:

    • 不幸的是,我试过了,但我需要一个宏,因为 size 没有被正确调用。
    • 那个尺寸问题有点奇怪。大小到底发生了什么?
    • 我宁愿现在不解决size 的问题,因为这不会回答我最初问题的意图。我正在寻找一个预处理器宏/指令。
    • 如你所愿!我的好奇心可以等待
    • 注意子例程需要一个显式接口(例如通过使其成为模块子例程)可能很有用,因为假定的形状虚拟参数 - 缺少这样的接口可能落后于 OP size 的问题。我绝不会建议使用预处理器来做这么简单的事情。
    【解决方案3】:

    宏本身不是 Fortran 的一部分。大多数(如果不是全部)编译器只需重用 C 预处理器即可实现它们。我从这里学到: https://gcc.gnu.org/onlinedocs/cpp/Macros.html

    这可能会奏效:(未经测试!)

    #define MYSUB(m) write(*,*) "Now giving information about ", #m;  \
                     call mysub(m, size(m,1), size(m,2) ); \
                     write(*,*) "About to do function on ",#m; \
                     call dofunction(m) ; \
                     write(*,*) #m , "is a nice matrix! Huzzah!" ;
    

    请注意,您必须使用适当的编译器标志才能让编译器运行预处理器。

    【讨论】:

    • 很遗憾,这不适用于gfortran,因为它不支持#m。我花了很长时间才弄清楚 - 请参阅下面的答案......
    猜你喜欢
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多