ftol2 の関数を調べてみて分かった事
ftol は float(浮動小数点) から long 型、
ftol2 は float(浮動小数点) から long^2 型つまりlonglong型64bit 整数に変換する関数だと長いこと思っていました。
ところが、VC++ のインライン関数を調べてみるとそうでないことが分かりました
_ftol2_sse: 00411640 83 3D B8 75 41 00 00 cmp dword ptr [___sse2_available (4175B8h)],0 00411647 74 2D je _ftol2 (411676h) _ftol2_pentium4: 00411649 55 push ebp 0041164A 8B EC mov ebp,esp 0041164C 83 EC 08 sub esp,8 0041164F 83 E4 F8 and esp,0FFFFFFF8h 00411652 DD 1C 24 fstp qword ptr [esp] 00411655 F2 0F 2C 04 24 cvttsd2si eax,mmword ptr [esp] 0041165A C9 leave 0041165B C3 ret _ftol2_sse_excpt: 0041165C 83 3D B8 75 41 00 00 cmp dword ptr [___sse2_available (4175B8h)],0 00411663 74 11 je _ftol2 (411676h) 00411665 83 EC 04 sub esp,4 00411668 D9 3C 24 fnstcw word ptr [esp] 0041166B 58 pop eax 0041166C 66 83 E0 7F and ax,7Fh 00411670 66 83 F8 7F cmp ax,7Fh 00411674 74 D3 je _ftol2_pentium4 (411649h) _ftol2: 00411676 55 push ebp 00411677 8B EC mov ebp,esp 00411679 83 EC 20 sub esp,20h 0041167C 83 E4 F0 and esp,0FFFFFFF0h 0041167F D9 C0 fld st(0) 00411681 D9 54 24 18 fst dword ptr [esp+18h] 00411685 DF 7C 24 10 fistp qword ptr [esp+10h] 00411689 DF 6C 24 10 fild qword ptr [esp+10h] 0041168D 8B 54 24 18 mov edx,dword ptr [esp+18h] 00411691 8B 44 24 10 mov eax,dword ptr [esp+10h] 00411695 85 C0 test eax,eax 00411697 74 3C je integer_QnaN_or_zero (4116D5h) arg_is_not_integer_QnaN: 00411699 DE E9 fsubp st(1),st 0041169B 85 D2 test edx,edx 0041169D 79 1E jns positive (4116BDh) 0041169F D9 1C 24 fstp dword ptr [esp] 004116A2 8B 0C 24 mov ecx,dword ptr [esp] 004116A5 81 F1 00 00 00 80 xor ecx,80000000h 004116AB 81 C1 FF FF FF 7F add ecx,7FFFFFFFh 004116B1 83 D0 00 adc eax,0 004116B4 8B 54 24 14 mov edx,dword ptr [esp+14h] 004116B8 83 D2 00 adc edx,0 004116BB EB 2C jmp localexit (4116E9h) positive: 004116BD D9 1C 24 fstp dword ptr [esp] 004116C0 8B 0C 24 mov ecx,dword ptr [esp] 004116C3 81 C1 FF FF FF 7F add ecx,7FFFFFFFh 004116C9 83 D8 00 sbb eax,0 004116CC 8B 54 24 14 mov edx,dword ptr [esp+14h] 004116D0 83 DA 00 sbb edx,0 004116D3 EB 14 jmp localexit (4116E9h) integer_QnaN_or_zero: 004116D5 8B 54 24 14 mov edx,dword ptr [esp+14h] 004116D9 F7 C2 FF FF FF 7F test edx,7FFFFFFFh 004116DF 75 B8 jne arg_is_not_integer_QnaN (411699h) 004116E1 D9 5C 24 18 fstp dword ptr [esp+18h] 004116E5 D9 5C 24 18 fstp dword ptr [esp+18h] localexit: 004116E9 C9 leave 004116EA C3 & nbsp; ret |
赤文字のところに注目、これ、どう見ても、double から 32bit long 型への変換
ftol2_sse やftol2_pentium4 は、 ftol2 の名前を関してるにもかかわらず、変換先が longlong ではなかったという
|。・ω・) 。o (えー!なんで?)
一方の、 ftol2 の素の処理をみると、ちゃんと 64bit long long で処理を行っている。
試行錯誤してみたら、
int ii=(double)xx;
のような処理は ftol2_sse がコールされるけど、
long long ii=(double)xx;
のような処理は ftol2 がコールされることが分かったよ・ω・
だるだる団 DaruDaruDan プログラムメモ - (PC,Android,OpenGL)
Visual C++ 2002 以降では float/double から__int64/int の変換に_ftol2 を使い、 2005 以降では更に float/double から int の変換に _ftol2_sse を試行した後 _ftol2 を使用する。 これらの関数の中では浮動小数点制御ワードの変更を行わず切り捨てを実現する。 _ftol2 の中では浮動小数点のビット表現を利用した計算のみで切り捨てを行う。 |
確かにこの通りになった。
c++ - _ftol2_sse, are there faster options? - Stack Overflow
global _startsection .dataalign 16 n section .text_start: cvtps2dq xmm1, [fv1] ; Convert four 32-bit(single precision) ;floats to 32-bit(double word) integers ;and place the result in xmm1 |
速くなるかな?と思ったら 4つの浮動小数点を32bitの4つの結果に格納なので違った・ω・
c++ - Incorrect double to long conversion - Stack Overflow
これを見ると、VC++2010以前のftol2にはバグがある(一番上のコード)って書いてる。
push ebp mov ebp,esp add esp,0FFFFFFF4h wait fnstcw word ptr [ebp-2] wait mov ax,word ptr [ebp-2] or ah,0Ch mov word ptr [ebp-4],ax fldcw word ptr [ebp-4] fistp qword ptr [ebp-0Ch] fldcw word ptr [ebp-2] mov eax,dword ptr [ebp-0Ch] mov edx,dword ptr [ebp-8] leave ret |
大人しくこれ使うしかないのかしら・ω・(VC++6のコード)
LONGLONG ull = 0xf000000000000000; printf("%I64X\n",ull); double xx=ull; printf("%f\n",xx); LONGLONG tt=xx; printf("%I64X\n",tt); |
試してみたら、普通に表示できた・ω・;
なるほどわからん!
Comments