NAG Fortran 编译器常见问题

  1. 如何使用 CDABS, DCMPLX, DCONJG, DIMAG DREAL? Answer.
  2. 有提供诸如 CDEXP 这样的非标准 Fortrna 的内建函数吗? Answer.
  3. 编译器中有提供 DTIMEETIME 函数吗? Answer.
  4. 有提供 FLUSH 函数吗? Answer.
  5. 有提供 GETENV 函数吗? Answer.
  6. 有提供 SYSTEM 函数吗? Answer.
  7. 我可以在 format 中使用 ‘$’ 禁止输出新的一行吗? Answer.
  8. 我如何能够没有错误的编译非常旧的 Fortran 程序 (Fortran 66/77)? Answer.
  9. 为什么会出现 "TAB format input" 警告讯息,这是甚么意思? Answer.
  10. 警告讯息 "Byte count on numeric data type" 是甚么意思? Answer.
  11. 为什么在 NAG Fortran 编译器中会得到错误讯息 "KIND value does not specify a valid representation method"? Answer.
  12. 警告讯息 "Buffer overflow on output" 表示甚么? Answer.
  13. 为什么会发生 “Variable X size of N bytes is too big” 的讯息? Answer.
  14. 我如何控制 (PARAMETER) 参数的大小? Answer.
  15. 当我执行混合编程项目时,甚么是 f90_initf90_io_finish 函数? Answer.
  16. 当程序中断时,出现 “Floating underflow occurred” 讯息,我如何知道是在哪发生的? Answer.
  17. 当程序中断时,会出现 “Floating underflow occurred” 警告讯息,我如何停止这样的讯息产生? Answer.
  18. 如何能在系统中读取不同格式的非格式化文件? Answer.
  19. 如何能输出不同格式的非格式化文件,可在系统中读取? Answer.
  20. 我可以将 NAG Fortran 编译器编译过的程序发布到别的环境吗? Answer.

Question: 如何使用 CDABS, DCMPLX, DCONJG, DIMAGDREAL?
Answer: 这些并非标准的 Fortran 内建函数,虽然他们相当普遍。我们建议您采用以下的说明将其转换为标准 Fortran。
函数 相对应的标准 Fortran 内建函数
CDABS(A) Abs(a)
DCMPLX(X,Y) Cmplx(x,y,Kind=Kind(0d0))
DCONJG(Z) Conjg(z)
DIMAG(Z) Aimag(z)
DREAL(Z) Real(z)

此外,您可以透过 ‘-dcfuns’ 参数让编译器认得这些函数。


Question: 有提供诸如 CDEXP 这样的非标准 Fortrna 的内建函数吗?
Answer:

没有。这些函数并非属于任何 Fortran 标准,而且其名称也非一致。

况且,这些函数也非必须。只需要使用标准内建的函数 ABSACOSASINATANATAN2CONJGCOSCOSHDIMEXPLOGLOG10MAXMINSIGNSINSINHSQRTTANTANH 就可以应用到任何精确的实数 (或复数) 资料。

若您的程序中有使用以上标准或非标准内建函数时,您只需要移除函数前缀即可 (通常是 CCDCQDQZ),例如:原程序中参考到内建函数 CEXPDEXPCDEXPCQEXPDCEXPQEXPZEXP 可以直接以 EXP 取代。

有些新函数,其规则可能有些不同:xINTxNINT,其中的 x 是以上所提的各种前缀,但是需要分别将函数名改为 AINTANINT


Question: 编译器中有提供 DTIMEETIME 函数吗?
Answer: 没有。

这些并不是标准 Fortran 95 的内建函数。我们建议您改用标准的 Fortran 内建函数 CPU_TIME 与 SYSTEM_CLOCK。若您的程序中仍需要 DTIME 或 ETIME 函数,您可以将以下的程序片段加到您的程序中:第一个例子是采用标准 Fortran 95 程序 (可以在各种不同的 Fortran 95 编译器中使用),第二个例子则是透过 NAG Fortran 的 Posix 接口。

请您注意:此 DTIMEETIME 函数并非线程安全函数。若您的程序可能在多线程的环境中执行,您必须使用 SYSTEM_CLOCK 来计算所经过的时间。

 

! DTIME in standard Fortran.
Real Function dtime(time)
  Real time(2)
  Double Precision,Save :: last_time = 0
  Double Precision this_time
  Intrinsic Cpu_Time
  Call Cpu_Time(this_time)
  time(1) = this_time - last_time
  time(2) = 0
  dtime = time(1)
  last_time = this_time
