NAG Fortran Compiler 7.1 リリースノート

 

1 概要

NAG Fortranコンパイラ リリース 7.1 はメジャーアップデートです。

NAG Fortranコンパイラの以前のリリースからアップグレードするお客様は、 このリリースの新しいライセンスキーが必要になります。

Kusariライセンス管理の詳細については KLICENCE.txt を参照してください。

2 リリースの概要

NAG Fortran コンパイラのリリース 7.1 は、以下を含む、Fortran 2008 のすべてをサポートしています。

  • データポインタを返す関数への参照が、代入文の左側を含む多くの場面で変数として使用できます。
  • その他、マイナーな機能追加が行われ、ポインタ指示先の初期化(これにより割付け可能な要素が再帰的もしくは相互に再帰的な型を持つことができる)や 手続ポインタを返す関数がが行えるようになりました。

このリリースには、以下を含む、Fortran 2018の機能が大幅に追加されました。

  • 組込みの“collective”サブルーチン(CO_SUM他)の追加により、 Fortran 2018の共配列並列プログラミング機能をすべてサポートしました。 項目
  • C言語の高度な相互運用性を部分的にサポートしました。 具体的には、assumed-rank引数、assumed-type引数、およびC記述子がサポートされます。
  • RANK組み込み関数とSELECT_RANK構文を用いて、 (Cではなく)Fortranで直接次元引継ぎ引数が利用できます。
  • いくつかのマイナーな機能追加が行われ、 省略可能な仮引数が組み込み配列関数(SUMなど)のDIM引数として使用できるようになりました。

OpenMPプログラムでも、未定義変数のチェックができるようになり、OpenMPプログラミングへの対応が改善されました。 また、新しいOpenMPのマイナーな機能も追加されています。

最後に、追加のエラーチェックが可能となり、バンドルされているツールでもいくつかの機能が追加されています。

3 互換性

3.1 リリース7.0との互換性

リリース7.1は、-C=callsオプションを指定してコンパイルされたファイルが、 手続ポインタ引数を持つ手続を含んでいる場合に再コンパイルが必要である点を除き、 Release 7.0と互換性があります。

3.2 リリース6.2との互換性

MacOSでは、-abi=32 で利用可能であった32ビットABIモードは削除されました。 その結果、64ビットコンパイルのみがサポートされ、-abi=オプションは完全に削除されました。

これ以外については共配列が使用される場合、 または-C=callsオプションを選択戻りを持つサブルーチンに対して用いた場合を除き、 リリース7.1とリリース6.2は完全に互換性があります。このようなプログラムはすべて再コンパイルする必要があります。

3.3 リリース6.1との互換性

ILEN組み込み関数やHPF_LIBRARYモジュールなど、 HPF(High Performance Fortran)の機能を使用するプログラムはサポートされなくなりました。

Linux x86-64で以前廃止予定機能であった-abi=64オプションは廃止されました。 このオプションは、64ビットポインターを持つが32ビットのオブジェクトサイズと添え字演算を備えるABIを提供していましたが、 これはリリース5.1以前との互換性のためにのみ存在していました。

HPFサポートと非推奨のオプションの削除を除き、NAG Fortranコンパイラのリリース7.1はリリース6.1と完全に互換性があります。

3.4 リリース6.0との互換性

HPFサポートと非推奨オプションの削除を除き、NAG Fortranコンパイラのリリース7.1はリリース6.0と互換性があります。 ただし、“パラメタ化構造型”の割付け配列を使用するプログラムは再コンパイルする必要があります (これはモジュール変数及び仮引数にのみ影響します)。

3.5 リリース5.3.1、5.3および5.2との互換性

HPFサポートと非推奨のオプションの削除を除き、NAG Fortranコンパイラのリリース7.1はリリース5.3.1と完全に互換性があります。 またWindowsでは、名前がドル記号($)で始まるモジュールまたはプロシージャを再コンパイルする必要があることを除いて、 リリース5.3および5.2と完全に互換性があります。

新しい“パラメタ化構造型”機能を使用するプログラムの場合、 動的型がパラメーター化された派生型である可能性のある多相性変数を割り当て、 割り当て解除、初期化、またはコピーするプログラムのすべての部分を リリース7.1でコンパイルすることが強く推奨されています。

3.6 リリース5.1との互換性

NAG Fortranコンパイラのリリース7.1は、次の点を除き、NAGWare f95 リリース5.1と互換性があります。
  • HPFの機能を使用するプログラムはサポートされていません。
  • CLASSキーワードを使用する、または拡張される型を含むプログラムまたはライブラリは、 再コンパイルする必要があります。
  • Linux x86-64(製品NPL6A51NA)上でリリース5.1でコンパイルされた64ビットプログラム、 およびライブラリはバイナリ互換ではないため、再コンパイルする必要があります。

