中田真秀(なかたまほ)のブログ

研究について、日常について、その他。

double-double (疑似四倍精度)はC99のlong doubleとして採用できない。

2010-04-16 15:19:28 | 日記
double-double (疑似四倍精度)はC99のlong doubleとしてありえない。
端的に言うと、規格からはlong doubleで表される数は、doubleで表される数を含まねばならないが、そうではないからだ。double-doubleでは、doubleで表される最小の数を表現できないのである。

なぜこんなこと考えたかというと、C/C++に四倍精度が欲しいわけだ。だがソフトウェアでの実装はどうしても遅くなりすぎる。ハードウェア実装も見込めない。そこで手軽な四倍精度が欲しい、そうなるとdouble-doubleか。だったらlong doubleをdouble-doubleとして疑似四倍精度とすればいいではないか、ということである。実際IBM AIXやMacOSX PowerPC版はそうしている。

さて、規格...ドラフトだけど、読んでみよう。
C99ドラフト
p.458より
The long double type matches an IEC60559 extended format,310) else a
non-IEC 60559 extended format, else the IEC 60559 double format.
Anynon-IEC 60559extended format used for thelong double type shall have more
precision than IEC 60559 double and at least the range of IEC 60559 double.311)
Recommended practice
2 The long double type should match an IEC 60559 extended format.

つまり、
> long double type shall have more precision than IEC 60559 double
ここが引っかかる。

わかりやすくいうと最小のexponentを持つdouble型の変数はdouble-doubleでは扱えないということだ。正確な表現では、正規化された数の最小値が大きくなる、からだ。たとえば、Hidaさんのqdからsrc/dd_const.cppを読むと

const double dd_real::_eps = 4.93038065763132e-32; // 2^-104
const double dd_real::_min_normalized = 2.0041683600089728e-292; // = 2^(-1022 + 53)

となっている。正規化された数の最小値はdouble-doubleでは、doubleより少し大きくなってしまうのだ。

というわけで、C99に準拠する限り、long doubleを疑似四倍精度であるdouble-doubleで、ということは不可能ということが分かる。たとえばIBM AIXやMacOSX PowerPC版では、long doubleはdouble-doubleである。これはC99に違反するのだ。実際の利用には精度の問題がある。ご注意あれ。