Delphi Tokyo 64 ビットは非正規数をゼロにフラッシュしますか? 質問する

Delphi Tokyo 64 ビットは非正規数をゼロにフラッシュしますか? 質問する

system.math のソース コードをざっと見たところ、次のプログラムからわかるように、64 ビット バージョンの Delphi Tokyo 10.2.3 では非正規化 IEEE-Double がゼロにフラッシュされることが分かりました。

{$apptype console}
uses
  system.sysutils, system.math;
var
  x: double;
const
  twopm1030 : UInt64 = $0000100000000000; {2^(-1030)}
begin
  x := PDouble(@twopm1030)^;
  writeln(x);
  x := ldexp(1,-515);
  writeln(x*x);
  x := ldexp(1,-1030);
  writeln(x);
end.

32ビットの場合、出力は予想通りです

8.69169475979376E-0311
8.69169475979376E-0311
8.69169475979376E-0311

しかし64ビットでは

 8.69169475979375E-0311
 0.00000000000000E+0000
 0.00000000000000E+0000

したがって、基本的に Tokyo は 64 ビット モードで非正規数を処理でき、定数は正しく書き込まれますが、算術演算や ldexp を使用した場合でも、非正規数の結果はゼロにフラッシュされます。

この現象は他のシステムでも確認できますか? 確認できる場合、どこに文書化されていますか? (ゼロフラッシュに関して私が見つけることができた唯一の情報は、 ですDenormals become zero when stored in a Real48)。

アップデート:私は知っている両方32 ビットと 64 ビットでは、単精度オーバーロードが使用されます。32 ビットでは x87 FPU が使用され、ASM コードはすべての精度 (単精度、倍精度、拡張) で実質的に同一です。FPU は常に 80 ビットの拡張を返し、これは早期切り捨てなしで倍精度に格納されます。64 ビットのコードは、格納する前に精度調整を行います。その間、私は問題レポートを提出しました (https://quality.embarcadero.com/browse/RSP-20925)、32 ビットまたは 64 ビットの一貫性のない結果に焦点を当てています。

ベストアンサー1

アップデート:

違いは、コンパイラがオーバーロードされた選択を処理する方法だけです。

@Graymatter が発見したように、LdExp呼び出されたオーバーロードはSingle32 ビット コンパイラと 64 ビット コンパイラの両方の型です。唯一の違いはコードベースで、32 ビット コンパイラは asm コードを使用しているのに対し、64 ビット コンパイラは purepascal 実装を使用しています。

正しいオーバーロードを使用するようにコードを修正するには、LdExp()次のように最初の引数の型を明示的に定義します (64 ビット)。

program Project116;

{$APPTYPE CONSOLE}
uses
  system.sysutils, system.math;
var
  x: double;
const
  twopm1030 : UInt64 = $0000100000000000; {2^(-1030)}
begin
  x := PDouble(@twopm1030)^;
  writeln(x);
  x := ldexp(Double(1),-515);
  writeln(x*x);
  x := ldexp(Double(1),-1030);
  writeln(x);
  ReadLn;
end. 

出力:

 8.69169475979375E-0311
 8.69169475979375E-0311
 8.69169475979375E-0311

あなたのケースで選択されたオーバーロードされた関数は 型なので、 Single Double この動作は RTL バグとして報告されるべきだと思います 。結果の型は であり 、コンパイラはそれに応じて確実に適応するはずです。32 ビット コンパイラと 64 ビット コンパイラは同じ結果を生成するはずです。


注記浮動小数点型の型Double(1)キャストは、Delphi 10.2 Tokyoで導入されました。以前のバージョンでの解決策については、double(10)のような型キャストを可能にするDelphiの最初のバージョンは何ですか?

おすすめ記事