4 Fortran 2008の新機能

  • 割付け成分は型を前方参照できます。
    例)
           Type t2
             Type(t),Pointer :: p
             Type(t),Allocatable :: a
           End Type
           Type t
             Integer c
           End Type
    

    割付け成分は再帰的な型、もしくは二つの型がお互いに再帰的であっても構いません。
    例)

           Type t
             Integer v
             Type(t),Allocatable :: a
           End Type
    
    これにより、割付け成分を用いてリストやツリーを構築できます。 割付けにはポインタ代入に類似したものがないため、 このようなデータ構造の構築や探索には通常、再帰的な手続呼び出しが必要です。

    このような再帰的なデータ構造がどんなに深くネストされても、 循環させることはできません。(これもポインタ代入がないため) いつものように、このような構造体の最上位オブジェクトの割付けを解除すると、 すべての割付けが再帰的に解除されます。

  • 仮引数は、関数結果の型パラメタ(文字長など)を指定しない限り、 要素別副プログラムの宣言式に使用できます。 関数結果の型パラメタについては、 問合せが無指定についてでない場合にのみ、宣言問合せ(LENなど)で利用できます。

    例)

      Elemental Subroutine s(x,n,y)
        Real,Intent(In) :: x
        Integer,Intent(In) :: n
        Real,Intent(Out) :: y
        Real temp(n)
        ...
    
    上記コードで、仮引数Nを用いて局所配列TEMPを宣言する事ができます。
  • ポインタおよびポインタ成分は、指示先を示すように初期化できます。 指示先はそのポインタに対して有効でなければなりません。(例:同じ型、次元数など) 主なケースは以下の通りです。
    名前付きポインタ初期化
    データポインタの場合、指示先にSAVE属性が必要です。 (モジュールや主プログラム内の変数は暗黙のうちにこの属性を持ちます) 手続ポインタの場合、指示先はモジュール手続または外部手続でなければならず、 仮手続、内部手続、文関数であってはなりません。

    例)

      Module m
        Real,Target :: x
        Real,Pointer :: p => x
      End Module
      Program test
        Use m
        p = 3
        Print *,x ! Will print the value 3.0
      End Program
    
    成分の暗黙的初期値指定
    ポインタ成分は、指示先を指すように暗黙的初期化することができます。 指示先に関する要件は、名前付きポインタの初期化の場合と同じです。

    例)

      Module m
        Real,Target :: x
        Type t
          Real,Pointer :: p => x
        End Type
      End Module
      Program test
        Use m
        Type(t) y
        y%p = 3
        Print *,x ! 値 3.0 を出力
      End Program
    
    構築子による成分の初期化
    定数式の構築子は、任意のポインタ成分の指示先を指定することができます。 指示先に関する要件は、名前付きポインタの初期化の場合と同じです。

    例)

      Module m
        Real,Target :: x
        Type t
          Real,Pointer :: p
        End Type
      End Module
      Program test
        Use m
        Type(t) :: y = t(x)
        y%p = 3
        Print *,x ! 値 3.0 を出力
      End Program
    
  • ポインタを返す関数への参照は、多くの場面で変数として使用することができます。 特に、代入文の変数として、INTENT(OUT)INTENT(INOUT)の仮引数に対応する実引数として、 また結合名を変更するASSOCIATESELECT TYPE構文の選択子として使用することが可能です。

    例)

      Module m
        Real,Target,Save :: table(100) = 0
      Contains
        Function f(n)
          Integer,Intent(In) :: n
          Real,Pointer :: f
          f => table(Min(Max(1,n),Size(table)))
        End Function
      End Module
    
    上記モジュールおよび以下のコードでは “-1.23E+02” が出力されます。
      Program example
        Use m
        f(13) = -123
        Print 1,f(13)
      1 Format(ES10.3)
      End Program
    

    注意すべきは、文関数定義の構文は、変数としてのポインタ関数参照の構文の一部と同じであり、 スコープ内でアクセス可能なポインタ値関数が存在するかどうかで、そのどちらであるかが決定されることです。 このため、状況によっては、混乱しやすいエラーメッセージとなる場合があります。

    上述のモジュールで、ASSOCIATE構文の使い方を示すプログラムを以下に示します。

      Program assoc_eg
        Use m
        Associate(x=>f(3), y=>f(4))
          x = 0.5
          y = 3/x
        End Associate
        Print 1,table(3:4) !  "  5.00E-01  6.00E+00" を出力
      1 Format(2ES10.2)
      End Program
    

    最後に、引数渡しを使った例を示します。

      Program argument_eg
        Use m
        Call set(f(7))
        Print 1,table(7) !  "1.41421" を出力
      1 Format(F7.5)
      Contains
        Subroutine set(x)
          Real,Intent(Out) :: x
          x = Sqrt(2.0)
        End Subroutine
      End Program
    

    変数名の代わりにポインタ値関数への参照が使用できる他の場合には、以下のようなものがあります。

    • WRITE文の内部ファイル指定子として使用する。 (関数は文字列または配列へのポインタを返さなければならない)
    • READ文の入力項目として使用する。
    • ALLOCATEまたはDEALLOCATE文、またはEVENT WAITなどの像制御文で、 STAT=またはERRMSG=変数として使用する。
    • FORM TEAMの像のチーム変数として使用する。
  • 関数の結果は手続ポインタであっても構いません。
    例)
      Module ppfun
        Private
        Abstract Interface
          Subroutine charsub(string)
            Character(*),Intent(In) :: string
          End Subroutine
        End Interface
        Public charsub,hello_goodbye
      Contains
        Subroutine hello(string)
          Character(*),Intent(In) :: string
          Print *,'Hello: ',string
        End Subroutine
        Subroutine bye(string)
          Character(*),Intent(In) :: string
          Print *,'Goodbye: ',string
          Stop
        End Subroutine
        Function hello_goodbye(flag)
          Logical,Intent(In) :: flag
          Procedure(hello),Pointer :: hello_goodbye
          If (flag) Then
            hello_goodbye => hello
          Else
            hello_goodbye => bye
          End If
        End Function
      End Module
      Program example
        Use ppfun
        Procedure(charsub),Pointer :: pp
        pp => hello_goodbye(.True.)
        Call pp('One')
        pp => hello_goodbye(.False.)
        Call pp('Two')
      End Program
    
    モジュールppfunの関数hello_goodbyeは手続へのポインタを返し、 そのポインタは手続ポインタに代入して起動する必要があり、 実行されると、この例では以下が出力されます。
     Hello: One
     Goodbye: Two
    

    この機能の使用は、データ実体と手続の境界を曖昧にし、 コードメンテナンス時に混乱や誤解を招く可能性があるため、推奨されません。 この機能は、手続ポインタ成分で既に提供されている以上の機能を提供しません。

