--- libraries/base/GHC/Enum.lhs.orig 2008-01-31 16:30:38.000000000 +0000 +++ libraries/base/GHC/Enum.lhs 2008-01-31 20:57:25.000000000 +0000 @@ -481,13 +481,19 @@ -- Watch out for y=maxBound; hence ==, not > -- Be very careful not to have more than one "c" -- so that when eftInfFB is inlined we can inline - -- whatver is bound to "c" + -- whatever is bound to "c" ----------------------------------------------------- -- efdInt and efdtInt deal with [a,b..] and [a,b..c], which are much less common --- so we are less elaborate. The code is more complicated anyway, because --- of worries about Int overflow, so we don't both with rules and deforestation +-- so we are less elaborate. The code is more complicated because of worries +-- about Int overflow. + +{-# RULES +"efdtInt" [~1] forall x1 x2 y. efdtInt x1 x2 y = build (\ c n -> efdtIntFB c n x1 x2 y) +"efdtIntUpList" [1] efdtIntFB (:) [] = efdtInt + #-} + efdInt :: Int# -> Int# -> [Int] -- [x1,x2..maxInt] @@ -501,6 +507,12 @@ | x2 >=# x1 = efdtIntUp x1 x2 y | otherwise = efdtIntDn x1 x2 y +{-# INLINE [0] efdtIntFB #-} +efdtIntFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r +efdtIntFB c n x1 x2 y + | x2 >=# x1 = efdtIntUpFB c n x1 x2 y + | otherwise = efdtIntDnFB c n x1 x2 y + efdtIntUp :: Int# -> Int# -> Int# -> [Int] efdtIntUp x1 x2 y -- Be careful about overflow! | y <# x2 = if y <# x1 then [] else [I# x1] @@ -516,7 +528,23 @@ | otherwise = I# x : go_up (x +# delta) in I# x1 : go_up x2 - + +efdtIntUpFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r +efdtIntUpFB c n x1 x2 y -- Be careful about overflow! + | y <# x2 = if y <# x1 then n else I# x1 `c` n + | otherwise + = -- Common case: x1 < x2 <= y + let + delta = x2 -# x1 + y' = y -# delta + -- NB: x1 <= y'; hence y' is representable + + -- Invariant: x <= y; and x+delta won't overflow + go_up x | x ># y' = I# x `c` n + | otherwise = I# x `c` go_up (x +# delta) + in + I# x1 `c` go_up x2 + efdtIntDn :: Int# -> Int# -> Int# -> [Int] efdtIntDn x1 x2 y -- x2 < x1 | y ># x2 = if y ># x1 then [] else [I# x1] @@ -532,5 +560,21 @@ | otherwise = I# x : go_dn (x +# delta) in I# x1 : go_dn x2 + +efdtIntDnFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r +efdtIntDnFB c n x1 x2 y -- x2 < x1 + | y ># x2 = if y ># x1 then n else I# x1 `c` n + | otherwise + = -- Common case: x1 > x2 >= y + let + delta = x2 -# x1 + y' = y -# delta + -- NB: x1 <= y'; hence y' is representable + + -- Invariant: x >= y; and x+delta won't overflow + go_dn x | x <# y' = I# x `c` n + | otherwise = I# x `c` go_dn (x +# delta) + in + I# x1 `c` go_dn x2 \end{code}