ぐだぐだ低レベルプログラミング(220)x86(16bit)、浮動小数点数の丸めと制御

Joseph Halfmoon

前回は、非正規数(デノーマル)とか疑似無限大とか「ヤバイ奴ら」の説明で力尽きてしまいました。しかし説明書きながらも「座りの悪さ」を感じていたのです。そういえば、メンドイ奴ら、丸めと計算精度の制御とか、無限大の計算モードとかやってなかったじゃないかと。8087の制御ワードの説明がいるな。それには8087の内部型も要説明。

※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら

Temporary Real型

以下の過去回で、8087レジスタの図を掲げたので、8087が内部の計算で使っているTemporary Real型とか制御レジスタCWとかについても説明したような気になってました。

ぐだぐだ低レベルプログラミング(213)x86(16bit)、8087のレジスタ

しかしレジスタのイメージを絵にしただけ、説明がなかったです。まずは、8087の内部計算に使われるTemporary Real型から。TemporaryReal

8087のレジスタ・スタックのビット幅80ビットいっぱいの「型」です。32ビットの単精度実数(float型)も64ビットの倍精度実数(double)型も8087にロードするとみなこの型に押し込められて以降の計算がなされる、という塩梅です。押し込められるといっても

    • 単精度実数型、符号1ビット、指数部8ビット、仮数部23ビット(MSBに暗黙の1があるので実質24ビット)
    • 倍精度実数型、符号1ビット、指数部11ビット、仮数部52ビット(MSBに暗黙の1があるので実質53ビット)
    • テンポラリ実数型、符号1ビット、指数部15ビット、仮数部64ビット(暗黙のビットは実体化してビット63に実在する。正規化数であればMSBは常に1。非正規化数の場合0。)

のようにテンポラリ実数型は「大は小を兼ねている」ので、単精度や倍精度の実数を軽々と飲み込んでくれます。そして単精度や倍精度の「メモリ上の数値表現」では隠されていた暗黙のMSBが実体化して存在します(無いと計算できないし。)

※なお、この時代「もっと幅の狭い」浮動小数(半精度とか)が必要になるとか、今のAIへの流れを誰も予想してなかったと思うので、8087実数型の最狭は単精度っす。

なお、指数部はいずれも「下駄履き」です。下駄は単精度の場合127(符号なしの指数部に127と書いてあると指数は2の0乗、128なら1乗、126ならマイナス1乗ということね)、倍精度の場合1023、そしてテンポラリ実数型の場合16383です。

通常、8087は、テンポラリ実数型の80ビットの幅をフル活用して計算を進めてくれるみたいです。よって「丸め」は64ビットの仮数部のその下をウロチョロしているらしいっす。ちょっとやそっとでは丸め誤差が累積するとか無さそうな感じ。しかし、浮動小数プロの人々にとってはその辺の出し入れが死命を制するみたい。知らんけど。

丸めの精度

計算結果をレジスタに書き戻すとき(レジスタ上の仮数部表現は64ビットだが、8087の計算ハードウエアは68ビット幅ある)、丸めが発生し64ビット表現で戻されるのが8087の「通常運転」らしいです。しかし、8087ほどの精度が無いハード上で倍精度や単精度で計算した結果と「同じ」結果が欲しい、みたいな玄人筋の御要望に応えるため?Precision Control(PC)というビットが制御レジスタCWの中に存在します。8087CW

上記のCWの図の緑色のビットです。ここのビットによってレジスタへの書き戻しであっても

    • 00:24ビット(単精度)
    • 01:リザーブ(使っちゃいけない)
    • 10:53ビット(倍精度)
    • 11:64ビット(テンポラリ実数)

の有効数字のビット幅に収まるように丸めをしてくれるみたいです。勿論、メモリ上に単精度や、倍精度表現で書き出す場合は何も言わずともその有効数字になるように丸めてくれる筈。

丸めモード

さらにCWにはRC、Rouding Controlビットあり、4種類の丸めからどれを使うか指定できるようになってます。

    • 00:近い方に丸め
    • 01:マイナス無限大方向丸め
    • 10:プラス無限大方向丸め
    • 11:ゼロ方向に丸め(チョップ)

チョップするのはBCD整数扱うときなどかな?BCDもクセ強で近寄りたくないんだけど。

無限大にもモードあり

丸めモードのRCの上にあるビットICが、Infinity Controlです。前回、無限大の表現にはプラス無限大とマイナス無限大あり、と申し上げましたが、

    • PROJECTIVE CLOSURE、であれば+∞とー∞は同じ∞という一つの値(世界はドーナツ型?)
    • AFFINE CLOSURE、であれば+∞とー∞は異なる値

という扱いになるのだそうな。なおデフォルトはPROJECTIVE CLOSUREっす。

素人老人には理解のおよばぬ世界が広がっておるのよ、万歳。

ぐだぐだ低レベルプログラミング(219)x86(16bit)、浮動小数点数の検査FXAM へ戻る