[GHC] #9617: Implement `quot` and `rem` using `quotRem`; implement `div` and `mod` using `divMod` (was: Try to replace `quot` and `rem` with `quotRem` when possible)

GHC ghc-devs at haskell.org
Sun Sep 21 08:28:50 UTC 2014


#9617: Implement `quot` and `rem` using `quotRem`; implement `div` and `mod` using
`divMod`
-------------------------------------+-------------------------------------
              Reporter:  dfeuer      |            Owner:
                  Type:  feature     |           Status:  new
  request                            |        Milestone:
              Priority:  normal      |          Version:  7.9
             Component:  Compiler    |         Keywords:
            Resolution:              |     Architecture:  Unknown/Multiple
      Operating System:              |       Difficulty:  Unknown
  Unknown/Multiple                   |       Blocked By:
       Type of failure:              |  Related Tickets:
  None/Unknown                       |
             Test Case:              |
              Blocking:              |
Differential Revisions:              |
-------------------------------------+-------------------------------------

Comment (by dfeuer):

 Good news:

 It seems it may not even be necessary (for `Int`, at least) to find a way
 to turn the `quotRemInt#` back into `quotInt#` or `remInt#`—the
 performance difference there appears to be somewhere between tiny and
 nonexistent. It's not clear to me whether that will be the same for
 `divMod`, which adds a few more operations over `div` or `mod` (but fast
 ones).

 More good news:

 After bashing my head against it for a few hours, I managed to get
 `divMod` to do what I wanted. I had to swap the divide by zero test with
 the arithmetic overflow test. I don't understand ''why'' this made it
 work, but it seems to have done the job. It looks like this:

 {{{#!hs
 divZeroError# :: Void# -> (# Int#, Int# #)
 divZeroError# a = error "Divide by zero"

 overflowError# :: Void# -> Int#
 overflowError# a = error "Arithmetic overflow: attempted to divide
 minBound by -1"

 divModInt# :: Int# -> Int# -> (# Int#, Int# #)
 x# `divModInt#` y#
  | isTrue# (y# ==# (-1#)) &&
      isTrue# (x# ==# (case minBound of I# mb -> mb))
        = (# overflowError# void#, 0# #)
  | isTrue# (y# ==# 0#) = divZeroError# void#
  | isTrue# (x# ># 0#) && isTrue# (y# <# 0#) =
                                     case (x# -# 1#) `quotRemInt#` y# of
                                       (# q, r #) -> (# q -# 1#, r +# y# +#
 1# #)
  | isTrue# (x# <# 0#) && isTrue# (y# ># 0#) =
                                     case (x# +# 1#) `quotRemInt#` y# of
                                       (# q, r #) -> (# q -# 1#, r +# y# -#
 1# #)
  | otherwise                                =
                                     x# `quotRemInt#` y#

 divModInt :: Int -> Int -> (Int, Int)
 (I# x) `divModInt` (I# y) = case x `divModInt#` y of
                             (# q, r #) -> (I# q, I# r)

 div :: Int -> Int -> Int
 {-# INLINE div #-}
 div x y = fst (divModInt x y)
 infixl 7 `div`

 mod :: Int -> Int -> Int
 {-# INLINE mod #-}
 x `mod` y = snd (divModInt x y)
 infixl 7 `mod`
 }}}

 Using these definitions, it seems things stay sufficiently similar long
 enough for CSE to do its job, so

 {{{#!hs
 divPlusMod :: Int -> Int -> Int
 divPlusMod x y = div x y + mod x y
 }}}

 compiles into something very similar to what you'd get from

 {{{#!hs
 divPlusModStandard :: Int -> Int -> Int
 divPlusModStandard x y = case divMod x y of
                            (q, r) -> q + r
 }}}

 but with the proposed definitions, I'm getting quite a bit less code
 duplication, which seems to be a small but good thing.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9617#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list