当前位置 : 主页 > 编程语言 > delphi >

Delphi:如何翻译这个C代码,它对IEEE浮点数进行低级访问?

来源:互联网 收集:自由互联 发布时间:2021-06-23
以下C函数来自 fastapprox项目. static inline float fasterlog2 (float x){ union { float f; uint32_t i; } vx = { x }; float y = vx.i; y *= 1.1920928955078125e-7f; return y - 126.94269504f;} 我知道C union可以翻译成Delphi变体记录
以下C函数来自 fastapprox项目.

static inline float 
fasterlog2 (float x)
{
  union { float f; uint32_t i; } vx = { x };
  float y = vx.i;
  y *= 1.1920928955078125e-7f;
  return y - 126.94269504f;
}

我知道C union可以翻译成Delphi变体记录,但是我仍然难以将这种低级C代码翻译成Delphi.我希望这里的Delphi专家愿意提供帮助.

更多信息

我稍后会添加此部分,这不是问题的一部分.本节为希望获得更高准确性的读者提供信息.

>在fastapprox中,quicklog2()被故意设计为更简单,更快但不太准确的Log2功能.任何期望更高准确度的人都可以使用他们提供的更准确的功能,即fastlog2().
>他们包括一个Mathematica notebook,解释了他们的算法以及一些神秘值的起源,例如:126.94269504. Mathematica website为.nb文件提供免费查看器.
>另见:Why the IEEE-754 exponent bias used in this C code is 126.94269504 instead of 127?

我想我会通过使用指针强制转换来对其进行编码以实现重新解释转换:

function fasterlog2(x: single): single;
const
  c1: Single = 1.1920928955078125e-7;
  c2: Single = 126.94269504;
var
  y: single;
begin
  y := PCardinal(@x)^;
  Result := y * c1 - c2;
end;

请注意,我使用了type类型的类型常量来确保与C代码完全匹配.

我真的不认为在Delphi实现中需要变量记录.

或者你可以使用纯粹的asm方法. x86版本如下所示:

function fasterlog2asm(x: single): single;
const
  c1: Single = 1.1920928955078125e-7;
  c2: Single = 126.94269504;
asm
  FILD    DWORD PTR [ESP+$08]
  FMUL    c1
  FSUB    c2
  FWAIT
end;

对于x64,SSE实现将是

function fasterlog2asm64(x: single): single;
const
  c1: double = 1.1920928955078125e-7;
  c2: double = 126.94269504;
asm
  CVTDQ2PD  xmm0, xmm0
  MULSD     xmm0, c1
  SUBSD     xmm0, c2
  CVTSD2SS  xmm0, xmm0
end;

在x64中,汇编版本的性能仅为纯pascal函数的两倍. x86汇编版本的性能超过了五倍 – 这完全是由于SSE与x87中类型转换(整数/单/双)的成本较高.

可以使用此方法的原因是浮点数表示为

significand * base^exponent

并且值2用作基础.

网友评论