End Function
! DTIME via NAG Fortran Compiler Posix module.
Real Function dtime(time)
  Use F90_Unix_Env,Only:tms,times
  Real time(2)
  Type(tms),Save :: lastbuf
  Logical :: start = .True.
  Type(tms) buffer
  Integer junk
  junk = times(buffer)
  If (start) Then
    lastbuf%utime = 0
    lastbuf%stime = 0
    start = .false.
  End If
  time(1) = buffer%utime - lastbuf%utime
  time(2) = buffer%stime - lastbuf%stime
  dtime = time(1) + time(2)
  lastbuf = buffer
End Function
! ETIME in standard Fortran.
Real Function etime(time)
  Real time(2)
  Call Cpu_Time(etime)
  time(1) = etime
  time(2) = 0
End Function
! ETIME via NAG Fortran Compiler Posix module.
Real Function etime(time)
  Use F90_Unix_Env,Only:tms,times
  Real time(2)
  Type(tms) buffer
  Integer junk
  junk = times(buffer)
  time(1) = buffer%utime
  time(2) = buffer%stime
  etime = buffer%utime + buffer%stime
End Function

Question: 有提供 FLUSH 函数吗?
Answer: 有。

NAG Fortran 编译器有许多内建的模块,提供用户直接调用为数众多的 Posix 相关的系统函数。若要使用这些功能,需要透过 USE 叙述加入适当的模块。FLUSH 函数在 F90_UNIX_IO 模块中。

自 Fortran 2003 标准后,这功能已经可以直接以 FLUSH 叙述调用了;我们建议您在新的程序中以这样的方式调用。以下我们以简单的示例说明如何使用:

Program slow_dots
!
! This program prints 10 dots, one per second, then finishes.
!
  Use Iso_Fortran_Env,Only:output_unit
  Implicit None
  Integer i
  Do i = 1,10
    Write(*,'(a)',Advance='No') '.'
    Call delay
    Flush(output_unit)
  End Do
  Print *,'Done.'
Contains
  Subroutine delay
    Integer per_second,start,now
    Intrinsic System_Clock
    Call System_Clock(Count=start,Count_Rate=per_second)
    If (start==-huge(start)) Stop 'No clock.'
    Do
      Call System_Clock(Count=now)
      If (now<start .Or. now>=start+per_second) Exit
    End Do
  End Subroutine
End Program

 


Question: 有提供 GETENV 函数吗?
Answer: 有。

NAG Fortran 编译器有许多内建的模块,提供用户直接调用为数众多的 Posix 相关的系统函数。若要使用这些功能,需要透过 USE 叙述加入适当的模块。GETENV 函数在 F90_UNIX_ENV 模块中。

自 Fortran 2003 标准后,这功能已经可以直接以 GET_ENVIRONMENT_VARIABLE 叙述调用了;我们建议您在新的程序中以这样的方式调用。以下我们以简单的示例说明如何使用:

Program environment_example
!
! This program displays the values of the environment variables FRED and
USERNAME
! (if they exist).
!
  Implicit None
  Call show('FRED')
  Call show('USERNAME')
Contains
  Subroutine show(name)
    Character(*),Intent(In) :: name
    Character(:),Allocatable :: value
    Integer len,status
    Intrinsic Get_Environment_Variable
    Call Get_Environment_Variable(name,Status=status,Length=len)
    If (status==1) Then
      Print *,'Environment variable "',name,'" does not exist.'
    Else If (status/=0) Then
      Print *,'Unexpected error',status,'for environment variable "',name,'"'
    Else
      Allocate(Character(len) :: value)
      Call Get_Environment_Variable(name,Value=value)
      Print *,'The value of environment variable "',name,'" is "',value,'".'
    End If
  End Subroutine
End Program

 


Question: 有提供 SYSTEM 函数吗?
Answer: 有。NAG Fortran 编译器有许多内建的模块,提供用户直接调用为数众多的 Posix 相关的系统函数。若要使用这些功能,需要透过 USE 叙述加入适当的模块。SYSTEM 函数在 F90_UNIX_PROC 模块中。以下我们以非常简单的例子说明如何使用 SYSTEM 函数。
Program system_example
  Use f90_unix_proc
  Call system('dir')
End Program

Question: 我可以在 format 中使用 ‘$’ 禁止输出新的一行吗?
Answer:

不行。NAG Fortran 编译器并未支持这样的扩充。

