えぐち@エスアンドイー です。

>>> In message [ruby-math:00089] Re: NaN again
    On Fri, 21 Jan 2000 02:22:26 +0900 (JST), gotoken / math.sci.hokudai.ac.jp (GOTO Kentaro) said:

ご> ごとけんです
ご> 
ご> In message "[ruby-math:00085] Re: NaN again"
ご>     on 00/01/20, EGUCHI Osamu <eguchi / shizuokanet.ne.jp> writes:
ご> 
ご> >あ、今回は問題ないけど long が 64 ビットな場合は、
ご> >問題あるんでしたっけ?
ご> 
ご> 64bitはきちんと定義してあるので大丈夫のはずです。その他の長
ご> さだとどうなるかいまいち分かりませんが一応は考慮してあります。

コードを読んでみました、なるほどちゃんと考えてありますね、
#PDP Endian には未対応みたい(<誰も使ってないって) ;-p

ご> >全順序集合ではない事や、1.0 / 0.0 → Infinity など
ご> >IEEE754 って『数学』と言う見方でみると、かなり
ご> > ``???'' ではあるんですけど、実施の演算としての
ご> >実行を考えると、妥協の産物としてはうまく整合してると思います。
ご> 
ご> それには同意します。ただNaNの使い道がそれほど詳しく説明され
ご> てないのは惜しいと思います。いちおう、NaNのフォーマットに余
ご> 裕があるのはエラー追跡のためらしいんですけど、現状ではほとん
ご> ど使われてないですよね。

規格に NaNs って複数形で出ているのはそのためなんですよね。
#最初は Signaling と Quitet の2種類で NaNs だと思ってました ^^;;

ご> >ご> >どちらかと言うと、1.0 <=> NaN = NaN 説に傾きつつあります。
ご> >ご> >(1.0 - NaN = NaN からの類推、例外は発生しないと言う立場です)
ご> >ご> 
ご> >ご> うーむ、それはそれでよいなぁ。NaNも一応Numericだし。一票入れ
ご> >ご> ときます。
ご> >
ご> >ごとけんさんに賛同いただけると心強いです。
ご> 
ご> # てれてれ /(^^;;
ご> 
ご> ともかく、<=> はsortのためであるのでそこでそれなりの例外が出
ご> ればよいでしょうね。また、ほとんど全順序だけど、ちょびっとだ
ご> け全順序でないものに <=> を実装したい場合の手本にもなるでしょ
ご> うし。

<=> に関する奇妙な挙動として強いて言えば、 Inf <=> Inf があります。 
Inf - Inf は、NaN ですが Inf == Inf は、真 Inf <=> Inf は 0
#finite <=> NaN とは様子が違いますが、
#比較と減算は完全には対応しない実例として、あげられます。

こう言うと、 finite <=> NaN → NaN 論と整合しないようですが、、、
IEEE754 の例外のディフォルトの挙動は「なにもしない」なので、
Ruby では何もしないで NaN を返す様ことが妥当だと考えたわけです。

「全順序でないものに <=> を実装したい場合」の
『全順序でないもの』って Set (集合) の様な物を想定してますか?
とすると、、

Set a と Set b に置いて、
  a が b の部分集合 ⇒ a <=> b → -1
  b が a の部分集合 ⇒ a <=> b →  1
  a が b の部分集合でなく、b が a の部分集合でない ⇒ a <=> b → NaN 
でしょうか?(集合の比較に <=> は無理あり?)

と言った応用的な用途を考えると、.kind_of? Float な NaN よりも
nil や false が相応しくも思えます。

要するに finite <=> NaN の時(及び NaN <=> finete の時)

   Numeric でない有意な値を返し、例外は発生させない

のであれば、「Numeric でない有意な値」は何でもいいです。 ^^;;;

ご> >まづ、ちゃんと -0.0 を作れるかを確認してからチェックしないと、、
ご> 
ご> -0.0 のフォーマットはユニークなので、configureの際は基準とな
ご> るものをビットマップで作るのが良いと思います。またFPU例外を
ご> 制御するのが面倒なので比較もビットマップとして行った方が良い
ご> でしょう。参考までにこれらをつけときます。

mzero() の -0.0 の作り方が凝ってますね。(^^)

ところで、

	double p = +0.0;
	double n = -0.0;
	return memcmp(&p, &n, sizeof p) != 0;

程度だとまずいでしょうか?

ご> # isnan() もこんな感じで実装しちゃった方が確実かも。

NaN を変数に入れて、引数とビット毎の比較と言う事ですね。

NaN != NaN が真にあるバグを持ったコンパイラに関して考えると
考慮に値すると思います。

しかし、NaN のフォーマットが

  仮数が非ゼロかつ(バイアス済みの)指数がオールビット1

なので、その場で用意した NaN と違うビットパターンの
NaN が来る事もあるのが問題です。(NaNs なんです)

あ、それとも  NaN != NaN ⇒ true がうまく行っていたと思っていたら、
じつは右辺と左辺は違うビットパタンの NaN だったってケースの問題?

	えぐち