[GHC] #8695: Arithmetic overflow from (minBound :: Int) `quot` (-1)
GHC
ghc-devs at haskell.org
Tue Jan 28 15:00:50 UTC 2014
#8695: Arithmetic overflow from (minBound :: Int) `quot` (-1)
------------------------------------------------+--------------------------
Reporter: rleslie | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: libraries/haskell2010 | Version: 7.6.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Incorrect result at runtime | Unknown/Multiple
Test Case: | Difficulty:
Blocking: | Unknown
| Blocked By:
| Related Tickets:
------------------------------------------------+--------------------------
Comment (by ekmett):
One could argue that it is the status quo making the special case out of
{{{y = -1}}}.
But, without prejudging the answer, let's look at what the class is
attempting to model.
It has taken me a few times to get this to come out to the correct answer
here, so I'm going to be very very pedantic. =)
The current class laws are insufficient to properly model the notion of a
Euclidean domain.
To be a proper Euclidean domain
{{{(x `quot` y)*y + (x `rem` y) == x}}}
isn't the only law.
The standard statement of the Euclidean domain axiom is that there exists
a Euclidean gauge function `f :: r -> Nat` such that if `a` and `b` are in
the domain and `b /= 0`, then there are `q` and `r` such that `a = bq + r`
and either `r = 0` or `f(r) < f(b)`.
Both the (`div`,`mod`) pair and the (`quot`, `rem`) pair (more or less)
satisfy these conditions with `f = abs`, so whenever I say `f` in the
sequel, you can just think `abs`, but I'm using it to keep my head
straight. It'll only matter that I'm making this distinction at the very
end.
The assumption that `b` is non-zero rules out Herbert's case directly, but
if you remove the side-condition that `b /= 0`, it is ruled out by the
conditions on `r`.
e.g. If `(q,r) = quotRem x 0` then {{{x = q*0 + r}}} by the simplified
definition, but then `x = r`, so `f(x) < f(r)` fails to hold and the `r ==
0` case only saves you when you divide 0 by 0.
These rules kind of rule out the tongue-in-cheek extension of `quotRem` to
cover `0` in one sense.
In another, however, the definition doesn't say what happens when `b ==
0`. For simplicity I'd like to carry on with the convention that either `r
= 0` or `f(r) < f(y)` holds regardless and continue to treat `b == 0` as
an error it makes sense both by convention and by the underlying
mathematics.
With that as a warmup, let's get back to {{{(x `quot` -1)}}} in {{{Z mod
2^n}}}.
{{{
(minBound `quot` -1)* (-1) + (minBound `rem` y)
minBound + (minBound `rem` y) = minBound
}}}
says that `q = minBound` and `r = 0` would be the required answers.
The only issue here is that stating `f = abs` doesn't work as we have the
wart forced on us by the asymmetry of 2s complement arithmetic
{{{
>>> abs (minBound :: Int)
-9223372036854775808
}}}
on the other hand, we've been using `abs` as an approximation of an
injection into the natural numbers `f`, which does not have this
limitation!
Basically this requires `f = abs . toInteger`, then the side condition on
`f` holds.
So all of this indicates to me that the extension to support
{{{minBound `quot` -1 = minBound}}}
is correct and _is_ consistent with the definition of a Euclidean domain
independent of 2s complement concerns.
This frankly seems like a slam dunk to me and I'm in favor of the change.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8695#comment:8>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list