\begin{code}
-{-# OPTIONS -fno-implicit-prelude #-}
+{-# OPTIONS_GHC -XNoImplicitPrelude #-}
+-- We believe we could deorphan this module, by moving lots of things
+-- around, but we haven't got there yet:
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-# OPTIONS_HADDOCK hide #-}
-----------------------------------------------------------------------------
-- |
-- Module : GHC.Num
-- Copyright : (c) The University of Glasgow 1994-2002
-- License : see libraries/base/LICENSE
---
+--
-- Maintainer : cvs-ghc@haskell.org
-- Stability : internal
-- Portability : non-portable (GHC Extensions)
#include "MachDeps.h"
#if SIZEOF_HSWORD == 4
-#define LEFTMOST_BIT 2147483648
+#define DIGITS 9
+#define BASE 1000000000
#elif SIZEOF_HSWORD == 8
-#define LEFTMOST_BIT 9223372036854775808
+#define DIGITS 18
+#define BASE 1000000000000000000
#else
-#error Please define LEFTMOST_BIT to be 2^(SIZEOF_HSWORD*8-1)
+#error Please define DIGITS and BASE
+-- DIGITS should be the largest integer such that
+-- 10^DIGITS < 2^(SIZEOF_HSWORD * 8 - 1)
+-- BASE should be 10^DIGITS. Note that ^ is not available yet.
#endif
-module GHC.Num where
+-- #hide
+module GHC.Num (module GHC.Num, module GHC.Integer) where
-import {-# SOURCE #-} GHC.Err
import GHC.Base
-import GHC.List
import GHC.Enum
import GHC.Show
+import GHC.Integer
infixl 7 *
infixl 6 +, -
-default () -- Double isn't available yet,
- -- and we shouldn't be using defaults anyway
+default () -- Double isn't available yet,
+ -- and we shouldn't be using defaults anyway
\end{code}
%*********************************************************
-%* *
+%* *
\subsection{Standard numeric class}
-%* *
+%* *
%*********************************************************
\begin{code}
+-- | Basic numeric class.
+--
+-- Minimal complete definition: all except 'negate' or @(-)@
class (Eq a, Show a) => Num a where
- (+), (-), (*) :: a -> a -> a
- negate :: a -> a
- abs, signum :: a -> a
- fromInteger :: Integer -> a
-
- x - y = x + negate y
- negate x = 0 - x
-
+ (+), (-), (*) :: a -> a -> a
+ -- | Unary negation.
+ negate :: a -> a
+ -- | Absolute value.
+ abs :: a -> a
+ -- | Sign of a number.
+ -- The functions 'abs' and 'signum' should satisfy the law:
+ --
+ -- > abs x * signum x == x
+ --
+ -- For real numbers, the 'signum' is either @-1@ (negative), @0@ (zero)
+ -- or @1@ (positive).
+ signum :: a -> a
+ -- | Conversion from an 'Integer'.
+ -- An integer literal represents the application of the function
+ -- 'fromInteger' to the appropriate value of type 'Integer',
+ -- so such literals have type @('Num' a) => a@.
+ fromInteger :: Integer -> a
+
+ {-# INLINE (-) #-}
+ {-# INLINE negate #-}
+ x - y = x + negate y
+ negate x = 0 - x
+
+-- | the same as @'flip' ('-')@.
+--
+-- Because @-@ is treated specially in the Haskell grammar,
+-- @(-@ /e/@)@ is not a section, but an application of prefix negation.
+-- However, @('subtract'@ /exp/@)@ is equivalent to the disallowed section.
{-# INLINE subtract #-}
subtract :: (Num a) => a -> a -> a
subtract x y = y - x
%*********************************************************
-%* *
+%* *
\subsection{Instances for @Int@}
-%* *
+%* *
%*********************************************************
\begin{code}
instance Num Int where
- (+) = plusInt
- (-) = minusInt
+ (+) = plusInt
+ (-) = minusInt
negate = negateInt
- (*) = timesInt
+ (*) = timesInt
abs n = if n `geInt` 0 then n else negateInt n
signum n | n `ltInt` 0 = negateInt 1
- | n `eqInt` 0 = 0
- | otherwise = 1
-
- fromInteger = integer2Int
-\end{code}
+ | n `eqInt` 0 = 0
+ | otherwise = 1
-
-\begin{code}
--- These can't go in GHC.Base with the defn of Int, because
--- we don't have pairs defined at that time!
+ fromInteger i = I# (toInt# i)
quotRemInt :: Int -> Int -> (Int, Int)
-a@(I# _) `quotRemInt` b@(I# _) = (a `quotInt` b, a `remInt` b)
+quotRemInt a@(I# _) b@(I# _) = (a `quotInt` b, a `remInt` b)
-- OK, so I made it a little stricter. Shoot me. (WDP 94/10)
divModInt :: Int -> Int -> (Int, Int)
-- Stricter. Sorry if you don't like it. (WDP 94/10)
\end{code}
-
-%*********************************************************
-%* *
-\subsection{The @Integer@ type}
-%* *
-%*********************************************************
-
-\begin{code}
-data Integer
- = S# Int# -- small integers
-#ifndef ILX
- | J# Int# ByteArray# -- large integers
-#else
- | J# Void BigInteger -- .NET big ints
-
-foreign type dotnet "BigInteger" BigInteger
-#endif
-\end{code}
-
-Convenient boxed Integer PrimOps.
-
-\begin{code}
-zeroInteger :: Integer
-zeroInteger = S# 0#
-
-int2Integer :: Int -> Integer
-{-# INLINE int2Integer #-}
-int2Integer (I# i) = S# i
-
-integer2Int :: Integer -> Int
-integer2Int (S# i) = I# i
-integer2Int (J# s d) = case (integer2Int# s d) of { n# -> I# n# }
-
-toBig (S# i) = case int2Integer# i of { (# s, d #) -> J# s d }
-toBig i@(J# _ _) = i
-\end{code}
-
-
%*********************************************************
-%* *
-\subsection{Dividing @Integers@}
-%* *
+%* *
+\subsection{The @Integer@ instances for @Show@}
+%* *
%*********************************************************
\begin{code}
-quotRemInteger :: Integer -> Integer -> (Integer, Integer)
-quotRemInteger a@(S# (-LEFTMOST_BIT#)) b = quotRemInteger (toBig a) b
-quotRemInteger (S# i) (S# j)
- = case quotRemInt (I# i) (I# j) of ( I# i, I# j ) -> ( S# i, S# j )
-quotRemInteger i1@(J# _ _) i2@(S# _) = quotRemInteger i1 (toBig i2)
-quotRemInteger i1@(S# _) i2@(J# _ _) = quotRemInteger (toBig i1) i2
-quotRemInteger (J# s1 d1) (J# s2 d2)
- = case (quotRemInteger# s1 d1 s2 d2) of
- (# s3, d3, s4, d4 #)
- -> (J# s3 d3, J# s4 d4)
-
-divModInteger a@(S# (-LEFTMOST_BIT#)) b = divModInteger (toBig a) b
-divModInteger (S# i) (S# j)
- = case divModInt (I# i) (I# j) of ( I# i, I# j ) -> ( S# i, S# j)
-divModInteger i1@(J# _ _) i2@(S# _) = divModInteger i1 (toBig i2)
-divModInteger i1@(S# _) i2@(J# _ _) = divModInteger (toBig i1) i2
-divModInteger (J# s1 d1) (J# s2 d2)
- = case (divModInteger# s1 d1 s2 d2) of
- (# s3, d3, s4, d4 #)
- -> (J# s3 d3, J# s4 d4)
-
-remInteger :: Integer -> Integer -> Integer
-remInteger ia 0
- = error "Prelude.Integral.rem{Integer}: divide by 0"
-remInteger a@(S# (-LEFTMOST_BIT#)) b = remInteger (toBig a) b
-remInteger (S# a) (S# b) = S# (remInt# a b)
-{- Special case doesn't work, because a 1-element J# has the range
- -(2^32-1) -- 2^32-1, whereas S# has the range -2^31 -- (2^31-1)
-remInteger ia@(S# a) (J# sb b)
- | sb ==# 1# = S# (remInt# a (word2Int# (integer2Word# sb b)))
- | sb ==# -1# = S# (remInt# a (0# -# (word2Int# (integer2Word# sb b))))
- | 0# <# sb = ia
- | otherwise = S# (0# -# a)
--}
-remInteger ia@(S# _) ib@(J# _ _) = remInteger (toBig ia) ib
-remInteger (J# sa a) (S# b)
- = case int2Integer# b of { (# sb, b #) ->
- case remInteger# sa a sb b of { (# sr, r #) ->
- S# (integer2Int# sr r) }}
-remInteger (J# sa a) (J# sb b)
- = case remInteger# sa a sb b of (# sr, r #) -> J# sr r
-
-quotInteger :: Integer -> Integer -> Integer
-quotInteger ia 0
- = error "Prelude.Integral.quot{Integer}: divide by 0"
-quotInteger a@(S# (-LEFTMOST_BIT#)) b = quotInteger (toBig a) b
-quotInteger (S# a) (S# b) = S# (quotInt# a b)
-{- Special case disabled, see remInteger above
-quotInteger (S# a) (J# sb b)
- | sb ==# 1# = S# (quotInt# a (word2Int# (integer2Word# sb b)))
- | sb ==# -1# = S# (quotInt# a (0# -# (word2Int# (integer2Word# sb b))))
- | otherwise = zeroInteger
--}
-quotInteger ia@(S# _) ib@(J# _ _) = quotInteger (toBig ia) ib
-quotInteger (J# sa a) (S# b)
- = case int2Integer# b of { (# sb, b #) ->
- case quotInteger# sa a sb b of (# sq, q #) -> J# sq q }
-quotInteger (J# sa a) (J# sb b)
- = case quotInteger# sa a sb b of (# sg, g #) -> J# sg g
-\end{code}
-
-
-
-\begin{code}
-gcdInteger :: Integer -> Integer -> Integer
--- SUP: Do we really need the first two cases?
-gcdInteger a@(S# (-LEFTMOST_BIT#)) b = gcdInteger (toBig a) b
-gcdInteger a b@(S# (-LEFTMOST_BIT#)) = gcdInteger a (toBig b)
-gcdInteger (S# a) (S# b) = case gcdInt (I# a) (I# b) of { I# c -> S# c }
-gcdInteger ia@(S# 0#) ib@(J# 0# _) = error "GHC.Num.gcdInteger: gcd 0 0 is undefined"
-gcdInteger ia@(S# a) ib@(J# sb b)
- | a ==# 0# = abs ib
- | sb ==# 0# = abs ia
- | otherwise = S# (gcdIntegerInt# absSb b absA)
- where absA = if a <# 0# then negateInt# a else a
- absSb = if sb <# 0# then negateInt# sb else sb
-gcdInteger ia@(J# _ _) ib@(S# _) = gcdInteger ib ia
-gcdInteger (J# 0# _) (J# 0# _) = error "GHC.Num.gcdInteger: gcd 0 0 is undefined"
-gcdInteger (J# sa a) (J# sb b)
- = case gcdInteger# sa a sb b of (# sg, g #) -> J# sg g
-
-lcmInteger :: Integer -> Integer -> Integer
-lcmInteger a 0
- = zeroInteger
-lcmInteger 0 b
- = zeroInteger
-lcmInteger a b
- = (divExact aa (gcdInteger aa ab)) * ab
- where aa = abs a
- ab = abs b
-
-divExact :: Integer -> Integer -> Integer
-divExact a@(S# (-LEFTMOST_BIT#)) b = divExact (toBig a) b
-divExact (S# a) (S# b) = S# (quotInt# a b)
-divExact (S# a) (J# sb b)
- = S# (quotInt# a (integer2Int# sb b))
-divExact (J# sa a) (S# b)
- = case int2Integer# b of
- (# sb, b #) -> case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d
-divExact (J# sa a) (J# sb b)
- = case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d
-\end{code}
+instance Show Integer where
+ showsPrec p n r
+ | p > 6 && n < 0 = '(' : integerToString n (')' : r)
+ -- Minor point: testing p first gives better code
+ -- in the not-uncommon case where the p argument
+ -- is a constant
+ | otherwise = integerToString n r
+ showList = showList__ (showsPrec 0)
+-- Divide an conquer implementation of string conversion
+integerToString :: Integer -> String -> String
+integerToString n0 cs0
+ | n0 < 0 = '-' : integerToString' (- n0) cs0
+ | otherwise = integerToString' n0 cs0
+ where
+ integerToString' :: Integer -> String -> String
+ integerToString' n cs
+ | n < BASE = jhead (fromInteger n) cs
+ | otherwise = jprinth (jsplitf (BASE*BASE) n) cs
+
+ -- Split n into digits in base p. We first split n into digits
+ -- in base p*p and then split each of these digits into two.
+ -- Note that the first 'digit' modulo p*p may have a leading zero
+ -- in base p that we need to drop - this is what jsplith takes care of.
+ -- jsplitb the handles the remaining digits.
+ jsplitf :: Integer -> Integer -> [Integer]
+ jsplitf p n
+ | p > n = [n]
+ | otherwise = jsplith p (jsplitf (p*p) n)
+
+ jsplith :: Integer -> [Integer] -> [Integer]
+ jsplith p (n:ns) =
+ case n `quotRemInteger` p of
+ (# q, r #) ->
+ if q > 0 then q : r : jsplitb p ns
+ else r : jsplitb p ns
+ jsplith _ [] = error "jsplith: []"
+
+ jsplitb :: Integer -> [Integer] -> [Integer]
+ jsplitb _ [] = []
+ jsplitb p (n:ns) = case n `quotRemInteger` p of
+ (# q, r #) ->
+ q : r : jsplitb p ns
+
+ -- Convert a number that has been split into digits in base BASE^2
+ -- this includes a last splitting step and then conversion of digits
+ -- that all fit into a machine word.
+ jprinth :: [Integer] -> String -> String
+ jprinth (n:ns) cs =
+ case n `quotRemInteger` BASE of
+ (# q', r' #) ->
+ let q = fromInteger q'
+ r = fromInteger r'
+ in if q > 0 then jhead q $ jblock r $ jprintb ns cs
+ else jhead r $ jprintb ns cs
+ jprinth [] _ = error "jprinth []"
+
+ jprintb :: [Integer] -> String -> String
+ jprintb [] cs = cs
+ jprintb (n:ns) cs = case n `quotRemInteger` BASE of
+ (# q', r' #) ->
+ let q = fromInteger q'
+ r = fromInteger r'
+ in jblock q $ jblock r $ jprintb ns cs
+
+ -- Convert an integer that fits into a machine word. Again, we have two
+ -- functions, one that drops leading zeros (jhead) and one that doesn't
+ -- (jblock)
+ jhead :: Int -> String -> String
+ jhead n cs
+ | n < 10 = case unsafeChr (ord '0' + n) of
+ c@(C# _) -> c : cs
+ | otherwise = case unsafeChr (ord '0' + r) of
+ c@(C# _) -> jhead q (c : cs)
+ where
+ (q, r) = n `quotRemInt` 10
-%*********************************************************
-%* *
-\subsection{The @Integer@ instances for @Eq@, @Ord@}
-%* *
-%*********************************************************
+ jblock = jblock' {- ' -} DIGITS
-\begin{code}
-instance Eq Integer where
- (S# i) == (S# j) = i ==# j
- (S# i) == (J# s d) = cmpIntegerInt# s d i ==# 0#
- (J# s d) == (S# i) = cmpIntegerInt# s d i ==# 0#
- (J# s1 d1) == (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ==# 0#
-
- (S# i) /= (S# j) = i /=# j
- (S# i) /= (J# s d) = cmpIntegerInt# s d i /=# 0#
- (J# s d) /= (S# i) = cmpIntegerInt# s d i /=# 0#
- (J# s1 d1) /= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) /=# 0#
-
-------------------------------------------------------------------------
-instance Ord Integer where
- (S# i) <= (S# j) = i <=# j
- (J# s d) <= (S# i) = cmpIntegerInt# s d i <=# 0#
- (S# i) <= (J# s d) = cmpIntegerInt# s d i >=# 0#
- (J# s1 d1) <= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <=# 0#
-
- (S# i) > (S# j) = i ># j
- (J# s d) > (S# i) = cmpIntegerInt# s d i ># 0#
- (S# i) > (J# s d) = cmpIntegerInt# s d i <# 0#
- (J# s1 d1) > (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ># 0#
-
- (S# i) < (S# j) = i <# j
- (J# s d) < (S# i) = cmpIntegerInt# s d i <# 0#
- (S# i) < (J# s d) = cmpIntegerInt# s d i ># 0#
- (J# s1 d1) < (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <# 0#
-
- (S# i) >= (S# j) = i >=# j
- (J# s d) >= (S# i) = cmpIntegerInt# s d i >=# 0#
- (S# i) >= (J# s d) = cmpIntegerInt# s d i <=# 0#
- (J# s1 d1) >= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) >=# 0#
-
- compare (S# i) (S# j)
- | i ==# j = EQ
- | i <=# j = LT
- | otherwise = GT
- compare (J# s d) (S# i)
- = case cmpIntegerInt# s d i of { res# ->
- if res# <# 0# then LT else
- if res# ># 0# then GT else EQ
- }
- compare (S# i) (J# s d)
- = case cmpIntegerInt# s d i of { res# ->
- if res# ># 0# then LT else
- if res# <# 0# then GT else EQ
- }
- compare (J# s1 d1) (J# s2 d2)
- = case cmpInteger# s1 d1 s2 d2 of { res# ->
- if res# <# 0# then LT else
- if res# ># 0# then GT else EQ
- }
+ jblock' :: Int -> Int -> String -> String
+ jblock' d n cs
+ | d == 1 = case unsafeChr (ord '0' + n) of
+ c@(C# _) -> c : cs
+ | otherwise = case unsafeChr (ord '0' + r) of
+ c@(C# _) -> jblock' (d - 1) q (c : cs)
+ where
+ (q, r) = n `quotRemInt` 10
\end{code}
%*********************************************************
-%* *
+%* *
\subsection{The @Integer@ instances for @Num@}
-%* *
+%* *
%*********************************************************
\begin{code}
(+) = plusInteger
(-) = minusInteger
(*) = timesInteger
- negate = negateInteger
- fromInteger x = x
-
- -- ORIG: abs n = if n >= 0 then n else -n
- abs (S# (-LEFTMOST_BIT#)) = LEFTMOST_BIT
- abs (S# i) = case abs (I# i) of I# j -> S# j
- abs n@(J# s d) = if (s >=# 0#) then n else J# (negateInt# s) d
-
- signum (S# i) = case signum (I# i) of I# j -> S# j
- signum (J# s d)
- = let
- cmp = cmpIntegerInt# s d 0#
- in
- if cmp ># 0# then S# 1#
- else if cmp ==# 0# then S# 0#
- else S# (negateInt# 1#)
-
-plusInteger i1@(S# i) i2@(S# j) = case addIntC# i j of { (# r, c #) ->
- if c ==# 0# then S# r
- else toBig i1 + toBig i2 }
-plusInteger i1@(J# _ _) i2@(S# _) = i1 + toBig i2
-plusInteger i1@(S# _) i2@(J# _ _) = toBig i1 + i2
-plusInteger (J# s1 d1) (J# s2 d2) = case plusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
-
-minusInteger i1@(S# i) i2@(S# j) = case subIntC# i j of { (# r, c #) ->
- if c ==# 0# then S# r
- else toBig i1 - toBig i2 }
-minusInteger i1@(J# _ _) i2@(S# _) = i1 - toBig i2
-minusInteger i1@(S# _) i2@(J# _ _) = toBig i1 - i2
-minusInteger (J# s1 d1) (J# s2 d2) = case minusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
-
-timesInteger i1@(S# i) i2@(S# j) = if mulIntMayOflo# i j ==# 0#
- then S# (i *# j)
- else toBig i1 * toBig i2
-timesInteger i1@(J# _ _) i2@(S# _) = i1 * toBig i2
-timesInteger i1@(S# _) i2@(J# _ _) = toBig i1 * i2
-timesInteger (J# s1 d1) (J# s2 d2) = case timesInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
-
-negateInteger (S# (-LEFTMOST_BIT#)) = LEFTMOST_BIT
-negateInteger (S# i) = S# (negateInt# i)
-negateInteger (J# s d) = J# (negateInt# s) d
+ negate = negateInteger
+ fromInteger x = x
+
+ abs = absInteger
+ signum = signumInteger
\end{code}
%*********************************************************
-%* *
+%* *
\subsection{The @Integer@ instance for @Enum@}
-%* *
+%* *
%*********************************************************
\begin{code}
instance Enum Integer where
- succ x = x + 1
- pred x = x - 1
- toEnum n = int2Integer n
- fromEnum n = integer2Int n
+ succ x = x + 1
+ pred x = x - 1
+ toEnum (I# n) = smallInteger n
+ fromEnum n = I# (toInt# n)
{-# INLINE enumFrom #-}
{-# INLINE enumFromThen #-}
{-# INLINE enumFromThenTo #-}
enumFrom x = enumDeltaInteger x 1
enumFromThen x y = enumDeltaInteger x (y-x)
- enumFromTo x lim = enumDeltaToInteger x 1 lim
+ enumFromTo x lim = enumDeltaToInteger x 1 lim
enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim
{-# RULES
-"enumDeltaInteger" [~1] forall x y. enumDeltaInteger x y = build (\c _ -> enumDeltaIntegerFB c x y)
-"efdtInteger" [~1] forall x y l.enumDeltaToInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l)
-"enumDeltaInteger" [1] enumDeltaIntegerFB (:) = enumDeltaInteger
-"enumDeltaToInteger" [1] enumDeltaToIntegerFB (:) [] = enumDeltaToInteger
+"enumDeltaInteger" [~1] forall x y. enumDeltaInteger x y = build (\c _ -> enumDeltaIntegerFB c x y)
+"efdtInteger" [~1] forall x y l.enumDeltaToInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l)
+"enumDeltaInteger" [1] enumDeltaIntegerFB (:) = enumDeltaInteger
+"enumDeltaToInteger" [1] enumDeltaToIntegerFB (:) [] = enumDeltaToInteger
#-}
enumDeltaIntegerFB :: (Integer -> b -> b) -> Integer -> Integer -> b
-enumDeltaIntegerFB c x d = x `c` enumDeltaIntegerFB c (x+d) d
+enumDeltaIntegerFB c x d = x `seq` (x `c` enumDeltaIntegerFB c (x+d) d)
enumDeltaInteger :: Integer -> Integer -> [Integer]
-enumDeltaInteger x d = x : enumDeltaInteger (x+d) d
-
+enumDeltaInteger x d = x `seq` (x : enumDeltaInteger (x+d) d)
+-- strict accumulator, so
+-- head (drop 1000000 [1 .. ]
+-- works
+
+{-# NOINLINE [0] enumDeltaToIntegerFB #-}
+-- Don't inline this until RULE "enumDeltaToInteger" has had a chance to fire
+enumDeltaToIntegerFB :: (Integer -> a -> a) -> a
+ -> Integer -> Integer -> Integer -> a
enumDeltaToIntegerFB c n x delta lim
| delta >= 0 = up_fb c n x delta lim
| otherwise = dn_fb c n x delta lim
+enumDeltaToInteger :: Integer -> Integer -> Integer -> [Integer]
enumDeltaToInteger x delta lim
| delta >= 0 = up_list x delta lim
| otherwise = dn_list x delta lim
-up_fb c n x delta lim = go (x::Integer)
- where
- go x | x > lim = n
- | otherwise = x `c` go (x+delta)
-dn_fb c n x delta lim = go (x::Integer)
- where
- go x | x < lim = n
- | otherwise = x `c` go (x+delta)
-
-up_list x delta lim = go (x::Integer)
- where
- go x | x > lim = []
- | otherwise = x : go (x+delta)
-dn_list x delta lim = go (x::Integer)
- where
- go x | x < lim = []
- | otherwise = x : go (x+delta)
-
+up_fb :: (Integer -> a -> a) -> a -> Integer -> Integer -> Integer -> a
+up_fb c n x0 delta lim = go (x0 :: Integer)
+ where
+ go x | x > lim = n
+ | otherwise = x `c` go (x+delta)
+dn_fb :: (Integer -> a -> a) -> a -> Integer -> Integer -> Integer -> a
+dn_fb c n x0 delta lim = go (x0 :: Integer)
+ where
+ go x | x < lim = n
+ | otherwise = x `c` go (x+delta)
+
+up_list :: Integer -> Integer -> Integer -> [Integer]
+up_list x0 delta lim = go (x0 :: Integer)
+ where
+ go x | x > lim = []
+ | otherwise = x : go (x+delta)
+dn_list :: Integer -> Integer -> Integer -> [Integer]
+dn_list x0 delta lim = go (x0 :: Integer)
+ where
+ go x | x < lim = []
+ | otherwise = x : go (x+delta)
\end{code}
-
-%*********************************************************
-%* *
-\subsection{The @Integer@ instances for @Show@}
-%* *
-%*********************************************************
-
-\begin{code}
-instance Show Integer where
- showsPrec p n r
- | p > 6 && n < 0 = '(' : jtos n (')' : r)
- -- Minor point: testing p first gives better code
- -- in the not-uncommon case where the p argument
- -- is a constant
- | otherwise = jtos n r
- showList = showList__ (showsPrec 0)
-
-jtos :: Integer -> String -> String
-jtos n cs
- | n < 0 = '-' : jtos' (-n) cs
- | otherwise = jtos' n cs
- where
- jtos' :: Integer -> String -> String
- jtos' n' cs'
- | n' < 10 = case unsafeChr (ord '0' + fromInteger n') of
- c@(C# _) -> c:cs'
- | otherwise = case unsafeChr (ord '0' + fromInteger r) of
- c@(C# _) -> jtos' q (c:cs')
- where
- (q,r) = n' `quotRemInteger` 10
-\end{code}