Bug 8666 – std.math.abs(int.min) returns int.min

Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2012-09-15T22:02:00Z
Last change time
2014-01-24T11:32:32Z
Assigned to
nobody
Creator
iteronvexor

Comments

Comment #0 by iteronvexor — 2012-09-15T22:02:34Z
pragma(msg, abs(int.min)); prints: -2147483648 pragma(msg, abs(cast(long)int.min)); prints: 2147483648L
Comment #1 by andrei — 2012-09-16T03:41:26Z
This is a known anomaly. I assume you are proposing that returning long is the right way to go about it, but it really isn't. One possibility would be to return uint for int and smaller, and ulong for long. That would be a principled way to go about it, but would break existing code in rather subtle ways. We could add uabs to return an unsigned type.
Comment #2 by iteronvexor — 2012-09-16T10:53:57Z
(In reply to comment #1) > This is a known anomaly. I assume you are proposing that returning long is the > right way to go about it, but it really isn't. > > One possibility would be to return uint for int and smaller, and ulong for > long. That would be a principled way to go about it, but would break existing > code in rather subtle ways. > > We could add uabs to return an unsigned type. No, I wasn't trying to propose that returning a long is the solution. I was simply trying to demonstrate that the bug isn't triggered when the int is converted to a long. When I reported this, the anomaly wasn't obvious to me, and I thought there was a bug in math.abs. In my code I had a template: template Fun(long a) { enum b = abs(a); //... } but I was instantiating it with Fun!(int.min). Things started to go wrong when I changed the template to: template Fun(int a) { enum b = abs(a); //... } In this case the int was being implicitly converted to a long. I don't think the problem has a solution, but D's contracts will really help those who aren't aware of the anomaly: Num abs(Num)(Num x) out(result) { assert(result >= 0, "...and a helpful message."); } body { // ... } What do you guys think?
Comment #3 by clugdbug — 2014-01-24T01:50:36Z
This is just a consequence of the fact that overflow checking never happens for integral types. int x = abs(int.min); returns an incorrect result, in the same way that int y = int.max + int.max; returns an incorrect result. There's really nothing special going on here, all of the types are correct. It's not unsigned, there is no doubt about how to interpret the number -- it's positive. It just doesn't fit! If we declare that integer overflow is an error, as has been proposed a few times, we could use bound checking to statically detect some of these cases.
Comment #4 by bugzilla — 2014-01-24T11:32:32Z
There's really nothing to be done about this. Adding runtime checks would seriously degrade performance.