1,183
社区成员
发帖
与我相关
我的任务
分享
float InvSqrt(float x){
float xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = *(float*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
function InvSqrt(x: Single): Single;
var
xhalf: Single;
i: Integer;
begin
xhalf := x * 0.5;
i := PInteger(@xhalf)^;
i := $5f3759d5 - (i shr 1);
x := PSingle(@i)^;
Result := x * (1.5 - xhalf*x*x);
end;
var
OneHalf: DWORD = $3FC00000;
function f_invsqrt(v: Single): Single;
asm
MOV EAX, DWORD PTR [EBP+8] // i := PInteger(@x)^;
SUB EAX, $800000
PUSH EAX // xhalf := x*2
ADD EAX, $800000
MOV EDX, $5F3759D5
SHR EAX, 1
SUB EDX, EAX // i := 5f3759d5-(i shr 1)
PUSH EDX
FLD DWORD PTR [ESP] // x := PSingle(@i)^
FLD ST(0)
FMUL ST(0), ST(0)
FMUL DWORD PTR [ESP+4]
FSUBR DWORD PTR OneHalf
FMULP // result := x * (1.5 - xhalf*x*x);
ADD ESP, 8
end;
function f_div(x, y: Single): Single;
begin
if y<0 then
begin
y := -y;
x := -x;
end;
result :=f_invsqrt(y) * f_invsqrt(y) * x;
end;
function f_div(v1, v2: Single): Single;
asm
/* 调整v1, v2的值: v2取绝对值并相应调整v1的正负 */
MOV EAX, DWORD PTR [EBP+8]
MOV EDX, $80000000
AND EDX, EAX
AND EAX, $7FFFFFFF
XOR DWORD PTR [EBP+12], EDX
FLD DWORD PTR [EBP+12]
/* 计算v2的Inverse sqrt再平方再乘以v1 */
SUB EAX, $800000
PUSH EAX
ADD EAX, $800000
MOV EDX, $5F3759D5
SHR EAX, 1
SUB EDX, EAX
PUSH EDX
FLD DWORD PTR [ESP]
FMUL ST(0), ST(0)
FMUL ST(1), ST(0)
FMUL DWORD PTR [ESP+4]
FSUBR DWORD PTR OneHalf
FMUL ST(0), ST(0)
FMULP
ADD ESP, 8
end;