木村です.

> 鶴谷さん [FreeBSD-users-jp 91686] Re: long double の bug ? について 
> おそらくは、
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17778
> が原因でgccにこんなコードが挿入されたのだと思うのですが、
この Bugzilla での話とその後の流れを要約すると,次のようになります.

(1) FreeBSD/i386 においては,FPU の精度は仮数部で 53bit に設定され,
  浮動小数点数の定数は long double であっても 53bit に丸められる.
(2) gcc 3.3.5 までは定数はその通りに丸められていたのだが,3.4.2
  ではそれがきちんとできていない.
(3) 以上の主張に基づいて,丸めが正しく行なわれるように修正した.
  それが ChangeLog (例えば /usr/src/contrib/gcc/config/ChangeLog)
  のこの部分である.

Changes by:     
[メールアドレス保護] 
2004-11-12 21:26:55
Log message:
        PR 17778
        * config/i386/i386.h (TARGET_96_ROUND_53_LONG_DOUBLE): New.
        * config/i386/freebsd.h (SUBTARGET_OVERRIDE_OPTIONS): Remove.
        (TARGET_96_ROUND_53_LONG_DOUBLE): New.
        * config/i386/i386-modes.def (XF): Use it.

(4) ただし,この修正が有効なのは 96bit long double の定数のみ.
  128bit のそれに関しては手付かずであり,一貫性がなくなっている.

---------------------------------------------------------------
  このうち (1) の前半は正しいです.(それゆえ fpsetprec(FP_PE);
で仮数部の精度を 64bit に切り換えているのです.)
  しかし,(1) の後半と (2) とは間違っていると考えます.私は今まで
long double の定数が 53bit に丸められてしまった経験はありません.[1]

改めて検討した以下の環境でも lc = 3.14159265358979323846L; の丸めは
生じませんでしたし,逆に Bugzilla の方のテストコードの,gcc 3.3.5 で
丸めが正常に行なわれているとする結果は再現されませんでした.[2]
(FreeBSD 4 系以前の printf() は long double に未対応なので使わず.)
FreeBSD 4.9 + gcc 2.95.4, 3.0.4
FreeBSD 3.4 + gcc 2.7.2.3
FreeBSD 2.2.6 + gcc 2.2.2.1

  加えて,この定数の丸めについて記した文書も見つかりません.

  すなわち,(3) の修正に至った前提である「FreeBSD/i386 においては,
浮動小数点数の定数は long double であっても 53bit に丸められる.」
の真偽を再確認する必要があると考えます.その後,
・偽ならば (3) の修正は元に戻してもらう.
・真ならば,その「仕様」を見直して Linux, Mac OS X, FreeBSD/amd64
  に合わせてもらう.(難しいでしょうね.)
・真偽いずれであっても,(4) の一貫性の問題は修正してもらう.
と話が素直に進んで欲しいところです.

  週末あたりにこの質問から入るような send-pr をしようと思っています.
Bugzilla でなく FreeBSD の土俵の方が良いような気がするからです.

[1] そもそも,(1) の後半が真であるとすれば,FreeBSD + i386 の
  環境では double でなく long double を使う理由に乏しいのです.
[2] 皆様の環境での追試は結構です.確認したいのは動作よりも仕様
  だからです.仕様の情報をお持ちの方はお知らせ下さい.

                      Satoshi Kimura  
([メールアドレス保護])

メールによる返信