module Data.Array.Repa.Repr.HintSmall
        (S, Array (..), hintSmall)
import Data.Array.Repa.Eval.Load
import Data.Array.Repa.Base
import Data.Array.Repa.Shape

-- | Hints that evaluating this array is only a small amount of work.
--   It will be evaluated sequentially in the main thread, instead of
--   in parallel on the gang. This avoids the associated scheduling overhead.
data S r1

instance Source r1 a => Source (S r1) a where
 data Array (S r1) sh a
        = ASmall !(Array r1 sh a)

 extent (ASmall arr) 
        = extent arr
 {-# INLINE extent #-}

 index  (ASmall arr) ix
        = index arr ix
 {-# INLINE index #-}

 unsafeIndex (ASmall arr) ix
        = unsafeIndex arr ix
 {-# INLINE unsafeIndex #-}

 linearIndex (ASmall arr) ix
        = linearIndex arr ix
 {-# INLINE linearIndex #-}

 unsafeLinearIndex (ASmall arr) ix
        = unsafeLinearIndex arr ix
 {-# INLINE unsafeLinearIndex #-}

 deepSeqArray (ASmall arr) x
        = deepSeqArray arr x
 {-# INLINE deepSeqArray #-}

-- | Wrap an array with a smallness hint.
hintSmall :: Array r1 sh e -> Array (S r1) sh e
hintSmall = ASmall

deriving instance Show (Array r1 sh e) 
        => Show (Array (S r1) sh e)

deriving instance Read (Array r1 sh e) 
        => Read (Array (S r1) sh e)

-- Load ----------------------------------------------------------------------
instance ( Shape sh, Load r1 sh e) 
        => Load (S r1) sh e where
 loadP (ASmall arr) marr
  = loadS arr marr
 {-# INLINE loadP #-}

 loadS (ASmall arr) marr
  = loadS arr marr
 {-# INLINE loadS #-}

-- LoadRange ------------------------------------------------------------------
instance ( Shape sh, LoadRange r1 sh e)
        => LoadRange (S r1) sh e where
 loadRangeP (ASmall arr) marr ix1 ix2
  = loadRangeS arr marr ix1 ix2
 {-# INLINE loadRangeP #-}

 loadRangeS (ASmall arr) marr ix1 ix2
  = loadRangeS arr marr ix1 ix2
 {-# INLINE loadRangeS #-}