5 Fortran 2018の新機能

  • 組込サブルーチンCO_BROADCASTCO_MAXCO_MINCO_REDUCE、およびCO_SUMcollective 演算を行います。 これらはCoarray並列のためのもので、明示的な同期をとることなく、現在のチーム内のすべての像にまたがる値を計算します。

    これらのサブルーチンは、いずれも省略可能なSTATERRMSGの引数を持ちます。 実行に成功すると、STAT引数には値0が代入され、ERRMSG引数は変更されないままとなります。 エラーが発生した場合、STATに正の値が代入され、ERRMSGには説明のメッセージが代入されます。 この方法で捕捉できる可能性があるのは、STAT_FAILED_IMAGESTAT_STOPPED_IMAGE のエラーのみです。 完全な同期がとられているわけではないので(下記参照)、像によって異なるエラーが発生したり、 全くエラーが発生しなかったりすることがあります。 エラーが発生し、STAT が存在しない場合、実行は終了されます。 なお、STATERRMSGの実引数が省略可能な仮引数である場合、 その引数はすべての像で存在するか、あるいはすべての像で存在しないか、のいずれかでなければなりません。

    これらのサブルーチンの1つへの参照 (CALL) は、像制御文であり、現在のセグメントを終了させず、同期も意味しません (ただし、計算中に部分的に同期が発生します)。 また、このような呼び出しは、像制御文が許可されている場合にのみ許されます。

    チーム内の各像は、チーム内の他の像と同じように、 集合サブルーチンのCALL文シーケンスを実行しなければなりません。 呼び出し時に像間で同期をとってはいけません。つまり呼び出しは順不同のセグメントからでなければなりません。

    すべての集合サブルーチンは第1引数 “A”を持ちます。 この引数はINTENT(INOUT)であり、並列添字付き実体であってはいけません。 また、この引数は計算のためのデータを含み、 現在のチーム内のすべての像で同じ型、型パラメタ、形状を持たなければなりません。 仮引数が共配列の場合は、すべての像で同じ末端引数を持たなければなりません。

    SUBROUTINE CO_BROADCAST ( A, SOURCE_IMAGE [, STAT, ERRMSG ] )

    A : 任意の型の変数。並列添字付き実体であってはならず、 現在のチームのすべての像で同じ型、型パラメタ、および形状を持っている必要がある。 code{A}が共配列の仮引数の場合、各像で同じ末端引数を持つ必要がある。

    SOURCE_IMAGE : 整数スカラ。1からNUM_IMAGES()の範囲、現在のチーム内のすべての像で同じ値でなければならない。

    STAT (optional) : 整数スカラ変数。並列添字付きであってはならない。

    ERRMSG (optional) : 基本種別の文字スカラ変数。並列添字付きであってはならない。

    SOURCE_IMAGE上の引数Aの値は、他のすべての像上の引数Aに代入される。

    SUBROUTINE CO_MAX ( A [, RESULT_IMAGE, STAT, ERRMSG ] )

    A: 整数型、実数型、もしくは文字型の変数。 並列添字付き実体であってはならず、 現在のチームのすべての像で同じ型、型パラメタ、および形状を持っている必要がある。 code{A}が共配列の仮引数の場合、各像で同じ末端引数を持つ必要がある。

    RESULT_IMAGE (optional) : 整数スカラ。1からNUM_IMAGES()の範囲。 この引数はすべての像で存在するか、あるいはすべての像で存在しないか、のいずれかでなければならない。 存在する場合は、現在のチームのすべての像で同じ値でなければならない。

    STAT (optional) : 整数スカラ変数。並列添字付きであってはならない。

    ERRMSG (optional) : 基本種別の文字スカラ変数。並列添字付きであってはならない。

    このサブルーチンは、Aの最大値をすべての像にわたって計算する。 Aが配列の場合、値は要素別に計算される。 code{RESULT_IMAGE}が存在する場合、結果はその像上の引数Aに代入され、 そうでない場合はすべての像上の引数Aに代入されます。

    SUBROUTINE CO_MIN ( A [, RESULT_IMAGE, STAT, ERRMSG ] )

    A: 整数型、実数型、もしくは文字型の変数。 並列添字付き実体であってはならず、 現在のチームのすべての像で同じ型、型パラメタ、および形状を持っている必要がある。 code{A}が共配列の仮引数の場合、各像で同じ末端引数を持つ必要がある。

    RESULT_IMAGE (optional) : 整数スカラ。1からNUM_IMAGES()の範囲。 この引数はすべての像で存在するか、あるいはすべての像で存在しないか、のいずれかでなければならない。 存在する場合は、現在のチームのすべての像で同じ値でなければならない。

    STAT (optional) : 整数スカラ変数。並列添字付きであってはならない。

    ERRMSG (optional) : 基本種別の文字スカラ変数。並列添字付きであってはならない。

    このサブルーチンは、すべての像にわたってAの最小値を計算する。 Aが配列の場合は、値は要素別に計算される。 code{RESULT_IMAGE}が存在する場合、結果はその像上の引数Aに代入され、 そうでない場合はすべての像上の引数Aに代入される。

    SUBROUTINE CO_REDUCE ( A, OPERATION [, RESULT_IMAGE, STAT, ERRMSG ] )

    A: 任意の型の非多相変数。並列添字付き実体であってはならず、 現在のチームのすべての像で同じ型、型パラメタ、および形状を持っている必要がある。 code{A}が共配列の仮引数の場合、各像で同じ末端引数を持つ必要がある。

    OPERATION : 引数を2つだけ持つ純粋関数。 OPERATIONの仮引数は,非割付け、非省略可能、非ポインタ、非多相の仮変数でなければならず、 各引数と関数の結果はAと同じ型と型パラメタを持つスカラでなければならない。

    RESULT_IMAGE (optional) : 整数スカラ。1からNUM_IMAGES()の範囲。 この引数はすべての像で存在するか、あるいはすべての像で存在しないか、のいずれかでなければならない。 存在する場合は、現在のチームのすべての像で同じ値でなければならない。

    STAT (optional) : 整数スカラ変数。並列添字付きであってはならない。

    ERRMSG (optional) : 基本種別の文字スカラ変数。並列添字付きであってはならない。

    このサブルーチンは、Aをすべての像にわたって任意に集約する。 Aが配列の場合は、値は要素別に計算される。 集約は、すべての像のAに対応する値の集合から計算される。 これは反復処理であり、集合から2つの値を取り出し、OPERATION関数を適用して1つの値に変換する。 このプロセスは値が一つになるまで継続され、その値が結果となる。 RESULT_IMAGEがあれば、その像上の引数Aに結果が代入され、 なければすべての像上の引数Aに代入される。

    SUBROUTINE CO_SUM ( A [, RESULT_IMAGE, STAT, ERRMSG ] )

    A: 整数型、実数型、もしくは複素型の変数。 並列添字付き実体であってはならず、 現在のチームのすべての像で同じ型、型パラメタ、および形状を持っている必要がある。 code{A}が共配列の仮引数の場合、各像で同じ末端引数を持つ必要がある。

    RESULT_IMAGE (optional) : 整数スカラ。1からNUM_IMAGES()の範囲。 この引数はすべての像で存在するか、あるいはすべての像で存在しないか、のいずれかでなければならない。 存在する場合は、現在のチームのすべての像で同じ値でなければならない。

    STAT (optional) : 整数スカラ変数。並列添字付きであってはならない。

    ERRMSG (optional) : 基本種別の文字スカラ変数。並列添字付きであってはならない。

    このサブルーチンは、Aのすべての像にわたる合計を計算する。 Aが配列の場合、値は要素別に計算される。 RESULT_IMAGEがあれば、その像上の引数Aに結果が代入され、 なければすべての像上の引数Aに代入される。

  • ALLANYFINDLOCIALLIANYIPARITYMAXLOCMAXVALMINLOCMINVALNORM2PARITYPRODUCTSUMに対するDIM引数は、実行時に存在すれば、省略可能な仮引数にすることができる。
    例)
      Subroutine sub(x,n)
        Real,Intent(In) :: x(:,:,:)
        Integer,Intent(In),Optional :: n
        If (Present(n)) Then
          Print *,Norm2(x,n) ! Rank two array result.
        Else
          Print *,Norm2(x)   ! Scalar result.
        End If
      End Subroutine
    
  • SIZE=指定子は、ADVANCE='NO' のないREAD文、 つまりADVANCE= 指定子のない、あるいは ADVANCE='YES' を明示した文に用いることができる。
    例)
        Character(65536) buf
        Integer nc
        Read(*,'(A)',Size=nc) buf
        Print *,'The number of characters on that line was',nc
    
    なお、SIZE=は並び書式、変数群書式では許可されません。 これは、そのような書式の編集記述子は存在せず、したがってSIZE=でカウントされる文字も存在しないからです。
  • 特定の組込関数は-f2018オプションで廃止予定機能(Obsolescent)として報告されます。 例えば、SQRTのような、個別でもありかつ総称でもある関数の場合、 実引数として渡す、手続引用仕様宣言として使う、手続ポインタ割り当ての指示先とするなど、 廃止された使い方の場合のみ報告されます。

    例)

      Program obsolete_cos_usage
        Real x
        Intrinsic cos
        Procedure(cos),Pointer :: pp    ! Obsolescent
        x = 1.5
        pp => cos                       ! Obsolescent
        Call other_procedure(cos)       ! Obsolescent
        Print *,cos(x),pp(x)
      End Program
      Subroutine other_procedure(f)
        Real,External :: f
        Print *,f(1.5)
      End Subroutine
    
    コメントで示された3行の場合のみ警告メッセージが表示されます。
  • 次元数引継ぎ仮引数は、任意の次元数の実引数を受け入れ、実引数の次元数を引継ぎます。 この次元数はゼロであってもよく(つまり、実引数がスカラであってもよい)、 さらに、次元数引継ぎ仮引数はALLOCATABLEまたはPOINTER属性を持つことができ、 したがって任意の次元数の割付け/ポインタ変数を受け入れることができます。

    書式は以下の通りです

      Real,Dimension(..) :: a, b
      Integer :: c(..)
    
    上記は、3つの変数(仮引数でなければならない)を次元数引継ぎとして宣言しています。

    次元数引継ぎのFortranでの利用は非常に限定的です。組込み照会関数が使用でき、 SELECT RANK構文も利用できますが、それ以外は、他の次元数引継ぎ引数に対応する手続の実引数としてのみ出現することが可能です。

    次元数引継ぎの主な用途は高度なC相互運用性です。 次元数引継ぎ引数は“C descriptor”として参照渡しされます。 引数が何を意味するかはCルーチン次第です。 Cディスクリプタは、それを操作するためのいくつかのユーティリティ関数とともに、ソースファイルISO_Fortran_binding.hで定義されています。これはコンパイラのライブラリディレクトリ(Linuxでは通常 /usr/local/lib/NAG_Fortran ですが、インストール時に変更可能です)に置かれています。

    このトピックは非常に複雑であり、リリースノートの範囲を超えています。 読者はFortran 2018標準、またはMetcalf、Reid、Cohenによる“Modern Fortran Explained”などの優れた教科書に注意を向ける必要があります。

    とてもシンプルな例)

      Program assumed_rank_example
        Real x(1,2),y(3,4,5,6,7)
        Call showrank(1.5)
        Call showrank(x)
        Call showrank(y)
      Contains
        Subroutine showrank(a)
          Real,Intent(In) :: a(..)
          Print *,'Rank is',Rank(a)
        End Subroutine
      End Program
    
    このプログラムは以下を出力します。
     Rank is 0
     Rank is 2
     Rank is 5
    
  • SELECT RANK構文はFortranでの次元数引継ぎ実体の使用を容易にし、以下の書式を持ちます。
      [ construct-name ] SELECT RANK ( [ assoc_name => ] assumed-rank-variable-name )
            [ rank-stmt
                block ]...
      END SELECT [ construct-name ]
    
    ここでrank-stmtは以下のいずれか一つです。
      RANK ( scalar-int-constant-expression ) [ construct-name ]
      RANK ( * ) [ construct-name ]
      RANK DEFAULT [ construct-name ]
    
    ある特定のSELECT RANK構文において、複数のRANK DEFAULT文、 複数の RANK (*) 文、または同じ値の整数式を持つ複数の RANK (integer) があってはなりません。 次元数引継ぎ変数がALLOCATABLEまたはPOINTER属性を持つ場合、 RANK (*)文は許可されません。

    整数の定数式を持つRANK文に続くblockは、 次元数引継ぎ変数がその次元数ランクを持つ非想定ランク実引数に結合され、 かつ大きさ引継ぎ配列でない場合に実行されます。 blockの中では、あたかもその次元数の形状引継ぎ配列であるかのように振る舞います。

    RANK (*)に続くblockは、末端引数が大きさ引継ぎ配列である場合に実行されます。 blockの中では、境界 ‘(1:*)’ で宣言されているかのように動作します。 異なる境界や順位が必要な場合は、シーケンス結合を使って別の手続に渡すことができます。

    RANK DEFAULT文に続くblockは、他のブロックが選択されていない場合に実行されます。 そのblock内では、まだ次元数引継ぎ変数です。(つまり変化はない)

    以下にシンプルなSELECT RANK構文の例を示します。

      Program select_rank_example
        Integer :: a = 123, b(1,2) = Reshape( [ 10,20 ], [ 1,2 ] ), c(1,3,1) = 777, d(1,1,1,1,1)
        Call show(a)
        Call show(b)
        Call show(c)
        Call show(d)
      Contains
        Subroutine show(x)
          Integer x(..)
          Select Rank(x)
          Rank (0)
            Print 1,'scalar',x
          Rank (1)
            Print 1,'vector',x
          Rank (2)
            Print 1,'matrix',x
          Rank (3)
            Print 1,'3D array',x
          Rank Default
            Print *,'Rank',Rank(x),'not supported'
          End Select
        1 Format(1x,a,*(1x,i0,:))
        End Subroutine
      End Program
    
    このプログラムは以下を出力します。
     scalar 123
     matrix 10 20
     3D array 777 777 777
     Rank 5 not supported
    
  • TYPE(*)型指定子を用いてスカラ、大きさ引継ぎ、次元数引継ぎの仮引数を宣言することができます。 このような引数は引継ぎ型と呼ばれ、対応する実引数は任意の型にすることができます。 また、ALLOCATABLECODIMENSIONINTENT (OUT)POINTERVALUE属性を持っていてはなりません。

    引継ぎ型変数はFortranでの直接の使用が非常に限られています。

    • 他の引継ぎ型仮引数に実引数として渡すことができる。
    • 組込み関数IS_CONTIGUOUSLBOUNDPRESENTSHAPESIZEUBOUND の第1引数として現れることがある。
    • 関数C_LOCISO_C_BINDING組込みモジュール内)の引数として使用できる。
    これら以外では、全く使用することができません。 配列の場合、添字を付けたり、そこから部分配列を作成することはできないことに注意してください。

    この機能は主にC言語プログラムとの相互運用に有効です。 TYPE(*)の仮引数は、“void *” として宣言された C の引数と相互運用されます。 C側ではスカラか大きさ引継ぎかの違いはありませんが、Fortran側では、仮引数がスカラなら実引数もスカラでなければならず、仮引数が配列なら実引数も配列でなければなりません。

    TYPE(*)仮引数に直接実引数を渡せるので、C_LOC関数は不要であり、 従って実引数のTARGET属性も不要です。

    例)

      Program type_star_example
        Interface
          Function checksum(scalar,size) Bind(C)
            Use Iso_C_Binding
            Type(*) scalar
            Integer(C_int),Value :: size
            Integer(C_int) checksum
          End Function
        End Interface
        Type myvec3
          Double Precision v(3)
        End Type
        Type(myvec3) x
        Call Random_Number(x%v)
        Print *,checksum(x,Storage_Size(x)/8)
      End Program
      int checksum(void *a,int n)
      {
        int i;
        int res = 0;
        unsigned char *p = a;
        for (i=0; i<n; i++) res = 0x3fffffff&((res<<1) + p[i]);
        return res;
      }
    
  • BIND(C)手続は、省略可能な引数を持つことができます。 そのような引数はVALUE属性を持つことはできません。

    BIND(C)手続の省略可能な引数が存在しない場合は、NULLポインタの引数を渡すことで示します。

    例)

      Program optional_example
        Use Iso_C_Binding
        Interface
          Function f(a,b) Bind(C)
            Import
            Integer(C_int),Intent(In) :: a
            Integer(C_int),Intent(In),Optional :: b
            Integer(C_int) f
          End Function
        End Interface
        Integer(C_int) x,y
        x = f(3,14)
        y = f(23)
        Print *,x,y
      End Program
    
      int f(int *arg1,int *arg2)
      {
        int res = *arg1;
        if (arg2) res += *arg2;
        return res;
      }
    
    fの2番目の参照では省略可能な引数bがないので、NULLポインタが渡されます。 出力結果は以下の通りとなります。
     17 23
    
  • 組込み照会関数RANKは、引数の次元数を返します。 以下の書式を持ちます。
    RANK ( A )
    

    A : 任意の型のデータ実体

    Result : 基本種別のスカラ整数

    結果はAの次元数となります。スカラであれば0、Aが1次元配列であれば1、というようになります。

    この関数は、Aが次元数引継ぎ変数である場合を除き、定数式で使用することができます。

  • 組込み関数REDUCEは、ユーザー定義の配列集約を実行します。 以下の書式を持ちます。
    REDUCE ( ARRAY, OPERATION [, MASK, IDENTITY, ORDERED ] ) もしくは
    REDUCE ( ARRAY, OPERATION DIM [, MASK, IDENTITY, ORDERED ] )
    

    ARRAY : 任意の型の配列

    OPERATION : 2つの引数を持つ純粋関数で、各引数はARRAYと同じ宣言型および型パラメタを持つスカラー、非割付け、非ポインタ、非多相、非省略可能な変数 一方の引数がASYNCHRONOUSTARGETVALUE属性を持つ場合、 他方もその属性を持たなければならない。 結果はARRAYと同じ型と型パラメタを持つ非多相のスカラ変数でなければならない。

    DIM : 1からNの範囲スカラ整数(ここでNARRAYの次元数)

    MASK : 論理型、スカラもしくはARRAYと同じ形状の配列

    IDENTITY : ARRAYと同じ宣言型および型パラメタを持つスカラ

    ORDERED : 論理型のスカラ

    Result : ARRAYと同じ型及び型パラメタ

    結果は、ARRAYをユーザが提供するOPERATIONで集約したものとなります。 DIM がない場合、(マスクされた) ARRAY全体がスカラ結果に集約されます。 DIM がある場合、その結果は次元数N-1であり、ARRAY の次元の形状を持ちます。 DIM を除去したもので、結果の各要素は、その次元のマスクされた要素の集約版となります。

    ちょうど1つの要素が結果値に寄与している場合、その値はその要素と等しくなります。 つまり、OPERATIONは複数の要素が現れたときのみ呼び出されます。

    どの要素も結果値に寄与しない場合、IDENTITY 引数が存在しなければならず、その値は IDENTITY と等しくなります。

    例)

    Module triplet_m
      Type triplet
        Integer i,j,k
      End Type
    Contains
      Pure Type(triplet) Function tadd(a,b)
        Type(triplet),Intent(In) :: a,b
        tadd%i = a%i + b%i
        tadd%j = a%j + b%j
        tadd%k = a%k + b%k
      End Function
    End Module
    Program reduce_example
      Use triplet_m
      Type(triplet) a(2,3)
      a = Reshape( [ triplet(1,2,3),triplet(1,2,4), &
                     triplet(2,2,5),triplet(2,2,6), &
                     triplet(3,2,7),triplet(3,2,8) ], [ 2,3 ] )
      Print 1, Reduce(a,tadd)
      Print 1, Reduce(a,tadd,1)
      Print 1, Reduce(a,tadd,a%i/=2)
      Print 1, Reduce(Array=a,Dim=2,Operation=tadd)
      Print 1, Reduce(a, Mask=a%i/=2, Dim=1, Operation=tadd, Identity=triplet(0,0,0))
    1 Format(1x,6('triplet(',I0,',',I0,',',I0,')',:,'; '))
    End Program
    
    This will produce the output:
     triplet(12,12,33)
     triplet(2,4,7); triplet(4,4,11); triplet(6,4,15)
     triplet(8,8,22)
     triplet(6,6,15); triplet(6,6,18)
     triplet(2,4,7); triplet(0,0,0); triplet(6,4,15)
    

