module Data.Vector.Fixed.Primitive (
    
    Vec
  , Vec1
  , Vec2
  , Vec3
  , Vec4
  , Vec5
    
  , MVec
    
  , Prim
  ) where
import Control.Monad
import Control.DeepSeq (NFData(..))
import Data.Data
import Data.Monoid              (Monoid(..))
import Data.Primitive.ByteArray
import Data.Primitive
import qualified Foreign.Storable as Foreign (Storable(..))
import Prelude (Show(..),Eq(..),Ord(..),Num(..))
import Prelude ((++),($),($!),undefined,seq)
import Data.Vector.Fixed hiding (index)
import Data.Vector.Fixed.Mutable
import qualified Data.Vector.Fixed.Cont as C
newtype Vec n a = Vec ByteArray
newtype MVec n s a = MVec (MutableByteArray s)
deriving instance Typeable Vec
deriving instance Typeable MVec
type Vec1 = Vec (S Z)
type Vec2 = Vec (S (S Z))
type Vec3 = Vec (S (S (S Z)))
type Vec4 = Vec (S (S (S (S Z))))
type Vec5 = Vec (S (S (S (S (S Z)))))
instance (Arity n, Prim a, Show a) => Show (Vec n a) where
  show v = "fromList " ++ show (toList v)
instance (Arity n, Prim a, NFData a) => NFData (Vec n a) where
  rnf = foldl (\r a -> r `seq` rnf a) ()
  
type instance Mutable (Vec n) = MVec n
instance (Arity n, Prim a) => MVector (MVec n) a where
  overlaps (MVec v) (MVec u) = sameMutableByteArray v u
  
  new = do
    v <- newByteArray $! arity (undefined :: n) * sizeOf (undefined :: a)
    return $ MVec v
  
  copy                       = move
  
  move (MVec dst) (MVec src) = copyMutableByteArray dst 0 src 0 (arity (undefined :: n))
  
  unsafeRead  (MVec v) i   = readByteArray  v i
  
  unsafeWrite (MVec v) i x = writeByteArray v i x
  
instance (Arity n, Prim a) => IVector (Vec n) a where
  unsafeFreeze (MVec v)   = do { a <- unsafeFreezeByteArray v; return $! Vec  a }
  unsafeThaw   (Vec  v)   = do { a <- unsafeThawByteArray   v; return $! MVec a }
  unsafeIndex  (Vec  v) i = indexByteArray v i
  
  
  
type instance Dim  (Vec  n) = n
type instance DimM (MVec n) = n
instance (Arity n, Prim a) => Vector (Vec n) a where
  construct  = constructVec
  inspect    = inspectVec
  basicIndex = index
  
  
  
instance (Arity n, Prim a) => VectorN Vec n a
instance (Arity n, Prim a, Eq a) => Eq (Vec n a) where
  (==) = eq
  
instance (Arity n, Prim a, Ord a) => Ord (Vec n a) where
  compare = ord
  
instance (Arity n, Prim a, Monoid a) => Monoid (Vec n a) where
  mempty  = replicate mempty
  mappend = zipWith mappend
  
  
instance (Typeable n, Arity n, Prim a, Data a) => Data (Vec n a) where
  gfoldl       = C.gfoldl
  gunfold      = C.gunfold
  toConstr   _ = con_Vec
  dataTypeOf _ = ty_Vec
ty_Vec :: DataType
ty_Vec  = mkDataType "Data.Vector.Fixed.Primitive.Vec" [con_Vec]
con_Vec :: Constr
con_Vec = mkConstr ty_Vec "Vec" [] Prefix
instance (Foreign.Storable a, Prim a, Arity n) => Foreign.Storable (Vec n a) where
  alignment = defaultAlignemnt
  sizeOf    = defaultSizeOf
  peek      = defaultPeek
  poke      = defaultPoke