[FreeBSD-users-jp 91680] long double の bug ? について

2008-06-15 スレッド表示 Satoshi Kimura
木村です.

  下記のようなトラブルに遭遇しました.調べた限りではこの問題は
報告されていないので,この 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 ? について

2008-06-15 スレッド表示 suzu


 小野です。

 結論から言えば、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 ? について

2008-06-15 スレッド表示 Satoshi Kimura
木村です.

 小野さん [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 ? について

2008-06-15 スレッド表示 suzu


 こんにちは、小野です。
 私こそ問題をちゃんと把握していなかったようで、すみません。

 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 ? について

2008-06-15 スレッド表示 suzu


 続けまして小野です。
 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 ? について

2008-06-15 スレッド表示 Tsurutani Naoki
こんにちは、鶴谷です。

[#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 制限

2008-06-15 スレッド表示 takesi

take です。


皆さん ありがとうございます。

milterでもcfでもできそうってことがわかってよかったです。
もうひとつわかった事は、私の圧倒的な知識不足のようです。
みなさんのアドバイスや設定例を頂いて、
なるほどなるほど、ではやってみようとなれない程に力量不足でした。

cf/README、こうもり本と修行をつんだ後
設定する事にしました。
(Fromを制限したからって抜本的なSpamやウィルス対策にはなっていないので)

また何かあれば報告させて頂きます。