6 追加のOpenMPサポート

  • -C=undefined オプションによる未定義変数検出がサポートされました。
    例)
      Program bad
        Use omp_lib
        Real x,y(10)
        x = 3
        !$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(y)
          Do i=1,Size(y)
            y(omp_get_thread_num() + 1) = x * omp_get_thread_num()
          End Do
        !$OMP END PARALLEL DO
        Print *,y
      End Program
    
    以下が出力されます。
    Runtime Error: bad.f90, line 7: Reference to undefined variable X
    Program terminated by fatal error
    
  • OpenMP 4.0のCANCELCANCELLATION POINT指示文がサポートされ、さらに OMP_CANCELLATION環境変数とOMP_GET_CANCELLATION関数もサポートされました。 また、CANCELIF節にあるOpenMP 5.0のCANCEL:キーワードもサポートされました。

    CANCEL指示文は以下の書式を持ちます。

      !$OMP CANCEL construct-type [ [,] IF ( [ CANCEL: ] scalar-logical-expr ) ]
    
    ここでconstruct-typePARALLELDOSECTIONSTASKGROUPのいずれか一つです。 指示文は、指定された型のOpenMP構文の中に密接にネストされている必要があります。 但しTASKGROUPは例外です。TASKGROUPはOpenMPのTASK構文の中に密接にネストされている必要があります。 SECTIONSの場合、構文がNOWAIT節を持っていてはなりません。 DOの場合、構成がNOWAIT節やORDERED節を持っていてはなりません。

    CANCEL指示文を実行すると、IF句があればそれを評価し、IF句がないか、 もしくは評価値が真でキャンセルが有効であれば、構文はキャンセルされます。 キャンセルされた場合、実行中のスレッドは即座に構文の最後にジャンプします。

    CANCELLATION POINT指示文は以下の書式を持ちます。

      !$OMP CANCELLATION POINT construct-type
    
    ここでconstruct-typeは、CANCEL指示文と同じです。 CANCELに関して、CANCELLATION POINT指示文は適切なOpenMP構文に密接にネストされている必要があります。 この構文は、CANCEL指示文も持つべきです。これがない場合、CANCELLATION POINT指示文による効果は(CPU時間の浪費以外に)何もありません。

    CANCELLATION POINT指示文を実行すると、構文がキャンセルされた場合は構文の最後に制御が移行し、それ以外の場合は何も影響しません。

    CANCELLATION POINT指示文以外に、CANCEL指示文 (たとえそれがfalseに評価されるIF節を持っていたとしても)、 BARRIER指示文、または暗黙のバリアー (NOWAITのないEND SINGLEなどが含まれる構文の終わり)にもキャンセルポイントが存在します。

    構文がキャンセルされた後、領域内で実行されるバリアはキャンセルされた指示文の内部に密接にネストされていなければなりません(つまり、構文から呼ばれる手続内ではない)、さもなければ(NAGコンパイラによる)実行時エラーとなるか、もしくは(キャンセルしたスレッドがバリアに到達しないため)無限ハングが発生します。

    環境変数OMP_CANCELLATIONの値が‘TRUE’である場合、キャンセルが有効になります。 (大文字・小文字を区別しない)また、この変数の値が‘FALSE’である場合は無効となります。 この変数が存在しない場合、設定はコンパイラ依存です。 NAG Fortranコンパイラの場合、デフォルトはFALSEです。

    OMP_GET_CANCELLATION関数の仕様は以下の通りです。

      LOGICAL FUNCTION OMP_GET_CANCELLATION()
      END FUNCTION
    
    キャンセルが有効な場合は.TRUE.、無効な場合は.FALSE.を返します。

    以下に、キャンセルのシンプルな例を示します。

      Program example
        Real a(20000,4),b(4)
        Logical ok
        Call Random_Number(a)
        a = a*10
        Call normalise(a,b,ok)
        Print 1,ok,b
        If (Any(a>2)) Print *,'Cancellation occurred'
        Call Random_Number(a)
        a = a*10
        a(:,2) = -a(:,2)
        Call normalise(a,b,ok)
        Print 1,ok,b
    1   Format(1X,'Succeeded = ',L1,', vmax =',4F8.4)
        If (Any(a>2)) Print *,'Cancellation occurred'
      Contains
        Subroutine normalise(x,y,succeeded)
          Use omp_lib
          Real,Intent(InOut) :: x(:,:)
          Real,Intent(Out) :: y(Size(x,2))
          Logical,Intent(Out) :: succeeded
          Real z
          Integer me,i
          succeeded = .True.
          !$OMP PARALLEL PRIVATE(me,i,z) SHARED(x,y) NUM_THREADS(Size(x,2))
            z = 0
            me = omp_get_thread_num() + 1
            Do i=1,Size(x,1)
              If (x(i,me)>z) z = x(i,me)
            End Do
            y(me) = z
            !$OMP CANCEL PARALLEL, IF (z==0)
            z = 2.0/z
            Do i=1,Size(x,1)
              x(i,me) = x(i,me)*z
              If (Iand(i,4095)==0) Then
                ! Every 4096 elements, check to see if the whole thing was cancelled already.
                !$OMP CANCELLATION POINT PARALLEL
              End If
            End Do
          !$OMP END PARALLEL
          succeeded = All(y/=0)
        End Subroutine
      End Program
    

    出力は例えば以下のようになります。

     Succeeded = T, vmax =  9.9993  9.9997  9.9998  9.9974
     Succeeded = F, vmax =  9.9999  0.0000  9.9996  9.9998
     Cancellation occurred
    
  • OpenMP 5.1のMASKED構文がサポートされました。 以下の形式を持ちます。
      !$OMP MASKED [ FILTER( スカラ整数式 ) ]
        構造化ブロック
      !$OMP END MASKED
    
    スレッドが構造化ブロックを実行するのは、スカラ整数式がスレッド番号と等しいと評価される場合のみです。 スレッド番号は0から始まり、PARALLEL領域のプライマリスレッドの番号です。 FILTER節が存在しない場合、FILTER(0)が存在するかのように振る舞います。つまり、プライマリスレッドのみが構造化ブロックを実行することになります。

    これは以下と完全に等価です。

      IF (omp_get_thread_num()==スカラ整数式) THEN
        構造化ブロック
      END IF
    

    整数式は各スレッドで同じ値を持つ必要はなく、 その場合は複数のスレッドが同時にマスク領域を実行できることに注意して下さい。 この構成によって暗示されるロックまたは同期はありません。 つまり、スレッドにローカルではない変数が更新された場合、 プログラマが明示的に必要なロックを挿入する必要があります。

