XL Fortran での丸め操作を理解すれば、予測可能な整合性のある結果を得るのに役立ちます。また、スピードと正確度との妥協点を定めなければならない場合に、情報を基に決定を下すのにも役立ちます。
MAF 演算と、中間結果に使用される高い精度のために、 XL Fortran プログラムから得られる浮動小数点計算は、一般に、他の処理系の場合よりも正確になります。 XL Fortran デフォルトでの精度拡張やパフォーマンスよりも、まったく同じ結果を得ることのほうが重要な場合は、 他のシステムの浮動小数点結果の再現を参照してください。
プログラムの丸めモードを変更するために、fpsets および fpgets ルーチンを呼び出すことができます。これらのルーチンは、インクルード・ファイル /usr/include/fpdt.h および /usr/include/fpdc.h に定義されている fpstat という名前の論理値の配列を使用します。fpstat 配列エレメントは、浮動小数点の状況レジスターおよび制御レジスターのビットに対応します。
浮動小数点の丸め制御の場合は、配列エレメント fpstat(fprn1) と fpstat(fprn2) が以下の表に記載されているとおりに設定されます。
表 19. fpsets および fpgets で使用する丸めモード・ビット
fpstat(fprn1) | fpstat(fprn2) | 例外を使用可能にした場合 |
---|---|---|
.true. | .true. | - 無限大方向への丸め |
.true. | .false. | + 無限大方向への丸め |
.false. | .true. | ゼロ方向への丸め |
.false. | .false. | 最も近い値への丸め |
たとえば、次のようになります。
program fptest include 'fpdc.h' print *, 'Before test: 2.0 / 3.0 = ', 2.0 / 3.0 print *, ' -2.0 / 3.0 = ', -2.0 / 3.0 call fpgets( fpstat ) ! Get current register values. fpstat(fprn1) = .TRUE. ! These 2 lines mean round towards fpstat(fprn2) = .FALSE. ! +INFINITY. call fpsets( fpstat ) r = 2.0 / 3.0 print *, 'Round towards +INFINITY: 2.0 / 3.0= ', r call fpgets( fpstat ) ! Get current register values. fpstat(fprn1) = .TRUE. ! These 2 lines mean round towards fpstat(fprn2) = .TRUE. ! -INFINITY. call fpsets( fpstat ) r = -2.0 / 3.0 print *, 'Round towards -INFINITY: -2.0 / 3.0= ', r end ! This block data program unit initializes the fpstat array, and so on. block data include 'fpdc.h' include 'fpdt.h' end
XL Fortran は、浮動小数点状況とプロセッサーの制御レジスターを直接制御するためのいくつかのプロシージャーを提供しています。これらのプロシージャーは、浮動小数点状況と制御レジスター (fpscr) を直接操作するインライン機械命令にマップされるので、 fpsets および fpgets サブルーチンより効率的です。
XL Fortran は、プロシージャー get_round_mode() を提供しており、これは xlf_fp_util モジュールの中で使用できます。このプロシージャーは、現在の浮動小数点丸めモードを戻します。
たとえば、次のようになります。
USE XLF_FP_UTIL INTEGER(FPSCR_KIND) MODE MODE=get_round_mode() IF (MODE .EQ. FP_RND_RZ) THEN ! ... END IF
注:
丸め誤差や、計算結果におけるその他の予期しないわずかな差を処理するいくつかの方法があります。以下の方法のうちの 1 つまたは複数の方法を考慮してみる必要があるでしょう。
丸め操作 (特にループの場合) によってコードのパフォーマンスは低下するので、計算の精度に対してよくない影響を与えることがあります。倍精度計算の一時結果を保管するときは、単精度変数ではなく倍精度を使うようにし、計算の最終結果が得られるまで丸め操作を遅らせるよう配慮してください。保管されている単精度の結果を元の倍精度に変換する代わりに、 -qfloat の hssngl サブオプションを指定することもできます。このサブオプションは、算出された倍精度結果を後でまた使用できるように保存します。
コンパイラーは、可能なら、コンパイル中に浮動小数点の式を評価します。したがって、その結果作成されたプログラムは、実行時の不必要な計算で実行スピードが遅くなることがありません。しかし、コンパイラーの評価による結果は、実行時の計算結果と正確に一致しない場合があります。これらの計算を実行時間まで遅らせるには、 -qfloat オプションの nofold サブオプションを指定してください。
それでも結果は同じにならない場合があります。たとえば、 DATA および PARAMETER ステートメント内の計算は、やはりコンパイル時に実行されるからです。
fold/nofold が原因で結果に最も大きな差が出るのは、拡張精度計算を実行したり、 -O オプションでコンパイルされたりする (またはこの両方) プログラムの場合です。
プログラム内部から fpsets サブルーチンを呼び出すことによって、デフォルトで設定されている最も近い値への丸めモードからモードを変更することができます。これを行う場合には、プログラムのすべての 丸め操作で同じモードを使用するように注意しなければなりません。
+ 無限大への丸めモードを一貫して使用した場合は、たとえば、次のコマンドを使用して、 丸めモードの選択の例のようなプログラムをコンパイルできます。
xlf95 -qieee=plus -qfloat=rrm changes_rounding_mode.f