Bug 7455 – Allow a cast to discard precision from a floating point during constant folding

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-02-06T19:46:00Z
Last change time
2013-10-30T11:55:13Z
Assigned to
nobody
Creator
code
Blocks
6531

Comments

Comment #0 by code — 2012-02-06T19:46:54Z
int main() { real a = 1.0L + float.epsilon; if (cast(float)(a + 1.0L) > 2.0L) return 1; return 0; } ----- cast(float) is skipped ----- A similar test with double and SSE works correctly.
Comment #1 by smjg — 2012-02-12T11:59:48Z
http://dlang.org/float.html "Regardless of the type of the operands, floating point constant folding is done in real or greater precision." I agree that an explicit cast should override this behaviour, at least to the point of discarding the extra precision from its operand, but it's technically an enhancement request.
Comment #2 by clugdbug — 2012-02-12T18:31:52Z
(In reply to comment #1) > http://dlang.org/float.html > "Regardless of the type of the operands, floating point constant folding is > done in real or greater precision." > > I agree that an explicit cast should override this behaviour, at least to the > point of discarding the extra precision from its operand, but it's technically > an enhancement request. There's no constant folding involved, but: "For floating point operations and expression intermediate values, a greater precision can be used than the type of the expression. Only the minimum precision is set by the types of the operands, not the maximum."
Comment #3 by code — 2012-02-12T18:50:14Z
static import std.conv; int main() { real a = 1.0L + float.epsilon; if (std.conv.to!float(a + 1.0L) > 2.0L) return 1; return 0; } ------ If I try the library version it's result will differ with '-O -inline'. Yeah I know, results may vary depending on compiler flags. So I've no reliable way to round to a single precision float? Does anybody have a good idea how to solve Bug 6531 then?
Comment #4 by bugzilla — 2012-02-13T01:56:55Z
> So I've no reliable way to round to a single precision float? Store it to a float variable that is owned by something the compiler doesn't know about (and so cannot optimize it). One way would be to pass it to an extern function: float foo(float); and implement foo: float foo(float f) { return f; } in some separately compiled module. I think such a method adequately addresses this, and no language enhancement is required.
Comment #5 by smjg — 2012-02-13T04:32:27Z
Therein lies the point - it's a bit convoluted. And I'm sure somebody will come up with a use case for rounding a number to float precision at compile time. Moreover, why allow cast(float) if it isn't supposed to work?
Comment #6 by code — 2012-02-13T10:30:16Z
>Moreover, why allow cast(float) if it isn't supposed to work? To summarize it. The floating point rules are relaxed such that omitting cast(real)cast(float) is a valid transformation. I think that's generally a better idea than to waste all those cycles. There is currently no mechanism to distinguish explicit casts from implicit casts in the backend. Walter's solution solves the problem so this should be fine. Any opinion on whether this would be a candidate for std.math?
Comment #7 by smjg — 2012-02-14T05:09:53Z
(In reply to comment #6) >> Moreover, why allow cast(float) if it isn't supposed to work? > > To summarize it. > The floating point rules are relaxed such that omitting cast(real)cast(float) > is a valid transformation. But why? I can't see any use case for someone writing cast(float) unless they want it to convert the operand to a float. I suppose what I meant to say is: What good reason is there for the design whereby cast(float) does nothing? (OK, so it allows it to be called on a library function with a float parameter, but this affects only the specific case where the CastExpression is directly used as an argument.) > I think that's generally a better idea than to waste > all those cycles. There is currently no mechanism to distinguish explicit casts > from implicit casts in the backend. That is in itself a problem to be addressed. It seems to be partly this that has led to issue 2006 as well. My guess is that there are other bugs that have this same root cause.
Comment #8 by bugzilla — 2012-02-14T12:02:13Z
The floating point rules in D are written with the following principle in mind: "An algorithm is invalid if it breaks if the floating point precision is increased. Floating point precision is always a minimum, not a maximum." I believe (although I don't have proof) this is a sound principle. Programs I've seen that legitimately depended on maximum precision were: 1. Compiler/library validation test suites 2. ones trying to programmatically test the precision (1) is not of value to user programming, and there are alternate ways to test the precision. (2) D has .properties that take care of that. What legitimate algorithm would require sloppy precision? Would you want a speedometer in your car that was less accurate? Cut a piece of metal to a less accurate length? Put a less accurate amount of milk in the carton? A less accurate autopilot? A square root further from the correct value? Programs that rely on a maximum accuracy need to be rethought. It reminds me of back when I worked in electronics. The reality of digital chips is they got faster every year (signal propagation delay). Hence, the golden rule in digital circuit design is to never, ever rely on a maximum propagation speed. Only rely on minimum speeds. Next year, you might not be able to get the slower parts anymore.
Comment #9 by code — 2013-10-30T11:55:13Z
(In reply to comment #8) > Programs that rely on a maximum accuracy need to be rethought. > It's more like programs that rely on a defined precision. When I write cast(float)a == cast(float)b then I want to compare two numbers that have been converted to floats. I understand your point that if 32-bit floats were no longer supported by a CPU we'd have troubles to implement this, but D defines a native float type with specified precision. Also C99 added a rule that casts and assignments are not allowed to use higher precision. http://stackoverflow.com/questions/503436/how-to-deal-with-excess-precision-in-floating-point-computations#answer-503523