7 追加のエラー診断

  • ALLOCATE文またはDEALLOCATE文で、同じ変数が複数回出現した場合、 エラーとして検出されるようになりました。
  • 型結合手続のオーバーライドとグローバルな整合性の診断で、仮引数の形状の違いを報告するようになりました。
  • SYSTEM_CLOCKへの8ビットまたは16ビットの整数引数は、値の受け取りには小さすぎるため、 エラーとして検出されるようになりました。
  • SYSTEM_CLOCKの引数の不一致で警告を出すようになりました。
    • 引数が無い場合
    • 整数引数が異なる種別である場合(Fortran 202xでは無効となるので)
    • 整数引数と実数引数が混同された場合
    • 整数引数がFortran 202xで推奨される64ビット整数でない場合
  • 変数が利用者定義入出力によって処理されない場合、割付け、ポインタ、またはアクセスできない成分の要素を持つ変数でNAMELISTを使用するとエラーが発生します。
  • 定数文字列の書式指定で、閉じる括弧の後に非空白文字がある場合、警告が発生します。
    例)
      Print '(1X,I0) whatever',13
    
    上記は以下のような警告を発します。
      Questionable: file.f90, line 2: Extraneous nonblank characters "whatever" after right
                                      parenthesis in character string format specification
    
  • CONTINUE文は何の効果も持ちませんが、文番号があれば分岐先の文になったり、 DOループの終わりになったりします。 しかし、文番号のないCONTINUE文は、何ら役に立ちません。 このような場合、Noteレベルの警告が発せられます。 CONTINUE文がDOループの中にある場合、 CプログラマはこれがCYCLE文の効果を持つと考えるかもしれないので、 Questionableに昇格されます。(Cではそうなっている)
    例)
      Program continues
        Continue
        Do i=1,10
          Print *,i**2
          Continue
        End Do
      End Program
    
    上記は以下の警告を発します。
    Note: file.f90, line 2: CONTINUE statement with no label
    Questionable: file.f90, line 5: CONTINUE statement with no label inside DO loop - did you
                                    mean CYCLE?
    
  • パラメタ化された構造型の共配列を割り付ける場合、異なる像で長さ型パラメタの値が異なる場合、 実行時エラーとして検出されるようになりました。
    例)
      Allocate(w[*],Mold=z)
    
    ここでZは別の像で異なる型パラメタ値を持つ仮引数を示しますが、この場合以下のような実行時エラーが発生します。
    Runtime Error: pco068.f90, line 17: Type parameter K1 in coarray allocation has value 1 on
                                        image one but 13 on image 2
    
  • 空のSELECT CASEおよびSELECT TYPE構文は、選択子の評価以外には何も行われないため、 Questionable として報告されます。

    例えばsub.f90が以下を含む場合、

      Subroutine sub(x,n)
        Class(*) x
        Integer n
        Select Case (n)
        End Select
        Select Type (x)
        End Select
      End Subroutine
    
    以下のような警告が発せられます。
    Questionable: sub.f90, line 4: Empty SELECT CASE construct
    Questionable: sub.f90, line 6: Empty SELECT TYPE construct
    

    また、最適化(-Oオプション)が使用されている場合、選択子の評価が行われない場合があります。

  • -C=intovfオプションは、SHAPESIZE組込み関数での整数オーバーフローを検出するようになりました。
    例)
      Program shape_overflow_example
        Real a(1,123456,3)
        Call sub(a)
      Contains
        Subroutine sub(x)
          Use Iso_Fortran_Env
          Real,Intent(In) :: x(:,:,:)
          Integer(int16) sh(3)
          sh = Shape(x,int16)
          Print *,sh
        End Subroutine
      End Program
    
    上記が-C=intovfを付けないでコンパイルされた場合、以下のようなナンセンスな結果となりますが
     1 -7616 3
    
    -C=intovfを付けてコンパイルした場合には、以下のような実行時エラーが発生します。
    Runtime Error: shape_overflow_example.f90, line 9: INTEGER(int16) overflow for intrinsic
     SHAPE, true result value is 123456
    
  • -C=callsオプションは、手続ポインタの仮引数を、データポインタを返す関数と、 手続を返す関数(手続呼び出しのどのレベルでも)とで異なるものとして扱うようになりました。 これらのエラーは、手続が不正確な引用仕様宣言で呼び出された場合にのみ発生します。

    例)

      Subroutine sub(f,x)
        Interface
          Function f(y)
            Real,Pointer :: f
          End Function
        End Interface
        Real,Intent(In) :: x
        Real,Pointer :: p
        p => f(x)
        Print *,Associated(p)
      End Subroutine
    
    上記手続が以下のような不正確な引用仕様宣言で呼び出された場合
      Program bad
        Interface
          Subroutine sub(f,x)
            Real,External,Pointer :: f
            Real,Intent(In) :: x
          End Subroutine
        End Interface
        Real,External,Pointer :: pp
        Intrinsic sqrt
        pp => sqrt
        Call sub(pp,1.5)
      End Program
    
    -C=callsオプション (さらにトレースバックを得るには-gline) を指定すると、 以下のような実行時エラーメッセージが出力されます。(指定しない場合はセグメンテーションフォルトとなります)
    Runtime Error: sub.f90, line 1: Incorrect interface block for SUB - Dummy argument F
      (number 1) is not a procedure pointer
    Program terminated by fatal error
    sub.f90, line 1: Error occurred in SUB
    bad.f90, line 11: Called by BAD
    

