content: {-# LANGUAGE ConstraintKinds   #-}
  {-# LANGUAGE FlexibleContexts  #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE MonoLocalBinds    #-}
  {-# OPTIONS_GHC -fno-warn-orphans #-}
  -- |
  -- Module      : Data.Array.Accelerate.Classes.Enum
  -- Copyright   : [2016..2020] The Accelerate Team
  -- License     : BSD3
  --
  -- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
  -- Stability   : experimental
  -- Portability : non-portable (GHC extensions)
  --
  
  module Data.Array.Accelerate.Classes.Enum (
  
    Enum,
    succ, pred,
  
  ) where
  
  import Data.Array.Accelerate.Classes.Num
  import Data.Array.Accelerate.Smart
  import Data.Array.Accelerate.Type
  import Text.Printf
  
  import Prelude                                                      ( ($), String, error, unlines, succ, pred )
  import qualified Prelude                                            as P
  
  
  -- | Operations over sequentially ordered types
  --
  type Enum a = P.Enum (Exp a)
  
  
  instance P.Enum (Exp Int) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Int8) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Int16) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Int32) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Int64) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Word) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Word8) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Word16) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Word32) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Word64) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CInt) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CUInt) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CLong) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CULong) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CLLong) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CULLong) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CShort) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CUShort) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Half) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Float) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp Double) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CFloat) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  instance P.Enum (Exp CDouble) where
    succ      = defaultSucc
    pred      = defaultPred
    toEnum    = defaultToEnum
    fromEnum  = defaultFromEnum
  
  defaultSucc :: Num a => Exp a -> Exp a
  defaultSucc x = x + 1
  
  defaultPred :: Num a => Exp a -> Exp a
  defaultPred x = x - 1
  
  defaultToEnum :: Int -> a
  defaultToEnum = preludeError "toEnum"
  
  defaultFromEnum :: a -> Int
  defaultFromEnum = preludeError "fromEnum"
  
  preludeError :: String -> a
  preludeError x
    = error
    $ unlines [ printf "Prelude.%s is not supported for Accelerate types" x
              , ""
              , "These Prelude.Enum instances are present only to fulfil superclass"
              , "constraints for subsequent classes in the standard Haskell numeric hierarchy."
              ]
  
  