Documentation
authorRoman Leshchinskiy <rl@cse.unsw.edu.au>
Tue, 13 Oct 2009 14:26:48 +0000 (14:26 +0000)
committerRoman Leshchinskiy <rl@cse.unsw.edu.au>
Tue, 13 Oct 2009 14:26:48 +0000 (14:26 +0000)
Data/Primitive/Addr.hs
Data/Primitive/Array.hs
Data/Primitive/ByteArray.hs
Data/Primitive/Types.hs

index c622f0a..4090ecb 100644 (file)
@@ -1,4 +1,16 @@
 {-# LANGUAGE MagicHash, UnboxedTuples #-}
+
+-- |
+-- Module      : Data.Primitive.Addr
+-- Copyright   : (c) Roman Leshchinskiy 2009
+-- License     : BSD-style
+--
+-- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
+-- Portability : non-portable
+-- 
+-- Primitive operations on machine addresses
+--
+
 module Data.Primitive.Addr (
   Addr(..),
 
@@ -22,29 +34,40 @@ instance Ord Addr where
   Addr a# < Addr b# = ltAddr# a# b#
   Addr a# <= Addr b# = leAddr# a# b#
 
+-- | The null address
 nullAddr :: Addr
 nullAddr = Addr nullAddr#
 
 infixl 6 `plusAddr`, `minusAddr`
 infixl 7 `remAddr`
 
+-- | Offset an address by the given number of bytes
 plusAddr :: Addr -> Int -> Addr
 plusAddr (Addr a#) (I# i#) = Addr (plusAddr# a# i#)
 
+-- | Distance in bytes between two addresses. The result is only valid if the
+-- difference fits in an 'Int'.
 minusAddr :: Addr -> Addr -> Int
 minusAddr (Addr a#) (Addr b#) = I# (minusAddr# a# b#)
 
 remAddr :: Addr -> Int -> Int
 remAddr (Addr a#) (I# i#) = I# (remAddr# a# i#)
 
+-- | Read a value from a memory position given by an address and an offset.
+-- The memory block the address refers to must be immutable. The offset is in
+-- elements of type @a@ rather than in bytes.
 indexOffAddr :: Prim a => Addr -> Int -> a
 {-# INLINE indexOffAddr #-}
 indexOffAddr (Addr addr#) (I# i#) = indexOffAddr# addr# i#
 
+-- | Read a value from a memory position given by an address and an offset.
+-- The offset is in elements of type @a@ rather than in bytes.
 readOffAddr :: (Prim a, PrimMonad m) => Addr -> Int -> m a
 {-# INLINE readOffAddr #-}
 readOffAddr (Addr addr#) (I# i#) = primitive (readOffAddr# addr# i#)
 
+-- | Write a value to a memory position given by an address and an offset.
+-- The offset is in elements of type @a@ rather than in bytes.
 writeOffAddr :: (Prim a, PrimMonad m) => Addr -> Int -> a -> m ()
 {-# INLINE writeOffAddr #-}
 writeOffAddr (Addr addr#) (I# i#) x = primitive_ (writeOffAddr# addr# i# x)
index f5aaf95..4c14a21 100644 (file)
@@ -1,4 +1,16 @@
 {-# LANGUAGE MagicHash, UnboxedTuples #-}
+
+-- |
+-- Module      : Data.Primitive.Array
+-- Copyright   : (c) Roman Leshchinskiy 2009
+-- License     : BSD-style
+--
+-- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
+-- Portability : non-portable
+-- 
+-- Primitive boxed arrays
+--
+
 module Data.Primitive.Array (
   Array(..), MutableArray(..),
 
@@ -11,33 +23,66 @@ import Control.Monad.Primitive
 import GHC.Base  ( Int(..) )
 import GHC.Prim
 
+-- | Boxed arrays
 data Array a = Array (Array# a)
+
+-- | Mutable boxed arrays associated with a primitive state-transformer monad.
 data MutableArray m a = MutableArray (MutableArray# (PrimState m) a)
 
+-- | Create a new mutable array of the specified size and initialise all
+-- elements with the given value.
 newArray :: PrimMonad m => Int -> a -> m (MutableArray m a)
 newArray (I# n#) x = primitive
    (\s# -> case newArray# n# x s# of
              (# s'#, arr# #) -> (# s'#, MutableArray arr# #))
 
+-- | Read a value from the array at the given index.
 readArray :: PrimMonad m => MutableArray m a -> Int -> m a
 readArray (MutableArray arr#) (I# i#) = primitive (readArray# arr# i#)
 
+-- | Write a value to the array at the given index.
 writeArray :: PrimMonad m => MutableArray m a -> Int -> a -> m ()
 writeArray (MutableArray arr#) (I# i#) x = primitive_ (writeArray# arr# i# x)
 
+-- | Read a value to the array at the given index and apply a function to it.
+-- This allows us to be strict in the vector if we want. Suppose we had
+--
+-- > leakyIndex :: Array a -> Int -> a
+--
+-- instead. Now, if we wanted to copy an array, we'd do something like
+--
+-- > copy marr arr ... = ... writeArray marr i (leakyIndex arr i) ...
+--
+-- Since primitive arrays are lazy, the call to 'indexArray' would not be
+-- evaluated. Rather, @marr@ would be filled with thunks each of which would
+-- retain a reference to @arr@. This is definitely not what we want!
+--
+-- With the current interface, we can instead write
+--
+-- > copy marr arr ... = ... indexArray arr i (writeArray marr i) ...
+--
+-- This code does not have the above problem because indexing (but not the
+-- returned element!) is evaluated immediately. To get the leaky behaviour of
+-- @leakyIndex@, simply use @'indexArray' arr i id@.
+--
 indexArray :: Array a -> Int -> (a -> b) -> b
 indexArray (Array arr#) (I# i#) f = case indexArray# arr# i# of (# x #) -> f x
 
+-- | Convert a mutable array to an immutable one without copying. The
+-- array should not be modified after the conversion.
 unsafeFreezeArray :: PrimMonad m => MutableArray m a -> m (Array a)
 unsafeFreezeArray (MutableArray arr#)
   = primitive (\s# -> case unsafeFreezeArray# arr# s# of
                         (# s'#, arr'# #) -> (# s'#, Array arr'# #))
 
+-- | Convert an immutable array to an mutable one without copying. The
+-- immutable array should not be used after the conversion.
 unsafeThawArray :: PrimMonad m => Array a -> m (MutableArray m a)
 unsafeThawArray (Array arr#)
   = primitive (\s# -> case unsafeThawArray# arr# s# of
                         (# s'#, arr'# #) -> (# s'#, MutableArray arr'# #))
 
+-- | Check whether the two arrays refer to the same memory block.
 sameMutableArray :: MutableArray m a -> MutableArray m a -> Bool
 sameMutableArray (MutableArray arr#) (MutableArray brr#)
   = sameMutableArray# arr# brr#
index 5678ecd..4a7f2b1 100644 (file)
@@ -1,4 +1,16 @@
 {-# LANGUAGE MagicHash, UnboxedTuples #-}
+
+-- |
+-- Module      : Data.Primitive.ByteArray
+-- Copyright   : (c) Roman Leshchinskiy 2009
+-- License     : BSD-style
+--
+-- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
+-- Portability : non-portable
+-- 
+-- Primitive operations on ByteArrays
+--
+
 module Data.Primitive.ByteArray (
   ByteArray(..), MutableByteArray(..),
 
@@ -15,52 +27,73 @@ import Data.Primitive.Types
 import GHC.Base ( Int(..) )
 import GHC.Prim
 
+-- | Byte arrays
 data ByteArray = ByteArray ByteArray#
+
+-- | Mutable byte arrays
 data MutableByteArray m = MutableByteArray (MutableByteArray# (PrimState m))
 
+-- | Create a new mutable byte array of the specified size.
 newByteArray :: PrimMonad m => Int -> m (MutableByteArray m)
 newByteArray (I# n#)
   = primitive (\s# -> case newByteArray# n# s# of
                         (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
 
+-- | Create a /pinned/ byte array of the specified size. The garbage collector
+-- is guaranteed not to move it.
 newPinnedByteArray :: PrimMonad m => Int -> m (MutableByteArray m)
 newPinnedByteArray (I# n#)
   = primitive (\s# -> case newPinnedByteArray# n# s# of
                         (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
 
+-- | Create a /pinned/ byte array of the specified size and with the give
+-- alignment. The garbage collector is guaranteed not to move it.
 newAlignedPinnedByteArray :: PrimMonad m => Int -> Int -> m (MutableByteArray m)
 newAlignedPinnedByteArray (I# n#) (I# k#)
   = primitive (\s# -> case newAlignedPinnedByteArray# n# k# s# of
                         (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
 
+-- | Yield a pointer to the array's data. This operation is only safe on
+-- /pinned/ byte arrays allocated by 'newPinnedByteArray' or
+-- 'newAlignedPinnedByteArray'.
 byteArrayContents :: ByteArray -> Addr
 byteArrayContents (ByteArray arr#) = Addr (byteArrayContents# arr#)
 
+-- | Check if the two arrays refer to the same memory block.
 sameMutableByteArray :: MutableByteArray m -> MutableByteArray m -> Bool
 sameMutableByteArray (MutableByteArray arr#) (MutableByteArray brr#)
   = sameMutableByteArray# arr# brr#
 
+-- | Convert a mutable byte array to an immutable one without copying. The
+-- array should not be modified after the conversion.
 unsafeFreezeByteArray :: PrimMonad m => MutableByteArray m -> m ByteArray
 unsafeFreezeByteArray (MutableByteArray arr#)
   = primitive (\s# -> case unsafeFreezeByteArray# arr# s# of
                         (# s'#, arr'# #) -> (# s'#, ByteArray arr'# #))
 
+-- | Size of the byte array.
 sizeofByteArray :: ByteArray -> Int
 sizeofByteArray (ByteArray arr#) = I# (sizeofByteArray# arr#)
 
+-- | Size of the mutable byte array.
 sizeofMutableByteArray :: MutableByteArray s -> Int
 sizeofMutableByteArray (MutableByteArray arr#) = I# (sizeofMutableByteArray# arr#)
 
+-- | Read a primitive value from the byte array. The offset is given in
+-- elements of type @a@ rather than in bytes.
 indexByteArray :: Prim a => ByteArray -> Int -> a
 indexByteArray (ByteArray arr#) (I# i#) = indexByteArray# arr# i#
 
-readByteArray :: (Prim a, PrimMonad m)
-              => MutableByteArray m -> Int -> m a
+-- | Read a primitive value from the byte array. The offset is given in
+-- elements of type @a@ rather than in bytes.
+readByteArray :: (Prim a, PrimMonad m) => MutableByteArray m -> Int -> m a
 readByteArray (MutableByteArray arr#) (I# i#)
   = primitive (readByteArray# arr# i#)
 
+-- | Write a primitive value to the byte array. The offset is given in
+-- elements of type @a@ rather than in bytes.
 writeByteArray :: (Prim a, PrimMonad m)
                => MutableByteArray m -> Int -> a -> m ()
 writeByteArray (MutableByteArray arr#) (I# i#) x
-  = primitive (\s# -> (# writeByteArray# arr# i# x s#, () #))
+  = primitive_ (writeByteArray# arr# i# x)
 
index 29043e1..414aa84 100644 (file)
@@ -34,23 +34,49 @@ import GHC.Int (
 
 import GHC.Prim
 
+-- | A machine address
 data Addr = Addr Addr#
 
+-- | Class of types supporting primitive array operations
 class Prim a where
+
+  -- | Size of values of type @a@. The argument is not used.
   sizeOf#    :: a -> Int#
+
+  -- | Alignment of values of type @a@. The argument is not used.
   alignment# :: a -> Int#
 
+  -- | Read a value from the array. The offset is in elements of type
+  -- @a@ rather than in bytes.
   indexByteArray# :: ByteArray# -> Int# -> a
+
+  -- | Read a value from the mutable array. The offset is in elements of type
+  -- @a@ rather than in bytes.
   readByteArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)
+
+  -- | Write a value to the mutable array. The offset is in elements of type
+  -- @a@ rather than in bytes.
   writeByteArray# :: MutableByteArray# s -> Int# -> a -> State# s -> State# s
 
+  -- | Read a value from a memory position given by an address and an offset.
+  -- The memory block the address refers to must be immutable. The offset is in
+  -- elements of type @a@ rather than in bytes.
   indexOffAddr# :: Addr# -> Int# -> a
+
+  -- | Read a value from a memory position given by an address and an offset.
+  -- The offset is in elements of type @a@ rather than in bytes.
   readOffAddr# :: Addr# -> Int# -> State# s -> (# State# s, a #)
+
+  -- | Write a value to a memory position given by an address and an offset.
+  -- The offset is in elements of type @a@ rather than in bytes.
   writeOffAddr# :: Addr# -> Int# -> a -> State# s -> State# s
 
+
+-- | Size of values of type @a@. The argument is not used.
 sizeOf :: Prim a => a -> Int
 sizeOf x = I# (sizeOf# x)
 
+-- | Alignment of values of type @a@. The argument is not used.
 alignment :: Prim a => a -> Int
 alignment x = I# (alignment# x)