这个扩充是 Fortran90 所提出的,但已经不再使用了。以下我们示范如何以标准 Fortran 产生相同的结果。

    Program prompting
      Character(80) name
      Write (*,90000,Advance='No')
90000 Format('What is your name? ')
      Read *, name
      Print *, 'Hello ', Trim(name)
    End Program

Question: 我如何能够没有错误的编译非常旧的 Fortran 程序 (Fortran 66/77)?
Answer:

NAG Fortran 编译器会执行相当严格的 Fortran 标准验证,同时也会执行大量不正确程序的确认工作。当开发新的程序时,这样严格的验证方式是相当必须的,然而,有些时候可能也需要允许部分不够严格的程序,尤其是对只符合旧 Fortran 标准的程序。我们提供了许多编译参数来处理这些旧的程序。

-dusty
将发现的错误更改为警告讯息,能让编译继续执行;此警告也可透过 ‘-w’ 编译参数取消。此参数隐含了 ‘-mismatch_all’ 参数。
-mismatch
将函数调用参数不一致的严重错误更改为警告讯息,调用同一个文件中的函数,其参数必须要一致。
-mismatch_all
如同 ‘-mismatch’,但是可以接受同文件中函数调用参数不一致。

 


Question: 为什么会出现 "TAB format input" 警告讯息,这是甚么意思?
Answer: TAB 格式是 Fortran 77 的扩充,当在固定格式文件中被发现后会进行操作。例如,在固定格式中会跳过前面的 Label 栏。由于它是扩充形式,便会产生警告讯息。此种格式有点复杂,我们并不建议在新的程序中使用此方法 (建议以自由格式取代)。

Question: 警告讯息 "Byte count on numeric data type" 是甚么意思?
Answer:

这是 Fortran 77 的扩充,已经在 Fortran 90 中移除了。值类型是后跟随星号与指定的位数来指明资料型别的大小。
在 Fortran 90 中,用每个资料型别的 KINDs 来取代指定的位数,并提供了许多内建的函数来选择合适的的属性 (SELECTED_INT_KIND 与 SELECTED_REAL_KIND)。NAGWare f95 也提供 F90_KIND 模块,透过常数的声明,让使用者更便利的选择 kind。 位数与 kinds 的相对应表如下

Type * Byte Size Type(Kind Name)
INTEGER*1 Integer(int8)
INTEGER*2 Integer(int16)
INTEGER*4 Integer(int32)
INTEGER*8 Integer(int64)
REAL*4 Real(real32)
REAL*8 Real(real64)
REAL*16 Real(real128)
COMPLEX*8 Complex(real32)
COMPLEX*16 Complex(real64)
COMPLEX*32 Complex(real128)

整数或实数常数后加上下底线的型别与数字;例如:120_int8 表示为 8-bit 的整数常数,3.14159265358979323846264_real64 表示 64-bit 的实数值。


Question: 为什么在 NAG Fortran 编译器中会得到错误讯息 "KIND value does not specify a valid representation method"?
Answer:

KIND 值是由编译器来决定的。目前至少有两种方式表示:连续型 (1 至 N,N 为 kind 数) 以及位数 (依位数决定)。NAG Fortran 编译器 (以及其他某些编译器) 默认设定会以连续数字方式指定 kind,所以单精度与双精度的实数为 REAL(1) 及 REAL(2), 而并非 REAL(4) 与 REAL(8)。以位数的方式指定其中一个缺点是,当指定 COMPLEX 时,是要指定全部的位数还是其中实部或虚部的位数,很容易造成混淆。

编译器选项 -kind=sequential 设定以默认的连续数字方式指定 kind,而 -kind=byte 则改为用 byte 形式。


Question: 警告讯息 "Buffer overflow on output" 表示甚么?
Answer:

此表示你的程序试图以格式化的形式将过多的位写入纪录中,导致文件的缓冲溢位。默认的格式化输出入大小是 1024 字符。对于非格式化的输入输出,则没有限制。

若要改变缓冲,可以在 OPEN 叙述中加上 RECL= 参数。例如:

Open(13,File="myfile",Form="Formatted",Recl=2048)
将会建立一个文件其缓冲大小为 2048 位。

 

请注意,Fortran 对于非格式化文件,可以透过 INQUIRE 叙述中的 IOLENGTH= 找出所需的数值 RECL=。例如:

Inquire(Iolength=n) big_array
Open(13,File="dump",Form="Unformatted",Recl=N)
将建立足够的缓冲区给 unit 13,能够完整的对 big_array 进行输入或输出。

 

