{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE Trustworthy #-}
{-# OPTIONS_HADDOCK hide #-}
#include "MachDeps.h"
module GHC.Enum(
        Bounded(..), Enum(..),
        boundedEnumFrom, boundedEnumFromThen,
        toEnumError, fromEnumError, succError, predError,
        
   ) where
import GHC.Base hiding ( many )
import GHC.Char
import GHC.Integer
import GHC.Num
import GHC.Show
default ()              
class  Bounded a  where
    minBound, maxBound :: a
class  Enum a   where
    
    succ                :: a -> a
    
    pred                :: a -> a
    
    toEnum              :: Int -> a
    
    
    
    fromEnum            :: a -> Int
    
    
    
    
    
    
    enumFrom            :: a -> [a]
    
    
    
    
    
    
    
    
    
    
    
    
    enumFromThen        :: a -> a -> [a]
    
    
    
    
    
    
    
    
    
    enumFromTo          :: a -> a -> [a]
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    enumFromThenTo      :: a -> a -> a -> [a]
    succ                   = toEnum . (+ 1)  . fromEnum
    pred                   = toEnum . (subtract 1) . fromEnum
    enumFrom x             = map toEnum [fromEnum x ..]
    enumFromThen x y       = map toEnum [fromEnum x, fromEnum y ..]
    enumFromTo x y         = map toEnum [fromEnum x .. fromEnum y]
    enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
boundedEnumFrom :: (Enum a, Bounded a) => a -> [a]
boundedEnumFrom n = map toEnum [fromEnum n .. fromEnum (maxBound `asTypeOf` n)]
boundedEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]
boundedEnumFromThen n1 n2
  | i_n2 >= i_n1  = map toEnum [i_n1, i_n2 .. fromEnum (maxBound `asTypeOf` n1)]
  | otherwise     = map toEnum [i_n1, i_n2 .. fromEnum (minBound `asTypeOf` n1)]
  where
    i_n1 = fromEnum n1
    i_n2 = fromEnum n2
{-# NOINLINE toEnumError #-}
toEnumError :: (Show a) => String -> Int -> (a,a) -> b
toEnumError inst_ty i bnds =
    errorWithoutStackTrace $ "Enum.toEnum{" ++ inst_ty ++ "}: tag (" ++
            show i ++
            ") is outside of bounds " ++
            show bnds
{-# NOINLINE fromEnumError #-}
fromEnumError :: (Show a) => String -> a -> b
fromEnumError inst_ty x =
    errorWithoutStackTrace $ "Enum.fromEnum{" ++ inst_ty ++ "}: value (" ++
            show x ++
            ") is outside of Int's bounds " ++
            show (minBound::Int, maxBound::Int)
{-# NOINLINE succError #-}
succError :: String -> a
succError inst_ty =
    errorWithoutStackTrace $ "Enum.succ{" ++ inst_ty ++ "}: tried to take `succ' of maxBound"
{-# NOINLINE predError #-}
predError :: String -> a
predError inst_ty =
    errorWithoutStackTrace $ "Enum.pred{" ++ inst_ty ++ "}: tried to take `pred' of minBound"
deriving instance Bounded ()
instance Enum () where
    succ _      = errorWithoutStackTrace "Prelude.Enum.().succ: bad argument"
    pred _      = errorWithoutStackTrace "Prelude.Enum.().pred: bad argument"
    toEnum x | x == 0    = ()
             | otherwise = errorWithoutStackTrace "Prelude.Enum.().toEnum: bad argument"
    fromEnum () = 0
    enumFrom ()         = [()]
    enumFromThen () ()  = let many = ():many in many
    enumFromTo () ()    = [()]
    enumFromThenTo () () () = let many = ():many in many
deriving instance (Bounded a, Bounded b)
        => Bounded (a,b)
deriving instance (Bounded a, Bounded b, Bounded c)
        => Bounded (a,b,c)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d)
        => Bounded (a,b,c,d)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e)
        => Bounded (a,b,c,d,e)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f)
        => Bounded (a,b,c,d,e,f)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g)
        => Bounded (a,b,c,d,e,f,g)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h)
        => Bounded (a,b,c,d,e,f,g,h)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h, Bounded i)
        => Bounded (a,b,c,d,e,f,g,h,i)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h, Bounded i, Bounded j)
        => Bounded (a,b,c,d,e,f,g,h,i,j)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k)
        => Bounded (a,b,c,d,e,f,g,h,i,j,k)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k,
          Bounded l)
        => Bounded (a,b,c,d,e,f,g,h,i,j,k,l)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k,
          Bounded l, Bounded m)
        => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k,
          Bounded l, Bounded m, Bounded n)
        => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m,n)
