Fast Power Bug ?
Skybuck Flying <[email protected]> Sun, 19 Feb 2023 22:32:42 -0800 (PST)
| Newsgroups | alt.comp.lang.borland-delphi |
|---|---|
| Message-ID | <[email protected]> |
FastPower(Single, Single) does not work with Base = 0,474733531475067 eg and Exponent = 150, should return zero. The same checks as in rtl before Result := FastExp2(AExponent * FastLog2(ABase)); make it work as it should. function FastPower(const ABase, AExponent: Single): Single; begin Result := FastExp2(AExponent * FastLog2(ABase)); end; // 32 bit implementation function FastExp2(const A: Single): Single; assembler; var OldFlags, NewFlags: UInt32; asm // Set rounding mode to Round Positive (=Round Down) stmxcsr [OldFlags] movss xmm0, [A] mov ecx, [OldFlags] xorps xmm1, xmm1 and ecx, SSE_ROUND_MASK movss xmm3, xmm0 or ecx, SSE_ROUND_DOWN movss xmm5, xmm0 mov [NewFlags], ecx movss xmm1, DWORD [SSE_EXP2_F1] ldmxcsr [NewFlags] // Z := A - RoundDown(A) cvtps2dq xmm3, xmm3 addss xmm1, xmm5 // A + 121.2740575 cvtdq2ps xmm3, xmm3 movss xmm2, DWORD [SSE_EXP2_F2] subss xmm0, xmm3 movss xmm3, DWORD [SSE_EXP2_F3] movss xmm4, DWORD [SSE_EXP2_F4] subss xmm3, xmm0 // (4.84252568 - Z) mulss xmm0, xmm4 // 1.49012907 * Z divss xmm2, xmm3 movss xmm5, DWORD [SSE_EXP2_F5] addss xmm1, xmm2 // A + 121.2740575 + 27.7280233 / (4.84252568 - Z) subss xmm1, xmm0 // A + 121.2740575 + 27.7280233 / (4.84252568 - Z) - 1.49012907 * Z mulss xmm1, xmm5 // (1 shl 23) * (A + 121.2740575 + 27.7280233 / (4.84252568 - Z) - 1.49012907 * Z) cvtps2dq xmm1, xmm1 // Restore rounding mode ldmxcsr [OldFlags] movss [Result], xmm1 end; function FastLog2(const A: Single): Single; assembler; asm movss xmm0, [A] movss xmm2, DWORD [SSE_MASK_FRACTION] movss xmm1, xmm0 // MX.I := (VX.I and $007FFFFF) or $3F000000 movss xmm3, DWORD [SSE_LOG2_I1] pand xmm0, xmm2 cvtdq2ps xmm1, xmm1 movss xmm4, DWORD [SSE_LOG2_F1] por xmm0, xmm3 movss xmm2, DWORD [SSE_LOG2_F2] mulss xmm1, xmm4 // VX.I * 1.1920928955078125e-7 movss xmm3, DWORD [SSE_LOG2_F3] subss xmm1, xmm2 // Result - 124.22551499 mulss xmm3, xmm0 movss xmm4, DWORD [SSE_LOG2_F5] subss xmm1, xmm3 // Result - 124.22551499 - 1.498030302 * MX.S movss xmm2, DWORD [SSE_LOG2_F4] addss xmm0, xmm4 divss xmm2, xmm0 subss xmm1, xmm2 // Result - 124.22551499 - 1.498030302 * MX.S - 1.72587999 / (0.3520887068 + MX.S) movss [Result], xmm1 end; // 64 bit implementation function FastExp2(const A: Single): Single; assembler; var OldFlags, NewFlags: UInt32; asm // Set rounding mode to Round Positive (=Round Down) stmxcsr [OldFlags] mov ecx, [OldFlags] xorps xmm1, xmm1 and ecx, SSE_ROUND_MASK movss xmm3, xmm0 or ecx, SSE_ROUND_DOWN movss xmm5, xmm0 mov [NewFlags], ecx movss xmm1, DWORD [SSE_EXP2_F1] ldmxcsr [NewFlags] // Z := A - RoundDown(A) cvtps2dq xmm3, xmm3 addss xmm1, xmm5 // A + 121.2740575 cvtdq2ps xmm3, xmm3 movss xmm2, DWORD [SSE_EXP2_F2] subss xmm0, xmm3 movss xmm3, DWORD [SSE_EXP2_F3] movss xmm4, DWORD [SSE_EXP2_F4] subss xmm3, xmm0 // (4.84252568 - Z) mulss xmm0, xmm4 // 1.49012907 * Z divss xmm2, xmm3 movss xmm5, DWORD [SSE_EXP2_F5] addss xmm1, xmm2 // A + 121.2740575 + 27.7280233 / (4.84252568 - Z) subss xmm1, xmm0 // A + 121.2740575 + 27.7280233 / (4.84252568 - Z) - 1.49012907 * Z mulss xmm1, xmm5 // (1 shl 23) * (A + 121.2740575 + 27.7280233 / (4.84252568 - Z) - 1.49012907 * Z) cvtps2dq xmm1, xmm1 // Restore rounding mode ldmxcsr [OldFlags] movss xmm0, xmm1 end; function FastLog2(const A: Single): Single; assembler; asm movss xmm2, DWORD [SSE_MASK_FRACTION] movss xmm1, xmm0 // MX.I := (VX.I and $007FFFFF) or $3F000000 movss xmm3, DWORD [SSE_LOG2_I1] pand xmm0, xmm2 cvtdq2ps xmm1, xmm1 movss xmm4, DWORD [SSE_LOG2_F1] por xmm0, xmm3 movss xmm2, DWORD [SSE_LOG2_F2] mulss xmm1, xmm4 // VX.I * 1.1920928955078125e-7 movss xmm3, DWORD [SSE_LOG2_F3] subss xmm1, xmm2 // Result - 124.22551499 mulss xmm3, xmm0 movss xmm4, DWORD [SSE_LOG2_F5] subss xmm1, xmm3 // Result - 124.22551499 - 1.498030302 * MX.S movss xmm2, DWORD [SSE_LOG2_F4] addss xmm0, xmm4 divss xmm2, xmm0 subss xmm1, xmm2 // Result - 124.22551499 - 1.498030302 * MX.S - 1.72587999 / (0.3520887068 + MX.S) movss xmm0, xmm1 end; Any idea what bug could be ? Bye, Skybuck.