3 ms·
So divide-by-zero is only undefined behaviour if the result is not representable. But it is representable in IEEE-754 (adherence to which is implementation-defi
by twoodfin 11y ago
So divide-by-zero is only undefined behaviour if the result is not representable. But it is representable in IEEE-754 (adherence to which is implementation-defined), so it should be fine.
That's not how I read the line of the standard you quoted. ISTM it's saying:
(Result not mathematically defined) ∨ (Result not in the range of representable values) ⇒ Behavior is undefined
In this case, 1.0/-0.0 is mathematically undefined as C++ specifies such things (I believe division-by-zero is called out specifically as such), and it doesn't help that IEEE-754 can represent it anyway. It's still a useful representation in the language because you can reach it through a series of calculations that are all included in the range of defined behavior.
I'm also skeptical that
x == 0 && 1/x == -inf
will work reliably for just that reason: I believe a compiler would be perfectly within its rights to unconditionally treat this expression as false, since x == 0 would imply UB.
Not at all an expert here, so would enjoy having a standards lawyer set me straight.
- conistonwater 11y agoPerhaps you're right. I just find IEEE-754's approach clear, and C++'s rule confusing. I would say that 1.0/-0.0 is mathematically defined in the pure sense: IEEE-754 defines a specific model of real numbers closed under such operations [-inf,inf]\union{NaN}. The thing is that that test should definitely work under IEEE-754, so I would be very surprised if C++ somehow forbids you from getting the IEEE-standard behaviour. For reference, here's a proof that it's correct: $ stack repl λ> import Data.SBV λ> prove $ do x <- sFloat "x"; return $ fpIsNegativeZero x <=> (x .== 0 &&& 1/x .== -infinity) Q.E.D.
- mikeash 11y agoUndefined behavior means anything can happen, and "anything" includes "following IEEE-754 rules." Any given C++ implementation is free to implement this case to follow IEEE-754 and declare that this behavior is supported.
- deleted 11y ago[deleted]
- conistonwater 11y agoI see, that makes sense given how the C++ standard omits specifying floating-point arithmetic. But isn't there still a problem, given that in the article clang gave the error message error: '(1.0e+0f / -0.0f)' is not a constant expression and the proposed explanation is that "undefined behavior is unusable in a constant expression"? So it seems clang is not following IEEE-754 rules. As I read 5.20.2.5 in N4296, undefined behaviour may not occur in constant expressions, so clang is not free to follow IEEE-754 for the division-by-zero, even though it can do that in regular code, because then it's UB. And anyway, why isn't it UB to invoke UB in a constant expression?
- mikeash 11y agoI think you're right, the compiler can follow IEEE-754 rules in general, but as written it couldn't do so for constant expressions. I find that rule to be really weird in general. Does that mean that, for example, if you try to use "1 << 32" in a constant expression, then whether it's actually a constant expression will depend on the target architecture? I wonder what the rationale is there.
- twoodfin 11y agoI find that rule to be really weird in general. Does that mean that, for example, if you try to use "1 << 32" in a constant expression, then whether it's actually a constant expression will depend on the target architecture? I wonder what the rationale is there. Yes, that's right. The rationale is that it's not particularly different from the way constant expressions in C have always worked: The compiler knows full well whether static const int x = 99999999999; or static const int x = 1 << 32; represents a valid assignment within the range of int on the target platform, and responds accordingly. constexpr just generalizes that behavior to more of the expression machinery.
- 11y ago
- Guvante 11y ago> I would say that 1.0/-0.0 is mathematically defined in the pure sense `1.0 / -0.0` isn't mathematically defined though, it is certainly undefined. IEEE-754 takes that and performs "limit of `1/x` as `x` approaches zero from the left". > IEEE-754 defines a specific model of real numbers closed under such operations [-inf,inf]\union{NaN}. No, IEEE-754 defines a way to handle the exception by convention.