9.6 IEEE算術サポート [特に明記しない限り4.x]
9.6.1 イントロダクション
3つの組込みモジュールがIEEE算術の利用を支援するために提供されます。それらは IEEE_ARITHMETIC, IEEE_EXCEPTIONS, IEEE_FEATURESです。 この拡張はISO Technical Report ISO/IEC TR 15580:1999で記述されているものに 対する若干のスーパーセットです。9.6.2 例外フラグ、モードと情報の流れ
Fortran 2003で使われるIEEE算術モデルでは、特定の浮動小数点例外(オーバーフロー 等)が発生したかどうかを示すグローバルな一群のフラグ、浮動小数点演算と例外処理 にかかわるいくつかの演算モード、良いパフォーマンスと信頼性を得るためのフラグや モードの伝搬に関する一群の規則が規定されています。例外フラグに対する伝搬規則は、情報は“上方向”に流れるということです。 従って個々の手続きはフラグをクリアした状態で開始され、復帰時にフラグが設定され ていた場合には呼び出し側の対応するフラグがセットされることになります。 これにより、並列に実行可能な手続きがIEEE例外フラグを介して相互干渉を起さないこ とが保証されます。 コンピュータハードウェアが1セットのグローバルフラグしかサポートしていない場合 には、手続き内で自らフラグのチェックを行う(IEEE_GET_FLAGまたは IEEE_GET_STATUSを用いる)ことが必要になります。
モードに関する伝搬規則は、モード設定は“下方向”に流れるということです。 これはすべてのルーチン内でのコードの動きの最適化を可能にします。そのための 唯一の代償は、モードを変更する手続きにおいては、その戻り時に手続きに入った時 点でのモードを回復しなくてはならないという点です。
利用可能なモードは次の通りです:
- それぞれの浮動小数点例外によってプログラムを終了させるか、あるいは(デフォ ルトの結果を提供し例外フラグを立てて)実行の継続を許すか
- 浮動小数点演算の丸めモード
- アンダーフローモード
9.6.3 モジュール内の手続き
これらのモジュールで提供されるすべての手続きは総称手続きで個別手続きではあり ません。これはそれらが実引数として渡せないことを意味しています。手続きの記述において、REAL(*)と記された場合には任意の種別のREAL を意味します(これは標準的なFortran構文ではありません)。 その反対にLOGICALと記述された場合には、デフォルトLOGICALのみを 意味し、他の種別のLOGICALは意味しません。
名前が‘IEEE_SUPPORT_’で始まる関数はすべて調査関数です。 これらの関数の多くはREAL(*)引数 X を取ります。 Xのその種別のみがこれらの調査関数で使われるので、Xは未定義、 非割付け状態、遊離状態、未定義ポインタであっても構いません。
手続きが使う機能をサポートしていないデータ型に対して手続きを呼び出してはなら ない点に注意して下さい。これを調べるために調査関数“support”を使うこと ができます。
9.6.4 IEEE_FEATURESモジュール
このモジュールは構造型IEEE_FEATURES_TYPE、及び最大11個のIEEE機能を示す その型の定数を定義します。これらは以下のとおりです。
IEEE_DATATYPE | IEEEデータ型が利用可能かどうか |
IEEE_DENORMAL | IEEE非正規化値が利用可能かどうか (*) |
IEEE_DIVIDE | 除算がIEEEで必要とされる精度を持っているかどうか (*) |
IEEE_HALTING | 停止制御がサポートされているかどうか |
IEEE_INEXACT_FLAG | 不正確な例外がサポートされているかどうか (*) |
IEEE_INF | IEEEの無限大(正、負)が利用可能かどうか (*) |
IEEE_INVALID_FLAG | 無効例外がサポートされているかどうか (*) |
IEEE_NAN | IEEE非数(NaN)が利用可能かどうか (*) |
IEEE_ROUNDING | すべてのIEEE丸めモードが利用可能かどうか (*) |
IEEE_SQRT | SQRTがIEEE標準に準拠しているかどうか (*) |
IEEE_UNDERFLOW_FLAG | アンダーフローフラグがサポートされているかどうか (*) |
(*) 最低1つのREAL種別に対して
ユーザ手続きで必要とされるこれらの機能種別は、USE文にONLY節をつけて
明示的に参照される必要があります。
例:
USE,INTRINSIC :: IEEE_FEATURES,ONLY:IEEE_SQRT
これにより指定された機能が利用可能で無い場合にはコンパイルが失敗するようになります。
IEEE_FEATURES_TYPE型はそれ自身ではあまり有用ではありません。
9.6.5 IEEE_EXCEPTIONS
IEEE浮動小数点例外を処理するためのデータ型、定数、総称手続きを提供します。9.6.5.1 型と定数
TYPE IEEE_STATUS_TYPEこの型の変数は浮動小数点の状態値を保持することができます。それはすべてのモード 設定とフラグを結合したものです。
TYPE IEEE_FLAG_TYPEこの型の値は個々のIEEE例外フラグを指定します。関連する定数は以下の通りです。
IEEE_DIVIDE_BY_ZERO | ゼロによる除算フラグ |
IEEE_INEXACT | 不正確な結果フラグ |
IEEE_INVALID | 無効な演算フラグ |
IEEE_OVERFLOW | オーバーフローフラグ |
IEEE_UNDERFLOW | アンダーフローフラグ |
更に2つの配列定数が良く使われるフラグの組合せを表すために利用可能です。
TYPE(IEEE_FLAG_TYPE),PARAMETER :: & IEEE_USUAL(3) = (/ IEEE_DIVIDE_BY_ZERO,IEEE_INVALID,IEEE_OVERFLOW /), & IEEE_ALL(5) = (/ IEEE_DIVIDE_BY_ZERO,IEEE_INVALID,IEEE_OVERFLOW, & IEEE_UNDERFLOW,IEEE_INEXACT /)
9.6.5.2 手続き
IEEE_EXCEPTIONSで提供される手続きは以下の通りです。ELEMENTAL SUBROUTINE IEEE_GET_FLAG(FLAG,FLAG_VALUE) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(OUT) :: FLAG_VALUEFLAGで示される例外が設定されている場合にFLAG_VALUEを.TRUE.に 設定します。そうでない場合には.FALSE.に設定します。
ELEMENTAL SUBROUTINE IEEE_GET_HALTING_MODE(FLAG,HALTING) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(OUT) :: HALTINGFLAGで示される浮動小数点例外によりプログラムが終了する場合には HALTINGを.TRUE.に設定します。そうでない場合には.FALSE.に 設定します。
PURE SUBROUTINE IEEE_GET_STATUS(STATUS_VALUE) TYPE(IEEE_STATUS_TYPE),INTENT(OUT) :: STATUS_VALUESTATUS_VALUEを現在の浮動小数点状態に設定します。これは現在のすべての 例外フラグとモード設定を含みます。
PURE SUBROUTINE IEEE_SET_FLAG(FLAG,FLAG_VALUE) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(IN) :: FLAG_VALUEFLAGで示される例外フラグをFLAG_VALUEに設定します。 FLAGは重複値がない限りどのような次元数の配列であっても構いません。 この場合FLAG_VALUEはスカラもしくは同じ形状の配列となります。
PURE SUBROUTINE IEEE_SET_HALTING_MODE(FLAG,HALTING) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG LOGICAL,INTENT(IN) :: HALTINGFLAGで示される例外の停止モードをHALTINGに設定します。 FLAGは重複値がない限りどのような次元数の配列であっても構いません。 この場合FLAG_VALUEはスカラもしくは同じ形状の配列となります。
PURE SUBROUTINE IEEE_SET_STATUS(STATUS_VALUE) TYPE(IEEE_STATUS_TYPE),INTENT(IN) :: STATUS_VALUESTATUS_VALUEに格納されている状態を浮動小数点状態に設定します。 状態はそれ以前にIEEE_GET_STATUSを呼び出して取得されたものである必要 があります。
PURE LOGICAL FUNCTION IEEE_SUPPORT_FLAG(FLAG) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAGFLAGで示される例外フラグがすべての種別のREALでサポートされて いるかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_FLAG(FLAG,X) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAG REAL(*),INTENT(IN) :: XFLAGで示される例外フラグがX種別のREALでサポートされて いるかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_HALTING(FLAG) TYPE(IEEE_FLAG_TYPE),INTENT(IN) :: FLAGFLAGで示される例外フラグに対する“停止モード”の制御がサポート されているかどうかを応答として返します。
9.6.6 IEEE_ARITHMETICモジュール
IEEE算術をサポートする追加関数を提供します。その中にはすべてのIEEE_EXCEPTIONS が含まれます。9.6.6.1 IEEEデータ型選択
IEEE_SELECTED_REAL_KIND関数はSELECTED_REAL_KIND組込み関数と似ていますが、 IEEEに準拠したREAL型のみを選択し準拠していないものを無視します。9.6.6.2 調査関数
PURE LOGICAL FUNCTION IEEE_SUPPORT_DATATYPE()すべての実変数XがIEEE_SUPPORT_DATATYPE(X)の条件を満たすかどうかを応答と して返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_DATATYPE(X) REAL(*),INTENT(IN) :: XXの種別の変数が以下の条件を満たすかどうかを応答として返します:
- 絶対値がTINY(X)とHUGE(X)の間の数値がIEEE浮動小数点形式のものである。
- +、-、*演算が最低一つの丸めモードに対するIEEEに準拠している。
- 関数IEEE_COPY_SIGN, IEEE_LOGB, IEEE_NEXT_AFTER, IEEE_REM, IEEE_SCALB, IEEE_UNORDEREDが利用可能である。
PURE LOGICAL FUNCTION IEEE_SUPPORT_DENORMAL() PURE LOGICAL FUNCTION IEEE_SUPPORT_DENORMAL(X) REAL(*),INTENT(IN) :: Xすべての実種別もしくはXの種別を持つ変数において(絶対値がゼロとTINYの 間の)非正規値がIEEEで必要とされる通りに存在し、それらに対する演算がIEEEに準拠して いるかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_DIVIDE() PURE LOGICAL FUNCTION IEEE_SUPPORT_DIVIDE(X) REAL(*),INTENT(IN) :: X組込み除算(/)がすべての実種別もしくはXの種別を持つ変数に対し IEEE準拠かどうかをそれぞれ応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_INF() PURE LOGICAL FUNCTION IEEE_SUPPORT_INF(X) REAL(*),INTENT(IN) :: Xすべての実種別もしくはXの種別を持つ変数に対し、正及び負の無限大値が 存在しIEEEに準拠した動作をするかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_IO() PURE LOGICAL FUNCTION IEEE_SUPPORT_IO(X) REAL(*),INTENT(IN) :: X[5.2] すべての実種別もしくはXの種別を持つ変数に対し、書式付き入出力に際して のテキストからおよびテキストへの変換が、入出力丸めモードROUND='DOWN', 'NEAREST', 'UP', 'ZERO' (及び対応する編集記述子 RD, RN, RU, RZ)に関しIEEEに準拠するかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_NAN() PURE LOGICAL FUNCTION IEEE_SUPPORT_NAN(X) REAL(*),INTENT(IN) :: Xすべての実種別もしくはXの種別を持つ変数に対し、正及び負の “Not-a-Number”値が存在し、IEEEに準拠するかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_ROUNDING(ROUND_VALUE) TYPE(IEEE_ROUND_TYPE),INTENT(IN) :: ROUND_VALUE PURE LOGICAL FUNCTION IEEE_SUPPORT_ROUNDING(ROUND_VALUE,X) TYPE(IEEE_ROUND_TYPE),INTENT(IN) :: ROUND_VALUE REAL(*),INTENT(IN) :: Xすべての実種別もしくはXの種別を持つ変数に対し、ROUND_VALUEで 示される丸めモードがIEEE_SET_ROUNDING_MODEを使って設定でき、IEEEに 準拠するかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_SQRT() PURE LOGICAL FUNCTION IEEE_SUPPORT_SQRT(X) REAL(*),INTENT(IN) :: Xすべての実種別もしくはXの種別を持つ変数に対し、組込み関数 SQRT がIEEEに準拠するかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_STANDARD() PURE LOGICAL FUNCTION IEEE_SUPPORT_STANDARD(X) REAL(*),INTENT(IN) :: Xすべての実種別もしくはXの種別を持つ変数に対し、IEEEモジュールで記述 されるすべての機能(入出力変換(IEEE_SUPPORT_IO参照)を除く)がサポ ートされ且つIEEEに準拠するかどうかを応答として返します。
PURE LOGICAL FUNCTION IEEE_SUPPORT_UNDERFLOW_CONTROL() PURE LOGICAL FUNCTION IEEE_SUPPORT_UNDERFLOW_CONTROL(X) REAL(*),INTENT(IN) :: X[5.2] すべての実種別もしくはXの種別を持つ変数に対し、アンダーフローモードが IEEE_SET_UNDERFLOW_MODEで制御できるかどうかを応答として返します。
9.6.6.3 丸めモード
TYPE IEEE_ROUND_TYPEこの型の値はIEEE丸めモードを指定します。以下の既定の定数が提供されます。
IEEE_DOWN | 切り下げる (負の無限大に向けて) |
IEEE_NEAREST | 四捨五入する |
IEEE_TO_ZERO | 正の数は切り下げる、負の数は切り上げる |
IEEE_UP | 切り上げる (正のの無限大に向けて) |
IEEE_OTHER | 他の丸めモード |
PURE SUBROUTINE IEEE_GET_ROUNDING_MODE(ROUND_VALUE) TYPE(IEEE_ROUND_TYPE),INTENT(OUT) :: ROUND_VALUEROUND_VALUEに現在の丸めモードを設定します。
PURE SUBROUTINE IEEE_SET_ROUNDING_MODE(ROUND_VALUE) TYPE(IEEE_ROUND_TYPE),INTENT(IN) :: ROUND_VALUE丸めモードをROUND_VALUEで示されるものに設定します。
9.6.6.4 アンダーフローモード
アンダーフローモードには、IEEE標準で規定される“緩やかなアンダーフロー (gradual underflow)”とそうでない“急激なアンダーフロー(abrupt underflow)” の2種類があります。緩やかなアンダーフローの場合、-TINY(X)とTINY(X)の空隙は均等に 配置された非正規数(“subnormal” numbers)によって満たされます。これら の数の間隔はTINY(X)の上の部分における数体系上の数の間隔に等しく設定さ れます(それは最小の非正規数に等しいものでもあります)。 これによって数が0に近づくときの精度の劣化が緩やかなものとなります。最小の数 は1ビットの精度しか持たないため、そのような値に対する計算は非常に大きな相対 誤差を持つことになります。
急激なアンダーフローの場合、-TINY(X)とTINY(X)の間にある値は0の みとなります。 この種のアンダーフローは非IEEE算術の世界では極めて普遍的であり、IEEE算術の 場合にも広くハードウェアによってサポートされています。 その主たる優位点はその高速性にあります。
SUBROUTINE IEEE_GET_UNDERFLOW_MODE(GRADUAL) LOGICAL,INTENT(OUT) :: GRADUAL現行のアンダーフローモードが緩やかなアンダーフローの場合にGRADUAL を.TRUE.にセット、急激なアンダーフローの場合には.FALSE.に セットします。
SUBROUTINE IEEE_SET_UNDERFLOW_MODE(GRADUAL) LOGICAL,INTENT(IN) :: GRADUALGRADUALが.TRUE.の場合にアンダーフローモードを緩やかなアンダ ーフローに、.FALSE.の場合には急激なアンダーフローに設定します。
9.6.6.5 数の分類
TYPE IEEE_CLASS_TYPEこの型の値は数のIEEE区分を示します。これは以下のいずれかの定数です:
IEEE_NEGATIVE_DENORMAL | −TINY(x)<x<0 の範囲にある負の非正規数 x |
IEEE_NEGATIVE_INF | −∞(負の無限大) |
IEEE_NEGATIVE_NORMAL | −HUGE(x)≤x≤−TINY(x) の範囲にある負の正規数 x |
IEEE_NEGATIVE_ZERO | −0 |
IEEE_POSITIVE_DENORMAL | 0<x<TINY(x) の範囲にある正の非正規数 x |
IEEE_POSITIVE_INF | +∞(正の無限大) |
IEEE_POSITIVE_NORMAL | TINY(x)≤x≤HUGE(x) の範囲にある正の正規数 x |
IEEE_POSITIVE_ZERO | +0 |
IEEE_QUIET_NAN | Not-a-Number(通常は不正な演算の結果) |
IEEE_SIGNALING_NAN | 参照で無効なシグナルを発するNot-a-Number |
[5.2] IEEE_OTHER_VALUE | 上記のいずれにも当てはまらないその他の値 |
比較演算子.EQ. (=) と .NE. (/=) はこの型の値を比較 するために提供されます。
ELEMENTAL TYPE(IEEE_CLASS_TYPE) FUNCTION IEEE_CLASS(X) REAL(*),INTENT(IN) :: XXの値の分類を応答として返します。
ELEMENTAL REAL(*) FUNCTION IEEE_VALUE(X,CLASS) REAL(*),INTENT(IN) :: X TYPE(IEEE_CLASS_TYPE),INTENT(IN) :: CLASSCLASSで示される区分とXの種別を持つ“sample”値を 応答として返します。
9.6.6.6 検査関数
以下の手続きがIEEEの値を検査するために提供されます。
ELEMENTAL LOGICAL FUNCTION IEEE_IS_FINITE(X) REAL(*),INTENT(IN) :: XXが“有限”(無限大、非数、IEEE_OTHER_VALUEでない)であるか どうかを応答として返します。
ELEMENTAL LOGICAL FUNCTION IEEE_IS_NAN(X) REAL(*),INTENT(IN) :: XXが非数かどうかを応答として返します。
ELEMENTAL LOGICAL FUNCTION IEEE_IS_NEGATIVE(X) REAL(*),INTENT(IN) :: XXが負であるかどうかを応答として返します。比較X<0との違いは負のゼロ の場合のみで、その場合には.TRUE.が応答として返されます。
ELEMENTAL LOGICAL FUNCTION IEEE_UNORDERED(X,Y) REAL(*),INTENT(IN) :: X,Y‘IEEE_IS_NAN(X) .OR. IEEE_IS_NAN(Y)’の値を応答として返します。
9.6.6.7 算術関数
ELEMENTAL REAL(*) FUNCTION IEEE_COPY_SIGN(X,Y) REAL(*),INTENT(IN) :: X,YYの符号ビットを持つXを応答として返します。
ELEMENTAL REAL(*) FUNCTION IEEE_LOGB(X) REAL(*),INTENT(IN) :: XXがゼロの場合、無限大がサポートされていれば−∞を、そう でない場合には-HUGE(X)を応答として返します。 Xがゼロでない場合にはEXPONENT(X)-1を応答として返します。
ELEMENTAL REAL(*) FUNCTION IEEE_NEXT_AFTER(X,Y) REAL(*),INTENT(IN) :: X,YXに一番近い数でYにより近い数を応答として返します。 XとYが等しい場合にはXを応答として返します。
ELEMENTAL REAL(*) FUNCTION IEEE_REM(X,Y) REAL(*),INTENT(IN) :: X,YXをYで割った際の正確な余りを応答として返します。
ELEMENTAL REAL(*) FUNCTION IEEE_RINT(X) REAL(*),INTENT(IN) :: XXを現在の丸めモードにしたがって丸めた整数値を応答として返します。
ELEMENTAL REAL(*) FUNCTION IEEE_SCALB(X,I) REAL(*),INTENT(IN) :: X INTEGER(*),INTENT(IN) :: ISCALE(X,I)(つまり 2Iを別に計算することなく X*2I)を応答として返します。