title: Floating point C++ compiler options | preventing a/b -> a* (1/b)
body: <p>I'm writing realtime numeric software, in C++, currently compiling it with Visual-C++ 2008.
  Now using 'fast' floating point model (<code>/fp:fast</code>), various optimizations, most of them useful my case, but specifically:</p>
  
  <pre><code>a/b -&gt; a*(1/b) Division by multiplicative inverse
  </code></pre>
  
  <p>is too numerically unstable for a-lot of my calculations.</p>
  
  <p>(see: <a href="http://msdn.microsoft.com/en-us/library/aa289157(VS.71).aspx" rel="nofollow noreferrer">Microsoft Visual C++ Floating-Point Optimization</a>)</p>
  
  <p>Switching to <code>/fp:precise</code> makes my application run more than twice as slow. Is is possible to either fine-tune the optimizer (ie. disable this specific optimization), or somehow manually bypass it?</p>
  
  <p>-
  Actual minimal-code example: -</p>
  
  <pre><code>void test(float a, float b, float c,
      float &amp;ret0, float &amp;ret1) {
    ret0 = b/a;
    ret1 = c/a;
  } 
  </code></pre>
  
  <p>[my actual code is mostly matrix related algorithms]</p>
  
  <p>Output: VC (cl, version 15, 0x86) is:</p>
  
  <pre><code>divss       xmm0,xmm1 
  mulss       xmm2,xmm0 
  mulss       xmm1,xmm0 
  </code></pre>
  
  <p>Having one div, instead of two is a big problem numerically, (xmm0, is preloaded with 1.0f from RAM), as depending on the values of xmm1,2 (which may be in different ranges) you might lose a lot of precision (Compiling without SSE, outputs similar stack-x87-FPU code).</p>
  
  <p>Wrapping the function with </p>
  
  <pre><code>#pragma float_control( precise, on, push )
  ...
  #pragma float_control(pop)
  </code></pre>
  
  <p>Does solve the accuracy problem, but firstly, it's only available on a function-level (global-scope), and second, it prevents inlining of the function, (ie, speed penalties are too high)</p>
  
  <p>'precise' output is being cast to 'double' back and forth as-well:</p>
  
  <pre><code> divsd       xmm1,xmm2 
   cvtsd2ss    xmm1,xmm1 
   divsd       xmm1,xmm0 
   cvtpd2ps    xmm0,xmm1 
  </code></pre>