packages feed

storable-static-array 0.4.1.0 → 0.5.0.0

raw patch · 2 files changed

+98/−53 lines, 2 files

Files

Foreign/Marshal/StaticArray.hs view
@@ -32,32 +32,57 @@  -} module Foreign.Marshal.StaticArray-       ( StaticArray-       , Mutable+       ( -- * Basic interface+         StaticArray        , toArray        , staticArray        , listStaticArray-       , StaticSize(..)+         -- * Adding new Storable instances+         --+         -- | This module only has 'Storable' instances for 'UArray'+         -- and 'Array' as backing types. This is the result of+         -- ensuring that 'peek' is not implemented with an additional+         -- copy. The mutable temporary array needs to have a+         -- representation compatible with that of the result array to+         -- avoid that extra copy.+         --+         -- The following functions provide correct implementations of+         -- a minimum complete 'Storable' implementation for+         -- 'StaticArray'. The helper function required by 'peek'' is+         -- the part necessary for efficient implementations which+         -- prevent creation of a fully polymorphic instance.+       , sizeOf'+       , alignment'+       , poke'+       , peek'+         -- * Adding new StaticSize instances+         --+         -- | This module contains instances of 'StaticSize' for types+         -- of kind 'Nat', types of the promoted kind \'['Nat'], and+         -- promoted tuples of 'Nat' up to 13 elements. For instances+         -- not relying on promoted data types, see the+         -- "Foreign.Marshal.StaticArray.Unpromoted" module.        , fromNat+       , StaticSize(..)        ) where  import GHC.TypeLits  import Control.Monad -import Data.Array.Base import Data.Array            (Array)+import Data.Array.Base import Data.Array.IO  hiding (unsafeFreeze) import Data.Functor          ((<$>)) import Data.Proxy            (Proxy(..))  import Foreign.Storable      (Storable(..)) import Foreign.Marshal.Array (advancePtr)-import Foreign.Ptr           (castPtr)+import Foreign.Ptr           (Ptr, castPtr)  --- | A minimal wrapper for instances of 'IArray' that encodes the full--- dimensions of the array in the type. Intended for interfacing with+-- | A minimal array wrapper that encodes the full dimensions of the+-- array in the type. Intended for interfacing with -- (possibly-)multidimensional arrays of fixed size in native code. -- -- The constructor is not exported to prevent creating a StaticArray@@ -72,21 +97,6 @@ instance (IArray b e, Ix (Bound d), Show e) => Show (StaticArray b d e) where     show = ("listStaticArray " ++) . show . elems . toArray --- | This class connects dimension description types with 'IArray'--- index types and values.------ This module contains instances for types of kind 'Nat', types of--- the promoted kind \'['Nat'], and promoted tuples of 'Nat' values up--- to 13 elements. For instances not relying on promoted data types,--- see the "Foreign.Marshal.StaticArray.Unpromoted" module.-class StaticSize d where-    -- | The bounding type for this dimension description-    type Bound d :: *-    -- | The concrete bounds for an array of this-    -- dimensionality. Implementations of this function should not-    -- examine their argument in any way.-    extent :: StaticArray b d e -> (Bound d, Bound d)- -- | Create a new 'StaticArray' from a list of indices and -- elements. This has all the semantic caveats of 'array', except that -- the bounds are as good as those provided by the 'StaticSize'@@ -101,46 +111,71 @@                    [e] -> StaticArray b d e listStaticArray ls = let a = StaticArray $ listArray (extent a) ls in a ---- | The 'Mutable' type family is used to associate instances of--- 'IArray' with instances of 'MArray' that give non-copying--- 'unsafeFreeze'. This is used to increase the efficiency of 'peek'--- in 'StaticArray' 's 'Storable' instance.------ If you're using an instance of 'IArray' other than 'Array' or--- 'UArray', you'll need to add a type instance for your type. If it--- supports non-copying 'unsafeFreeze', the type instance should--- return the type constructor for the appropriate 'MArray'--- instance. Otherwise, just have it return 'IOArray'-type family Mutable (a :: * -> * -> *) :: * -> * -> *-type instance Mutable Array = IOArray-type instance Mutable UArray = IOUArray--instance (StaticSize d, Ix (Bound d), Storable e, IArray b e,-          MArray (Mutable b) e IO) =>-         Storable (StaticArray b d e) where-    sizeOf a = sizeOf (undefined :: e) * rangeSize (extent a)-    alignment _ = alignment (undefined :: e)-    peek src' = do-        rec let b = extent arr-            m <- newArray_ b :: IO ((Mutable b) (Bound d) e)+------------------------------------------------------------------------ -            let src = castPtr src'-            forM_ [0 .. rangeSize b - 1] $ \i -> do-                x <- peek $ advancePtr src i-                unsafeWrite m i x+-- | Get the size, in bytes, of the native representation of this+-- 'StaticArray'.+sizeOf' :: forall b d e. (StaticSize d, Ix (Bound d), Storable e) =>+           StaticArray b d e -> Int+sizeOf' a = sizeOf (undefined :: e) * rangeSize (extent a) -            arr <- StaticArray <$> unsafeFreeze m-        return arr+-- | Get the alignment, in bytes, of the native representation of this+-- 'StaticArray'+alignment' :: forall b d e. Storable e => StaticArray b d e -> Int+alignment' _ = alignment (undefined :: e) -    poke dst' arr = do+-- | Write the contents of this 'StaticArray' to the given location in+-- memory.+poke' :: forall b d e. (Ix (Bound d), IArray b e, Storable e) =>+         Ptr (StaticArray b d e) -> StaticArray b d e -> IO ()+poke' dst' arr = do         let a = toArray arr             b = bounds a             dst = castPtr dst'         forM_ [0 .. rangeSize b - 1] $ \i ->             poke (advancePtr dst i) $ unsafeAt a i +-- | Create a new 'StaticArray' from the contents of the given+-- location in memory. Uses a temporary mutable array to build up the+-- result, then freezes it. The first argument is the+-- freezing function. Non-copying implementations of 'unsafeFreeze'+-- are safe as this argument, and preferred.+peek' :: forall b d e m . (StaticSize d, Ix (Bound d), Storable e,+                           IArray b e, MArray m e IO) =>+         (m (Bound d) e -> IO (b (Bound d) e)) ->+         Ptr (StaticArray b d e) ->+         IO (StaticArray b d e)+peek' freeze' src' = do+    rec let b = extent arr+        m <- newArray_ b +        let src = castPtr src'+        forM_ [0 .. rangeSize b - 1] $ \i -> do+            x <- peek $ advancePtr src i+            unsafeWrite m i x++        arr <- StaticArray <$> freeze' m+    return arr++instance (StaticSize d, Ix (Bound d), Storable e,+          IArray UArray e, MArray IOUArray e IO) =>+         Storable (StaticArray UArray d e) where+    sizeOf = sizeOf'+    alignment = alignment'+    poke = poke'+    peek = peek' (unsafeFreeze :: IOUArray (Bound d) e ->+                                  IO (UArray (Bound d) e))++instance (StaticSize d, Ix (Bound d), Storable e) =>+         Storable (StaticArray Array d e) where+    sizeOf = sizeOf'+    alignment = alignment'+    poke = poke'+    peek = peek' (unsafeFreeze :: IOArray (Bound d) e ->+                                  IO (Array (Bound d) e))++------------------------------------------------------------------------+ -- | A conversion function for converting type-level naturals to -- value-level. This is being exposed to aid in the creation of -- additional 'StaticSize' instances for those who might desire to do@@ -153,6 +188,16 @@ -- dictionary passing and type erasure. fromNat :: forall (proxy :: Nat -> *) (n :: Nat). SingI n => proxy n -> Int fromNat _ = fromInteger $ fromSing (sing :: Sing n)++-- | This class connects dimension description types with 'IArray'+-- index types and values.+class StaticSize d where+    -- | The bounding type for this dimension description+    type Bound d :: *+    -- | The concrete bounds for an array of this+    -- dimensionality. Implementations of this function should not+    -- examine their argument in any way.+    extent :: StaticArray b d e -> (Bound d, Bound d)  instance SingI n => StaticSize ('[n] :: [Nat]) where     type Bound ('[n]) = Int
storable-static-array.cabal view
@@ -1,5 +1,5 @@ name:                storable-static-array-version:             0.4.1.0+version:             0.5.0.0 synopsis:            Statically-sized array wrappers with Storable instances                      for FFI marshaling description:         Uses type-level numeric literals to wrap arrays in a type