1

In some inner loop I have:

    double x;
    ...
    int i = x/h_;
    double xx = x - i*h_;

Thinking that might be a better way to do this, I tried with std::remquo

    double x;
    ...
    int i;
    double xx = std::remquo(x, h_, &i);

Suddenly, timings went from 2.6 seconds to 40 seconds (for many executions of the loop).

The timing test is difficult to replicate here, but I did a online code to see if someone can help me to understand what is going on.

naive version: https://godbolt.org/z/PnsfR8

remquo version: https://godbolt.org/z/NSMwyW

It looks like the main difference is that remquo is not inlined and the naive code is. If that is the case, what is the purpose of remquo if it is going to be always slower than the manual code? Is it a matter of accuracy (e.g. for large argument) or not relying on (not well defined) casting conversion?


I just realized that the remquo version is not even doing something equivalent to the first code. So I am using it wrong. In any case, I am surprised that remquo is so slow.

alfC
  • 14,261
  • 4
  • 67
  • 118
  • What are you trying to achieve with your code? – nivpeled Aug 05 '19 at 06:38
  • 1
    [Quickbench's results](http://quick-bench.com/xTUve4zgiNUjLUzX1yQdwSAHJhQ) – Jarod42 Aug 05 '19 at 06:42
  • @nivpeled, I have a piecewise function `int(x/h)` gives me the index in an array (integer) and later I need the remainder of x/h to see the point in the subinterval. – alfC Aug 05 '19 at 07:05
  • 1
    Be careful with `int(x/h)` as it will cause undefined behaviour if the answer is outside the range of `int` – M.M Aug 05 '19 at 07:20
  • @M.M Good point, the actual version is `difference_type(x/h)` (where `difference_type` is typically `long int`). In any case it can loose precision even before it overflows, I think. The function must be evaluated in a range in which `x/h` can be converted to a integer type reliably and `x - int(x/h)*h` still has decent resolution. I though that `remquo` was good for that because of the examples for `sin` and `cos` around. – alfC Aug 05 '19 at 07:24
  • @M.M do you have an alternative? Other than using `Integer i = x/h; Float dx = x - i*h` that is what I am doing now. – alfC Aug 05 '19 at 21:31

1 Answers1

3

It's a rubbish function that was added to C99 to entice Fortran coders to switch to C. There's little reason to actually use it, so library vendors avoid wasting time optimizing it.

See also: What does the function remquo do and what can it be used for?.

BTW if you assumed that i gets the quotient stored in it, read the documentation more closely! (Or read the answers on the question linked in the previous paragraph).

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Got it "the sign and at least the three of the last bits of x/y will be stored in quo, sufficient to determine the octant of the result within a period.". Useless and confusing function. – alfC Aug 05 '19 at 07:03
  • Looks to me like @chux uses it rather brilliantly here: https://stackoverflow.com/questions/31502120/sin-and-cos-give-unexpected-results-for-well-known-angles#answer-31525208 That's actually the only solution I know of for that problem, at this moment. Given that I have no idea how remquo is implemented, I can't criticize its speed-- it seems plausible that it's an inherently tricky function to implement. – Don Hatch May 13 '22 at 06:20