deriving instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e,
          Bounded f, Bounded g, Bounded h, Bounded i, Bounded j, Bounded k,
          Bounded l, Bounded m, Bounded n, Bounded o)
        => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)
deriving instance Bounded Bool
instance Enum Bool where
  succ False = True
  succ True  = errorWithoutStackTrace "Prelude.Enum.Bool.succ: bad argument"
  pred True  = False
  pred False  = errorWithoutStackTrace "Prelude.Enum.Bool.pred: bad argument"
  toEnum n | n == 0    = False
           | n == 1    = True
           | otherwise = errorWithoutStackTrace "Prelude.Enum.Bool.toEnum: bad argument"
  fromEnum False = 0
  fromEnum True  = 1
  
  enumFrom     = boundedEnumFrom
  enumFromThen = boundedEnumFromThen
deriving instance Bounded Ordering
instance Enum Ordering where
  succ LT = EQ
  succ EQ = GT
  succ GT = errorWithoutStackTrace "Prelude.Enum.Ordering.succ: bad argument"
  pred GT = EQ
  pred EQ = LT
  pred LT = errorWithoutStackTrace "Prelude.Enum.Ordering.pred: bad argument"
  toEnum n | n == 0 = LT
           | n == 1 = EQ
           | n == 2 = GT
  toEnum _ = errorWithoutStackTrace "Prelude.Enum.Ordering.toEnum: bad argument"
  fromEnum LT = 0
  fromEnum EQ = 1
  fromEnum GT = 2
  
  enumFrom     = boundedEnumFrom
  enumFromThen = boundedEnumFromThen
instance  Bounded Char  where
    minBound =  '\0'
    maxBound =  '\x10FFFF'
