title: Benchmark functions in <cmath> with GCC and MSVS
body: <p>I am tasked to benchmark the time cost of almost every function in <code>cmath</code> for 64-bit integer and <code>double</code>. Here is my source code:</p>
  <pre><code>#include &lt;unordered_map&gt;
  #include &lt;string&gt;
  #include &lt;cmath&gt;
  #include &lt;cstdint&gt;
  #include &lt;vector&gt;
  #include &lt;random&gt;
  #include &lt;iostream&gt;
  #include &lt;fstream&gt;
  #include &lt;iomanip&gt;
  #include &lt;chrono&gt;
  #include &lt;numeric&gt;
  
  
  template&lt;typename timetype&gt;
  struct tiktok
  {
    std::chrono::time_point&lt;std::chrono::steady_clock&gt; start;
    // Return time passed since tik.
    std::size_t tik() { start = std::chrono::steady_clock::now(); return 0; }
    // Return time passed since tok.
    std::size_t tok()
    {
      return std::chrono::duration_cast&lt;timetype&gt; (
          std::chrono::steady_clock::now() - start).count();
    }
  };
  
  
  double mathHspeed(std::unordered_map&lt;std::string, int64_t&gt;&amp; M,
                    int rngSeed, int maxIter = 100000)
  {
    std::mt19937 rng(rngSeed);
    std::uniform_real_distribution&lt;double&gt; U(-5, 5);
    std::uniform_int_distribution&lt;int32_t&gt; Uint(-2147483647, 2147483647);
    tiktok&lt;std::chrono::nanoseconds&gt; timer;
    double S = 0;
    int64_t duration = 0;
    maxIter = (maxIter / 2) * 2; // Make sure maxIter is even.
    std::vector&lt;int64_t&gt; u(maxIter);
    std::vector&lt;double&gt; v(maxIter);
    int64_t loadingCost = 0;
    
    
    // Time cost of reading and writing 8-bytes = `loadingCost`
    // Let loadingCost just be 0 since we only need rough numbers.
    if (false)
    {
      for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = U(rng);
      
      
      timer.tik();
      for (int i = 0, iend = v.size() - 2; i &lt; iend; ++i) v[i] += v[i + 1];
      duration = timer.tok();
      
      
      timer.tik();
      for (int i = 0, iend = v.size() - 2; i &lt; iend; ++i) // one more addition.
        v[i] += v[i + 1] + v[i + 2];
      std::size_t duration2 = timer.tok();
      
      
      loadingCost = std::max&lt;int64_t&gt;(
        0, (int64_t)duration - ((int64_t)duration2 - (int64_t)duration));
      S += std::accumulate(v.begin(), v.end(), 0.0);
    }
    
    
  #define sampleDouble for(int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = U(rng);
  #define sampleInt for(int i = 0, iend = u.size(); i &lt; iend; ++i) u[i] = (int64_t)Uint(rng) - Uint(rng);
    
    
    sampleInt; timer.tik();
    for (int i = 0, iend = u.size() - 1; i &lt; iend; ++i)
      u[i] += u[i + 1];
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(u.begin(), u.end(), 0.0);
    M[&quot;+ ( int64 )&quot;] = duration;
    
    
    sampleInt; timer.tik();
    for (int i = 0, iend = u.size() - 1; i &lt; iend; ++i)
      u[i] *= u[i + 1];
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(u.begin(), u.end(), 0.0);
    M[&quot;x ( int64 )&quot;] = duration;
    
    
    for (int i = 0, iend = u.size() - 1; i &lt; iend; i += 2)
    {
      u[i] = (int64_t)Uint(rng) * Uint(rng); u[i + 1] = Uint(rng);
    }
    timer.tik();
    for (int i = 0, iend = u.size() - 1; i &lt; iend; ++i)
      u[i] = u[i] / u[i + 1] + u[i] % u[i + 1];
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost - M[&quot;+ ( int64 )&quot;], 0);
    S += std::accumulate(u.begin(), u.end(), 0.0);
    M[&quot;/% ( int64 )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] += v[i + 1];
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;+ ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] *= v[i + 1];
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;x ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] /= v[i + 1];
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;/ ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = u.size(); i &lt; iend; ++i) u[i] = (int64_t)Uint(rng) - Uint(rng);
    timer.tik();
    for (int i = 0, iend = u.size(); i &lt; iend; ++i)
      u[i] = std::abs(u[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(u.begin(), u.end(), 0.0);
    M[&quot;abs ( int64 )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::abs(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;abs ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size() - 1; i &lt; iend; i += 2)
    {
      v[i] = U(rng) * U(rng); v[i + 1] = U(rng);
    }
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::fmod(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;fmod ( double, double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size() - 1; i &lt; iend; i += 2)
    {
      v[i] = U(rng) * U(rng); v[i + 1] = U(rng);
    }
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::remainder(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;remainder ( double, double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size() - 1; i &lt; iend; i += 2)
    {
      v[i] = U(rng) * U(rng); v[i + 1] = U(rng);
    }
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
    {
      int tmp = 0;
      v[i] = std::remquo(v[i], v[i + 1], &amp;tmp) + tmp;
    }
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost - M[&quot;+ ( double )&quot;], 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;remquo ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 2; i &lt; iend; ++i)
      v[i] = std::fma(v[i], v[i + 1], v[i + 2]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;fma ( double, double, double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::fmax(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;fmax ( double, double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::fmin(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;fmin ( double, double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::fdim(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;fdim ( double, double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::exp(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;exp ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::exp2(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;exp2 ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::expm1(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;expm1 ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng)) + 1e-6;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::log(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;log ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng)) + 1e-6;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::log10(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;log10 ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng)) + 1e-6;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::log2(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;log2 ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng)) + 1e-6;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::log1p(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;log1p ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng));
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::pow(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;pow ( double, double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng));
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::sqrt(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;sqrt ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::cbrt(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;cbrt ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::hypot(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;hypot ( double, double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size() - 2; i &lt; iend; ++i)
      v[i] = std::hypot(v[i], v[i + 1], v[i + 2]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;hypot ( double, double, double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::sin(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;sin ( double )&quot;] = duration;
    
    
    sampleDouble; timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::cos(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;cos ( double )&quot;] = duration;
    
    
    std::uniform_real_distribution&lt;double&gt; UhalfPi(-3.14 / 2, 3.14 / 2);
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = UhalfPi(rng);
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::tan(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;tan ( double )&quot;] = duration;
    
    
    std::uniform_real_distribution&lt;double&gt; U_11(-0.99, 0.99);
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = U_11(rng);
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::asin(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;asin ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = U_11(rng);
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] =
      std::acos(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;acos ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::atan(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;atan ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::atan2(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;atan2 ( double, double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::sinh(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;sinh ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::cosh(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;cosh ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::tanh(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;tanh ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::asinh(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;asinh ( double )&quot;] = duration;
    
    
    std::uniform_real_distribution&lt;double&gt; U1_10(1.1, 10);
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = U1_10(rng);
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::acosh(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;acosh ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = U_11(rng);
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::atanh(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;atanh ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng));
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::erf(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;erf ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::erfc(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;erfc ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng)) + 1e-3;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::tgamma(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;tgamma ( double )&quot;] = duration;
    
    
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = std::abs(U(rng)) + 1e-3;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::lgamma(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;lgamma ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::ceil(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;ceil ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::floor(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;floor ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::trunc(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;trunc ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::round(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;round ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::nearbyint(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;nearbyint ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::rint(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;rint ( double )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
    {
      int tmp;
      v[i] = std::frexp(v[i], &amp;tmp) + tmp;
    }
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost - M[&quot;+ ( double )&quot;], 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;frexp ( double, int* )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
    {
      int tmp = (int)v[i + 1];
      v[i] = std::ldexp(v[i], tmp);
    }
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;ldexp ( double, int* )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
    {
      double tmp;
      v[i] = std::modf(v[i], &amp;tmp) + tmp;
    }
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;modf ( double, double* )&quot;] = duration;
    
    
    sampleDouble;
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::copysign(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;copysign ( double, double )&quot;] = duration;
    
    
    std::uniform_real_distribution&lt;double&gt; betaU(0.001, 30);
    for (int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = betaU(rng);
    timer.tik();
    for (int i = 0, iend = v.size() - 1; i &lt; iend; ++i)
      v[i] = std::beta(v[i], v[i + 1]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;beta ( double, double )&quot;] = duration; // test x, y in [0.001, 30]
    
    
    std::uniform_real_distribution&lt;double&gt; expintU(-30, 30);
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
    {
      v[i] = expintU(rng);
      if (v[i] &gt; -0.01 and v[i] &lt; 0.01) v[i] = 0.01;
    }
    timer.tik();
    for (int i = 0, iend = v.size(); i &lt; iend; ++i)
      v[i] = std::expint(v[i]);
    duration = std::max&lt;int64_t&gt;(timer.tok() - loadingCost, 0);
    S += std::accumulate(v.begin(), v.end(), 0.0);
    M[&quot;expint ( double )&quot;] = duration; // x != 0, test x in [-30, 30] &amp; x != 0
    
    
    // std::uniform_real_distribution&lt;double&gt; riemann_zetaU(-1, 2);
    // for(int i = 0, iend = v.size(); i &lt; iend; ++i) v[i] = riemann_zetaU(rng);
    // timer.tik();
    // for(int i = 0, iend = v.size(); i &lt; iend; ++i)
    //   v[i] = std::riemann_zeta(v[i]);
    // duration = std::max&lt;int64_t&gt; (timer.tok() - loadingCost, 0);
    // S += std::accumulate(v.begin(), v.end(), 0.0);
    // M[&quot;riemann_zeta ( double )&quot;] = duration; // test x in [-1, 2].
    
    
    return S;
  }
  
  
  int main()
  {
    std::cout &lt;&lt; &quot;Random seed: &quot;;
    int randomSeed;
    std::cin &gt;&gt; randomSeed;
    std::cout &lt;&lt; &quot;Max iteration: &quot;;
    int maxIter;
    std::cin &gt;&gt; maxIter;
    std::cout &lt;&lt; &quot;Save file path: &quot;;
    std::string save;
    std::cin &gt;&gt; save;
    
    
    std::unordered_map&lt;std::string, int64_t&gt; M;
    double S = mathHspeed(M, randomSeed, maxIter);
    
    
    // 57.
    constexpr int Nfuns = 56;
    std::string funNames[] = {
      &quot;+ ( int64 )&quot;, &quot;x ( int64 )&quot;, &quot;/% ( int64 )&quot;,
      &quot;+ ( double )&quot;, &quot;x ( double )&quot;, &quot;/ ( double )&quot;,
      &quot;abs ( int64 )&quot;, &quot;abs ( double )&quot;, &quot;fmod ( double, double )&quot;,
      &quot;remainder ( double, double )&quot;, &quot;remquo ( double )&quot;,
      &quot;fma ( double, double, double )&quot;, &quot;fmax ( double, double )&quot;,
      &quot;fmin ( double, double )&quot;, &quot;fdim ( double, double )&quot;,
      &quot;exp ( double )&quot;, &quot;exp2 ( double )&quot;, &quot;expm1 ( double )&quot;,
      &quot;log ( double )&quot;, &quot;log10 ( double )&quot;, &quot;log2 ( double )&quot;,
      &quot;log1p ( double )&quot;, &quot;pow ( double, double )&quot;, &quot;sqrt ( double )&quot;,
      &quot;cbrt ( double )&quot;, &quot;hypot ( double, double )&quot;,
      &quot;hypot ( double, double, double )&quot;, &quot;sin ( double )&quot;,
      &quot;cos ( double )&quot;, &quot;tan ( double )&quot;, &quot;asin ( double )&quot;,
      &quot;acos ( double )&quot;, &quot;atan ( double )&quot;, &quot;atan2 ( double, double )&quot;,
      &quot;sinh ( double )&quot;, &quot;cosh ( double )&quot;, &quot;tanh ( double )&quot;,
      &quot;asinh ( double )&quot;, &quot;acosh ( double )&quot;, &quot;atanh ( double )&quot;,
      &quot;erf ( double )&quot;, &quot;erfc ( double )&quot;, &quot;tgamma ( double )&quot;,
      &quot;lgamma ( double )&quot;, &quot;ceil ( double )&quot;, &quot;floor ( double )&quot;,
      &quot;trunc ( double )&quot;, &quot;round ( double )&quot;, &quot;nearbyint ( double )&quot;,
      &quot;rint ( double )&quot;, &quot;frexp ( double, int* )&quot;, &quot;ldexp ( double, int* )&quot;,
      &quot;modf ( double, double* )&quot;, &quot;copysign ( double, double )&quot;,
      &quot;beta ( double, double )&quot;, &quot;expint ( double )&quot;//, &quot;riemann_zeta ( double )&quot;
    };
    
    
    std::string funNamesNoComma[] = {
      &quot;+ ( int64 )&quot;, &quot;x ( int64 )&quot;, &quot;/% ( int64 )&quot;,
      &quot;+ ( double )&quot;, &quot;x ( double )&quot;, &quot;/ ( double )&quot;,
      &quot;abs ( int64 )&quot;, &quot;abs ( double )&quot;, &quot;fmod ( double double )&quot;,
      &quot;remainder ( double double )&quot;, &quot;remquo ( double )&quot;,
      &quot;fma ( double double double )&quot;, &quot;fmax ( double double )&quot;,
      &quot;fmin ( double double )&quot;, &quot;fdim ( double double )&quot;,
      &quot;exp ( double )&quot;, &quot;exp2 ( double )&quot;, &quot;expm1 ( double )&quot;,
      &quot;log ( double )&quot;, &quot;log10 ( double )&quot;, &quot;log2 ( double )&quot;,
      &quot;log1p ( double )&quot;, &quot;pow ( double double )&quot;, &quot;sqrt ( double )&quot;,
      &quot;cbrt ( double )&quot;, &quot;hypot ( double double )&quot;,
      &quot;hypot ( double double double )&quot;, &quot;sin ( double )&quot;,
      &quot;cos ( double )&quot;, &quot;tan ( double )&quot;, &quot;asin ( double )&quot;,
      &quot;acos ( double )&quot;, &quot;atan ( double )&quot;, &quot;atan2 ( double double )&quot;,
      &quot;sinh ( double )&quot;, &quot;cosh ( double )&quot;, &quot;tanh ( double )&quot;,
      &quot;asinh ( double )&quot;, &quot;acosh ( double )&quot;, &quot;atanh ( double )&quot;,
      &quot;erf ( double )&quot;, &quot;erfc ( double )&quot;, &quot;tgamma ( double )&quot;,
      &quot;lgamma ( double )&quot;, &quot;ceil ( double )&quot;, &quot;floor ( double )&quot;,
      &quot;trunc ( double )&quot;, &quot;round ( double )&quot;, &quot;nearbyint ( double )&quot;,
      &quot;rint ( double )&quot;, &quot;frexp ( double int* )&quot;, &quot;ldexp ( double int* )&quot;,
      &quot;modf ( double double* )&quot;, &quot;copysign ( double double )&quot;,
      &quot;beta ( double double )&quot;, &quot;expint ( double )&quot;//, &quot;riemann_zeta ( double )&quot;
    };
    
    
    double relativeTime[Nfuns];
    for (int i = 0; i &lt; Nfuns; ++i)
      relativeTime[i] = std::round(M[funNames[i]] / (M[&quot;+ ( int64 )&quot;] + 0.0) * 10) / 10.0;
    
    
    constexpr int nameWidth = 32;
    constexpr int realtimewd = 16;
    constexpr int relatimewd = 16;
    std::ofstream out(save.c_str());
    out &lt;&lt; std::setw(nameWidth) &lt;&lt; &quot;Function name,&quot;
        &lt;&lt; std::setw(realtimewd) &lt;&lt; &quot;Time cost (ms),&quot;
        &lt;&lt; std::setw(relatimewd) &lt;&lt; &quot;Relative&quot; &lt;&lt; std::endl;
    
    
    for (int i = 0; i &lt; Nfuns; ++i)
    {
      out &lt;&lt; std::setw(nameWidth) &lt;&lt; funNamesNoComma[i] &lt;&lt; &quot;,&quot;
          &lt;&lt; std::setw(realtimewd) &lt;&lt; std::round(M[funNames[i]] / 1000.0) &lt;&lt; &quot;,&quot;
          &lt;&lt; std::setw(relatimewd) &lt;&lt; relativeTime[i] &lt;&lt; std::endl;
    }
    
    
    std::cout &lt;&lt; &quot;\nDummy sum = &quot; &lt;&lt; S &lt;&lt; std::endl;
    
    
    return 0;
  }
  </code></pre>
  <p>Compile the code using GCC-8.3 (<code>-O0</code> or <code>-O3</code>), and MSVS Community 2019 (<code>/O2</code>), on a Windows 64-bit laptop with Intel i9-9980, 512KB L1 cache, 2MB L2 cache, 16MB L3 cache, and then input the following parameters:</p>
  <p><a href="https://i.stack.imgur.com/0D1NX.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/0D1NX.png" alt="enter image description here" /></a></p>
  <p>The table below shows the results:
  <a href="https://i.stack.imgur.com/F2QA8.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/F2QA8.png" alt="enter image description here" /></a></p>
  <p>To be more specific, the optimization menu in MSVS looks like this:
  <a href="https://i.stack.imgur.com/b3xHs.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/b3xHs.png" alt="enter image description here" /></a></p>
  <p>I cannot set &quot;Whole Program Optimization&quot; to Yes because MSVS keeps complaining about &quot;/ZI and /GL incompatible&quot;.</p>
  <p>My questions:</p>
  <p>(1) I am a newbie to the MSVS toolchain. Why is the executable built by MSVS so slow for most functions? MSVS <code>/O2</code> can not even outperform GCC <code>-O0</code>. How to make MSVS produce equally fast code? I noticed GCC produces a single <code>.exe</code> of about 3MB, but MSVS produces a <code>.exe</code> of about 154KB and a <code>.pdb</code> of 2.9MB.</p>
  <p>(2) Interestingly, there are a few functions such as <code>sin(x)</code>, <code>cos(x)</code> and <code>exp(x)</code> where MSVS code is much faster. Any reason besides possible different library implementations?</p>
  <p>(3) Why on earth is <code>exp2(x)</code> about 5x slower than <code>exp(x)</code> in MSVS? I tried swapping the code blocks of the two functions in the source file. It makes no difference.</p>
  <p>Thanks!</p>