{-# LANGUAGE DataKinds, GADTs, TypeFamilies #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE NoImplicitPrelude #-} module Numerical.Array.Shape( -- * Shape Shape(..) -- * Shape Utilities ,foldl ,foldr ,foldl' ,foldl1 ,foldr1 ,map ,map2 ,reverseShape ,Nat(..) ,shapeSize ,SNat(..) ,weaklyDominates ,strictlyDominates ,shapeToList ,Index ,backwards -- * Unboxed Vector Morphism ,UnBoxedShapeMorphism(..) ,unShapeVector ,reShapeVector ,T.traverse --,T.Traversable(..) ) where --import Data.Data import Data.Typeable import Data.Data import qualified Data.Functor as Fun import qualified Data.Foldable as F import qualified Control.Applicative as A import Control.Monad (liftM) import Control.Monad.ST (runST) import qualified Data.Traversable as T --import Control.NumericalMonad.State.Strict import Control.NumericalApplicative.Backwards import Numerical.Nat import qualified Data.Monoid as Monoid import Prelude hiding (map,foldl,foldr,init,scanl,scanr,scanl1,scanr1,foldl1,foldr1) import qualified Foreign.Storable as Store import qualified Foreign.Ptr as Ptr import qualified Data.Vector.Unboxed as UV import qualified Data.Vector.Unboxed.Mutable as UVM import qualified Data.Vector.Generic as GV import qualified Data.Vector.Generic.Mutable as GMV {- Shape may get renamed to Index in the near future! PSA: do not take the INLINE pragmas as a style suggestion. The only reason for the INLINEs, SPECIALIZE and the nonrecursive type class definitions of operations in this module are because shape will be used in the inner loops of array indexing heavy computations, -} {- the concern basically boils down to "will it specialize / inline well" -} {- should explore using the Reverse and Backwards transformers in the Transformers package, but not right now note also the *Tup operations could be done with a more general State monad for the tupled accumulation parameter. If theres no perf regression, should move to using that instead. -} infixr 3 :* type Index rank = Shape rank Int data Shape (rank :: Nat) a where Nil :: Shape 'Z a (:*) :: !(a) -> !(Shape r a ) -> Shape ('S r) a deriving instance Typeable Shape nilShapeConstrRep :: Constr nilShapeConstrRep = mkConstr shapeDataTypeRep "Nil" [] Prefix consShapeConstrRep :: Constr consShapeConstrRep = mkConstr shapeDataTypeRep ":*" [] Infix shapeDataTypeRep :: DataType shapeDataTypeRep = mkDataType "Numerical.Array.Shape.Shape" [nilShapeConstrRep,consShapeConstrRep] --deriving instance (Data a, Typeable n ) => Data (Shape n a) -- gfoldl f z xs = gfoldl f z (shapeToList xs) -- --gfoldl _ z Nil = z Nil -- --gfoldl f z (x :* xs) = z (:*) `f` x `f` xs -- I would like to have (Data (Shape n a)) but that seems tricky instance (Data a,Typeable 'Z) => Data (Shape 'Z a) where gfoldl _ z Nil = z Nil gunfold _ z _ = z Nil -- not sure if _ z _ is the right one, but typechecks dataTypeOf _ = shapeDataTypeRep toConstr _ = nilShapeConstrRep instance (Data a, Data (Shape n a), Typeable ('S n))=> Data (Shape ('S n) a ) where gfoldl k z (a :* b) = (z (:*) `k` a) `k` b gunfold k z _ = k (k (z (:*))) dataTypeOf _ = shapeDataTypeRep toConstr _ = consShapeConstrRep -- figure this out! --look at http://hackage.haskell.org/package/HList-0.3.4.1/docs/src/Data-HList-Data.html --and https://hackage.haskell.org/package/base-4.3.1.0/docs/Data-Data.html#nilConstr -- for examples --instance Data a => Data (Shape Z a) where --gfoldl --deriving instance Data (Shape Z a) --deriving instance (Data a,Data (Shape n a))=> (Data (Shape (S n) a)) {- too much work to do data instance with pre 7.8 typeable -} instance Eq (Shape 'Z a) where (==) _ _ = True {-#INLINE (==)#-} instance (Eq a,Eq (Shape s a))=> Eq (Shape ('S s) a ) where (==) (a:* as) (b:* bs) = (a == b) && (as == bs ) {-#INLINE (==)#-} instance Show (Shape 'Z a) where show _ = "Nil" instance (Show a, Show (Shape s a))=> Show (Shape ('S s) a) where show (a:* as) = show a ++ " :* " ++ show as -- at some point also try data model that -- has layout be dynamically reified, but for now -- keep it phantom typed for sanity / forcing static dispatch. -- NB: may need to make it more general at some future point --data Strided r a lay = Strided { getStrides :: Shape r a } -- may want to typeclassify this? shapeToList :: Shape n a -> [a] shapeToList Nil = [] shapeToList (a:* as) = a : (shapeToList as ) {- the Traversable instance for shape needs both Z and S Z base cases to interact nicely with the instances defined for foldable -} instance T.Traversable (Shape 'Z) where traverse = \ _ Nil -> A.pure Nil {-# INLINE traverse #-} sequenceA = T.traverse id mapM f = A.unwrapMonad . T.traverse (A.WrapMonad . f) sequence = T.mapM id {-#INLINE sequenceA #-} {-#INLINE mapM #-} {-#INLINE sequence #-} instance T.Traversable (Shape ('S 'Z)) where traverse = \ f (a:* as) -> (:*) A.<$> f a A.<*> T.traverse f as {-# INLINE traverse #-} sequenceA = T.traverse id mapM f = A.unwrapMonad . T.traverse (A.WrapMonad . f) sequence = T.mapM id {-#INLINE sequenceA #-} {-#INLINE mapM #-} {-#INLINE sequence #-} instance T.Traversable (Shape ('S n)) => T.Traversable (Shape ('S ('S n))) where traverse = \ f (a:* as) -> (:*) A.<$> f a A.<*> T.traverse f as {-#INLINE traverse #-} sequenceA = T.traverse id mapM f = A.unwrapMonad . T.traverse (A.WrapMonad . f) sequence = T.mapM id {-#INLINE sequenceA #-} {-#INLINE mapM #-} {-#INLINE sequence #-} backwards :: (T.Traversable t, A.Applicative f) => ((a -> Backwards f b) -> t a -> Backwards f (t b)) -> ((a -> f b) -> t a -> f (t b)) backwards= \ traver f container -> forwards $ traver (\x -> Backwards $ f x) container {-#INLINE backwards #-} --instance Fun.Functor (Shape r) where -- fmap = mapShape -- {-#INLINE fmap #-} instance Fun.Functor (Shape 'Z) where fmap = \ _ Nil -> Nil {-# INLINE fmap #-} instance (Fun.Functor (Shape r)) => Fun.Functor (Shape ('S r)) where fmap = \ f (a :* rest) -> f a :* ( Fun.fmap f rest ) {-# INLINE fmap #-} instance A.Applicative (Shape 'Z) where pure = \ _ -> Nil {-# INLINE pure #-} (<*>) = \ _ _ -> Nil {-# INLINE (<*>) #-} instance A.Applicative (Shape r)=> A.Applicative (Shape ('S r)) where pure = \ a -> a :* (A.pure a) {-# INLINE pure #-} (<*>) = \ (f:* fs) (a :* as) -> f a :* ((A.<*>)) fs as {-# INLINE (<*>) #-} {- only doing Foldable for ranks >= 1 does mean that we dont get the cute "rank zero arrays are references" property. But want foldr1 and foldl1 to always succeed lets try having rank 0 anyways, i'll be happier if i can support it -} instance F.Foldable (Shape 'Z) where foldl' = \ _ !init _-> init foldr' = \ _ !init _ -> init foldl = \ _ init _-> init foldr = \ _ init _-> init foldMap = \ _f _col -> mempty {-# INLINE foldMap #-} {-# INLINE foldl #-} {-# INLINE foldr #-} {-# INLINE foldl' #-} {-# INLINE foldr' #-} foldr1 = \ _ _ -> error "you can't call foldr1 on a rank Z(ero) Shape" foldl1 = \_ _ -> error "you can't call foldl1 on a rank Z(ero) Shape" instance F.Foldable (Shape ('S 'Z)) where foldl' = \ f !init (a:*Nil)-> f init a foldr' = \ f !init (a:*Nil)-> f a init foldl = \ f init (a:*Nil)-> f init a foldr = \ f init (a:*Nil)-> f a init foldMap = \ f (a :* Nil ) -> f a {-# INLINE foldMap #-} {-# INLINE foldl #-} {-# INLINE foldr #-} {-# INLINE foldl' #-} {-# INLINE foldr' #-} foldr1 = \ _ (a:* Nil) -> a foldl1 = \ _ (a:* Nil) -> a {-# INLINE foldl1 #-} {-# INLINE foldr1 #-} instance ( F.Foldable (Shape ('S r)) )=> F.Foldable (Shape ('S ('S r))) where foldl' = \ f init (a:* as) -> F.foldl' f (f init a) as foldr' = \f !init (a :* as ) -> f a $! F.foldr' f init as foldl = \ f init (a:* as) -> F.foldl' f (f init a) as foldr = \ f init (a:* as) -> f a $! F.foldr f init as foldl1 = \ f (a:* as) -> F.foldl' f a as foldr1 = \ f (a :* as) -> F.foldr' f a as foldMap = \ f (a :* as ) -> f a Monoid.<> F.foldMap f as {-# INLINE foldMap #-} {-# INLINE foldl #-} {-# INLINE foldr #-} {-# INLINE foldl' #-} {-# INLINE foldr' #-} {-# INLINE foldl1 #-} {-# INLINE foldr1 #-} instance (Semigroup a, A.Applicative (Shape n))=> (Semigroup (Shape n a)) where (<>) = \ a b -> A.pure (<>) A.<*> a A.<*> b instance (Monoid.Monoid a, A.Applicative (Shape n))=> Monoid.Monoid (Shape n a) where mempty = A.pure Monoid.mempty mappend = \ a b -> A.pure Monoid.mappend A.<*> a A.<*> b {- when you lift a toral order onto vectors, you get interesting partial order -} -- | 'weaklyDominates' is the '<=' operator lifted onto a sized vector to -- induce a partial order relation weaklyDominates :: (Ord a, A.Applicative (Shape n), F.Foldable (Shape n) )=> Shape n a -> Shape n a -> Bool weaklyDominates = \major minor -> foldl (&&) True $! map2 (>=) major minor {-# INLINE weaklyDominates #-} -- | 'strictlyDominates' is the '<' operator lifted onto a sized vector to -- induce a partial order relation strictlyDominates :: (Ord a, A.Applicative (Shape n), F.Foldable (Shape n) )=> Shape n a -> Shape n a -> Bool strictlyDominates = \major minor -> foldl (&&) True $! map2 (>) major minor {-# INLINE strictlyDominates #-} {-# INLINE reverseShape #-} reverseShape :: Shape n a -> Shape n a reverseShape Nil = Nil reverseShape r@(_ :* Nil)= r reverseShape (a:* b :* Nil) = b:* a :* Nil reverseShape (a:* b :* c:* Nil )= c :* b :* a :* Nil reverseShape (a:* b :* c :* d :* Nil)= d :* c :* b :* a :* Nil reverseShape list = go SZero Nil list where go :: SNat n1 -> Shape n1 a-> Shape n2 a -> Shape (n1 + n2) a go snat acc Nil = gcastWith (plus_id_r snat) acc go snat acc (h :* (t :: Shape n3 a)) = gcastWith (plus_succ_r snat (Proxy :: Proxy n3)) (go (SSucc snat) (h :* acc) t) {- TODO: abstract out all the different unrolled cases i have -} {-# INLINE map2 #-} map2 :: forall a b c r . (A.Applicative (Shape r))=> (a->b ->c) -> (Shape r a) -> (Shape r b) -> (Shape r c ) map2 = \ f shpa shpb -> f A.<$> shpa A.<*> shpb {-# INLINE map #-} map:: forall a b r . (A.Applicative (Shape r))=> (a->b) -> (Shape r a )->( Shape r b) map = \ f shp -> f A.<$> shp {-# INLINE foldr #-} foldr :: forall a b r . (F.Foldable (Shape r))=> (a->b-> b) -> b -> Shape r a -> b foldr = \ f init shp -> F.foldr f init shp {-# INLINE foldl #-} foldl :: forall a b r. (F.Foldable (Shape r))=> (b-> a -> b) -> b -> Shape r a -> b foldl = \ f init shp -> F.foldl f init shp {-# INLINE foldl' #-} foldl' :: forall a b r . (F.Foldable (Shape r))=> (b-> a -> b) -> b -> Shape r a -> b foldl' = \ f init shp -> F.foldl' f init shp {-# INLINE foldr1 #-} foldr1 :: forall b r . (F.Foldable (Shape ('S r)))=> (b->b-> b) -> Shape ('S r) b -> b foldr1 = \ f shp -> F.foldr1 f shp {-# INLINE foldl1 #-} foldl1 :: forall b r. (F.Foldable (Shape ('S r)))=> (b-> b -> b) -> Shape ('S r) b -> b foldl1 = \ f shp -> F.foldl1 f shp instance Store.Storable a =>Store.Storable (Shape ('S 'Z) a) where {-#INLINE sizeOf#-} sizeOf = \ _ -> (Store.sizeOf (undefined :: a)) -- might want to boost the alignment, but ignore for now {-# INLINE alignment #-} alignment = \ _ -> Store.alignment (undefined :: a ) {-# INLINE peek #-} peek = \ptr -> do res <- Store.peek (Ptr.castPtr ptr) ; return (res :* Nil) {-# INLINE poke #-} poke = \ptr (a:*_) -> Store.poke (Ptr.castPtr ptr) a {-# INLINE pokeElemOff #-} {-# INLINE peekElemOff #-} peekElemOff = \ ptr off -> Store.peekByteOff ptr (off * Store.sizeOf (undefined :: a )) pokeElemOff ptr off val = Store.pokeByteOff ptr (off * Store.sizeOf val) val peekByteOff ptr off = Store.peek (ptr `Ptr.plusPtr` off) pokeByteOff ptr off = Store.poke (ptr `Ptr.plusPtr` off) {-# INLINE peekByteOff #-} {-# INLINE pokeByteOff #-} instance (Store.Storable a,Store.Storable (Shape ('S n) a)) =>Store.Storable (Shape ('S ('S n)) a) where {-#INLINE sizeOf#-} sizeOf = \ _ -> Store.sizeOf (undefined :: a) + Store.sizeOf (undefined :: (Shape ('S n) a )) -- might want to boost the alignment, but ignore for now {-# INLINE alignment #-} alignment = \ _ -> Store.alignment (undefined :: a ) {-# INLINE peek #-} peek = \ptr -> do a <- Store.peek (Ptr.castPtr ptr) ; as <- Store.peek (ptr `Ptr.plusPtr` Store.sizeOf (undefined :: a )) return (a:* as) {-# INLINE poke #-} poke = \ptr (a:*as ) -> do Store.poke (Ptr.castPtr ptr) a Store.poke (ptr `Ptr.plusPtr` Store.sizeOf (undefined :: a )) as {-# INLINE pokeElemOff #-} {-# INLINE peekElemOff #-} peekElemOff = \ ptr off -> Store.peekByteOff ptr (off * Store.sizeOf (undefined :: (Shape ('S ('S n)) a) )) pokeElemOff ptr off val = Store.pokeByteOff ptr (off * Store.sizeOf val) val peekByteOff ptr off = Store.peek (ptr `Ptr.plusPtr` off) pokeByteOff ptr off = Store.poke (ptr `Ptr.plusPtr` off) {-# INLINE peekByteOff #-} {-# INLINE pokeByteOff #-} -- this instance is a bit weird and should never be used -- but probably legal instance Store.Storable a =>Store.Storable (Shape 'Z a) where {-#INLINE sizeOf#-} sizeOf = \ _ -> Store.sizeOf (undefined :: a ) -- might want to boost the alignment, but ignore for now {-# INLINE alignment #-} alignment = \ _ -> Store.alignment (undefined :: a ) {-# INLINE peek #-} peek = \ _ -> return Nil {-# INLINE poke #-} poke = \ _ _-> return () {-# INLINE pokeElemOff #-} {-# INLINE peekElemOff #-} peekElemOff = \ _ _ -> return Nil pokeElemOff = \ _ _ _ -> return () peekByteOff = \ _ _ -> return Nil pokeByteOff = \ _ _ _ -> return () {-# INLINE peekByteOff #-} {-# INLINE pokeByteOff #-} {-# INLINE shapeSize #-} shapeSize :: F.Foldable (Shape n)=>Shape n a -> Int shapeSize = \ as -> ( F.foldl (\ct _ -> ct +1) 0 as ) unShapeVector ::(UnBoxedShapeMorphism n a, T.Traversable (Shape n), UV.Unbox a) => UV.Vector (Shape n a) -> (Int, Shape n (UV.Vector a)) unShapeVector vs = runST $ do (l,mvs) <- fmap unShapeMVector $ UV.unsafeThaw vs shpvs <- T.traverse UV.unsafeFreeze mvs return (l,shpvs) reShapeVector::(UnBoxedShapeMorphism n a, T.Traversable (Shape n), UV.Unbox a)=> (Int, Shape n (UV.Vector a)) -> UV.Vector (Shape n a) reShapeVector (l,vs) = runST $ do mShapeV <- T.traverse UV.unsafeThaw vs mvShp <- return $ reShapeMVector (l,mShapeV) UV.unsafeFreeze mvShp {- THis is a convenience type class so i dont have to export the constructors -} class (UV.Unbox (Shape n a)) => UnBoxedShapeMorphism n a where --unShapeVector :: UV.Vector (Shape n a) -> (Int, Shape n (UV.Vector a)) --reShapeVector :: (Int, Shape n (UV.Vector a)) -> UV.Vector (Shape n a) unShapeMVector :: UVM.MVector s (Shape n a) -> (Int, Shape n (UV.MVector s a)) reShapeMVector :: (Int, Shape n (UVM.MVector s a)) -> UVM.MVector s (Shape n a) instance (UV.Unbox a)=> UnBoxedShapeMorphism 'Z a where --unShapeVector (V_ShapeZ l)= (l,Nil) unShapeMVector (MV_ShapeZ l) = (l,Nil ) --reShapeVector (l,Nil) = (V_ShapeZ l) reShapeMVector (l,Nil ) = (MV_ShapeZ l) instance (UV.Unbox a)=> UnBoxedShapeMorphism ('S 'Z) a where --unShapeVector (V_ShapeSZ v)= (UV.length v, v :* Nil) unShapeMVector (MV_ShapeSZ v) = (UVM.length v,v:* Nil ) --reShapeVector (l,v :* Nil) = (V_ShapeSZ v) reShapeMVector (_,v :* _ ) = (MV_ShapeSZ v) --UV.V_2 --UVM.MV_2 instance ((UV.Unbox a),UnBoxedShapeMorphism ('S n) a )=> UnBoxedShapeMorphism ('S ('S n)) a where --unShapeVector (V_ShapeSSN (UV.V_2 l vhead vtail))= (l, vhead :* snd (unShapeVector vtail) ) unShapeMVector (MV_ShapeSSN (UVM.MV_2 l vhead vtail)) = (l,vhead:* snd (unShapeMVector vtail )) --reShapeVector (l,vh :* vt) = (V_ShapeSSN (UV.V_2 l vh (reShapeVector (l,vt) ))) reShapeMVector (l,vh :* vt ) = (MV_ShapeSSN (UVM.MV_2 l vh (reShapeMVector (l,vt) ))) newtype instance UV.MVector s (Shape 'Z a) = MV_ShapeZ Int newtype instance UV.Vector (Shape 'Z a) = V_ShapeZ Int newtype instance UV.MVector s (Shape ('S 'Z) a) = MV_ShapeSZ (UV.MVector s a) newtype instance UV.Vector (Shape ('S 'Z) a) = V_ShapeSZ (UV.Vector a) newtype instance UV.MVector s (Shape ('S ('S n)) a) = MV_ShapeSSN (UV.MVector s (a, Shape ('S n) a) ) newtype instance UV.Vector (Shape ('S ('S n)) a) = V_ShapeSSN (UV.Vector (a, Shape ('S n) a) ) instance UV.Unbox a => UV.Unbox (Shape 'Z a) instance UV.Unbox a => UV.Unbox (Shape ('S 'Z) a) instance (UV.Unbox a,UV.Unbox (Shape ('S n) a) )=> UV.Unbox (Shape ('S ('S n)) a) instance UV.Unbox a => GMV.MVector UV.MVector (Shape 'Z a) where {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicOverlaps #-} {-# INLINE basicUnsafeNew #-} {-# INLINE basicUnsafeRead #-} {-# INLINE basicUnsafeWrite #-} {-# INLINE basicClear #-} {-# INLINE basicSet #-} {-# INLINE basicUnsafeCopy #-} {-# INLINE basicUnsafeGrow #-} {-# INLINE basicInitialize #-} basicInitialize = \ (MV_ShapeZ _n) -> return () basicLength = \ (MV_ShapeZ n) -> n basicUnsafeSlice = \ _ m (MV_ShapeZ _) -> MV_ShapeZ m basicOverlaps = \ _ _ -> False basicUnsafeNew = \ n -> return (MV_ShapeZ n) basicUnsafeRead = \ (MV_ShapeZ _) _ -> return Nil basicUnsafeWrite = \ (MV_ShapeZ _) _ Nil -> return () basicClear = \ _ -> return () basicSet = \ (MV_ShapeZ _) Nil -> return () basicUnsafeCopy = \ (MV_ShapeZ _) (MV_ShapeZ _) -> return () basicUnsafeGrow = \ (MV_ShapeZ n) m -> return $ MV_ShapeZ (n+m) instance UV.Unbox a => GV.Vector UV.Vector (Shape 'Z a) where {-# INLINE basicUnsafeFreeze #-} basicUnsafeFreeze = \ (MV_ShapeZ n) -> return $ V_ShapeZ n {-# INLINE basicUnsafeThaw #-} basicUnsafeThaw = \ (V_ShapeZ n) -> return $ MV_ShapeZ n {-# INLINE basicLength #-} basicLength = \(V_ShapeZ n) -> n {-# INLINE basicUnsafeSlice #-} basicUnsafeSlice = \ _ m (V_ShapeZ _) -> V_ShapeZ m {-# INLINE basicUnsafeIndexM #-} basicUnsafeIndexM = \ (V_ShapeZ _) _ -> return Nil {-# INLINE basicUnsafeCopy #-} basicUnsafeCopy = \ (MV_ShapeZ _) (V_ShapeZ _) -> return () {-# INLINE elemseq #-} elemseq = \ _ -> seq instance (UV.Unbox a) => GMV.MVector UV.MVector (Shape ('S 'Z) a) where {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicOverlaps #-} {-# INLINE basicUnsafeNew #-} {-# INLINE basicUnsafeReplicate #-} {-# INLINE basicUnsafeRead #-} {-# INLINE basicUnsafeWrite #-} {-# INLINE basicClear #-} {-# INLINE basicSet #-} {-# INLINE basicUnsafeCopy #-} {-# INLINE basicUnsafeGrow #-} {-# INLINE basicInitialize #-} basicInitialize = \ (MV_ShapeSZ v) -> GMV.basicInitialize v basicLength = \(MV_ShapeSZ v)-> GMV.basicLength v basicUnsafeSlice = \ i n (MV_ShapeSZ v) -> MV_ShapeSZ $ GMV.basicUnsafeSlice i n v basicOverlaps = \ (MV_ShapeSZ v1) (MV_ShapeSZ v2) -> GMV.basicOverlaps v1 v2 basicUnsafeNew = \ n -> MV_ShapeSZ `liftM` GMV.basicUnsafeNew n basicUnsafeReplicate = \ n (a:*_) -> MV_ShapeSZ `liftM` GMV.basicUnsafeReplicate n a basicUnsafeRead = \ (MV_ShapeSZ v) i -> ( :* Nil ) `liftM` GMV.basicUnsafeRead v i basicUnsafeWrite = \ (MV_ShapeSZ v) i (a:* _) -> GMV.basicUnsafeWrite v i a basicClear = \ (MV_ShapeSZ v) -> GMV.basicClear v basicSet = \ (MV_ShapeSZ v) (a:*_) -> GMV.basicSet v a basicUnsafeCopy = \ (MV_ShapeSZ v1) (MV_ShapeSZ v2) -> GMV.basicUnsafeCopy v1 v2 basicUnsafeMove = \ (MV_ShapeSZ v1) (MV_ShapeSZ v2) -> GMV.basicUnsafeMove v1 v2 basicUnsafeGrow = \ (MV_ShapeSZ v) n -> MV_ShapeSZ `liftM` GMV.basicUnsafeGrow v n instance ( UV.Unbox a) => GV.Vector UV.Vector (Shape ('S 'Z) a ) where {-# INLINE basicUnsafeFreeze #-} {-# INLINE basicUnsafeThaw #-} {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicUnsafeIndexM #-} {-# INLINE elemseq #-} basicUnsafeFreeze = \ (MV_ShapeSZ v) -> V_ShapeSZ `liftM` GV.basicUnsafeFreeze v basicUnsafeThaw = \ (V_ShapeSZ v) -> MV_ShapeSZ`liftM` GV.basicUnsafeThaw v basicLength = \ (V_ShapeSZ v)-> GV.basicLength v basicUnsafeSlice = \ i n (V_ShapeSZ v) -> V_ShapeSZ $ GV.basicUnsafeSlice i n v basicUnsafeIndexM = \ (V_ShapeSZ v) i -> ( :* Nil ) `liftM` GV.basicUnsafeIndexM v i basicUnsafeCopy = \ (MV_ShapeSZ mv) (V_ShapeSZ v) -> GV.basicUnsafeCopy mv v elemseq = \ _ (a:*_) z -> GV.elemseq (undefined :: UV.Vector a) a z instance (UV.Unbox a,UV.Unbox (Shape ('S n) a)) => GMV.MVector UV.MVector (Shape ('S ('S n)) a) where {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicOverlaps #-} {-# INLINE basicUnsafeNew #-} {-# INLINE basicUnsafeReplicate #-} {-# INLINE basicUnsafeRead #-} {-# INLINE basicUnsafeWrite #-} {-# INLINE basicClear #-} {-# INLINE basicSet #-} {-# INLINE basicUnsafeCopy #-} {-# INLINE basicUnsafeGrow #-} {-# INLINE basicInitialize #-} basicInitialize = \ (MV_ShapeSSN v) -> GMV.basicInitialize v basicLength = \ (MV_ShapeSSN v) -> GMV.basicLength v basicUnsafeSlice = \ i n (MV_ShapeSSN v) -> MV_ShapeSSN $ GMV.basicUnsafeSlice i n v basicOverlaps = \ (MV_ShapeSSN v1) (MV_ShapeSSN v2) -> GMV.basicOverlaps v1 v2 basicUnsafeNew = \ n -> MV_ShapeSSN `liftM` GMV.basicUnsafeNew n basicUnsafeReplicate = \ n (a :* as) -> MV_ShapeSSN `liftM` GMV.basicUnsafeReplicate n (a,as) basicUnsafeRead = \ (MV_ShapeSSN v) i -> uncurry (:*) `liftM` GMV.basicUnsafeRead v i basicUnsafeWrite = \(MV_ShapeSSN v) i (a :* as ) -> GMV.basicUnsafeWrite v i (a,as) basicClear = \ (MV_ShapeSSN v) -> GMV.basicClear v basicSet = \ (MV_ShapeSSN v) (a :* as) -> GMV.basicSet v (a,as) basicUnsafeCopy = \ (MV_ShapeSSN v1) (MV_ShapeSSN v2) -> GMV.basicUnsafeCopy v1 v2 basicUnsafeMove = \ (MV_ShapeSSN v1) (MV_ShapeSSN v2) -> GMV.basicUnsafeMove v1 v2 basicUnsafeGrow = \ (MV_ShapeSSN v) n -> MV_ShapeSSN `liftM` GMV.basicUnsafeGrow v n instance (UV.Unbox a,UV.Unbox (Shape ('S n) a)) => GV.Vector UV.Vector (Shape ('S ('S n)) a) where {-# INLINE basicUnsafeFreeze #-} {-# INLINE basicUnsafeThaw #-} {-# INLINE basicLength #-} {-# INLINE basicUnsafeSlice #-} {-# INLINE basicUnsafeIndexM #-} {-# INLINE elemseq #-} basicUnsafeFreeze = \ (MV_ShapeSSN v) -> V_ShapeSSN `liftM` GV.basicUnsafeFreeze v basicUnsafeThaw = \ (V_ShapeSSN v) -> MV_ShapeSSN `liftM` GV.basicUnsafeThaw v basicLength = \ (V_ShapeSSN v) -> GV.basicLength v basicUnsafeSlice = \ i n (V_ShapeSSN v) -> V_ShapeSSN $ GV.basicUnsafeSlice i n v basicUnsafeIndexM = \ (V_ShapeSSN v) i -> uncurry (:*) `liftM` GV.basicUnsafeIndexM v i basicUnsafeCopy = \ (MV_ShapeSSN mv) (V_ShapeSSN v) -> GV.basicUnsafeCopy mv v elemseq = \ _ (a :* as) z -> GV.elemseq (undefined :: UV.Vector a) a $ GV.elemseq (undefined :: UV.Vector (Shape ('S n) a)) as z