<p>What is the fastest way you know to convert a floating-point number to an int on an x86 CPU.  Preferrably in C or assembly (that can be in-lined in C) for any combination of the following:</p>

<ul>
<li>32/64/80-bit float -> 32/64-bit integer</li>
</ul>

<p>I'm looking for some technique that is faster than to just let the compiler do it.</p>

[{'answer_id': 78645, 'author': 'Dark Shikari', 'author_id': 11206, 'author_profile': 'https://Stackoverflow.com/users/11206', 'pm_score': 4, 'selected': False, 'text': '<p>Packed conversion using SSE is by far the fastest method, since you can convert multiple values in the same instruction.  <a href="https://github.com/FFmpeg/FFmpeg" rel="nofollow noreferrer">ffmpeg</a> has a lot of assembly for this (mostly for converting the decoded output of audio to integer samples); check it for some examples.</p>\n'}, {'answer_id': 78655, 'author': 'dreamlax', 'author_id': 10320, 'author_profile': 'https://Stackoverflow.com/users/10320', 'pm_score': 3, 'selected': False, 'text': "<p>There is one instruction to convert a floating point to an int in assembly: use the FISTP instruction. It pops the value off the floating-point stack, converts it to an integer, and then stores at at the address specified. I don't think there would be a faster way (unless you use extended instruction sets like MMX or SSE, which I am not familiar with).</p>\n\n<p>Another instruction, FIST, leaves the value on the FP stack but I'm not sure it works with quad-word sized destinations.</p>\n"}, {'answer_id': 78668, 'author': 'Don Neufeld', 'author_id': 13097, 'author_profile': 'https://Stackoverflow.com/users/13097', 'pm_score': 2, 'selected': False, 'text': '<p>If you really care about the speed of this make sure your compiler is generating the FIST instruction.  In MSVC you can do this with /QIfist, <a href="http://msdn.microsoft.com/en-us/library/6d9xx1d2.aspx" rel="nofollow noreferrer">see this MSDN overview</a></p>\n\n<p>You can also consider using SSE intrinsics to do the work for you, see this article from Intel: <a href="http://softwarecommunity.intel.com/articles/eng/2076.htm" rel="nofollow noreferrer">http://softwarecommunity.intel.com/articles/eng/2076.htm</a></p>\n'}, {'answer_id': 78681, 'author': 'Zach Burlingame', 'author_id': 2233, 'author_profile': 'https://Stackoverflow.com/users/2233', 'pm_score': 5, 'selected': True, 'text': '<p>It depends on if you want a truncating conversion or a rounding one and at what precision. By default, C will perform a truncating conversion when you go from float to int. There are FPU instructions that do it but it\'s not an ANSI C conversion and there are significant caveats to using it (such as knowing the FPU rounding state). Since the answer to your problem is quite complex and depends on some variables you haven\'t expressed, I recommend this article on the issue:</p>\n\n<p><a href="http://www.stereopsis.com/FPU.html" rel="noreferrer">http://www.stereopsis.com/FPU.html</a></p>\n'}, {'answer_id': 78687, 'author': 'user14504', 'author_id': 14504, 'author_profile': 'https://Stackoverflow.com/users/14504', 'pm_score': -1, 'selected': False, 'text': '<p>Generally, you can trust the compiler to be efficient and correct.  There is usually nothing to be gained by rolling your own functions for something that already exists in the compiler.</p>\n'}, {'answer_id': 78820, 'author': 'akauppi', 'author_id': 14455, 'author_profile': 'https://Stackoverflow.com/users/14455', 'pm_score': 3, 'selected': False, 'text': "<p>The Lua code base has the following snippet to do this (check in src/luaconf.h from www.lua.org).\nIf you find (SO finds) a faster way, I'm sure they'd be thrilled.</p>\n\n<p>Oh, <code>lua_Number</code> means double. :)</p>\n\n<pre><code>/*\n@@ lua_number2int is a macro to convert lua_Number to int.\n@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.\n** CHANGE them if you know a faster way to convert a lua_Number to\n** int (with any rounding method and without throwing errors) in your\n** system. In Pentium machines, a naive typecast from double to int\n** in C is extremely slow, so any alternative is worth trying.\n*/\n\n/* On a Pentium, resort to a trick */\n#if defined(LUA_NUMBER_DOUBLE) &amp;&amp; !defined(LUA_ANSI) &amp;&amp; !defined(__SSE2__) &amp;&amp; \\\n    (defined(__i386) || defined (_M_IX86) || defined(__i386__))\n\n/* On a Microsoft compiler, use assembler */\n#if defined(_MSC_VER)\n\n#define lua_number2int(i,d)   __asm fld d   __asm fistp i\n#define lua_number2integer(i,n)     lua_number2int(i, n)\n\n/* the next trick should work on any Pentium, but sometimes clashes\n   with a DirectX idiosyncrasy */\n#else\n\nunion luai_Cast { double l_d; long l_l; };\n#define lua_number2int(i,d) \\\n  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }\n#define lua_number2integer(i,n)     lua_number2int(i, n)\n\n#endif\n\n/* this option always works, but may be slow */\n#else\n#define lua_number2int(i,d) ((i)=(int)(d))\n#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))\n\n#endif\n</code></pre>\n"}, {'answer_id': 119538, 'author': 'Suma', 'author_id': 16673, 'author_profile': 'https://Stackoverflow.com/users/16673', 'pm_score': 3, 'selected': False, 'text': '<p>A commonly used trick for plain x86/x87 code is to force the mantissa part of the float to represent the int. 32 bit version follows.</p>\n\n<p>The 64-bit version is analogical. The Lua version posted above is faster, but relies on the truncation of double to a 32-bit result, therefore it requires the x87 unit to be set to double precision, and cannot be adapted for double to 64-bit int conversion.</p>\n\n<p>The nice thing about this code is it is completely portable for all platforms conforming to IEEE 754, the only assumption made is the floating point rounding mode is set to nearest. Note: Portable in the sense it compiles and works. Platforms other than x86 usually do not benefit much from this technique, if at all.</p>\n\n<pre><code>static const float Snapper=3&lt;&lt;22;\n\nunion UFloatInt {\n int i;\n float f;\n};\n\n/** by Vlad Kaipetsky\nportable assuming FP24 set to nearest rounding mode\nefficient on x86 platform\n*/\ninline int toInt( float fval )\n{\n  Assert( fabs(fval)&lt;=0x003fffff ); // only 23 bit values handled\n  UFloatInt &amp;fi = *(UFloatInt *)&amp;fval;\n  fi.f += Snapper;\n  return ( (fi.i)&amp;0x007fffff ) - 0x00400000;\n}\n</code></pre>\n'}, {'answer_id': 647671, 'author': 'akauppi', 'author_id': 14455, 'author_profile': 'https://Stackoverflow.com/users/14455', 'pm_score': 3, 'selected': False, 'text': '<p>If you can guarantee the CPU running your code is SSE3 compatible (even Pentium 5 is, JBB), you can allow the compiler to use its FISTTP instruction (i.e. -msse3 for gcc). It seems to do the thing like it should always have been done:</p>\n\n<p><a href="http://software.intel.com/en-us/articles/how-to-implement-the-fisttp-streaming-simd-extensions-3-instruction/" rel="noreferrer">http://software.intel.com/en-us/articles/how-to-implement-the-fisttp-streaming-simd-extensions-3-instruction/</a></p>\n\n<p>Note that FISTTP is different from FISTP (that has its problems, causing the slowness). It comes as part of SSE3 but is actually (the only) X87-side refinement.</p>\n\n<p>Other then X86 CPU\'s would probably do the conversion just fine, anyways. :)</p>\n\n<p><a href="http://en.wikipedia.org/wiki/SSE3#CPUs_with_SSE3" rel="noreferrer">Processors with SSE3 support</a></p>\n'}, {'answer_id': 16874325, 'author': 'Jan', 'author_id': 2016181, 'author_profile': 'https://Stackoverflow.com/users/2016181', 'pm_score': 2, 'selected': False, 'text': '<p>Since MS scews us out of inline assembly in X64 and forces us to use intrinsics, I looked up which to use. <a href="http://msdn.microsoft.com/en-us/library/shf1ys5b%28v=vs.90%29.aspx" rel="nofollow">MSDN doc</a> gives <code>_mm_cvtsd_si64x</code> with an example.</p>\n\n<p>The example works, but is horribly inefficient, using an unaligned load of 2 doubles, where we need just a single load, so getting rid of the additional alignment requirement. Then a lot of needless loads and reloads are produced, but they can be eliminated as follows:</p>\n\n<pre><code> #include &lt;intrin.h&gt;\n #pragma intrinsic(_mm_cvtsd_si64x)\n long long _inline double2int(const double &amp;d)\n {\n     return _mm_cvtsd_si64x(*(__m128d*)&amp;d);\n }\n</code></pre>\n\n<p>Result:</p>\n\n<pre><code>        i=double2int(d);\n000000013F651085  cvtsd2si    rax,mmword ptr [rsp+38h]  \n000000013F65108C  mov         qword ptr [rsp+28h],rax  \n</code></pre>\n\n<p>The rounding mode can be set without inline assembly, e.g.</p>\n\n<pre><code>    _control87(_RC_NEAR,_MCW_RC);\n</code></pre>\n\n<p>where rounding to nearest is default (anyway).</p>\n\n<p>The question whether to set the rounding mode at each call or to assume it will be restored (third party libs) will have to be answered by experience, I guess.\nYou will have to include <code>float.h</code> for <code>_control87()</code> and related constants.</p>\n\n<p>And, no, this will not work in 32 bits, so keep using the FISTP instruction:</p>\n\n<pre><code>_asm fld d\n_asm fistp i\n</code></pre>\n'}, {'answer_id': 22048816, 'author': 'the swine', 'author_id': 1140976, 'author_profile': 'https://Stackoverflow.com/users/1140976', 'pm_score': 3, 'selected': False, 'text': '<p>I assume truncation is required, same as if one writes <code>i = (int)f</code> in "C".</p>\n\n<p>If you have SSE3, you can use:</p>\n\n<pre><code>int convert(float x)\n{\n    int n;\n    __asm {\n        fld x\n        fisttp n // the extra \'t\' means truncate\n    }\n    return n;\n}\n</code></pre>\n\n<p>Alternately, with SSE2 (or in x64 where inline assembly might not be available), you can use almost as fast:</p>\n\n<pre><code>#include &lt;xmmintrin.h&gt;\nint convert(float x)\n{\n    return _mm_cvtt_ss2si(_mm_load_ss(&amp;x)); // extra \'t\' means truncate\n}\n</code></pre>\n\n<p>On older computers there is an option to set the rounding mode manually and perform conversion using the ordinary <code>fistp</code> instruction. That will probably only work for arrays of floats, otherwise care must be taken to not use any constructs that would make the compiler change rounding mode (such as casting). It is done like this:</p>\n\n<pre><code>void Set_Trunc()\n{\n    // cw is a 16-bit register [_ _ _ ic rc1 rc0 pc1 pc0 iem _ pm um om zm dm im]\n    __asm {\n        push ax // use stack to store the control word\n        fnstcw word ptr [esp]\n        fwait // needed to make sure the control word is there\n        mov ax, word ptr [esp] // or pop ax ...\n        or ax, 0xc00 // set both rc bits (alternately "or ah, 0xc")\n        mov word ptr [esp], ax // ... and push ax\n        fldcw word ptr [esp]\n        pop ax\n    }\n}\n\nvoid convertArray(int *dest, const float *src, int n)\n{\n    Set_Trunc();\n    __asm {\n        mov eax, src\n        mov edx, dest\n        mov ecx, n // load loop variables\n\n        cmp ecx, 0\n        je bottom // handle zero-length arrays\n\n    top:\n        fld dword ptr [eax]\n        fistp dword ptr [edx]\n        loop top // decrement ecx, jump to top\n    bottom:\n    }\n}\n</code></pre>\n\n<p>Note that the inline assembly only works with Microsoft\'s Visual Studio compilers (and maybe Borland), it would have to be rewritten to GNU assembly in order to compile with gcc.\nThe SSE2 solution with intrinsics should be quite portable, however.</p>\n\n<p>Other rounding modes are possible by different SSE2 intrinsics or by manually setting the FPU control word to a different rounding mode.</p>\n'}]
['https://Stackoverflow.com/questions/78619', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/10184/']