1

If I compile my program with -Ofast with clang, sometimes I will get an infinite float back, but isinf() and isfinite() don't work. U is a floating-point type, I (>=0) and wbits (>0) are integers.

        auto const tmp(f * std::pow(U(2), -I * wbits));

        std::cout << "??? " << tmp << " " << std::isinf(tmp) << std::endl;

and I get:

??? inf 0

Comparing tmp to INFINITY does not work, f > std::numeric_limits<U>::max() does not work. Doing bit-magic (reimplementing isinf()) would work, but I don't want to do this. Finally, why would std::pow() produce an infinite float when a negative exponent is provided?

user1095108
  • 14,119
  • 9
  • 58
  • 116
  • 2
    Does this answer your question? [What does clang's \`-Ofast\` option do in practical terms especially for any differences from gcc?](https://stackoverflow.com/questions/45685487/what-does-clangs-ofast-option-do-in-practical-terms-especially-for-any-diffe) _"...Assumes the code generates no NaN values...."_ and _"...Just like the above but for infinities...."_ – Richard Critten Nov 13 '22 at 20:41
  • 2
    Basic answer is: `-Ofast` sets `-menable-no-infs`, so `std::isinf(anything)` can be optimized to `false`. As for your first question, did you check if `f` isn't infinite to begin with, or if `f` is `std::numeric_limits::max()` and `I` is `0`? – Artyer Nov 13 '22 at 20:45
  • `I` can be zero, but so what? But `f` is never infinite to begin with and obviously `Inf` is still there, it just can't be detected. – user1095108 Nov 13 '22 at 20:47
  • 1
    N.B. You are manually (and expensively) calculating `ldexp(f, -I*wbits)`. – chtz Nov 13 '22 at 20:50
  • @chtz thank you, `ldexp()` saved the day. I still think `std::pow()` should work as well. – user1095108 Nov 13 '22 at 21:06
  • probably, `-Ofast` broke something in the `std::pow()` implementation. – user1095108 Nov 13 '22 at 21:16
  • @user1095108 Curious, what is your result of `tmp > DBL_MAX`? – chux - Reinstate Monica Nov 13 '22 at 21:40
  • For any further analysis what happened in your case with `std::pow` you need to provide a [mre] -- including what inputs you are giving. – chtz Nov 13 '22 at 21:54
  • 1
    I did the analysis myself and the problem was the `-I * wbits` expression, even though `I` is a `signed int`, the expression somehow produced `18446744073709551552`, `wbits` is of unsigned `std::size_t` type. This explains the `Inf` returned by `std::pow()`. `ldexp()` auto-converts the exponent into an `int` which solved the problem, while `std::pow()` does not do so. – user1095108 Nov 13 '22 at 23:08
  • Yes, unless the unsigned type is smaller than the signed type, the signed type gets converted to the unsigned type before the multiplication. Someone would probably have spotted that if you provided a [mre] in the first place (your wording that both `I` and `wbits` were integers kind of implied they were both signed). Also, enabling compiler warnings (`-Wall -Wextra`) could have helped. – chtz Nov 13 '22 at 23:32
  • @chtz yes, it's humiliating :) I was looking for a nice hack, like `f > std::numeric_limits::max()`, which would work despite `-Ofast`, but apparently there's none. – user1095108 Nov 14 '22 at 00:27

0 Answers0