title: Comparing Fortran & C++ assembler for int = floor(sqrt(...))
body: <p>I have implemented  a function in Fortran and C++ each:</p>
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;math.h&gt;
  
  void dbl_sqrt_c(double *x, double *y){
     *y = sqrt(*x - 1.0);
     return;
  }
  </code></pre>
  <pre><code>pure subroutine my_dbl_sqrt(x,y) bind(c, name=&quot;dbl_sqrt_fort&quot;)
     USE, INTRINSIC :: ISO_C_BINDING
     implicit none
     real(kind=c_double), intent(in)  :: x
     real(kind=c_double), intent(out) :: y
  
     y = sqrt(x - 1d0)
  end subroutine my_dbl_sqrt
  </code></pre>
  <p>I compared them in the compiler explorer:</p>
  <p>Fortran: <a href="https://godbolt.org/z/froz4rx97" rel="noreferrer">https://godbolt.org/z/froz4rx97</a><br />
  C++: <a href="https://godbolt.org/z/45aex99Yz" rel="noreferrer">https://godbolt.org/z/45aex99Yz</a></p>
  <p>And the way I read the assembler, they do basically the same thing, but C++ checks whether the argument of the sqrt is negative, which Fortran doesn't. I compared their performance using googles benchmark, but they are pretty evenly matched:</p>
  <pre><code>--------------------------------------------------------
  Benchmark              Time             CPU   Iterations
  --------------------------------------------------------
  bm_dbl_c/8          2.07 ns         2.07 ns    335965892
  bm_dbl_fort/8       2.06 ns         2.06 ns    338643106
  </code></pre>
  <p>Here is the interesting part. If I turn this into integer based functions:</p>
  <pre class="lang-cpp prettyprint-override"><code>void int_sqrt_c(int *x, int *y){
     *y = floor(sqrt(*x - 1.0));
     return;
  }
  </code></pre>
  <p>and</p>
  <pre><code>pure subroutine my_int_root(x,y) bind(c, name=&quot;int_sqrt_fort&quot;)
     USE, INTRINSIC :: ISO_C_BINDING
     implicit none
     integer(kind=c_int), intent(in)  :: x
     integer(kind=c_int), intent(out) :: y
  
     y = floor(sqrt(x - 1d0))
  end subroutine my_int_root
  </code></pre>
  <p>Then this is where they start to diverge:</p>
  <pre><code>--------------------------------------------------------
  Benchmark              Time             CPU   Iterations
  --------------------------------------------------------
  bm_int_c/8          3.05 ns         3.05 ns    229239198
  bm_int_fort/8       2.13 ns         2.13 ns    328933185
  </code></pre>
  <p>The Fortran code seems not significantly slower by this change, but the C++ code slowed down by 50%. This seems quite large. These are the assemblies:</p>
  <p>Fortran: <a href="https://godbolt.org/z/axqqrc5E1" rel="noreferrer">https://godbolt.org/z/axqqrc5E1</a><br />
  C++: <a href="https://godbolt.org/z/h7K75oKbn" rel="noreferrer">https://godbolt.org/z/h7K75oKbn</a></p>
  <p>The Fortran assembly seems pretty straight forward. It just adds conversion between <code>double</code> and <code>int</code> and not much else, but C++ seems to do a lot more, which I don't full understand.</p>
  <p>Why is the C++ assembler so much more complicated? How could I improve the C++ code to achieve matching performance?</p>