NAG Fortran コンパイラ 7.0 マニュアル

 
ナビゲーション:前へ   上へ   次へ

10.8 プログラムと手続 [大部分 5.3]

  • CONTAINS文の後に空の内部副プログラム部分、モジュール副プログラム部分、 及び型束縛手続部分の記述が許されるようになりました。 型束縛手続部分の場合では(特に効果のない)PRIVATE文が (指定する必要のない)CONTAINS文の後に許されるようになりました。
  • [6.0] 内部手続が実引数として渡せます。また手続きポインタへ代入もできます。 内部手続が仮引数経由もしくは手続きポインタ経由で実行された場合に、 親手続きの局所変数へのアクセスが可能となりました。 手続きポインタの場合には、ポインタは親手続が復帰するまでの間のみ有効です。 (これは局所変数がそれ以降存在しなくなるからです)

    例)

      SUBROUTINE mysub(coeffs)
        REAL,INTENT(IN) :: coeffs(0:) ! Coefficients of polynomial.
        REAL integral
        integral = integrate(myfunc,0.0,1.0) ! Integrate from 0.0 to 1.0.
        PRINT *,'Integral =',integral
      CONTAINS
        REAL FUNCTION myfunc(x) RESULT(y)
          REAL,INTENT(IN) :: x
          INTEGER i
          y = coeffs(UBOUND(coeffs,1))
          DO i=UBOUND(coeffs,1)-1,0,-1
            y = y*x + coeffs(i)
          END DO
        END FUNCTION
      END SUBROUTINE
    
  • Fortran 2008のルールが総称解決と総称内手続のあいまいさの判断に使われるようになりました。 このルールでは:
    • 仮手続は仮引数と区別が可能です。
    • ALLOCATABLE仮変数はINTENT(IN)を持つPOINTER仮変数と区別可能です。
  • [6.0] 遊離状態のポインタ及び割付られていない割付け変数は省略可能な非割付、非ポインタ仮引数に対しての実引数として渡す事ができます。 この場合実引数が存在していないかのように処理されます。
  • [5.3.1] 非純粋要素別処理手続はIMPUREキーワードを用いてが定義可能です。 非純粋要素別処理手続は要素別であるが故の制限(例えばすべての引数がスカラでなければならない)がありますが、“純粋”に関しても制限はありません。 これは非純粋要素別処理手続きに副作用があり得る事と、入出力及びSTOP文を含み得る事を意味します。 例)
        Impure Elemental Integer Function checked_addition(a,b) Result(c)
          Integer,Intent(In) :: a,b
          If (a>0 .And. b>0) Then
            If (b>Huge(c)-a) Stop 'Positive Integer Overflow'
          Else If (a<0 .And. b<0) Then
            If ((a+Huge(c))+b<0) Stop 'Negative Integer Overflow'
          End If
          c = a + b
        End Function
    
    引数が配列の場合、それぞれの成分に対して非純粋手続きが配列成分順に適用されます。 (これは特に順番が定められていない純粋要素別手続きとは異なります) 非純粋手続きは手続きが純粋でなければならない状況(例:FORALL構文内)では参照できません。

    非純粋要素別手続きはおそらく最終手続きと(入出力が許されているという理由により)デバッグ時に最も有用です。

  • [6.0] 純粋手続きの引数がVALUE属性を持つ場合、どのINTENT属性も必要ありません。 例)
       PURE SUBROUTINE s(a,b)
         REAL,INTENT(OUT) :: a
         REAL,VALUE :: b
         a = b
       END SUBROUTINE
    

    しかしながら、利用者定義代入サブルーチンの二番目の引数と利用者定義演算のすべての引数はこの限りではなく、VALUE属性を持つ場合でもINTENT(IN)属性を指定しなければなりません。

  • [5.3.1] 内部手続及びモジュール手続において、 END文の FUNCTION 及び SUBROUTINE キーワードが省略可能となりました。(手続名も指定しない場合のみ) 今までは外部手続でのみ省略可能でした。
  • ENTRY文は削除予定機能として扱われます。
  • [1.0] プログラム内の行がセミコロンで始まっても良くなりました。
  • [6.2] 結合名を持つ外部手続きの名前が大域識別子ではなく局所識別子として取り扱われるようになりました。 これが意味するのは、例えば以下のようなコードが標準準拠になったという事です。
          SUBROUTINE sub() BIND(C,NAME='one')
            PRINT *,'one'
          END SUBROUTINE
          SUBROUTINE sub() BIND(C,NAME='two')
            PRINT *,'two'
          END SUBROUTINE
          PROGRAM test
            INTERFACE
              SUBROUTINE one() BIND(C)
              END SUBROUTINE
              SUBROUTINE two() BIND(C)
              END SUBROUTINE
            END INTERFACE
            CALL one
            CALL two
          END PROGRAM
    
  • [6.2] NAME=指示子を持たない場合に限り、 内部手続がBIND(C)属性であっても許容されます。 このような手続きはCと相互運用可能ですが(NAME=''で指定するような)結合名を持ちません。
  • [6.2] VALUE属性を持つ仮引数が配列であっても許容されます。 また非定数及び/又は1ではない長さのCHARACTER型であっても許容されます。 (ALLOCATABLE又はPOINTER属性を持つ事は依然として許容されません。 また共配列も許容されません。)

    結果としては実引数の複製が作られ、仮引数はその複製と結合されます。 仮引数への変更は実引数に影響を及ぼしません。 例えば

           PROGRAM value_example_2008
             INTEGER :: a(3) = [ 1,2,3 ]
             CALL s('Hello?',a)
             PRINT '(7X,3I6)',a
           CONTAINS
             SUBROUTINE s(string,j)
               CHARACTER(*),VALUE :: string
               INTEGER,VALUE :: j(:)
               string(LEN(string):) = '!'
               j = j + 1
               PRINT '(7X,A,3I6)',string,j
             END SUBROUTINE
           END PROGRAM
    
    は以下を出力します。
           Hello!     2     3     4
                1     2     3
    
  • [7.0] サブモジュールは、個別モジュール手続きと共に、Fortranプログラムを構築する追加の方法を提供します。

    “個別モジュール手続き”は、引用仕様がモジュール宣言部で宣言され、その定義がモジュール自体もしくはそのモジュールのサブモジュールのいずれかで提供される手続きです。 個別モジュール手続きの引用仕様は、引用仕様本体の手続接頭句でMODULEキーワードを用いて宣言されます。 例)

           INTERFACE
             MODULE RECURSIVE SUBROUTINE sub(x,y)
               REAL,INTENT(INOUT) :: x,y
             END SUBROUTINE
           END INTERFACE
    
    個別モジュール手続きの引用仕様の重要な側面は、他の引用仕様本体とは異なり、IMPORT文を必要とせずに親子結合によってモジュールへアクセスする点です。 例)
           INTEGER,PARAMETER :: wp = SELECTED_REAL_KIND(15)
           INTERFACE
             MODULE REAL(wp) FUNCTION f(a,b)
               REAL(wp) a,b
             END FUNCTION
           END INTERFACE
    
    個別モジュール手続きの最終的な定義は、モジュール、サブモジュールに関わらず、引用仕様の宣言とまったく同じ特性、同じ仮引数名、同じ名前結果変数名(関数の場合)、 同じbinding-name(BIND(C)を使用する場合)、そしてRECURSIVEの場合はRECURSIVEでなければなりません。 これを実現する方法は以下の2つがあります。
    1. 通常の方法で手続きを定義し、すべての特性を正しく取得します。コンパイラによりチェックがなされます。 定義は手続接頭句にMODULEキーワードを含む必要があります。 例)
             ...
             CONTAINS
               MODULE REAL(wp) FUNCTION f(a,b)
                 REAL(wp)a,b
                 f = a**2 - b**3
               END FUNCTION
      
    2. または、引用仕様全体を、MODULE PROCEDURE文を用いて、再宣言することなく、アクセスする事も可能です。 例)
             ...
             CONTAINS
               MODULE PROCEDURE sub
                 ! 引数AとBとそれらの特性、再帰サブルーチンであるという点は
                 ! すべて引用仕様宣言から取得される。
                 IF (a>b) THEN
                   CALL sub(b,-ABS(a))
                 ELSE
                   a = b**2 - a
                 END IF
               END PROCEDURE
      
    サブモジュールの形式は次のとおりです(斜体の角括弧はオプションを示します):
           submodule-stmt
             declaration-part
           [ CONTAINS
              module-subprogram-part ]
           END [ SUBMODULE [ submodule-name ] ]
    
    初期のsubmodule-stmtの形式は
           SUBMODULE ( module-name [ : parent-submodule-name ] ) submodule-name
    
    module-nameは、1つ以上の個別モジュール手続きを持つモジュールの名前です。 parent-submodule-name(存在する場合)はそのモジュールの別のサブモジュールの名前であり、 parent-submodule-name(存在する場合)はそのモジュールの別のサブモジュールの名前であり、submodule-nameは定義されているサブモジュールの名前です。 したがって、モジュールのサブモジュールはツリー構造を形成し、一連のサブモジュールは他のサブモジュールを拡張できます。 ただし、サブモジュールの名前はそのモジュール内で一意です。 この構造は、モジュール自体にすべての基礎情報(タイプ、定数、および手続き)を配置することなく、複数のサブモジュールで使用できる内部基礎情報の作成を容易にするためのものです。

    定義されているサブモジュールは、親子結合によって親モジュールまたはサブモジュールにアクセスします。 モジュールの要素の場合、これにはPRIVATE要素へのアクセスが含まれます。 したがって、declaration-partで宣言する局所要素は、同じ名前を持つホスト内の要素へのアクセスをブロックします。

    サブモジュールによって宣言された要素(変数、型、手続き)は、そのサブモジュールに対して局所的です。 ただし、祖先モジュールで宣言され、サブモジュールで定義された個別モジュール手続きは例外です。 束縛名が引用仕様と同じである必要がある別のモジュール手続きの場合を除き、手続きは束縛名を持つことはできません。

    例)

           MODULE mymod
             INTERFACE
               MODULE INTEGER FUNCTION next_number() RESULT(r)
               END FUNCTION
               MODULE SUBROUTINE reset()
               END SUBROUTINE
             END INTERFACE
           END MODULE
           SUBMODULE (mymod) variables
             INTEGER :: next = 1
           END SUBMODULE
           SUBMODULE (mymod:variables) functions
           CONTAINS
             MODULE PROCEDURE next_number
               r = next
               next = next + 1
             END PROCEDURE
           END SUBMODULE
           SUBMODULE (mymod:variables) subroutines
           CONTAINS
             MODULE SUBROUTINE reset()
               PRINT *,'Resetting'
               next = 1
             END SUBROUTINE
           END SUBMODULE
           PROGRAM demo
             USE mymod
             PRINT *,'Hello',next_number()
             PRINT *,'Hello again',next_number()
             CALL reset
             PRINT *,'Hello last',next_number()
           END PROGRAM
    

    他のサブモジュールで使用するサブモジュール情報は、 NAG Fortranコンパイラーによってmodule.submodule.subという名前のファイルに、.modと同様の形式で保存されます。 .modファイルの作成を抑制する-nomodオプションは、.subファイルの作成も抑止します。

Privacy Policy  /  Trademarks