[FreeBSD-users-jp 91680] long double の bug ? について
木村です. 下記のようなトラブルに遭遇しました.調べた限りではこの問題は 報告されていないので,この ML で情報を募りたくメール致しました. 1. 状況 FreeBSD 5.3 + gcc(3.4.2) で作成した,拡張倍精度 (long double) を使ったプログラムを FreeBSD 6.2 + gcc(3.4.6) にて使用すると, 結果が違いました.検討した末,以下のことが分かりました. gcc に -m96bit-long-double (default) と -m128bit-long-double の option を付けた場合を各々 96bit, 128bit と書くことにしますと, (1) FreeBSD 5.3 (96, 128bit), FreeBSD 6.2 (128bit) の三者の 結果は同じになる. (2) FreeBSD 6.2 (96bit) の場合,(1) よりも概して精度が悪い. 2. 原因 この問題の生じ方を探りますと,「FreeBSD 6.2 において拡張倍 精度として 96bit を使うと,式の中の定数の精度が double に 落とされてしまう」ことに起因していることが分かりました. (この段階では「原因」とは言えないでしょうが.) 例えば,こんな使い方をした場合です. x = 3.14159265358979323846L; x = sqrtl(1.5L); 参考までに,この問題の簡単な確認法を示します. main(void) { double c; long double lc; c = 3.14159265358979323846; lc = 3.14159265358979323846L; } これを s.c とし,二通りにコンパイルしてアセンブラを出力します. % gcc -m96bit-long-double -S s.c -o s1.a % gcc -m128bit-long-double -S s.c -o s2.a 両者のアセンブラの,この数値に関連した部分は次のようになります. (ちなみに,FreeBSD 5.3 の二つと,FreeBSD 6.2 にて -m128bit-long-double を規定した場合の三者は同じです.) 変数 c .long 1413754136 ← 仮数部 (2) .long 1074340347 ← 符合,指数部,仮数部 (1) が混在 変数 lc movl$560513024, %eax ← 仮数部 (2). 128bit では $560513589 movl$-921707870, %edx ← 仮数部 (1) movl$16384, %ecx ← 符合と指数部 この数値から double の変数 c の仮数部 (mant) を求めると次のようになります. double : 1074340347 1413754136 mant = 09 21 fb 54 44 2d 18 これを long double の変数 lc の仮数部と比較するために, 左に 3bit シフトして,かつ最上位の 1bit を立てます. それと lc の 96, 128bit の場合の仮数部を並記すると次のようになります. double :mant = c9 0f da a2 21 68 c0 96bit : -921707870 560513024 mant = c9 0f da a2 21 68 c0 00 128bit : -921707870 560513589 mant = c9 0f da a2 21 68 c2 35 すなわち,96bit の拡張倍精度の場合,定数の精度が倍精度に落とされ てしまっています. 3. お願い 以下の二点を確認して,必要ならば send-pr しようと思います. (1) これは bug なのか,隠れ compile option などがあるのか? (2) bug であったとして,FreeBSD 6.3 や 7.0 でもこの問題は起き 続けているのか? (これらはうちにないので確認できません.) 先ず,(1) について御存じの方,情報をお願い致します. Satoshi Kimura ([#x30E1;#x30FC;#x30EB;#x30A2;#x30C9;#x30EC;#x30B9;#x4FDD;#x8B77;])
[FreeBSD-users-jp 91681] Re: long double の bug ? について
小野です。 結論から言えば、i386システム用のgccにおけるコン パイルオプションなのではないでしょうか。 % gcc -m96bit-long-double -S s.c -o s1.a % gcc -m128bit-long-double -S s.c -o s2.a これを簡易に試してみました。いづれもプラットフォームはIntel Core2DuoのMacintoshです。 1) MacOSXネイティヴな環境 (OSX 10.5.2) この環境では、二つのアセンブラソースは僅かに違い、変数lcの定 義において96bitオプションでは LC1: .long 560513589 .long -921707870 .long 16384 .text 128bitオプションでは LC1: .long 560513589 .long -921707870 .long 16384 .long 0 .text となります。gccのヴァージョン情報は % gcc --version i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5465) Copyright (C) 2005 Free Software Foundation, Inc. ですので、いわゆるi386システム用であることがわかります。 2) FreeBSD/amd64 on VMWare Fusion こちらの環境では、両アセンブラソースは完全に一致します。変数lc の定義部分は .LCFI1: movabsq $4614256656552045848, %rax movq%rax, -8(%rbp) movabsq $-2958705157555305931, %rax movl$16384, %edx movq%rax, -32(%rbp) movl%edx, -24(%rbp) となっています。gccのヴァージョン情報は % gcc -v Using built-in specs. Confugured with: FreeBSD/amd64 system compiler Thread model: posix gcc version 3.4.6 [FreeBSD] 20060305 です。すなわち、amd64システム用であることがわかります。 以上の結果から、冒頭に述べたようにこれはi386システム用の gccにおけるコンパイルオプションであると思われます。いかがで しょうか。 -- ;; So I must go before you see me fall ;; 小野すず@平城京右京五条三坊
[FreeBSD-users-jp 91682] Re: long double の bug ? について
木村です. 小野さん [FreeBSD-users-jp 91681] Re: long double の bug ? について 結論から言えば、i386システム用のgccにおけるコン パイルオプションなのではないでしょうか。 済みません.書き忘れていました.i386 での話です. -m96bit-long-double, -m128bit-long-double は確かに i386 用の option ですが,私が問題にしているのは,少なくとも FreeBSD 6.2 にて, この option の差異によって,計算結果に本来生じるべきでない差異が 現われることと,それが実行時でなくコンパイルの段階で生じていること です. 1) MacOSXネイティヴな環境 (OSX 10.5.2) % gcc --version i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5465) 2) FreeBSD/amd64 on VMWare Fusion % gcc -v Using built-in specs. Confugured with: FreeBSD/amd64 system compiler Thread model: posix gcc version 3.4.6 [FreeBSD] 20060305 ちゃんと i386 と書かなかったのでお手間をとらせて申し訳 ありませんでした.お試しいただいた二つの環境では,この問題 は生じていないのですね.小野さんの Mac の結果を参考に,明日 (もう今日) gcc version 4 も試してみます. ところで,本題からはずれますが, .LCFI1: movabsq $4614256656552045848, %rax movq%rax, -8(%rbp) movabsq $-2958705157555305931, %rax movabsq されている二つの行はどちらも変数 lc の仮数部なのでしょうか? amd64 の sizeof(long double) っていくつなのでしょうか? Satoshi Kimura ([#x30E1;#x30FC;#x30EB;#x30A2;#x30C9;#x30EC;#x30B9;#x4FDD;#x8B77;])
[FreeBSD-users-jp 91684] Re: long double の bug ? について
こんにちは、小野です。 私こそ問題をちゃんと把握していなかったようで、すみません。 96bitオプションをつけた場合、拡張倍精度の仮数部が 52bit(=doubleの仮数部のビット幅)程度しかない、というの が問題だったんですね。そうだとすると、MacOSXに載っているgcc4 では、どちらのオプションを付けても仮数部(2)が64bit幅の $560513589になっていますから、FreeBSD/i386 6.2のgcc 固有の問題ということになりそうですね。 ところで movabsq されている二つの行はどちらも変数 lc の仮数部 なのでしょうか? amd64 の sizeof(long double) っていくつなのでしょうか? ですが、多分そうだと思います。拡張倍精度の指数部のバイアスが +16383であることを考えると、直後に movl $16384, -32(%rbp) していますから、この二つのmovabsqは仮数部の代入命令だと 思います。 なお、amd64のsizeof(long double)は16でした。 -- ;; So I must go before you see me fall ;; 小野すず@平城京右京五条三坊
[FreeBSD-users-jp 91685] Re: long double の bug ? について
続けまして小野です。 FreeBSD/i386 7.0Rを導入して試してみましたが、同様の問 題は残存しています。やはり拡張倍精度の変数への代入部分のアセ ンブラコードはオプションの違いによって異なっていますね。数値は6.2 の場合と同じです。gccは4.2.1 20070719になっている のですが。 -- ;; So I must go before you see me fall ;; 小野すず@平城京右京五条三坊
[FreeBSD-users-jp 91686] Re: long double の bug ? について
こんにちは、鶴谷です。 [#x30E1;#x30FC;#x30EB;#x30A2;#x30C9;#x30EC;#x30B9;#x4FDD;#x8B77;] さん 続けまして小野です。 FreeBSD/i386 7.0Rを導入して試してみましたが、同様の問 題は残存しています。やはり拡張倍精度の変数への代入部分のアセ ンブラコードはオプションの違いによって異なっていますね。数値は6.2 の場合と同じです。gccは4.2.1 20070719になっている のですが。 うちでもこうでした: FreeBSD 7.0, gcc 4.2.1 : NG FreeBSD 6.3, gcc 3.4.6 : NG FreeBSD 6.3, gcc 4.2.4 : NG cygwin, gcc 3.4.4 : OK Debian, gcc 3.2.3 : OK おそらくは、 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17778 が原因でgccにこんなコードが挿入されたのだと思うのですが、 私には、どういう問題なのか、また、どうするべきなのか、理解できていません。 試しに、FreeBSD 6.3で、ports/lang/gcc42に、 --- gcc/config/i386/freebsd.h.orig 2007-09-02 00:28:30.0 +0900 +++ gcc/config/i386/freebsd.h 2008-06-16 09:09:00.0 +0900 @@ -137,4 +137,4 @@ /* FreeBSD sets the rounding precision of the FPU to 53 bits. Let the compiler get the contents of float.h and std::numeric_limits correct. */ #undef TARGET_96_ROUND_53_LONG_DOUBLE -#define TARGET_96_ROUND_53_LONG_DOUBLE (!TARGET_64BIT) +#define TARGET_96_ROUND_53_LONG_DOUBLE 0 のようなパッチを当ててビルドして使ってみると、 -m96bit-long-doubleと-m128bit-long-doubleの出力の違いはなくなりました。 しかし、よくわからない問題が残っています。 上述のバグレポートで提示されているテストコードをビルドした結果を見ると、 ほかのOSでの結果と異なります。 Debian : -m96bit-long-doubleなどのオプションがあっても無くても、 0xc.90fdaa22168c4p-2 0xc.90fdaa22168c4p-2 FreeBSD : -m96bit-long-doubleなどのオプションがあっても無くても、 0xc.90fdaa22168c4p-2 0xc.90fdaa22168cp-2 cygwinでは、%Laが動きませんでした。 そこで、出力時の変換指定子をを%40.30Lfとして実行すると、 Debian : 3.141592653589793338042568393575 3.141592653589793338042568393575 cygwin : 3.141592653589793338042568393575 3.141592653589793338042568393575 FreeBSD 6.3 : 3.141592653589793115997963468544 3.141592653589793115997963468544 FreeBSD 6.3 (上記の修正を行ったgcc42): 3.141592653589793338042568393575 3.141592653589793115997963468544 となりました... FreeBSDでは、浮動小数点演算はlong doubleで行ってくれないということでしょうか? -- 鶴谷 直樹 E-mail: [#x30E1;#x30FC;#x30EB;#x30A2;#x30C9;#x30EC;#x30B9;#x4FDD;#x8B77;]
[FreeBSD-users-jp 91687] Re: sendmail の From 制限
take です。 皆さん ありがとうございます。 milterでもcfでもできそうってことがわかってよかったです。 もうひとつわかった事は、私の圧倒的な知識不足のようです。 みなさんのアドバイスや設定例を頂いて、 なるほどなるほど、ではやってみようとなれない程に力量不足でした。 cf/README、こうもり本と修行をつんだ後 設定する事にしました。 (Fromを制限したからって抜本的なSpamやウィルス対策にはなっていないので) また何かあれば報告させて頂きます。