没有限制的缓冲区可以使用 Fortran 2003 的串流功能,但是将无法执行 BACKSPACE 叙述。例如:

Open(13,File="list",Form="Formatted",Access="Stream")
将对 unit 13 实行串流存取,允许格式化没有纪录长度限制的输入输出,但后退功能将会取消。

 


Question: 为什么会发生 “Variable X size of N bytes is too big” 的讯息?
Answer:

这个错误讯息表示您的变量超过了 NAG Fortran Compiler 编译器所支援的大小。编译器支持的变量大小限制如下:

应用系统 变量大小限制
32-bit 2GB
64-bit 1TB

这些限制同时适用于执行期所有变量所占的内存大小。


Question: 我如何控制 (PARAMETER) 参数的大小?
Answer:

常数参数的大小是由 −max_parameter_size= 参数所控制。默认值是 −max_parameter_size=50 (MB)。


Question: 当我执行混合编程项目时,甚么是 f90_init f90_io_finish 函数?
Answer:

当主程序是 C 语言时,这些函数都是必须使用的。f90_init 函数默认 Fortran 环境,包含了浮点数状态、命令行参数与输入输出功能。f90_io_finish 函数会输出所有 Fortran 暂存区的内容,并关闭所有 Fortran 文件。以下的例子说明如何使用这些函数。

int main(int argc,char *argv[])
{
  f90_init(argc,argv);
  /* At this point Fortran routines can be safely called. */
  f90_io_finish();
  return 0;
}

Question: 当程序中断时,出现 “Floating underflow occurred” 讯息,我如何知道是在哪发生的?
Answer:

在程序中 Floating underflow 相当普遍,但鲜少会是问题。若您认为它确实存在问题,您可以透过 IEEE 模式,在 underflow 发生时便中断程序,您也需同时设定 “Traceback for runtime errors (−gline)” 选项,才能将错误位置显示出。

以下程序说明如何使用 IEEE 终止模式找出 underflow 发生的位置。

Program underflow_halt
  Use Ieee_Exceptions
  Implicit None
  Call Ieee_Set_Halting_Mode(Ieee_Underflow, .True.)
  Call make_underflow(0.5)
Contains
  Subroutine make_underflow(x)
    Real, Intent(In) :: x
    Real :: y
    Integer :: n
    y = x
    n = 1
    Do
      y = y**2
      If (y==0) Exit
      n = n + 1
      Print *, 'Step', n, 'value', y
    End Do
    Print *, 'Zero reached at step', n
  End Subroutine
End Program

Question: 当程序中断时,会出现 “Floating underflow occurred” 警告讯息,我如何停止这样的讯息产生?
Answer:

Floating underflow 的警告讯息可以透过下面两种方法取消:

  • 在程序中断前可将 underflow 指标设为 false
  • 在链接时可透过 −no_underflow_warning 参数设定

     

    以下程序说明如何透过 IEEE halting 模式将 underflow 警告关掉。

    Program turn_underflow_flag_off
      Use Ieee_Exceptions
      Implicit None
      Call make_underflow(0.5)
      Call Ieee_Set_Flag(Ieee_Underflow, .False.)
    Contains
      Subroutine make_underflow(x)
        Real, Intent(In) :: x
        Real :: y
        Integer :: n
        y = x
        n = 1
        Do
          y = y**2
          If (y==0) Exit
          n = n + 1
          Print *, 'Step', n, 'value', y
        End Do
        Print *, 'Zero reached at step', n
      End Subroutine
    End Program

Question: 如何能在系统中读取不同格式的非格式化文件?
如何能输出不同格式的非格式化文件,可在系统中读取?
Answer:

非格式化的文件是由三种机制提供:

  • −convert= 参数
  • OPEN 指令中指定 CONVERT= 参数
  • 透过 FORT_CONVERTn 环境变量

     

    文件的格式转换会同时影响其读与写,所以他们都采用相同的机制。

    最常见转换的需求是 IEEE 格式储存的浮点资料 big-endian 文件,可以透过 “−convert=big_ieee” 参数指定,或者在 NAG Fortran 编译器中的 Project Settings 选单中 的 Detail (1) 设定。

    有关完整详细的转换机制,请您参考 NAG Fortran 编译器手册;相关的编译参数说明在 2.4 节,,相关参数与环境变量可在 5.1.5 节中找到说明。


Question: 我可以将 NAG Fortran 编译器编译过的程序发布到别的环境吗??
Answer:

可以,这是可行的。最简便的方法就是链接时指定静态链结方式 −unsharedrts。