5 ms·
Perhaps 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: I
by conistonwater 11y ago
Perhaps 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.
- mikeash 11y agoRight, but those examples still compile, they just invoke UB. Normally you want to avoid that, but sometimes you actually do want to, and the fact that the result is UB gives the compiler the freedom to support additional semantics. For something closer to the original topic, consider: static const double x = 1.0/0.0; That's UB, but the compiler is free to declare that it follows IEEE-754 and fully support this. The equivalent with constexpr doesn't allow that same freedom, and the compiler must consider 1.0/0.0 to not be a constexpr.
- twoodfin 11y agoAh, I see what you mean. A few years of warnings-as-errors mode made me forget that the most bizarre constant expressions (not constexprs) will compile even if their results or what you do with them are complete nonsense. I'd argue that the constexpr behavior is an improvement, in that it enables errors for large swaths of obviously buggy expressions without breaking backward compatibility. If the committee wants to remove float-division-by-0 from the set of UB expressions, they should do that independently of the rules for constexprs/constant expressions (as some Googling gives me the impression the C standard did with Annex F). Generally, I think compiler vendors should not be distinguishing themselves by "reliably" implementing some "defined" behavior for what the standard declares to be UB[1]. At that point you're effectively implementing a proprietary language extension. "Implementation-defined" parts of the standard—and tooling/libraries, of course—are where vendors should be differentiating. [1] I had a very traumatic experience with HP-UX and its configurable null-pointer-dereference semantics that may be biasing me here.
- 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.