instance  Enum Char  where
    succ (C# c#)
       | isTrue# (ord# c# /=# 0x10FFFF#) = C# (chr# (ord# c# +# 1#))
       | otherwise             = errorWithoutStackTrace ("Prelude.Enum.Char.succ: bad argument")
    pred (C# c#)
       | isTrue# (ord# c# /=# 0#) = C# (chr# (ord# c# -# 1#))
       | otherwise                = errorWithoutStackTrace ("Prelude.Enum.Char.pred: bad argument")
    toEnum   = chr
    fromEnum = ord
    {-# INLINE enumFrom #-}
    enumFrom (C# x) = eftChar (ord# x) 0x10FFFF#
        
    {-# INLINE enumFromTo #-}
    enumFromTo (C# x) (C# y) = eftChar (ord# x) (ord# y)
    {-# INLINE enumFromThen #-}
    enumFromThen (C# x1) (C# x2) = efdChar (ord# x1) (ord# x2)
    {-# INLINE enumFromThenTo #-}
    enumFromThenTo (C# x1) (C# x2) (C# y) = efdtChar (ord# x1) (ord# x2) (ord# y)
{-# RULES
"eftChar"       [~1] forall x y.        eftChar x y       = build (\c n -> eftCharFB c n x y)
"efdChar"       [~1] forall x1 x2.      efdChar x1 x2     = build (\ c n -> efdCharFB c n x1 x2)
"efdtChar"      [~1] forall x1 x2 l.    efdtChar x1 x2 l  = build (\ c n -> efdtCharFB c n x1 x2 l)
"eftCharList"   [1]  eftCharFB  (:) [] = eftChar
"efdCharList"   [1]  efdCharFB  (:) [] = efdChar
"efdtCharList"  [1]  efdtCharFB (:) [] = efdtChar
 #-}
{-# INLINE [0] eftCharFB #-} 
eftCharFB :: (Char -> a -> a) -> a -> Int# -> Int# -> a
eftCharFB c n x0 y = go x0
                 where
                    go x | isTrue# (x ># y) = n
                         | otherwise        = C# (chr# x) `c` go (x +# 1#)
{-# NOINLINE [1] eftChar #-}
eftChar :: Int# -> Int# -> String
eftChar x y | isTrue# (x ># y ) = []
            | otherwise         = C# (chr# x) : eftChar (x +# 1#) y
{-# INLINE [0] efdCharFB #-} 
efdCharFB :: (Char -> a -> a) -> a -> Int# -> Int# -> a
efdCharFB c n x1 x2
  | isTrue# (delta >=# 0#) = go_up_char_fb c n x1 delta 0x10FFFF#
  | otherwise              = go_dn_char_fb c n x1 delta 0#
  where
    !delta = x2 -# x1
{-# NOINLINE [1] efdChar #-}
efdChar :: Int# -> Int# -> String
efdChar x1 x2
  | isTrue# (delta >=# 0#) = go_up_char_list x1 delta 0x10FFFF#
  | otherwise              = go_dn_char_list x1 delta 0#
  where
    !delta = x2 -# x1
{-# INLINE [0] efdtCharFB #-} 
efdtCharFB :: (Char -> a -> a) -> a -> Int# -> Int# -> Int# -> a
efdtCharFB c n x1 x2 lim
  | isTrue# (delta >=# 0#) = go_up_char_fb c n x1 delta lim
  | otherwise              = go_dn_char_fb c n x1 delta lim
  where
    !delta = x2 -# x1
{-# NOINLINE [1] efdtChar #-}
efdtChar :: Int# -> Int# -> Int# -> String
efdtChar x1 x2 lim
  | isTrue# (delta >=# 0#) = go_up_char_list x1 delta lim
  | otherwise              = go_dn_char_list x1 delta lim
  where
    !delta = x2 -# x1
go_up_char_fb :: (Char -> a -> a) -> a -> Int# -> Int# -> Int# -> a
go_up_char_fb c n x0 delta lim
  = go_up x0
  where
    go_up x | isTrue# (x ># lim) = n
            | otherwise          = C# (chr# x) `c` go_up (x +# delta)
go_dn_char_fb :: (Char -> a -> a) -> a -> Int# -> Int# -> Int# -> a
go_dn_char_fb c n x0 delta lim
  = go_dn x0
  where
    go_dn x | isTrue# (x <# lim) = n
            | otherwise          = C# (chr# x) `c` go_dn (x +# delta)
go_up_char_list :: Int# -> Int# -> Int# -> String
go_up_char_list x0 delta lim
  = go_up x0
  where
    go_up x | isTrue# (x ># lim) = []
            | otherwise          = C# (chr# x) : go_up (x +# delta)
go_dn_char_list :: Int# -> Int# -> Int# -> String
go_dn_char_list x0 delta lim
  = go_dn x0
  where
    go_dn x | isTrue# (x <# lim) = []
            | otherwise          = C# (chr# x) : go_dn (x +# delta)
instance  Bounded Int where
    minBound =  minInt
    maxBound =  maxInt
instance  Enum Int  where
    succ x
       | x == maxBound  = errorWithoutStackTrace "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"
       | otherwise      = x + 1
    pred x
       | x == minBound  = errorWithoutStackTrace "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"
       | otherwise      = x - 1
    toEnum   x = x
    fromEnum x = x
    {-# INLINE enumFrom #-}
    enumFrom (I# x) = eftInt x maxInt#
        where !(I# maxInt#) = maxInt
        
    {-# INLINE enumFromTo #-}
    enumFromTo (I# x) (I# y) = eftInt x y
    {-# INLINE enumFromThen #-}
    enumFromThen (I# x1) (I# x2) = efdInt x1 x2
    {-# INLINE enumFromThenTo #-}
    enumFromThenTo (I# x1) (I# x2) (I# y) = efdtInt x1 x2 y
{-# RULES
"eftInt"        [~1] forall x y. eftInt x y = build (\ c n -> eftIntFB c n x y)
"eftIntList"    [1] eftIntFB  (:) [] = eftInt
 #-}
{-# NOINLINE [1] eftInt #-}
eftInt :: Int# -> Int# -> [Int]
eftInt x0 y | isTrue# (x0 ># y) = []
            | otherwise         = go x0
               where
                 go x = I# x : if isTrue# (x ==# y)
                               then []
                               else go (x +# 1#)
{-# INLINE [0] eftIntFB #-} 
eftIntFB :: (Int -> r -> r) -> r -> Int# -> Int# -> r
eftIntFB c n x0 y | isTrue# (x0 ># y) = n
                  | otherwise         = go x0
                 where
                   go x = I# x `c` if isTrue# (x ==# y)
                                   then n
                                   else go (x +# 1#)
                        
        
        
        
{-# 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]
efdInt x1 x2
 | isTrue# (x2 >=# x1) = case maxInt of I# y -> efdtIntUp x1 x2 y
 | otherwise           = case minInt of I# y -> efdtIntDn x1 x2 y
{-# NOINLINE [1] efdtInt #-}
efdtInt :: Int# -> Int# -> Int# -> [Int]
efdtInt x1 x2 y
 | isTrue# (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
 | isTrue# (x2 >=# x1) = efdtIntUpFB c n x1 x2 y
 | otherwise           = efdtIntDnFB c n x1 x2 y
efdtIntUp :: Int# -> Int# -> Int# -> [Int]
efdtIntUp x1 x2 y    
 | isTrue# (y <# x2) = if isTrue# (y <# x1) then [] else [I# x1]
 | otherwise = 
               let !delta = x2 -# x1 
                   !y' = y -# delta  
                   
                   
                   
                   go_up x | isTrue# (x ># y') = [I# x]
                           | otherwise         = I# x : go_up (x +# delta)
               in I# x1 : go_up x2
{-# INLINE [0] efdtIntUpFB #-} 
efdtIntUpFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r
efdtIntUpFB c n x1 x2 y    
 | isTrue# (y <# x2) = if isTrue# (y <# x1) then n else I# x1 `c` n
 | otherwise = 
               let !delta = x2 -# x1 
                   !y' = y -# delta  
                   
                   
                   
                   go_up x | isTrue# (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    
 | isTrue# (y ># x2) = if isTrue# (y ># x1) then [] else [I# x1]
 | otherwise = 
               let !delta = x2 -# x1 
                   !y' = y -# delta  
                   
                   
                   
                   go_dn x | isTrue# (x <# y') = [I# x]
                           | otherwise         = I# x : go_dn (x +# delta)
   in I# x1 : go_dn x2
{-# INLINE [0] efdtIntDnFB #-} 
efdtIntDnFB :: (Int -> r -> r) -> r -> Int# -> Int# -> Int# -> r
efdtIntDnFB c n x1 x2 y    
 | isTrue# (y ># x2) = if isTrue# (y ># x1) then n else I# x1 `c` n
 | otherwise = 
               let !delta = x2 -# x1 
                   !y' = y -# delta  
                   
                   
                   
                   go_dn x | isTrue# (x <# y') = I# x `c` n
                           | otherwise         = I# x `c` go_dn (x +# delta)
               in I# x1 `c` go_dn x2
instance Bounded Word where
    minBound = 0
    
    
#if WORD_SIZE_IN_BITS == 32
    maxBound = W# (int2Word# 0xFFFFFFFF#)
#elif WORD_SIZE_IN_BITS == 64
    maxBound = W# (int2Word# 0xFFFFFFFFFFFFFFFF#)
#else
#error Unhandled value for WORD_SIZE_IN_BITS
#endif
instance Enum Word where
    succ x
        | x /= maxBound = x + 1
        | otherwise     = succError "Word"
    pred x
        | x /= minBound = x - 1
        | otherwise     = predError "Word"
    toEnum i@(I# i#)
        | i >= 0        = W# (int2Word# i#)
        | otherwise     = toEnumError "Word" i (minBound::Word, maxBound::Word)
    fromEnum x@(W# x#)
        | x <= maxIntWord = I# (word2Int# x#)
        | otherwise       = fromEnumError "Word" x
    {-# INLINE enumFrom #-}
    enumFrom (W# x#)      = eftWord x# maxWord#
        where !(W# maxWord#) = maxBound
        
    {-# INLINE enumFromTo #-}
    enumFromTo (W# x) (W# y) = eftWord x y
    {-# INLINE enumFromThen #-}
    enumFromThen (W# x1) (W# x2) = efdWord x1 x2
    {-# INLINE enumFromThenTo #-}
    enumFromThenTo (W# x1) (W# x2) (W# y) = efdtWord x1 x2 y
maxIntWord :: Word
maxIntWord = W# (case maxInt of I# i -> int2Word# i)
{-# RULES
"eftWord"        [~1] forall x y. eftWord x y = build (\ c n -> eftWordFB c n x y)
"eftWordList"    [1] eftWordFB  (:) [] = eftWord
 #-}
{-# NOINLINE [1] eftWord #-}
eftWord :: Word# -> Word# -> [Word]
eftWord x0 y | isTrue# (x0 `gtWord#` y) = []
             | otherwise                = go x0
                where
                  go x = W# x : if isTrue# (x `eqWord#` y)
                                then []
                                else go (x `plusWord#` 1##)
{-# INLINE [0] eftWordFB #-} 
eftWordFB :: (Word -> r -> r) -> r -> Word# -> Word# -> r
eftWordFB c n x0 y | isTrue# (x0 `gtWord#` y) = n
                   | otherwise                = go x0
                  where
                    go x = W# x `c` if isTrue# (x `eqWord#` y)
                                    then n
                                    else go (x `plusWord#` 1##)
                        
        
        
        
{-# RULES
"efdtWord"       [~1] forall x1 x2 y.
                     efdtWord x1 x2 y = build (\ c n -> efdtWordFB c n x1 x2 y)
"efdtWordUpList" [1]  efdtWordFB (:) [] = efdtWord
 #-}
efdWord :: Word# -> Word# -> [Word]
efdWord x1 x2
 | isTrue# (x2 `geWord#` x1) = case maxBound of W# y -> efdtWordUp x1 x2 y
 | otherwise                 = case minBound of W# y -> efdtWordDn x1 x2 y
{-# NOINLINE [1] efdtWord #-}
efdtWord :: Word# -> Word# -> Word# -> [Word]
efdtWord x1 x2 y
 | isTrue# (x2 `geWord#` x1) = efdtWordUp x1 x2 y
 | otherwise                 = efdtWordDn x1 x2 y
{-# INLINE [0] efdtWordFB #-} 
efdtWordFB :: (Word -> r -> r) -> r -> Word# -> Word# -> Word# -> r
efdtWordFB c n x1 x2 y
 | isTrue# (x2 `geWord#` x1) = efdtWordUpFB c n x1 x2 y
 | otherwise                 = efdtWordDnFB c n x1 x2 y
efdtWordUp :: Word# -> Word# -> Word# -> [Word]
efdtWordUp x1 x2 y    
 | isTrue# (y `ltWord#` x2) = if isTrue# (y `ltWord#` x1) then [] else [W# x1]
 | otherwise = 
               let !delta = x2 `minusWord#` x1 
                   !y' = y `minusWord#` delta  
                   
                   
                   
                   go_up x | isTrue# (x `gtWord#` y') = [W# x]
                           | otherwise                = W# x : go_up (x `plusWord#` delta)
               in W# x1 : go_up x2
{-# INLINE [0] efdtWordUpFB #-} 
efdtWordUpFB :: (Word -> r -> r) -> r -> Word# -> Word# -> Word# -> r
efdtWordUpFB c n x1 x2 y    
 | isTrue# (y `ltWord#` x2) = if isTrue# (y `ltWord#` x1) then n else W# x1 `c` n
 | otherwise = 
               let !delta = x2 `minusWord#` x1 
                   !y' = y `minusWord#` delta  
                   
                   
                   
                   go_up x | isTrue# (x `gtWord#` y') = W# x `c` n
                           | otherwise                = W# x `c` go_up (x `plusWord#` delta)
               in W# x1 `c` go_up x2
efdtWordDn :: Word# -> Word# -> Word# -> [Word]
efdtWordDn x1 x2 y    
 | isTrue# (y `gtWord#` x2) = if isTrue# (y `gtWord#` x1) then [] else [W# x1]
 | otherwise = 
               let !delta = x2 `minusWord#` x1 
                   !y' = y `minusWord#` delta  
                   
                   
                   
                   go_dn x | isTrue# (x `ltWord#` y') = [W# x]
                           | otherwise                = W# x : go_dn (x `plusWord#` delta)
   in W# x1 : go_dn x2
{-# INLINE [0] efdtWordDnFB #-} 
efdtWordDnFB :: (Word -> r -> r) -> r -> Word# -> Word# -> Word# -> r
efdtWordDnFB c n x1 x2 y    
 | isTrue# (y `gtWord#` x2) = if isTrue# (y `gtWord#` x1) then n else W# x1 `c` n
 | otherwise = 
               let !delta = x2 `minusWord#` x1 
                   !y' = y `minusWord#` delta  
                   
                   
                   
                   go_dn x | isTrue# (x `ltWord#` y') = W# x `c` n
                           | otherwise                = W# x `c` go_dn (x `plusWord#` delta)
               in W# x1 `c` go_dn x2
instance  Enum Integer  where
    succ x               = x + 1
    pred x               = x - 1
    toEnum (I# n)        = smallInteger n
    fromEnum n           = I# (integerToInt n)
    {-# INLINE enumFrom #-}
    {-# INLINE enumFromThen #-}
    {-# INLINE enumFromTo #-}
    {-# INLINE enumFromThenTo #-}
    enumFrom x             = enumDeltaInteger   x 1
    enumFromThen x y       = enumDeltaInteger   x (y-x)
    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 d l. enumDeltaToInteger x d l     = build (\c n -> enumDeltaToIntegerFB  c n x d l)
"efdtInteger1"          [~1] forall x l.   enumDeltaToInteger x 1 l     = build (\c n -> enumDeltaToInteger1FB c n x l)
"enumDeltaToInteger1FB" [1] forall c n x.  enumDeltaToIntegerFB c n x 1 = enumDeltaToInteger1FB c n x
"enumDeltaInteger"      [1] enumDeltaIntegerFB    (:)     = enumDeltaInteger
"enumDeltaToInteger"    [1] enumDeltaToIntegerFB  (:) []  = enumDeltaToInteger
"enumDeltaToInteger1"   [1] enumDeltaToInteger1FB (:) []  = enumDeltaToInteger1
 #-}
{-# INLINE [0] enumDeltaIntegerFB #-}
enumDeltaIntegerFB :: (Integer -> b -> b) -> Integer -> Integer -> b
enumDeltaIntegerFB c x0 d = go x0
  where go x = x `seq` (x `c` go (x+d))
{-# NOINLINE [1] enumDeltaInteger #-}
enumDeltaInteger :: Integer -> Integer -> [Integer]
enumDeltaInteger x d = x `seq` (x : enumDeltaInteger (x+d) d)
{-# INLINE [0] enumDeltaToIntegerFB #-}
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
{-# INLINE [0] enumDeltaToInteger1FB #-}
enumDeltaToInteger1FB :: (Integer -> a -> a) -> a
                      -> Integer -> Integer -> a
enumDeltaToInteger1FB c n x0 lim = go (x0 :: Integer)
                      where
                        go x | x > lim   = n
                             | otherwise = x `c` go (x+1)
{-# NOINLINE [1] enumDeltaToInteger #-}
enumDeltaToInteger :: Integer -> Integer -> Integer -> [Integer]
enumDeltaToInteger x delta lim
  | delta >= 0 = up_list x delta lim
  | otherwise  = dn_list x delta lim
{-# NOINLINE [1] enumDeltaToInteger1 #-}
enumDeltaToInteger1 :: Integer -> Integer -> [Integer]
enumDeltaToInteger1 x0 lim = go (x0 :: Integer)
                      where
                        go x | x > lim   = []
                             | otherwise = x : go (x+1)
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)
#if defined(MIN_VERSION_integer_gmp)
instance Enum Natural where
    succ n = n `plusNatural`  wordToNaturalBase 1##
    pred n = n `minusNatural` wordToNaturalBase 1##
    toEnum = intToNatural
    fromEnum (NatS# w)
      | i >= 0    = i
      | otherwise = errorWithoutStackTrace "fromEnum: out of Int range"
      where
        i = I# (word2Int# w)
    fromEnum n = fromEnum (naturalToInteger n)
    enumFrom x        = enumDeltaNatural      x (wordToNaturalBase 1##)
    enumFromThen x y
      | x <= y        = enumDeltaNatural      x (y-x)
      | otherwise     = enumNegDeltaToNatural x (x-y) (wordToNaturalBase 0##)
    enumFromTo x lim  = enumDeltaToNatural    x (wordToNaturalBase 1##) lim
    enumFromThenTo x y lim
      | x <= y        = enumDeltaToNatural    x (y-x) lim
      | otherwise     = enumNegDeltaToNatural x (x-y) lim
enumDeltaNatural :: Natural -> Natural -> [Natural]
enumDeltaNatural !x d = x : enumDeltaNatural (x+d) d
enumDeltaToNatural :: Natural -> Natural -> Natural -> [Natural]
enumDeltaToNatural x0 delta lim = go x0
  where
    go x | x > lim   = []
         | otherwise = x : go (x+delta)
enumNegDeltaToNatural :: Natural -> Natural -> Natural -> [Natural]
enumNegDeltaToNatural x0 ndelta lim = go x0
  where
    go x | x < lim     = []
         | x >= ndelta = x : go (x-ndelta)
         | otherwise   = [x]
#else
instance Enum Natural where
  pred (Natural 0) = errorWithoutStackTrace "Natural.pred: 0"
  pred (Natural n) = Natural (pred n)
  {-# INLINE pred #-}
  succ (Natural n) = Natural (succ n)
  {-# INLINE succ #-}
  fromEnum (Natural n) = fromEnum n
  {-# INLINE fromEnum #-}
  toEnum n | n < 0     = errorWithoutStackTrace "Natural.toEnum: negative"
           | otherwise = Natural (toEnum n)
  {-# INLINE toEnum #-}
  enumFrom     = coerce (enumFrom     :: Integer -> [Integer])
  enumFromThen x y
    | x <= y    = coerce (enumFromThen :: Integer -> Integer -> [Integer]) x y
    | otherwise = enumFromThenTo x y (wordToNaturalBase 0##)
  enumFromTo   = coerce (enumFromTo   :: Integer -> Integer -> [Integer])
  enumFromThenTo
    = coerce (enumFromThenTo :: Integer -> Integer -> Integer -> [Integer])
#endif
deriving instance Bounded VecCount
deriving instance Enum VecCount
deriving instance Bounded VecElem
deriving instance Enum VecElem