仓库源文站点原文


layout: post title: 【转】Fortran的奇淫技巧 categories:


原文: Fortran Cookbook:收集Fortran的奇淫技巧

本人准备写一本关于Fortran语言技巧的资料, 草稿提纲如下:

常用内置函数

数组操作

  1. 数组置零:

    1. A=0
  2. 数组切片置零:

    1. 某列置零A(:, 2)=0
    2. 某行置零A(2,:)=0
    3. 奇数行置零A(1::2,:)=0
    4. 奇数行偶数列置零: A(1::2,2::2)=0
  3. 数组Copy:

    1. 整体Copy:A=B
    2. 部分切片复制:A=C(1:10:2, :)
  4. 数组运算

    1. 加法:A=B+C
    2. 乘法:A=B*C
    3. 除法:A=B/C
    4. 矩阵乘法:A=matmul(B,C)
  5. IO读写:

    1. write(11) A
    2. read(11) A
    3. write(11) A(:,2)
    4. read(11) A(:,2)

说明

代码阅读、调试、编译、链接

  1. implicit none.
    Fortran默认情况下变量是不需要声明, 调试程序的时候多数人会遇见因为拼写错误, 获得一些异常结果, 将变量声明打开, 编译时会检查出这类错误.

  2. namelist.
    名字列表在调试期间和测试期间比较有用, 它可以将多个变量捆成一组, 进行集中输出和输入. 有些情况下可以用namelist代替命令行参数传入:将需要的参数以namelist的方式传入程序, 避免了繁琐的参数解析过程!

    namelist确实很方便, 比如对于数组A(3,2), 可以使用类似 A(1:3,2) = 5,3,4 A(1:3,1) = 2,0,9 或者 A = 2,0,9,5,3,4 这样的方式来输入

    namelist在调试和测试中使用是非常不错的!举个例子:

    program main
      implicit none
      integer ::a
      real(4)::x
      real(8)::y
      
      namelist /debug1/ a
      namelist /debug2/ x, y
      namelist /debug3/ a, x, y
      
      a=100
      x=1.1111_4
      y=2.2222_8
      
      write(*, nml=debug1)
      write(*, nml=debug2)
      write(*, nml=debug3)  
    end program main
    
  3. Preprocess.
    Fortran支持类C的预处理, fpp, 在调试程序时较有用处.

  4. Emacs.
    Emacs内置Fortran语言支持, 编码和调试都可在Emacs下进行.

  5. understand for fortran 是阅读代码不错的工具软件, 类似SourceInsight

    understand for fortran是要钱的, 破解找起来比较烦. 建议使用Doxygen生成HTML文档, 所有的调用/被调用, 引用关系全部能够生成. 在浏览器里面点点就知道程序的结构了.

  6. linux工具:gdb, ddd, nm, ldd, od.
    gdb+ddd通用调试工具; nm可以看目标文件的符号等信息, 可以帮助诊断连接中的问题, 比如找不到符号; ldd能用来看程序需要的共享库信息; od能直接看二进制文件内容.

文件IO

  1. 创建临时文件: open(unit=11, status='scratch',...)

  2. 查看IO操作状态

    1. IO操作返回值:open(unit=11, iostat=stat, ...), 检查整数stat的值, 可以确定IO操作的成功与否!
    2. EOF、ERR
    3. 说明: Fortran的IO操作是可以返回状态的, 以检查操作成功与否, 在健壮性要求较高的程序中, 一般都应该检查这些值
  3. 流文件(二进制文件)

    1. 打开二进制文件:open(unit=11, access='stream',...)
    2. 将数组写入二进制打开的文件:write(unit=11) A
    3. 从二进制文件读数组: read(unit=11) A
    4. 说明. 传统的Fortran文件读写都是基于记录的, 不管是有格式的还是无格式的, 新标准支持二进制读写, 和C语言很类似
  4. 异步IO

    1. 异步打开文件:open(unit=11, asynchronous='yes',...)
    2. 异步写:write(unit=11, id=handle, asynchronous='yes',....) ....
    3. 异步读:read(unit=11, id=handle, asynchronous='yes',....) .....
    4. 等待异步IO完成:wait(unit=11, id=handle)
    5. 说明: 如果文件中有大块数据的IO操作, 用异步IO能在一定程度上使计算和磁盘IO重叠进行, 提高效率!
  5. 第三方库

    1. MPI-IO:MPI-IO提供一套类似C语言的IO函数, 如果在MPI_File_open()中指定comm是MPI_COMM_SELF, 就相当于操作本地文件.
    2. HDF5:
    3. NetCDF、PnetCDF:
    4. 说明: HDF5、NetCDF、PnetCDF都提供结构化的存储模式, 而且都提供并行IO操作接口.

浮点数运算(提纲)

  1. 浮点运算异常

    1. 除零
    2. 向下溢出
    3. 向上溢出
    4. 捕获浮点运算异常
    5. 查询浮点数信息:Fortran内置函数
    6. IEEE浮点数标准
    7. IEEE浮点数异常控制
    8. IEEE_FEATURES
    9. IEEE_EXCEPTIONS
    10. IEEE_ARITHMETIC
  2. 浮点数运算

    1. 不满足结合律, 运算次序非常重要:(A+B)+C .NEQ. A+(B+C)
    2. 舍入误差
    3. 差不多的两数相减
    4. 避免进行等于比较: A .EQ. B 5.数组求和:使用内置函数SUM
    5. HYPOT计算: SQRT(X2+Y2)
    6. 二次方程求根
    7. 三角形面积:海伦公式
    8. 对数函数:Ln(1+X)
    9. X2-Y2
    10. 级数求和
    11. 特殊情况特殊对待
    12. 使用扩展精度
    13. 带符号零
    14. 浮点运算的Guard Bits
    15. 相对误差
    16. 绝对误差
    17. 特殊数: -NaN, +NaN, -Infinity, +Infinity
    18. 极大极小值: HUGE, TINY, EPSILON

参考

  1. David, Goldberg, What Every Computer Scientist Should Know About Floating-Point Arithmetic
  2. D.Knuth
  3. IEEE 754
  4. The Fortran 2003 Handbook
  5. Fortran 90,95 Explained