8 その他の追加機能

  • 整形ツール(polish)のオプション-idcase=-kwcase=に、 新たな選択肢が加わりました。squote{Camel_Case}です。 これは‘Capitalised’と異なり、最初の文字だけではなくアンダースコアの後の文字も大文字になります。 -kwcase=Camel_Case の場合、影響を受けるキーワードはNon_IntrinsicNon_OverridableNon_Recursive、及びOpenMPキーワードNum_Threadsです。 なお、選択肢の指定時に大文字と小文字は区別されず、Camel_Caseの場合(‘cam’と省略できる)を除いて、最初の一文字のみにまで省略する事も可能です。
  • ソース整形ツールのオプション-idcase=に新たな選択肢squote{Asis}が加わりました。 これは、ユーザー定義演算子(固有演算子は含まない)を含むすべての識別子の大文字と小文字を、 入力に現れたままの状態で保持するものです。 例えば、入力が大文字小文字の整合性が取れていない状態の“eX = Ex + 1”であった場合、 出力はそのまま全く同じ形のものとなります。 このオプションは、拡張整形ツールや他のツールでは使用できません。
  • 拡張ソース整形ツールオプション -case: は、 名前の種類によって異なる大文字・小文字の設定を可能にします。 コロンの後には、“kind=case”のカンマ区切りリストが続きます。 ここでcaseは、ケース指定 (UPPERCASElowercaseCapitalisedCamel_Case)で、 kindは以下に示すカテゴリーのうちの1つになります。

    comp 要素
    constr 構文名
    intr 組込み手続
    param パラメタ
    proc 手続
    tbp 型結合手続
    tparam 構造型パラメタ
    type 構造型
    var 変数

    例えば-case:var=lower,proc=uは変数に小文字を、手続に大文字を指定します。 特定の種類の名前に対する設定がない場合、適切なカテゴリにフォールバックします。 code{param}、typecomptparamprocはすべてvarに、 intrprocに、tbpcompproc にフォールバックされます。 ルールやフォールバックルールがない場合は、 -idcase=オプション設定(もしくはデフォルト)が使用されます。

  • 拡張ソース整形ツールオプション-casex:は、大文字小文字の規則の例外を指定します。 コロンの後に、任意の大文字・小文字指定を適用する例外文字列をカンマで区切ったリストを記述します。 例えば、-casex:MaxVal,XYz は、maxvalxyzと同等の名前が出現するたびに、 それぞれを、MaxValXYzとします。
  • -quietオプションは、コンパイラ(またはツール)のバナーメッセージと、最後の要約行を抑止します。 つまり診断メッセージのみが出力されるようになります。
  • Extensionメッセージは、それがどのような種類の拡張であるかの情報を提供するようになりました。 追加の情報は、その機能を追加したFortran標準の版 (例: “Extension(F2018)”) か、NAGの拡張か (“Extension(NAG)”)か、標準機能に取って代わられた FORTRAN77 などの古い拡張か (“Non-standard(Obsolete)”) のいずれかであることを示します。
  • Informationalメッセージは3つのレベルに分けられました。 Note(最高)、Info、Remark(最低)です。 デフォルトではNoteメッセージは出力されるようになっていますが、-w=noteオプションでこれを抑制することもできます。 -infoオプションでInfoとRemarkの両方のメッセージを表示させることができます。
Privacy Policy  /  Trademarks