title: On 32-bit machines, atan2 is nondeterministic when I don't store its result in a variable. Why?
body: <p>Consider this piece of C code:</p>
  <pre><code>#include &lt;math.h&gt;
  #include &lt;stdbool.h&gt;
  #include &lt;stdio.h&gt;
  
  bool foo(int a, int b, int c, int d) {
      double P = atan2(a, b);
      double Q = atan2(c, d);
      return P &lt; Q;
  }
  
  bool bar(int a, int b, int c, int d) {
      return atan2(a, b) &lt; atan2(c, d);
  }
  
  int main() {
      if (foo(2, 1, 2, 1)) puts(&quot;true&quot;); else puts(&quot;false&quot;);
      if (bar(2, 1, 2, 1)) puts(&quot;true&quot;); else puts(&quot;false&quot;);
      return 0;
  }
  </code></pre>
  <p>When I compile it with <code>gcc -lm -m64</code>, it prints</p>
  <pre><code>false
  false
  </code></pre>
  <p>as expected. However, <a href="https://tio.run/##nY9NDsIgFIT3PcVL3UDSGq3LVs9gj8BfWxIKpoWV8eoipKg1bowseGSGjxlY2TPm/UZqphwX0IzEDtvhlL2V2XJqjPoSpYlSFj3ojEFSWyAFxEGXwZbBMVwzCIsbR5WAMxyBWKIrFK5TXK@99uUFmCdvEtZNOnANtHV2S5mUTD9kJnaVF175SAjvRWIkUqMnJTtA8U9VAfsC4o4xXJydUW4nJ3Jcg1CzSFJHwjlPZSMaq/2Bpq670Mn7O@sU6WdfqtGX46F6AA" rel="noreferrer">when I compile it with <code>gcc -lm -m32</code></a>, the output is</p>
  <pre><code>false
  true
  </code></pre>
  <p>Why does such a trivial difference as storing the result in a variable change the behavior of the code? Is it because the floating point registers are 80-bit? How should I write my code such that weirdness like this is avoided?</p>
  <p>(I originally used the variant in <code>bar</code> in a C++ program as a compare function for <code>std::sort</code>. This triggered undefined behavior because <code>comp(a, a)</code> returned true - how should I compare vectors by their angle without UB?)</p>
  <h2>Comment summary so far</h2>
  <p>It seems there is consensus that this is because of the differences in where the results are rounded to the range of the <code>double</code>. The C/C++ standards allow this, even when the results differ as a consequence.</p>
  <p>A workaround of comparing the input as <code>a * d &lt; b * c</code>, which would indeed help in this example. However, I seek to avoid this category of issues in the future, and not just fix the bug and move on. The issue could still manifest if the inputs themselves were <code>double</code>s.</p>
  <p>I accept that the comparison might be inaccurate due to the nature of floating-point arithmetic, however if the angles are this close, I still want to achieve the strict weak ordering required by <code>std::sort</code>, such that no UB happens.</p>