packages feed

carray 0.1.5.2 → 0.1.6

raw patch · 15 files changed

+962/−831 lines, 15 filesdep +QuickCheckdep +carraydep ~arraydep ~basedep ~binaryPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: QuickCheck, carray

Dependency ranges changed: array, base, binary, bytestring, ix-shapable, syb

API changes (from Hackage documentation)

- Data.Array.CArray.Base: instance (Data i, Data e) => Data (CArray i e)
- Data.Array.CArray.Base: instance (Data i, Data e) => Data (IOCArray i e)
- Data.Array.CArray.Base: instance (Ix i, Binary i, Binary e, Storable e) => Binary (CArray i e)
- Data.Array.CArray.Base: instance (Ix ix, Eq e, Storable e) => Eq (CArray ix e)
- Data.Array.CArray.Base: instance (Ix ix, Ord e, Storable e) => Ord (CArray ix e)
- Data.Array.CArray.Base: instance (Ix ix, Show ix, Show e, Storable e) => Show (CArray ix e)
- Data.Array.CArray.Base: instance Abs (Complex Double) Double
- Data.Array.CArray.Base: instance Abs (Complex Float) Float
- Data.Array.CArray.Base: instance Abs Double Double
- Data.Array.CArray.Base: instance Abs Float Float
- Data.Array.CArray.Base: instance Storable e => IArray CArray e
- Data.Array.CArray.Base: instance Storable e => MArray IOCArray e IO
- Data.Array.CArray.Base: instance Typeable2 CArray
- Data.Array.CArray.Base: instance Typeable2 IOCArray
+ Data.Array.CArray.Base: instance (Data.Data.Data i, Data.Data.Data e) => Data.Data.Data (Data.Array.CArray.Base.CArray i e)
+ Data.Array.CArray.Base: instance (Data.Data.Data i, Data.Data.Data e) => Data.Data.Data (Data.Array.CArray.Base.IOCArray i e)
+ Data.Array.CArray.Base: instance (GHC.Arr.Ix i, Data.Binary.Class.Binary i, Data.Binary.Class.Binary e, Foreign.Storable.Storable e) => Data.Binary.Class.Binary (Data.Array.CArray.Base.CArray i e)
+ Data.Array.CArray.Base: instance (GHC.Arr.Ix i, Test.QuickCheck.Arbitrary.Arbitrary i, Foreign.Storable.Storable e, Test.QuickCheck.Arbitrary.Arbitrary e) => Test.QuickCheck.Arbitrary.Arbitrary (Data.Array.CArray.Base.CArray i e)
+ Data.Array.CArray.Base: instance (GHC.Arr.Ix i, Test.QuickCheck.Arbitrary.CoArbitrary i, Foreign.Storable.Storable e, Test.QuickCheck.Arbitrary.CoArbitrary e) => Test.QuickCheck.Arbitrary.CoArbitrary (Data.Array.CArray.Base.CArray i e)
+ Data.Array.CArray.Base: instance (GHC.Arr.Ix ix, GHC.Classes.Eq e, Foreign.Storable.Storable e) => GHC.Classes.Eq (Data.Array.CArray.Base.CArray ix e)
+ Data.Array.CArray.Base: instance (GHC.Arr.Ix ix, GHC.Classes.Ord e, Foreign.Storable.Storable e) => GHC.Classes.Ord (Data.Array.CArray.Base.CArray ix e)
+ Data.Array.CArray.Base: instance (GHC.Arr.Ix ix, GHC.Show.Show ix, GHC.Show.Show e, Foreign.Storable.Storable e) => GHC.Show.Show (Data.Array.CArray.Base.CArray ix e)
+ Data.Array.CArray.Base: instance Data.Array.CArray.Base.Abs (Data.Complex.Complex GHC.Types.Double) GHC.Types.Double
+ Data.Array.CArray.Base: instance Data.Array.CArray.Base.Abs (Data.Complex.Complex GHC.Types.Float) GHC.Types.Float
+ Data.Array.CArray.Base: instance Data.Array.CArray.Base.Abs GHC.Types.Double GHC.Types.Double
+ Data.Array.CArray.Base: instance Data.Array.CArray.Base.Abs GHC.Types.Float GHC.Types.Float
+ Data.Array.CArray.Base: instance Foreign.Storable.Storable e => Data.Array.Base.IArray Data.Array.CArray.Base.CArray e
+ Data.Array.CArray.Base: instance Foreign.Storable.Storable e => Data.Array.Base.MArray Data.Array.CArray.Base.IOCArray e GHC.Types.IO
- Data.Array.CArray: unsafeCArrayToByteString :: Storable e => CArray i e -> ByteString
+ Data.Array.CArray: unsafeCArrayToByteString :: (Storable e) => CArray i e -> ByteString
- Data.Array.CArray.Base: CArray :: !i -> !i -> Int -> !ForeignPtr e -> CArray i e
+ Data.Array.CArray.Base: CArray :: !i -> !i -> Int -> !(ForeignPtr e) -> CArray i e
- Data.Array.CArray.Base: IOCArray :: !i -> !i -> Int -> !ForeignPtr e -> IOCArray i e
+ Data.Array.CArray.Base: IOCArray :: !i -> !i -> Int -> !(ForeignPtr e) -> IOCArray i e
- Data.Array.CArray.Base: unsafeCArrayToByteString :: Storable e => CArray i e -> ByteString
+ Data.Array.CArray.Base: unsafeCArrayToByteString :: (Storable e) => CArray i e -> ByteString
- Data.Array.CArray.Base: unsafeFreezeIOCArray :: Ix i => IOCArray i e -> IO (CArray i e)
+ Data.Array.CArray.Base: unsafeFreezeIOCArray :: (Ix i) => IOCArray i e -> IO (CArray i e)
- Data.Array.CArray.Base: unsafeThawIOCArray :: Ix i => CArray i e -> IO (IOCArray i e)
+ Data.Array.CArray.Base: unsafeThawIOCArray :: (Ix i) => CArray i e -> IO (IOCArray i e)

Files

− Data/Array/CArray.hs
@@ -1,91 +0,0 @@--- |--- Module      : Data.Array.CArray--- Copyright   : (c) 2008 Jed Brown--- License     : BSD-style--- --- Maintainer  : jed@59A2.org--- Stability   : experimental--- Portability : non-portable------ This module provides the immutable 'CArray' which uses pinned memory on the--- GC'd heap.  Elements are stored according to the class 'Storable'.  You can--- obtain a pointer to the array contents to manipulate elements from--- languages like C.------ 'CArray' is 16-byte aligned by default.  If you create a 'CArray' with--- 'unsafeForeignPtrToCArray' then it may not be aligned.  This will be an issue--- if you intend to use SIMD instructions.------ 'CArray' is similar to 'Data.Array.Unboxed.UArray' but slower if you stay--- within Haskell.  'CArray' can handle more types and can be used by external--- libraries.------ 'CArray' has an instance of 'Binary'.--------------------------------------------------------------------------------module Data.Array.CArray (-    -- * CArray type-    CArray,--    -- * Multi-dimensional--    -- ** Fast reshaping-    reshape,-    flatten,--    -- ** Query-    rank,-    shape,-    size,--    -- * Mapping--    -- ** General-    ixmapWithIndP,-    ixmapWithInd,-    ixmapWithP,-    ixmapWith,-    ixmapP,--    -- ** Slicing-    sliceStrideWithP,-    sliceStrideWith,-    sliceStrideP,-    sliceStride,-    sliceWithP,-    sliceWith,-    sliceP,-    slice,--    -- * Lifting-    liftArrayP,-    liftArray,-    liftArray2P,-    liftArray2,-    liftArray3P,-    liftArray3,--    -- * Norms-    normp,-    norm2,-    normSup,--    -- * Types-    Shapable,-    Abs,--    -- * Unsafe low-level-    withCArray,-    unsafeForeignPtrToCArray,-    toForeignPtr,-    unsafeCArrayToByteString,-    unsafeByteStringToCArray,-    createCArray,--   -- * The overloaded immutable array interface-   module Data.Array.IArray-) where--import Data.Ix.Shapable-import Data.Array.IArray-import Data.Array.CArray.Base
− Data/Array/CArray/Base.hs
@@ -1,537 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-}-#ifdef __GLASGOW_HASKELL__-#if __GLASGOW_HASKELL__ < 610-{-# OPTIONS_GHC -frewrite-rules #-}-#else-{-# OPTIONS_GHC -fenable-rewrite-rules #-}-#endif-#endif--------------------------------------------------------------------------------- |--- Module      : Data.Array.CArray.Base--- Copyright   : (c) 2001 The University of Glasgow---               (c) 2008 Jed Brown--- License     : BSD-style--- --- Maintainer  : jed@59A2.org--- Stability   : experimental--- Portability : non-portable------ This module provides both the immutable 'CArray' and mutable 'IOCArray'.  The--- underlying storage is exactly the same - pinned memory on the GC'd heap.--- Elements are stored according to the class 'Storable'.  You can obtain a--- pointer to the array contents to manipulate elements from languages like C.------ 'CArray' is 16-byte aligned by default.  If you create a 'CArray' with--- 'unsafeForeignPtrToCArray' then it may not be aligned.  This will be an issue--- if you intend to use SIMD instructions.------ 'CArray' is similar to 'Data.Array.Unboxed.UArray' but slower if you stay--- within Haskell.  'CArray' can handle more types and can be used by external--- libraries.------ 'IOCArray' is equivalent to 'Data.Array.Storable.StorableArray' and similar--- to 'Data.Array.IO.IOUArray' but slower.  'IOCArray' has O(1) versions of--- 'unsafeFreeze' and 'unsafeThaw' when converting to/from 'CArray'.--------------------------------------------------------------------------------module Data.Array.CArray.Base where--import Control.Applicative-import Control.Monad-import Data.Ix-import Data.Ix.Shapable-import Data.Array.Base-import Data.Array.MArray        ()-import Data.Array.IArray        ()-import qualified Data.ByteString.Internal as S-import Data.Binary-import Data.Complex-import Data.List-import System.IO.Unsafe         (unsafePerformIO)-import Foreign.Storable-import Foreign.ForeignPtr-import Foreign.Ptr-import Foreign.Marshal.Array    (copyArray, withArray)-import Data.Word                ()--import Data.Generics            (Data(..), Typeable(..))-import GHC.Ptr                  (Ptr(..))-import GHC.ForeignPtr           (ForeignPtr(..), mallocPlainForeignPtrBytes)---- | The immutable array type.-data CArray i e = CArray !i !i Int !(ForeignPtr e)-    deriving (Data, Typeable)---- | Absolutely equivalent representation, but used for the mutable interface.-data IOCArray i e = IOCArray !i !i Int !(ForeignPtr e)-    deriving (Data, Typeable)--instance Storable e => MArray IOCArray e IO where-    getBounds (IOCArray l u _ _) = return (l,u)--    getNumElements (IOCArray _ _ n _) = return n--    newArray (l,u) e0 = do-        fp <- mallocForeignPtrArrayAligned n-        withForeignPtr fp $ \a ->-            sequence_ [pokeElemOff a i e0 | i <- [0 .. n - 1]]-        return (IOCArray l u n fp)-        where n = rangeSize (l,u)--    unsafeNewArray_ (l,u) = do-        let n = rangeSize (l,u)-        fp <- mallocForeignPtrArrayAligned n-        return (IOCArray l u n fp)--    newArray_ = unsafeNewArray_--    unsafeRead (IOCArray _ _ _ fp) i =-        withForeignPtr fp $ \a -> peekElemOff a i--    unsafeWrite (IOCArray _ _ _ fp) i e =-        withForeignPtr fp $ \a -> pokeElemOff a i e---- | The pointer to the array contents is obtained by 'withCArray'.--- The idea is similar to 'ForeignPtr' (used internally here).--- The pointer should be used only during execution of the 'IO' action--- retured by the function passed as argument to 'withCArray'.-withCArray :: CArray i e -> (Ptr e -> IO a) -> IO a-withCArray (CArray _ _ _ fp) f = withForeignPtr fp f--withIOCArray :: IOCArray i e -> (Ptr e -> IO a) -> IO a-withIOCArray (IOCArray _ _ _ fp) f = withForeignPtr fp f---- | If you want to use it afterwards, ensure that you--- 'touchCArray' after the last use of the pointer,--- so the array is not freed too early.-touchIOCArray :: IOCArray i e -> IO ()-touchIOCArray (IOCArray _ _ _ fp) = touchForeignPtr fp---- | /O(1)/ Construct a 'CArray' from an arbitrary 'ForeignPtr'.  It is--- the caller's responsibility to ensure that the 'ForeignPtr' points to--- an area of memory sufficient for the specified bounds.-unsafeForeignPtrToCArray-   :: Ix i => ForeignPtr e -> (i,i) -> IO (CArray i e)-unsafeForeignPtrToCArray p (l,u) =-   return (CArray l u (rangeSize (l,u)) p)---- | /O(1)/ Construct a 'CArray' from an arbitrary 'ForeignPtr'.  It is--- the caller's responsibility to ensure that the 'ForeignPtr' points to--- an area of memory sufficient for the specified bounds.-unsafeForeignPtrToIOCArray-   :: Ix i => ForeignPtr e -> (i,i) -> IO (IOCArray i e)-unsafeForeignPtrToIOCArray p (l,u) =-   return (IOCArray l u (rangeSize (l,u)) p)---- | /O(1)/ Extract ForeignPtr from a CArray.-toForeignPtr :: CArray i e -> (Int, ForeignPtr e)-toForeignPtr (CArray _ _ n fp) = (n, fp)---- | /O(1)/ Turn a CArray into a ByteString.  Unsafe because it uses--- 'castForeignPtr' and thus is not platform independent.-unsafeCArrayToByteString :: (Storable e) => CArray i e -> S.ByteString-unsafeCArrayToByteString (CArray _ _ l fp) = go undefined fp-    where go :: (Storable e) => e -> ForeignPtr e -> S.ByteString-          go dummy fp' = S.fromForeignPtr (castForeignPtr fp') 0 (l * sizeOf dummy)---- | /O(1)/ Turn a ByteString into a CArray.  Unsafe because it uses--- 'castForeignPtr' and thus is not platform independent.  Returns 'Nothing' if--- the range specified is larger than the size of the ByteString or the start of--- the ByteString does not fulfil the alignment requirement of the resulting--- CArray (as specified by the Storable instance).-unsafeByteStringToCArray :: (Ix i, Storable e)-                            => (i,i) -> S.ByteString -> Maybe (CArray i e)-unsafeByteStringToCArray lu bs = go undefined lu-    where go :: (Ix i, Storable e) => e -> (i,i) -> Maybe (CArray i e)-          go dummy (l,u) | safe = Just (CArray l u n fp)-                         | otherwise = Nothing-              where n = rangeSize (l,u)-                    !((ForeignPtr addr contents), off, len) = S.toForeignPtr bs-                    !p@(Ptr addr') = Ptr addr `plusPtr` off-                    fp = ForeignPtr addr' contents-                    safe = sizeOf dummy * n <= len && p == p `alignPtr` alignment dummy--copy :: (Ix i, Storable e) => CArray i e -> IO (CArray i e)-copy ain@(CArray l u n _) =-    createCArray (l,u) $ \op ->-        withCArray ain $ \ip ->-            copyArray op ip n--freezeIOCArray :: (Ix i, Storable e) => IOCArray i e -> IO (CArray i e)-freezeIOCArray = unsafeFreezeIOCArray >=> copy--unsafeFreezeIOCArray :: (Ix i) => IOCArray i e -> IO (CArray i e)-unsafeFreezeIOCArray (IOCArray l u n fp) = return (CArray l u n fp)--thawIOCArray :: (Ix i, Storable e) => CArray i e -> IO (IOCArray i e)-thawIOCArray = copy >=> unsafeThawIOCArray--unsafeThawIOCArray :: (Ix i) => CArray i e -> IO (IOCArray i e)-unsafeThawIOCArray (CArray l u n fp) = return (IOCArray l u n fp)---- Since we can remove the (Storable e) restriction for these, the rules are--- compact and general.-{-# RULES-"unsafeFreeze/IOCArray" unsafeFreeze = unsafeFreezeIOCArray-"unsafeThaw/IOCArray" unsafeThaw = unsafeThawIOCArray-  #-}---- Since we can't parameterize the rules with the (Storable e) constraint, we--- have to specialize manually.  This is unfortunate since it is less general.-{-# RULES-"freeze/IOCArray/Int"    freeze      = freezeIOCArray :: (Ix i) => IOCArray i Int -> IO (CArray i Int)-"freeze/IOCArray/Float"  freeze      = freezeIOCArray :: (Ix i) => IOCArray i Float -> IO (CArray i Float)-"freeze/IOCArray/Double" freeze      = freezeIOCArray :: (Ix i) => IOCArray i Double -> IO (CArray i Double)-"thaw/IOCArray/Int"      thaw        = thawIOCArray   :: (Ix i) => CArray i Int -> IO (IOCArray i Int)-"thaw/IOCArray/Float"    thaw        = thawIOCArray   :: (Ix i) => CArray i Float -> IO (IOCArray i Float)-"thaw/IOCArray/Double"   thaw        = thawIOCArray   :: (Ix i) => CArray i Double -> IO (IOCArray i Double)-  #-}---instance Storable e => IArray CArray e where-    {-# INLINE bounds #-}-    bounds (CArray l u _ _) = (l,u)-    {-# INLINE numElements #-}-    numElements (CArray _ _ n _) = n-    {-# NOINLINE unsafeArray #-}-    unsafeArray lu ies = unsafePerformIO $ unsafeArrayCArray lu ies (zeroElem (undefined :: e))-    {-# INLINE unsafeAt #-}-    unsafeAt (CArray _ _ _ fp) i = S.inlinePerformIO $-                                   withForeignPtr fp $ \a -> peekElemOff a i-    {-# NOINLINE unsafeReplace #-}-    unsafeReplace arr ies = unsafePerformIO $ unsafeReplaceCArray arr ies-    {-# NOINLINE unsafeAccum #-}-    unsafeAccum f arr ies = unsafePerformIO $ unsafeAccumCArray f arr ies-    {-# NOINLINE unsafeAccumArray #-}-    unsafeAccumArray f e0 lu ies = unsafePerformIO $ unsafeAccumArrayCArray f e0 lu ies----- | Hackish way to get the zero element for a Storable type.-{-# NOINLINE zeroElem #-}-zeroElem :: Storable a => a -> a-zeroElem u = unsafePerformIO $-    withArray (replicate (sizeOf u) (0 :: Word8)) $ peek . castPtr--{-# INLINE unsafeArrayCArray #-}-unsafeArrayCArray :: (Storable e, Ix i)-                  => (i,i) -> [(Int, e)] -> e -> IO (CArray i e)-unsafeArrayCArray lu ies default_elem = do-        marr <- newArray lu default_elem-        sequence_ [unsafeWrite marr i e | (i, e) <- ies]-        unsafeFreezeIOCArray marr--{-# INLINE unsafeReplaceCArray #-}-unsafeReplaceCArray :: (Storable e, Ix i)-                       => CArray i e -> [(Int, e)] -> IO (CArray i e)-unsafeReplaceCArray arr ies = do-    marr <- thawIOCArray arr-    sequence_ [unsafeWrite marr i e | (i, e) <- ies]-    unsafeFreezeIOCArray marr--{-# INLINE unsafeAccumCArray #-}-unsafeAccumCArray :: (Storable e, Ix i)-                            => (e -> e' -> e) -> CArray i e -> [(Int, e')]-                                              -> IO (CArray i e)-unsafeAccumCArray f arr ies = do-    marr <- thawIOCArray arr-    sequence_ [do-        old <- unsafeRead marr i-        unsafeWrite marr i (f old new)-        | (i, new) <- ies]-    unsafeFreezeIOCArray marr--{-# INLINE unsafeAccumArrayCArray #-}-unsafeAccumArrayCArray :: (Storable e, Ix i)-                          => (e -> e' -> e) -> e -> (i,i) -> [(Int, e')]-                                            -> IO (CArray i e)-unsafeAccumArrayCArray f e0 lu ies = do-    marr <- newArray lu e0-    sequence_ [do-        old <- unsafeRead marr i-        unsafeWrite marr i (f old new)-        | (i, new) <- ies]-    unsafeFreezeIOCArray marr--{-# INLINE eqCArray #-}-eqCArray :: (Storable e, Ix i, Eq e)-                   => CArray i e -> CArray i e -> Bool-eqCArray arr1@(CArray l1 u1 n1 _) arr2@(CArray l2 u2 n2 _) =-    if n1 == 0 then n2 == 0 else-        l1 == l2 && u1 == u2 &&-           and [unsafeAt arr1 i == unsafeAt arr2 i | i <- [0 .. n1 - 1]]--{-# INLINE cmpCArray #-}-cmpCArray :: (Storable e, Ix i, Ord e)-                    => CArray i e -> CArray i e -> Ordering-cmpCArray arr1 arr2 = compare (assocs arr1) (assocs arr2)--{-# INLINE cmpIntCArray #-}-cmpIntCArray :: (Storable e, Ord e)-                       => CArray Int e -> CArray Int e -> Ordering-cmpIntCArray arr1@(CArray l1 u1 n1 _) arr2@(CArray l2 u2 n2 _) =-    if n1 == 0 then if n2 == 0 then EQ else LT else-    if n2 == 0 then GT else-    case compare l1 l2 of-        EQ    -> foldr cmp (compare u1 u2) [0 .. (n1 `min` n2) - 1]-        other -> other-    where-    cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of-        EQ    -> rest-        other -> other--{-# RULES "cmpCArray/Int" cmpCArray = cmpIntCArray #-}--instance (Ix ix, Eq e, Storable e) => Eq (CArray ix e) where-    (==) = eqCArray--instance (Ix ix, Ord e, Storable e) => Ord (CArray ix e) where-    compare = cmpCArray--instance (Ix ix, Show ix, Show e, Storable e) => Show (CArray ix e) where-    showsPrec = showsIArray------- General purpose array operations which happen to be very fast for CArray.------- | O(1) reshape an array.  The number of elements in the new shape must not--- exceed the number in the old shape.  The elements are in C-style ordering.-reshape :: (Ix i, Ix j) => (j,j) -> CArray i e -> CArray j e-reshape (l',u') (CArray _ _ n fp) | n' > n = error "reshape: new size too large"-                                  | otherwise = CArray l' u' n' fp-    where n' = rangeSize (l', u')---- | O(1) make a rank 1 array from an arbitrary shape.--- It has the property that 'reshape (0, size a - 1) a == flatten a'.-flatten :: Ix i => CArray i e -> CArray Int e-flatten (CArray _ _ n fp) = CArray 0 (n - 1) n fp------- None of the following are specific to CArray.  Some could have slightly--- faster versions specialized to CArray.  In general, slicing is expensive--- because the slice is not contiguous in memory, so must be copied.  There are--- many specialized versions.------- | Generic slice and map.  This takes the new range, the inverse map on--- indices, and function to produce the next element.  It is the most general--- operation in its class.-ixmapWithIndP :: (Ix i, Ix i', IArray a e, IArray a' e')-                 => (i',i') -> (i' -> i) -> (i -> e -> i' -> e') -> a i e -> a' i' e'-ixmapWithIndP lu f g arr = listArray lu-                           [ let i = f i' in g i (arr ! i) i' | i' <- range lu ]---- | Less polymorphic version.-ixmapWithInd :: (Ix i, Ix i', IArray a e, IArray a e')-                => (i',i') -> (i' -> i) -> (i -> e -> i' -> e') -> a i e -> a i' e'-ixmapWithInd = ixmapWithIndP---- | Perform an operation on the elements, independent of their location.-ixmapWithP  :: (Ix i, Ix i', IArray a e, IArray a' e')-               => (i',i') -> (i' -> i) -> (e -> e') -> a i e -> a' i' e'-ixmapWithP lu f g arr = listArray lu-                        [ g (arr ! f i') | i' <- range lu ]---- | Less polymorphic version.-ixmapWith  :: (Ix i, Ix i', IArray a e, IArray a e')-              => (i',i') -> (i' -> i) -> (e -> e') -> a i e -> a i' e'-ixmapWith = ixmapWithP---- | More polymorphic version of 'ixmap'.-ixmapP :: (Ix i, Ix i', IArray a e, IArray a' e)-          => (i',i') -> (i' -> i) -> a i e -> a' i' e-ixmapP lu f arr = ixmapWithP lu f id arr---- | More friendly sub-arrays with element mapping.-sliceStrideWithP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e')-                    => (i',i') -> (i,i,i) -> (e -> e') -> a i e -> a' i' e'-sliceStrideWithP lu (start,next,end) f arr-    | all (inRange (bounds arr)) [start,next,end] = listArray lu es-    | otherwise = error "sliceStrideWith: out of bounds"-    where is = offsetShapeFromThenTo (shape arr) (index' start) (index' next) (index' end)-          es = map (f . (unsafeAt arr)) is-          index' = indexes arr---- | Less polymorphic version.-sliceStrideWith :: (Ix i, Shapable i, Ix i', IArray a e, IArray a e')-                   => (i',i') -> (i,i,i) -> (e -> e') -> a i e -> a i' e'-sliceStrideWith = sliceStrideWithP---- | Strided sub-array without element mapping.-sliceStrideP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e)-                => (i',i') -> (i,i,i) -> a i e -> a' i' e-sliceStrideP lu sne = sliceStrideWithP lu sne id---- | Less polymorphic version.-sliceStride :: (Ix i, Shapable i, Ix i', IArray a e)-               => (i',i') -> (i,i,i) -> a i e -> a i' e-sliceStride = sliceStrideP---- | Contiguous sub-array with element mapping.-sliceWithP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e')-              => (i',i') -> (i,i) -> (e -> e') -> a i e -> a' i' e'-sliceWithP lu (start,end) f arr-    | all (inRange (bounds arr)) [start,end] = listArray lu es-    | otherwise = error "sliceWith: out of bounds"-    where is = offsetShapeFromTo (shape arr) (index' start) (index' end)-          es = map (f . (unsafeAt arr)) is-          index' = indexes arr---- | Less polymorphic version.-sliceWith :: (Ix i, Shapable i, Ix i', IArray a e, IArray a e')-             => (i',i') -> (i,i) -> (e -> e') -> a i e -> a i' e'-sliceWith = sliceWithP---- | Contiguous sub-array without element mapping.-sliceP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e)-          => (i',i') -> (i,i) -> a i e -> a' i' e-sliceP lu se = sliceWithP lu se id---- | Less polymorphic version.-slice ::  (Ix i, Shapable i, Ix i', IArray a e)-          => (i',i') -> (i,i) -> a i e -> a i' e-slice = sliceP---- | In-place map on CArray.  Note that this is /IN PLACE/ so you should not--- retain any reference to the original.  It flagrantly breaks referential--- transparency!-{-# INLINE mapCArrayInPlace #-}-mapCArrayInPlace :: (Ix i, Storable e) => (e -> e) -> CArray i e -> CArray i e-mapCArrayInPlace f a = S.inlinePerformIO $ do-    withCArray a $ \p ->-        forM_ [0 .. size a - 1] $ \i ->-            peekElemOff p i >>= pokeElemOff p i . f-    return a---------------------------------------------- These are meant to be internal only-indexes :: (Ix i, Shapable i, IArray a e) => a i e -> i -> [Int]-indexes a i = map pred $ (sShape . fst . bounds) a i--offsetShapeFromThenTo :: [Int] -> [Int] -> [Int] -> [Int] -> [Int]-offsetShapeFromThenTo s a b c = foldr (liftA2 (+)) [0] (ilists stride a b c)-    where ilists = zipWith4 (\s' a' b' c' -> map (*s') $ enumFromThenTo a' b' c')-          stride = shapeToStride s--offsetShapeFromTo :: [Int] -> [Int] -> [Int] -> [Int]-offsetShapeFromTo = offsetShapeFromTo' id--offsetShapeFromTo' :: ([[Int]] -> [[Int]]) -> [Int] -> [Int] -> [Int] -> [Int]-offsetShapeFromTo' f s a b = foldr (liftA2 (+)) [0] (f $ ilists stride a b)-    where ilists = zipWith3 (\s' a' b' -> map (*s') $ enumFromTo a' b')-          stride = shapeToStride s--offsets :: (Ix a, Shapable a) => (a, a) -> a -> [Int]-offsets lu i = reverse . osets (index lu i) . reverse . scanl1 (*) . uncurry sShape $ lu-    where osets 0 [] = []-          osets i' (b:bs) = r : osets d bs-              where (d,r) = i' `divMod` b-          osets _ _ = error "osets"---------------------------------------------- | p-norm on the array taken as a vector-normp :: (Ix i, RealFloat e', Abs e e', IArray a e) => e' -> a i e -> e'-normp p a | 1 <= p && not (isInfinite p) = (** (1/p)) $ foldl' (\z e -> z + (abs_ e) ** p) 0 (elems a)-          | otherwise = error "normp: p < 1"---- | 2-norm on the array taken as a vector (Frobenius norm for matrices)-norm2 :: (Ix i, Floating e', Abs e e', IArray a e) => a i e -> e'-norm2 a = sqrt $ foldl' (\z e -> z + abs_ e ^ (2 :: Int)) 0 (elems a)---- | Sup norm on the array taken as a vector-normSup :: (Ix i, Num e', Ord e', Abs e e', IArray a e) => a i e -> e'-normSup a = foldl' (\z e -> z `max` abs_ e) 0 (elems a)---- | Polymorphic version of amap.-liftArrayP :: (Ix i, IArray a e, IArray a1 e1)-              => (e -> e1) -> a i e -> a1 i e1-liftArrayP f a = listArray (bounds a) (map f (elems a))---- | Equivalent to amap.  Here for consistency only.-liftArray :: (Ix i, IArray a e, IArray a e1)-              => (e -> e1) -> a i e -> a i e1-liftArray = liftArrayP---- | Polymorphic 2-array lift.-liftArray2P :: (Ix i, IArray a e, IArray a1 e1, IArray a2 e2)-              => (e -> e1 -> e2) -> a i e -> a1 i e1 -> a2 i e2-liftArray2P f a b | aBounds == bounds b =-                     listArray aBounds (zipWith f (elems a) (elems b))-                 | otherwise = error "liftArray2: array bounds must match"-    where aBounds = bounds a---- | Less polymorphic version.-liftArray2 :: (Ix i, IArray a e, IArray a e1, IArray a e2)-              => (e -> e1 -> e2) -> a i e -> a i e1 -> a i e2-liftArray2 = liftArray2P---- | Polymorphic 3-array lift.-liftArray3P :: (Ix i, IArray a e, IArray a1 e1, IArray a2 e2, IArray a3 e3)-               => (e -> e1 -> e2 -> e3) -> a i e -> a1 i e1 -> a2 i e2 -> a3 i e3-liftArray3P f a b c | aBounds == bounds b && aBounds == bounds c =-                       listArray aBounds (zipWith3 f (elems a) (elems b) (elems c))-                   | otherwise = error "liftArray2: array bounds must match"-    where aBounds = bounds a---- | Less polymorphic version.-liftArray3 :: (Ix i, IArray a e, IArray a e1, IArray a e2, IArray a e3)-              => (e -> e1 -> e2 -> e3) -> a i e -> a i e1 -> a i e2 -> a i e3-liftArray3 = liftArray3P----- | Hack so that norms have a sensible type.-class Abs a b | a -> b where-    abs_ :: a -> b-instance Abs (Complex Double) Double where-    abs_ = magnitude-instance Abs (Complex Float) Float where-    abs_ = magnitude-instance Abs Double Double where-    abs_ = abs-instance Abs Float Float where-    abs_ = abs----- | Allocate an array which is 16-byte aligned.  Essential for SIMD instructions.-mallocForeignPtrArrayAligned :: Storable a => Int -> IO (ForeignPtr a)-mallocForeignPtrArrayAligned n = doMalloc undefined-  where-    doMalloc :: Storable b => b -> IO (ForeignPtr b)-    doMalloc dummy = mallocForeignPtrBytesAligned (n * sizeOf dummy)---- | Allocate memory which is 16-byte aligned.  This is essential for SIMD--- instructions.  We know that mallocPlainForeignPtrBytes will give word-aligned--- memory, so we pad enough to be able to return the desired amount of memory--- after aligning our pointer.-mallocForeignPtrBytesAligned :: Int -> IO (ForeignPtr a)-mallocForeignPtrBytesAligned n = do-    (ForeignPtr addr contents) <- mallocPlainForeignPtrBytes (n + pad)-    let !(Ptr addr') = alignPtr (Ptr addr) 16-    return (ForeignPtr addr' contents)-    where pad = 16 - sizeOf (undefined :: Word)---- | Make a new CArray with an IO action.-createCArray :: (Ix i, Storable e) => (i,i) -> (Ptr e -> IO ()) -> IO (CArray i e)-createCArray lu f = do-    fp <- mallocForeignPtrArrayAligned (rangeSize lu)-    withForeignPtr fp f-    unsafeForeignPtrToCArray fp lu--unsafeCreateCArray :: (Ix i, Storable e) => (i,i) -> (Ptr e -> IO ()) -> CArray i e-unsafeCreateCArray lu =  unsafePerformIO . createCArray lu---instance (Ix i, Binary i, Binary e, Storable e) => Binary (CArray i e) where-    put a = do-        put (bounds a)-        mapM_ put (elems a)-    get = do-        lu <- get-        es <- replicateM (rangeSize lu) get-        return $ listArray lu es
− Data/Array/IOCArray.hs
@@ -1,40 +0,0 @@--------------------------------------------------------------------------------- |--- Module      : Data.Array.IOCArray--- Copyright   : (c) 2008 Jed Brown--- License     : BSD-style--- --- Maintainer  : jed@59A2.org--- Stability   : experimental--- Portability : non-portable------ This module provides both the mutable 'IOCArray' which uses pinned memory on--- the GC'd heap.  Elements are stored according to the class 'Storable'.  You--- can obtain a pointer to the array contents to manipulate elements from--- languages like C.------ 'IOCArray' is 16-byte aligned by default.  If you create a 'IOCArray' with--- 'unsafeForeignPtrToIOCArray' then it may not be aligned.  This will be an--- issue if you intend to use SIMD instructions.------ 'IOCArray' is equivalent to 'Data.Array.Storable.StorableArray' and similar--- to 'Data.Array.IO.IOUArray' but slower.  'IOCArray' has O(1) versions of--- 'unsafeFreeze' and 'unsafeThaw' when converting to/from 'CArray'.---------------------------------------------------------------------------------module Data.Array.IOCArray (-    -- * IOCArray type-    IOCArray,--    -- * Foreign support-    withIOCArray,-    touchIOCArray,-    unsafeForeignPtrToIOCArray,--    -- * The overloaded mutable array interface-    module Data.Array.MArray-) where--import Data.Array.CArray.Base-import Data.Array.MArray
Makefile view
@@ -1,5 +1,6 @@ test:-	runhaskell Setup configure --user+	runhaskell Setup configure --user --enable-tests --enable-benchmarks 	runhaskell Setup build 	runhaskell Setup haddock+	./dist/build/test/test 	(cd tests; sh runtests.sh)
carray.cabal view
@@ -1,39 +1,33 @@ name:                carray-version:             0.1.5.2+version:             0.1.6 synopsis:            A C-compatible array library. description:-		     A C-compatible array library.-		     .-		     Provides both an immutable and mutable (in the IO monad) interface.-		     Includes utilities for multi-dimensional arrays, slicing and norms.-		     Memory is 16-byte aligned by default to enable use of SIMD instructions.-		     .+  A C-compatible array library.+  .+  Provides both an immutable and mutable (in the IO monad) interface.+  Includes utilities for multi-dimensional arrays, slicing and norms.+  Memory is 16-byte aligned by default to enable use of SIMD instructions. category:            Data license:             BSD3 license-file:        LICENSE author:              Jed Brown maintainer:          Jed Brown <jed@59A2.org>, Henning Thielemann <fft@henning-thielemann.de> stability:	     experimental-cabal-version:       >=1.6+cabal-version:       >=1.14 build-type:	     Simple -extra-source-files: tests/meteor-contest-c.hs-                    tests/meteor-contest-u.hs-                    tests/nsieve-bits-c.hs-                    tests/nsieve-bits-s.hs-                    tests/nsieve-bits-u.hs-                    tests/tests.hs-                    tests/runtests.sh-                    Makefile+extra-source-files:+  tests/runtests.sh+  Makefile  source-repository this-  tag:         0.1.5.2+  tag:         0.1.6   type:        darcs-  location:    http://code.haskell.org/carray/+  location:    http://hub.darcs.net/thielema/carray/  source-repository head   type:        darcs-  location:    http://code.haskell.org/carray/+  location:    http://hub.darcs.net/thielema/carray/   flag splitBase@@ -44,23 +38,94 @@   description: syb was split from base >= 4   library-  build-depends:   ix-shapable, binary+  build-depends:+    ix-shapable >=0.1 && <0.2,+    binary >=0.5 && <0.8,+    QuickCheck >=2.4 && <2.8+   if flag(bytestringInBase)-    build-depends: base >= 2.0 && < 2.2+    build-depends: base >=2.0 && <2.2   else-    build-depends: base < 2.0 || >= 3, bytestring+    build-depends: base <2.0 || >=3, bytestring >=0.9 && <0.11    if flag(splitBase)-    build-depends: base >= 3, array+    build-depends: base >=3, array >=0.1 && <0.6   else-    build-depends: base < 3+    build-depends: base <3    if flag(base4)-    build-depends: base >= 4 && < 5, syb >= 0.1+    build-depends: base >=4 && <5, syb >=0.1 && <0.6   else-    build-depends: base < 4+    build-depends: base <4 -  exposed-modules:   Data.Array.CArray-                     Data.Array.IOCArray-                     Data.Array.CArray.Base+  exposed-modules:+    Data.Array.CArray+    Data.Array.IOCArray+    Data.Array.CArray.Base   ghc-options: -Wall+  hs-source-dirs: src+  default-language:  Haskell98++test-suite test+  main-is: tests.hs+  ghc-options: -Wall+  hs-source-dirs: tests+  type: exitcode-stdio-1.0+  default-language:  Haskell98+  build-depends:+    QuickCheck,+    ix-shapable,+    carray,+    array,+    base++benchmark meteor-contest-c+  main-is: meteor-contest-c.hs+  ghc-options: -Wall+  hs-source-dirs: tests+  type: exitcode-stdio-1.0+  default-language:  Haskell98+  build-depends:+    carray,+    base++benchmark meteor-contest-u+  main-is: meteor-contest-u.hs+  ghc-options: -Wall+  hs-source-dirs: tests+  type: exitcode-stdio-1.0+  default-language:  Haskell98+  build-depends:+    array,+    base++benchmark nsieve-bits-c+  main-is: nsieve-bits-c.hs+  ghc-options: -Wall+  hs-source-dirs: tests+  type: exitcode-stdio-1.0+  default-language:  Haskell98+  build-depends:+    carray,+    array,+    base++benchmark nsieve-bits-s+  main-is: nsieve-bits-s.hs+  ghc-options: -Wall+  hs-source-dirs: tests+  type: exitcode-stdio-1.0+  default-language:  Haskell98+  build-depends:+    array,+    base++benchmark nsieve-bits-u+  main-is: nsieve-bits-u.hs+  ghc-options: -Wall+  hs-source-dirs: tests+  type: exitcode-stdio-1.0+  default-language:  Haskell98+  build-depends:+    array,+    base
+ src/Data/Array/CArray.hs view
@@ -0,0 +1,91 @@+-- |+-- Module      : Data.Array.CArray+-- Copyright   : (c) 2008 Jed Brown+-- License     : BSD-style+-- +-- Maintainer  : jed@59A2.org+-- Stability   : experimental+-- Portability : non-portable+--+-- This module provides the immutable 'CArray' which uses pinned memory on the+-- GC'd heap.  Elements are stored according to the class 'Storable'.  You can+-- obtain a pointer to the array contents to manipulate elements from+-- languages like C.+--+-- 'CArray' is 16-byte aligned by default.  If you create a 'CArray' with+-- 'unsafeForeignPtrToCArray' then it may not be aligned.  This will be an issue+-- if you intend to use SIMD instructions.+--+-- 'CArray' is similar to 'Data.Array.Unboxed.UArray' but slower if you stay+-- within Haskell.  'CArray' can handle more types and can be used by external+-- libraries.+--+-- 'CArray' has an instance of 'Binary'.+-----------------------------------------------------------------------------++module Data.Array.CArray (+    -- * CArray type+    CArray,++    -- * Multi-dimensional++    -- ** Fast reshaping+    reshape,+    flatten,++    -- ** Query+    rank,+    shape,+    size,++    -- * Mapping++    -- ** General+    ixmapWithIndP,+    ixmapWithInd,+    ixmapWithP,+    ixmapWith,+    ixmapP,++    -- ** Slicing+    sliceStrideWithP,+    sliceStrideWith,+    sliceStrideP,+    sliceStride,+    sliceWithP,+    sliceWith,+    sliceP,+    slice,++    -- * Lifting+    liftArrayP,+    liftArray,+    liftArray2P,+    liftArray2,+    liftArray3P,+    liftArray3,++    -- * Norms+    normp,+    norm2,+    normSup,++    -- * Types+    Shapable,+    Abs,++    -- * Unsafe low-level+    withCArray,+    unsafeForeignPtrToCArray,+    toForeignPtr,+    unsafeCArrayToByteString,+    unsafeByteStringToCArray,+    createCArray,++   -- * The overloaded immutable array interface+   module Data.Array.IArray+) where++import Data.Ix.Shapable+import Data.Array.IArray+import Data.Array.CArray.Base
+ src/Data/Array/CArray/Base.hs view
@@ -0,0 +1,565 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-}+#ifdef __GLASGOW_HASKELL__+#if __GLASGOW_HASKELL__ < 610+{-# OPTIONS_GHC -frewrite-rules #-}+#else+{-# OPTIONS_GHC -fenable-rewrite-rules #-}+#endif+#endif+-----------------------------------------------------------------------------+-- |+-- Module      : Data.Array.CArray.Base+-- Copyright   : (c) 2001 The University of Glasgow+--               (c) 2008 Jed Brown+-- License     : BSD-style+-- +-- Maintainer  : jed@59A2.org+-- Stability   : experimental+-- Portability : non-portable+--+-- This module provides both the immutable 'CArray' and mutable 'IOCArray'.  The+-- underlying storage is exactly the same - pinned memory on the GC'd heap.+-- Elements are stored according to the class 'Storable'.  You can obtain a+-- pointer to the array contents to manipulate elements from languages like C.+--+-- 'CArray' is 16-byte aligned by default.  If you create a 'CArray' with+-- 'unsafeForeignPtrToCArray' then it may not be aligned.  This will be an issue+-- if you intend to use SIMD instructions.+--+-- 'CArray' is similar to 'Data.Array.Unboxed.UArray' but slower if you stay+-- within Haskell.  'CArray' can handle more types and can be used by external+-- libraries.+--+-- 'IOCArray' is equivalent to 'Data.Array.Storable.StorableArray' and similar+-- to 'Data.Array.IO.IOUArray' but slower.  'IOCArray' has O(1) versions of+-- 'unsafeFreeze' and 'unsafeThaw' when converting to/from 'CArray'.+-----------------------------------------------------------------------------++module Data.Array.CArray.Base where++import Data.Array.Base+            (bounds, elems, listArray, unsafeAt, assocs, (!),+             numElements, getNumElements, showsIArray,+             unsafeFreeze, unsafeThaw,+             unsafeRead, unsafeWrite,+             unsafeArray, unsafeReplace, unsafeAccum,+             unsafeAccumArray, unsafeNewArray_)+import Data.Array.MArray+            (MArray(getBounds, newArray, newArray_), freeze, thaw)+import Data.Array.IArray (IArray)+import Data.Ix.Shapable (Shapable, shape, sShape, shapeToStride, size)+import Data.Ix (Ix, rangeSize, range, inRange, index)++import qualified Test.QuickCheck as QC+import Test.QuickCheck (Arbitrary, arbitrary, CoArbitrary, coarbitrary,)+import qualified Data.ByteString.Internal as S+import Data.Binary (Binary, get, put)++import System.IO.Unsafe (unsafePerformIO)+import Foreign.Storable+            (Storable, sizeOf, alignment, peek, peekElemOff, pokeElemOff)+import Foreign.ForeignPtr+            (ForeignPtr, withForeignPtr, castForeignPtr, touchForeignPtr)+import Foreign.Marshal.Array (copyArray, withArray)+import Foreign.Ptr (plusPtr, alignPtr, castPtr)++import Data.Word                (Word8, Word)+import Data.Generics            (Data(..), Typeable)+import GHC.Ptr                  (Ptr(..))+import GHC.ForeignPtr           (ForeignPtr(..), mallocPlainForeignPtrBytes)++import Data.Complex (Complex, magnitude)+import Data.List (zipWith4, foldl')+import Control.Monad (replicateM, forM_, (>=>))+import Control.Applicative (liftA2)+++-- | The immutable array type.+data CArray i e = CArray !i !i Int !(ForeignPtr e)+    deriving (Data, Typeable)++-- | Absolutely equivalent representation, but used for the mutable interface.+data IOCArray i e = IOCArray !i !i Int !(ForeignPtr e)+    deriving (Data, Typeable)++instance Storable e => MArray IOCArray e IO where+    getBounds (IOCArray l u _ _) = return (l,u)++    getNumElements (IOCArray _ _ n _) = return n++    newArray (l,u) e0 = do+        fp <- mallocForeignPtrArrayAligned n+        withForeignPtr fp $ \a ->+            forM_ [0 .. n - 1] $ \i -> pokeElemOff a i e0+        return (IOCArray l u n fp)+        where n = rangeSize (l,u)++    unsafeNewArray_ (l,u) = do+        let n = rangeSize (l,u)+        fp <- mallocForeignPtrArrayAligned n+        return (IOCArray l u n fp)++    newArray_ = unsafeNewArray_++    unsafeRead (IOCArray _ _ _ fp) i =+        withForeignPtr fp $ \a -> peekElemOff a i++    unsafeWrite (IOCArray _ _ _ fp) i e =+        withForeignPtr fp $ \a -> pokeElemOff a i e++-- | The pointer to the array contents is obtained by 'withCArray'.+-- The idea is similar to 'ForeignPtr' (used internally here).+-- The pointer should be used only during execution of the 'IO' action+-- retured by the function passed as argument to 'withCArray'.+withCArray :: CArray i e -> (Ptr e -> IO a) -> IO a+withCArray (CArray _ _ _ fp) f = withForeignPtr fp f++withIOCArray :: IOCArray i e -> (Ptr e -> IO a) -> IO a+withIOCArray (IOCArray _ _ _ fp) f = withForeignPtr fp f++-- | If you want to use it afterwards, ensure that you+-- 'touchCArray' after the last use of the pointer,+-- so the array is not freed too early.+touchIOCArray :: IOCArray i e -> IO ()+touchIOCArray (IOCArray _ _ _ fp) = touchForeignPtr fp++-- | /O(1)/ Construct a 'CArray' from an arbitrary 'ForeignPtr'.  It is+-- the caller's responsibility to ensure that the 'ForeignPtr' points to+-- an area of memory sufficient for the specified bounds.+unsafeForeignPtrToCArray+   :: Ix i => ForeignPtr e -> (i,i) -> IO (CArray i e)+unsafeForeignPtrToCArray p (l,u) =+   return (CArray l u (rangeSize (l,u)) p)++-- | /O(1)/ Construct a 'CArray' from an arbitrary 'ForeignPtr'.  It is+-- the caller's responsibility to ensure that the 'ForeignPtr' points to+-- an area of memory sufficient for the specified bounds.+unsafeForeignPtrToIOCArray+   :: Ix i => ForeignPtr e -> (i,i) -> IO (IOCArray i e)+unsafeForeignPtrToIOCArray p (l,u) =+   return (IOCArray l u (rangeSize (l,u)) p)++-- | /O(1)/ Extract ForeignPtr from a CArray.+toForeignPtr :: CArray i e -> (Int, ForeignPtr e)+toForeignPtr (CArray _ _ n fp) = (n, fp)++-- | /O(1)/ Turn a CArray into a ByteString.  Unsafe because it uses+-- 'castForeignPtr' and thus is not platform independent.+unsafeCArrayToByteString :: (Storable e) => CArray i e -> S.ByteString+unsafeCArrayToByteString (CArray _ _ l fp) = go undefined fp+    where go :: (Storable e) => e -> ForeignPtr e -> S.ByteString+          go dummy fp' = S.fromForeignPtr (castForeignPtr fp') 0 (l * sizeOf dummy)++-- | /O(1)/ Turn a ByteString into a CArray.  Unsafe because it uses+-- 'castForeignPtr' and thus is not platform independent.  Returns 'Nothing' if+-- the range specified is larger than the size of the ByteString or the start of+-- the ByteString does not fulfil the alignment requirement of the resulting+-- CArray (as specified by the Storable instance).+unsafeByteStringToCArray :: (Ix i, Storable e)+                            => (i,i) -> S.ByteString -> Maybe (CArray i e)+unsafeByteStringToCArray lu bs = go undefined lu+    where go :: (Ix i, Storable e) => e -> (i,i) -> Maybe (CArray i e)+          go dummy (l,u) | safe = Just (CArray l u n fp)+                         | otherwise = Nothing+              where n = rangeSize (l,u)+                    !((ForeignPtr addr contents), off, len) = S.toForeignPtr bs+                    !p@(Ptr addr') = Ptr addr `plusPtr` off+                    fp = ForeignPtr addr' contents+                    safe = sizeOf dummy * n <= len && p == p `alignPtr` alignment dummy++copy :: (Ix i, Storable e) => CArray i e -> IO (CArray i e)+copy ain@(CArray l u n _) =+    createCArray (l,u) $ \op ->+        withCArray ain $ \ip ->+            copyArray op ip n++freezeIOCArray :: (Ix i, Storable e) => IOCArray i e -> IO (CArray i e)+freezeIOCArray = unsafeFreezeIOCArray >=> copy++unsafeFreezeIOCArray :: (Ix i) => IOCArray i e -> IO (CArray i e)+unsafeFreezeIOCArray (IOCArray l u n fp) = return (CArray l u n fp)++thawIOCArray :: (Ix i, Storable e) => CArray i e -> IO (IOCArray i e)+thawIOCArray = copy >=> unsafeThawIOCArray++unsafeThawIOCArray :: (Ix i) => CArray i e -> IO (IOCArray i e)+unsafeThawIOCArray (CArray l u n fp) = return (IOCArray l u n fp)++-- Since we can remove the (Storable e) restriction for these, the rules are+-- compact and general.+{-# RULES+"unsafeFreeze/IOCArray" unsafeFreeze = unsafeFreezeIOCArray+"unsafeThaw/IOCArray" unsafeThaw = unsafeThawIOCArray+  #-}++-- Since we can't parameterize the rules with the (Storable e) constraint, we+-- have to specialize manually.  This is unfortunate since it is less general.+{-# RULES+"freeze/IOCArray/Int"    freeze      = freezeIOCArray :: (Ix i) => IOCArray i Int -> IO (CArray i Int)+"freeze/IOCArray/Float"  freeze      = freezeIOCArray :: (Ix i) => IOCArray i Float -> IO (CArray i Float)+"freeze/IOCArray/Double" freeze      = freezeIOCArray :: (Ix i) => IOCArray i Double -> IO (CArray i Double)+"thaw/IOCArray/Int"      thaw        = thawIOCArray   :: (Ix i) => CArray i Int -> IO (IOCArray i Int)+"thaw/IOCArray/Float"    thaw        = thawIOCArray   :: (Ix i) => CArray i Float -> IO (IOCArray i Float)+"thaw/IOCArray/Double"   thaw        = thawIOCArray   :: (Ix i) => CArray i Double -> IO (IOCArray i Double)+  #-}+++instance Storable e => IArray CArray e where+    {-# INLINE bounds #-}+    bounds (CArray l u _ _) = (l,u)+    {-# INLINE numElements #-}+    numElements (CArray _ _ n _) = n+    {-# NOINLINE unsafeArray #-}+    unsafeArray lu ies = unsafePerformIO $ unsafeArrayCArray lu ies (zeroElem (undefined :: e))+    {-# INLINE unsafeAt #-}+    unsafeAt (CArray _ _ _ fp) i = S.inlinePerformIO $+                                   withForeignPtr fp $ \a -> peekElemOff a i+    {-# NOINLINE unsafeReplace #-}+    unsafeReplace arr ies = unsafePerformIO $ unsafeReplaceCArray arr ies+    {-# NOINLINE unsafeAccum #-}+    unsafeAccum f arr ies = unsafePerformIO $ unsafeAccumCArray f arr ies+    {-# NOINLINE unsafeAccumArray #-}+    unsafeAccumArray f e0 lu ies = unsafePerformIO $ unsafeAccumArrayCArray f e0 lu ies+++-- | Hackish way to get the zero element for a Storable type.+{-# NOINLINE zeroElem #-}+zeroElem :: Storable a => a -> a+zeroElem u = unsafePerformIO $+    withArray (replicate (sizeOf u) (0 :: Word8)) $ peek . castPtr++{-# INLINE unsafeArrayCArray #-}+unsafeArrayCArray :: (Storable e, Ix i)+                  => (i,i) -> [(Int, e)] -> e -> IO (CArray i e)+unsafeArrayCArray lu ies default_elem = do+    marr <- newArray lu default_elem+    mapM_ (uncurry $ unsafeWrite marr) ies+    unsafeFreezeIOCArray marr++{-# INLINE unsafeReplaceCArray #-}+unsafeReplaceCArray :: (Storable e, Ix i)+                       => CArray i e -> [(Int, e)] -> IO (CArray i e)+unsafeReplaceCArray arr ies = do+    marr <- thawIOCArray arr+    mapM_ (uncurry $ unsafeWrite marr) ies+    unsafeFreezeIOCArray marr++{-# INLINE unsafeAccumCArray #-}+unsafeAccumCArray :: (Storable e, Ix i)+                            => (e -> e' -> e) -> CArray i e -> [(Int, e')]+                                              -> IO (CArray i e)+unsafeAccumCArray f arr ies = do+    marr <- thawIOCArray arr+    forM_ ies $ \(i, new) -> do+        old <- unsafeRead marr i+        unsafeWrite marr i (f old new)+    unsafeFreezeIOCArray marr++{-# INLINE unsafeAccumArrayCArray #-}+unsafeAccumArrayCArray :: (Storable e, Ix i)+                          => (e -> e' -> e) -> e -> (i,i) -> [(Int, e')]+                                            -> IO (CArray i e)+unsafeAccumArrayCArray f e0 lu ies = do+    marr <- newArray lu e0+    forM_ ies $ \(i, new) -> do+        old <- unsafeRead marr i+        unsafeWrite marr i (f old new)+    unsafeFreezeIOCArray marr++{-# INLINE eqCArray #-}+eqCArray :: (Storable e, Ix i, Eq e)+                   => CArray i e -> CArray i e -> Bool+eqCArray arr1@(CArray l1 u1 n1 _) arr2@(CArray l2 u2 n2 _) =+    if n1 == 0 then n2 == 0 else+        l1 == l2 && u1 == u2 &&+           and [unsafeAt arr1 i == unsafeAt arr2 i | i <- [0 .. n1 - 1]]++{-# INLINE [1] cmpCArray #-}+cmpCArray :: (Storable e, Ix i, Ord e)+                    => CArray i e -> CArray i e -> Ordering+cmpCArray arr1 arr2 = compare (assocs arr1) (assocs arr2)++{-# INLINE cmpIntCArray #-}+cmpIntCArray :: (Storable e, Ord e)+                       => CArray Int e -> CArray Int e -> Ordering+cmpIntCArray arr1@(CArray l1 u1 n1 _) arr2@(CArray l2 u2 n2 _) =+    if n1 == 0 then if n2 == 0 then EQ else LT else+    if n2 == 0 then GT else+    case compare l1 l2 of+        EQ    -> foldr cmp (compare u1 u2) [0 .. (n1 `min` n2) - 1]+        other -> other+    where+    cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of+        EQ    -> rest+        other -> other++{-# RULES "cmpCArray/Int" cmpCArray = cmpIntCArray #-}++instance (Ix ix, Eq e, Storable e) => Eq (CArray ix e) where+    (==) = eqCArray++instance (Ix ix, Ord e, Storable e) => Ord (CArray ix e) where+    compare = cmpCArray++instance (Ix ix, Show ix, Show e, Storable e) => Show (CArray ix e) where+    showsPrec = showsIArray++--+-- General purpose array operations which happen to be very fast for CArray.+--++-- | O(1) reshape an array.  The number of elements in the new shape must not+-- exceed the number in the old shape.  The elements are in C-style ordering.+reshape :: (Ix i, Ix j) => (j,j) -> CArray i e -> CArray j e+reshape (l',u') (CArray _ _ n fp) | n' > n = error "reshape: new size too large"+                                  | otherwise = CArray l' u' n' fp+    where n' = rangeSize (l', u')++-- | O(1) make a rank 1 array from an arbitrary shape.+-- It has the property that 'reshape (0, size a - 1) a == flatten a'.+flatten :: Ix i => CArray i e -> CArray Int e+flatten (CArray _ _ n fp) = CArray 0 (n - 1) n fp++--+-- None of the following are specific to CArray.  Some could have slightly+-- faster versions specialized to CArray.  In general, slicing is expensive+-- because the slice is not contiguous in memory, so must be copied.  There are+-- many specialized versions.+--++-- | Generic slice and map.  This takes the new range, the inverse map on+-- indices, and function to produce the next element.  It is the most general+-- operation in its class.+ixmapWithIndP :: (Ix i, Ix i', IArray a e, IArray a' e')+                 => (i',i') -> (i' -> i) -> (i -> e -> i' -> e') -> a i e -> a' i' e'+ixmapWithIndP lu f g arr = listArray lu+                           [ let i = f i' in g i (arr ! i) i' | i' <- range lu ]++-- | Less polymorphic version.+ixmapWithInd :: (Ix i, Ix i', IArray a e, IArray a e')+                => (i',i') -> (i' -> i) -> (i -> e -> i' -> e') -> a i e -> a i' e'+ixmapWithInd = ixmapWithIndP++-- | Perform an operation on the elements, independent of their location.+ixmapWithP  :: (Ix i, Ix i', IArray a e, IArray a' e')+               => (i',i') -> (i' -> i) -> (e -> e') -> a i e -> a' i' e'+ixmapWithP lu f g arr = listArray lu+                        [ g (arr ! f i') | i' <- range lu ]++-- | Less polymorphic version.+ixmapWith  :: (Ix i, Ix i', IArray a e, IArray a e')+              => (i',i') -> (i' -> i) -> (e -> e') -> a i e -> a i' e'+ixmapWith = ixmapWithP++-- | More polymorphic version of 'ixmap'.+ixmapP :: (Ix i, Ix i', IArray a e, IArray a' e)+          => (i',i') -> (i' -> i) -> a i e -> a' i' e+ixmapP lu f arr = ixmapWithP lu f id arr++-- | More friendly sub-arrays with element mapping.+sliceStrideWithP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e')+                    => (i',i') -> (i,i,i) -> (e -> e') -> a i e -> a' i' e'+sliceStrideWithP lu (start,next,end) f arr+    | all (inRange (bounds arr)) [start,next,end] = listArray lu es+    | otherwise = error "sliceStrideWith: out of bounds"+    where is = offsetShapeFromThenTo (shape arr) (index' start) (index' next) (index' end)+          es = map (f . (unsafeAt arr)) is+          index' = indexes arr++-- | Less polymorphic version.+sliceStrideWith :: (Ix i, Shapable i, Ix i', IArray a e, IArray a e')+                   => (i',i') -> (i,i,i) -> (e -> e') -> a i e -> a i' e'+sliceStrideWith = sliceStrideWithP++-- | Strided sub-array without element mapping.+sliceStrideP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e)+                => (i',i') -> (i,i,i) -> a i e -> a' i' e+sliceStrideP lu sne = sliceStrideWithP lu sne id++-- | Less polymorphic version.+sliceStride :: (Ix i, Shapable i, Ix i', IArray a e)+               => (i',i') -> (i,i,i) -> a i e -> a i' e+sliceStride = sliceStrideP++-- | Contiguous sub-array with element mapping.+sliceWithP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e')+              => (i',i') -> (i,i) -> (e -> e') -> a i e -> a' i' e'+sliceWithP lu (start,end) f arr+    | all (inRange (bounds arr)) [start,end] = listArray lu es+    | otherwise = error "sliceWith: out of bounds"+    where is = offsetShapeFromTo (shape arr) (index' start) (index' end)+          es = map (f . (unsafeAt arr)) is+          index' = indexes arr++-- | Less polymorphic version.+sliceWith :: (Ix i, Shapable i, Ix i', IArray a e, IArray a e')+             => (i',i') -> (i,i) -> (e -> e') -> a i e -> a i' e'+sliceWith = sliceWithP++-- | Contiguous sub-array without element mapping.+sliceP :: (Ix i, Shapable i, Ix i', IArray a e, IArray a' e)+          => (i',i') -> (i,i) -> a i e -> a' i' e+sliceP lu se = sliceWithP lu se id++-- | Less polymorphic version.+slice ::  (Ix i, Shapable i, Ix i', IArray a e)+          => (i',i') -> (i,i) -> a i e -> a i' e+slice = sliceP++-- | In-place map on CArray.  Note that this is /IN PLACE/ so you should not+-- retain any reference to the original.  It flagrantly breaks referential+-- transparency!+{-# INLINE mapCArrayInPlace #-}+mapCArrayInPlace :: (Ix i, Storable e) => (e -> e) -> CArray i e -> CArray i e+mapCArrayInPlace f a = S.inlinePerformIO $ do+    withCArray a $ \p ->+        forM_ [0 .. size a - 1] $ \i ->+            peekElemOff p i >>= pokeElemOff p i . f+    return a++-----------------------------------------+-- These are meant to be internal only+indexes :: (Ix i, Shapable i, IArray a e) => a i e -> i -> [Int]+indexes a i = map pred $ (sShape . fst . bounds) a i++offsetShapeFromThenTo :: [Int] -> [Int] -> [Int] -> [Int] -> [Int]+offsetShapeFromThenTo s a b c = foldr (liftA2 (+)) [0] (ilists stride a b c)+    where ilists = zipWith4 (\s' a' b' c' -> map (*s') $ enumFromThenTo a' b' c')+          stride = shapeToStride s++offsetShapeFromTo :: [Int] -> [Int] -> [Int] -> [Int]+offsetShapeFromTo = offsetShapeFromTo' id++offsetShapeFromTo' :: ([[Int]] -> [[Int]]) -> [Int] -> [Int] -> [Int] -> [Int]+offsetShapeFromTo' f s a b = foldr (liftA2 (+)) [0] (f $ ilists stride a b)+    where ilists = zipWith3 (\s' a' b' -> map (*s') $ enumFromTo a' b')+          stride = shapeToStride s++offsets :: (Ix a, Shapable a) => (a, a) -> a -> [Int]+offsets lu i = reverse . osets (index lu i) . reverse . scanl1 (*) . uncurry sShape $ lu+    where osets 0 [] = []+          osets i' (b:bs) = r : osets d bs+              where (d,r) = i' `divMod` b+          osets _ _ = error "osets"+-----------------------------------------++-- | p-norm on the array taken as a vector+normp :: (Ix i, RealFloat e', Abs e e', IArray a e) => e' -> a i e -> e'+normp p a | 1 <= p && not (isInfinite p) = (** (1/p)) $ foldl' (\z e -> z + (abs_ e) ** p) 0 (elems a)+          | otherwise = error "normp: p < 1"++-- | 2-norm on the array taken as a vector (Frobenius norm for matrices)+norm2 :: (Ix i, Floating e', Abs e e', IArray a e) => a i e -> e'+norm2 a = sqrt $ foldl' (\z e -> z + abs_ e ^ (2 :: Int)) 0 (elems a)++-- | Sup norm on the array taken as a vector+normSup :: (Ix i, Num e', Ord e', Abs e e', IArray a e) => a i e -> e'+normSup a = foldl' (\z e -> z `max` abs_ e) 0 (elems a)++-- | Polymorphic version of amap.+liftArrayP :: (Ix i, IArray a e, IArray a1 e1)+              => (e -> e1) -> a i e -> a1 i e1+liftArrayP f a = listArray (bounds a) (map f (elems a))++-- | Equivalent to amap.  Here for consistency only.+liftArray :: (Ix i, IArray a e, IArray a e1)+              => (e -> e1) -> a i e -> a i e1+liftArray = liftArrayP++-- | Polymorphic 2-array lift.+liftArray2P :: (Ix i, IArray a e, IArray a1 e1, IArray a2 e2)+              => (e -> e1 -> e2) -> a i e -> a1 i e1 -> a2 i e2+liftArray2P f a b | aBounds == bounds b =+                     listArray aBounds (zipWith f (elems a) (elems b))+                 | otherwise = error "liftArray2: array bounds must match"+    where aBounds = bounds a++-- | Less polymorphic version.+liftArray2 :: (Ix i, IArray a e, IArray a e1, IArray a e2)+              => (e -> e1 -> e2) -> a i e -> a i e1 -> a i e2+liftArray2 = liftArray2P++-- | Polymorphic 3-array lift.+liftArray3P :: (Ix i, IArray a e, IArray a1 e1, IArray a2 e2, IArray a3 e3)+               => (e -> e1 -> e2 -> e3) -> a i e -> a1 i e1 -> a2 i e2 -> a3 i e3+liftArray3P f a b c | aBounds == bounds b && aBounds == bounds c =+                       listArray aBounds (zipWith3 f (elems a) (elems b) (elems c))+                   | otherwise = error "liftArray2: array bounds must match"+    where aBounds = bounds a++-- | Less polymorphic version.+liftArray3 :: (Ix i, IArray a e, IArray a e1, IArray a e2, IArray a e3)+              => (e -> e1 -> e2 -> e3) -> a i e -> a i e1 -> a i e2 -> a i e3+liftArray3 = liftArray3P+++-- | Hack so that norms have a sensible type.+class Abs a b | a -> b where+    abs_ :: a -> b+instance Abs (Complex Double) Double where+    abs_ = magnitude+instance Abs (Complex Float) Float where+    abs_ = magnitude+instance Abs Double Double where+    abs_ = abs+instance Abs Float Float where+    abs_ = abs+++-- | Allocate an array which is 16-byte aligned.  Essential for SIMD instructions.+mallocForeignPtrArrayAligned :: Storable a => Int -> IO (ForeignPtr a)+mallocForeignPtrArrayAligned n = doMalloc undefined+  where+    doMalloc :: Storable b => b -> IO (ForeignPtr b)+    doMalloc dummy = mallocForeignPtrBytesAligned (n * sizeOf dummy)++-- | Allocate memory which is 16-byte aligned.  This is essential for SIMD+-- instructions.  We know that mallocPlainForeignPtrBytes will give word-aligned+-- memory, so we pad enough to be able to return the desired amount of memory+-- after aligning our pointer.+mallocForeignPtrBytesAligned :: Int -> IO (ForeignPtr a)+mallocForeignPtrBytesAligned n = do+    (ForeignPtr addr contents) <- mallocPlainForeignPtrBytes (n + pad)+    let !(Ptr addr') = alignPtr (Ptr addr) 16+    return (ForeignPtr addr' contents)+    where pad = 16 - sizeOf (undefined :: Word)++-- | Make a new CArray with an IO action.+createCArray :: (Ix i, Storable e) => (i,i) -> (Ptr e -> IO ()) -> IO (CArray i e)+createCArray lu f = do+    fp <- mallocForeignPtrArrayAligned (rangeSize lu)+    withForeignPtr fp f+    unsafeForeignPtrToCArray fp lu++unsafeCreateCArray :: (Ix i, Storable e) => (i,i) -> (Ptr e -> IO ()) -> CArray i e+unsafeCreateCArray lu =  unsafePerformIO . createCArray lu+++instance (Ix i, Binary i, Binary e, Storable e) => Binary (CArray i e) where+    put a = do+        put (bounds a)+        mapM_ put (elems a)+    get = do+        lu <- get+        es <- replicateM (rangeSize lu) get+        return $ listArray lu es+++instance+    (Ix i, Arbitrary i, Storable e, Arbitrary e) =>+        Arbitrary (CArray i e) where+    arbitrary = do+        a <- QC.arbitrary+        b <- QC.arbitrary+        let rng = (min a b, max a b)+        fmap (listArray rng) $ QC.vector (rangeSize rng)++instance+    (Ix i, CoArbitrary i, Storable e, CoArbitrary e) =>+        CoArbitrary (CArray i e) where+    coarbitrary a = coarbitrary (assocs a)
+ src/Data/Array/IOCArray.hs view
@@ -0,0 +1,40 @@+-----------------------------------------------------------------------------+-- |+-- Module      : Data.Array.IOCArray+-- Copyright   : (c) 2008 Jed Brown+-- License     : BSD-style+-- +-- Maintainer  : jed@59A2.org+-- Stability   : experimental+-- Portability : non-portable+--+-- This module provides both the mutable 'IOCArray' which uses pinned memory on+-- the GC'd heap.  Elements are stored according to the class 'Storable'.  You+-- can obtain a pointer to the array contents to manipulate elements from+-- languages like C.+--+-- 'IOCArray' is 16-byte aligned by default.  If you create a 'IOCArray' with+-- 'unsafeForeignPtrToIOCArray' then it may not be aligned.  This will be an+-- issue if you intend to use SIMD instructions.+--+-- 'IOCArray' is equivalent to 'Data.Array.Storable.StorableArray' and similar+-- to 'Data.Array.IO.IOUArray' but slower.  'IOCArray' has O(1) versions of+-- 'unsafeFreeze' and 'unsafeThaw' when converting to/from 'CArray'.+-----------------------------------------------------------------------------+++module Data.Array.IOCArray (+    -- * IOCArray type+    IOCArray,++    -- * Foreign support+    withIOCArray,+    touchIOCArray,+    unsafeForeignPtrToIOCArray,++    -- * The overloaded mutable array interface+    module Data.Array.MArray+) where++import Data.Array.CArray.Base+import Data.Array.MArray
tests/meteor-contest-c.hs view
@@ -7,13 +7,17 @@ --   Sterling Clover's translation of Tim Hochberg's Clean implementation  module Main where-import System.Environment-import Data.Bits-import Data.List-import Data.Array.CArray-import Control.Arrow +import System.Environment (getArgs)+import Data.Bits (setBit, testBit, shiftL, shiftR, (.&.), (.|.))+import Data.List (partition, intersperse, find, delete)+import Data.Array.CArray (CArray, Array, array, (!))+import Control.Arrow (first, (&&&))+import Prelude hiding (flip)++ --- The Board ---+n_elem, n_col, n_row :: Int n_elem = 5 n_col = 5 n_row = 10@@ -27,8 +31,13 @@ colors :: [Color] colors = [0..9] +cellAt :: Int -> Int -> Int cellAt x y = x + n_col * y++coordOf :: Int -> (Int, Int) coordOf i = snd &&& fst $ i `quotRem` n_col++isValid :: Int -> Col -> Bool isValid x y = 0 <= x && x < n_col && 0 <= y && y < n_row  --- Piece Operations ---@@ -53,9 +62,9 @@ 	  [E,  NW, NW, NW]]  permutations :: Piece -> [Piece]-permutations p = take 12 (perms p)+permutations = take 12 . perms     where-      perms p = p:(flip p) : perms (rotate p)+      perms p = p : flip p : perms (rotate p)       rotate piece = map r piece           where r E  = NE                 r NE = NW@@ -96,8 +105,13 @@     | otherwise = 1 + first0 (i `shiftR` 1)  --- Making the Bitmasks ---+mod2 :: Int -> Int mod2 x = x .&. 1++packSize :: Num a => a -> a -> a packSize a b = a*5+b++unpackSize :: Integral a => a -> (a, a) unpackSize n = quotRem n 5  move :: Direction -> CellCoord -> CellCoord@@ -153,7 +167,7 @@         | test mask x = x         | otherwise   = fnd test (x+step) -noLeftIslands :: Mask -> Bool+noLeftIslands, noRightIslands :: Mask -> Bool noLeftIslands  mask  = noLineIslands mask 0 20 5 noRightIslands mask  = noLineIslands mask 4 24 5 @@ -173,7 +187,7 @@     | x < 0 || x >= n_col = m     | y < 0 || y >= 6     = m     | testBit m i = m-    | otherwise = foldl (\m d -> fill m (move d cc)) (setBit m i)+    | otherwise = foldl (\mi d -> fill mi (move d cc)) (setBit m i)                   [E, NE, NW, W, SW, SE]     where i = cellAt x y @@ -182,9 +196,10 @@ masksForColor c = concatMap atCell cells   where     (evens, odds) = templatesForColor c-    atCell n-        | even y = [(y, retag (m `shiftL` x) c) | m <- evens , isok m x y]-        | odd  y = [(y, retag (m `shiftL` x) c) | m <- odds  , isok m x y]+    atCell n =+        if even y+          then [(y, retag (m `shiftL` x) c) | m <- evens , isok m x y]+          else [(y, retag (m `shiftL` x) c) | m <- odds  , isok m x y]         where (x, y) = coordOf n  isok :: Mask -> Row -> Col -> Bool@@ -250,7 +265,7 @@ solutions = solveCell 0 colors 0 [] []  solveCell :: Row -> [Color] -> Mask -> Solution -> [String] -> [String]-solveCell _ [] board soln results = let s = toString soln+solveCell _ [] _board soln results = let s = toString soln                                     in  s:(reverse s):results solveCell !row !todo !board !soln results     | top/=m_top = foldr solveMask results@@ -258,9 +273,10 @@     | otherwise  = solveCell (row+1) todo (board `shiftR` n_col) soln results     where top = board .&. m_top           masks = masksAtCell ! (row, (firstZero ! top) )-          solveMask (!m,!c) results =-              solveCell row (delete c todo) (untag m .|. board) (m:soln) results+          solveMask (!m,!c) ress =+              solveCell row (delete c todo) (untag m .|. board) (m:soln) ress +main :: IO () main = do     n <- return.read.head =<< getArgs     let nsolutions = take n solutions
tests/meteor-contest-u.hs view
@@ -7,13 +7,17 @@ --   Sterling Clover's translation of Tim Hochberg's Clean implementation  module Main where-import System.Environment-import Data.Bits-import Data.List-import Data.Array.Unboxed-import Control.Arrow +import System.Environment (getArgs)+import Data.Bits (setBit, testBit, shiftL, shiftR, (.&.), (.|.))+import Data.List (partition, intersperse, find, delete)+import Data.Array.Unboxed (UArray, Array, array, (!))+import Control.Arrow (first, (&&&))+import Prelude hiding (flip)++ --- The Board ---+n_elem, n_col, n_row :: Int n_elem = 5 n_col = 5 n_row = 10@@ -27,8 +31,13 @@ colors :: [Color] colors = [0..9] +cellAt :: Int -> Int -> Int cellAt x y = x + n_col * y++coordOf :: Int -> (Int, Int) coordOf i = snd &&& fst $ i `quotRem` n_col++isValid :: Int -> Col -> Bool isValid x y = 0 <= x && x < n_col && 0 <= y && y < n_row  --- Piece Operations ---@@ -53,9 +62,9 @@ 	  [E,  NW, NW, NW]]  permutations :: Piece -> [Piece]-permutations p = take 12 (perms p)+permutations = take 12 . perms     where-      perms p = p:(flip p) : perms (rotate p)+      perms p = p : flip p : perms (rotate p)       rotate piece = map r piece           where r E  = NE                 r NE = NW@@ -96,8 +105,13 @@     | otherwise = 1 + first0 (i `shiftR` 1)  --- Making the Bitmasks ---+mod2 :: Int -> Int mod2 x = x .&. 1++packSize :: Num a => a -> a -> a packSize a b = a*5+b++unpackSize :: Integral a => a -> (a, a) unpackSize n = quotRem n 5  move :: Direction -> CellCoord -> CellCoord@@ -153,7 +167,7 @@         | test mask x = x         | otherwise   = fnd test (x+step) -noLeftIslands :: Mask -> Bool+noLeftIslands, noRightIslands :: Mask -> Bool noLeftIslands  mask  = noLineIslands mask 0 20 5 noRightIslands mask  = noLineIslands mask 4 24 5 @@ -173,7 +187,7 @@     | x < 0 || x >= n_col = m     | y < 0 || y >= 6     = m     | testBit m i = m-    | otherwise = foldl (\m d -> fill m (move d cc)) (setBit m i)+    | otherwise = foldl (\mi d -> fill mi (move d cc)) (setBit m i)                   [E, NE, NW, W, SW, SE]     where i = cellAt x y @@ -182,9 +196,10 @@ masksForColor c = concatMap atCell cells   where     (evens, odds) = templatesForColor c-    atCell n-        | even y = [(y, retag (m `shiftL` x) c) | m <- evens , isok m x y]-        | odd  y = [(y, retag (m `shiftL` x) c) | m <- odds  , isok m x y]+    atCell n =+        if even y+          then [(y, retag (m `shiftL` x) c) | m <- evens , isok m x y]+          else [(y, retag (m `shiftL` x) c) | m <- odds  , isok m x y]         where (x, y) = coordOf n  isok :: Mask -> Row -> Col -> Bool@@ -250,7 +265,7 @@ solutions = solveCell 0 colors 0 [] []  solveCell :: Row -> [Color] -> Mask -> Solution -> [String] -> [String]-solveCell _ [] board soln results = let s = toString soln+solveCell _ [] _board soln results = let s = toString soln                                     in  s:(reverse s):results solveCell !row !todo !board !soln results     | top/=m_top = foldr solveMask results@@ -258,9 +273,10 @@     | otherwise  = solveCell (row+1) todo (board `shiftR` n_col) soln results     where top = board .&. m_top           masks = masksAtCell ! (row, (firstZero ! top) )-          solveMask (!m,!c) results =-              solveCell row (delete c todo) (untag m .|. board) (m:soln) results+          solveMask (!m,!c) ress =+              solveCell row (delete c todo) (untag m .|. board) (m:soln) ress +main :: IO () main = do     n <- return.read.head =<< getArgs     let nsolutions = take n solutions
tests/nsieve-bits-c.hs view
@@ -1,4 +1,5 @@ {-# OPTIONS -O2 -optc-O #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE BangPatterns#-}  --@@ -9,24 +10,31 @@ -- nsieve over an ST monad Bool array -- -import Data.Array.IOCArray-import Data.Array.Base-import Data.Array.CArray.Base-import System.IO.Unsafe (unsafePerformIO)-import System.Environment-import Control.Monad-import Data.Bits-import Text.Printf+import Data.Array.IOCArray (IOCArray)+import Data.Array.MArray (MArray, newArray)+import Data.Array.Base (unsafeRead, unsafeWrite) +import System.Environment (getArgs)+import Control.Monad (when)+import Data.Bits (shiftL)+import Text.Printf (printf)+++main :: IO () main = do     n <- getArgs >>= readIO . head :: IO Int     mapM_ (sieve . (10000 *) . (2 ^)) [n, n-1, n-2] +sieve :: Int -> IO () sieve n = do-   let r = unsafePerformIO (do a <- newArray (2,n) True :: IO (IOCArray Int Bool)-                               go a n 2 0)+   r <- do+      a <- newArray (2,n) True :: IO (IOCArray Int Bool)+      go a n 2 0    printf "Primes up to %8d %8d\n" (n::Int) (r::Int) :: IO () +go ::+   (MArray array Bool m, Num a) =>+   array Int Bool -> Int -> Int -> a -> m a go !a !m !n !c     | n == m    = return c     | otherwise = do@@ -40,5 +48,3 @@                           | otherwise = go a m (n+1) (c+1)                     in loop (n `shiftL` 1)                else go a m (n+1) c--
tests/nsieve-bits-s.hs view
@@ -1,4 +1,5 @@ {-# OPTIONS -O2 -optc-O #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE BangPatterns#-}  --@@ -9,24 +10,31 @@ -- nsieve over an ST monad Bool array -- -import Control.Monad-import Data.Array.Storable-import Data.Array.Base-import System.IO.Unsafe (unsafePerformIO)-import System.Environment-import Control.Monad-import Data.Bits-import Text.Printf+import Data.Array.Storable (StorableArray)+import Data.Array.MArray (MArray, newArray)+import Data.Array.Base (unsafeRead, unsafeWrite) +import System.Environment (getArgs)+import Control.Monad (when)+import Data.Bits (shiftL)+import Text.Printf (printf)+++main :: IO () main = do     n <- getArgs >>= readIO . head :: IO Int     mapM_ (sieve . (10000 *) . (2 ^)) [n, n-1, n-2] +sieve :: Int -> IO () sieve n = do-   let r = unsafePerformIO (do a <- newArray (2,n) True :: IO (StorableArray Int Bool)-                               go a n 2 0)+   r <- do+      a <- newArray (2,n) True :: IO (StorableArray Int Bool)+      go a n 2 0    printf "Primes up to %8d %8d\n" (n::Int) (r::Int) :: IO () +go ::+   (MArray array Bool m, Num a) =>+   array Int Bool -> Int -> Int -> a -> m a go !a !m !n !c     | n == m    = return c     | otherwise = do@@ -40,5 +48,3 @@                           | otherwise = go a m (n+1) (c+1)                     in loop (n `shiftL` 1)                else go a m (n+1) c--
tests/nsieve-bits-u.hs view
@@ -1,4 +1,5 @@ {-# OPTIONS -O2 -optc-O #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE BangPatterns#-}  --@@ -9,23 +10,31 @@ -- nsieve over an ST monad Bool array -- -import Control.Monad.ST-import Data.Array.ST-import Data.Array.Base-import System.Environment-import Control.Monad-import Data.Bits-import Text.Printf+import Control.Monad.ST (ST, runST)+import Data.Array.ST (STUArray)+import Data.Array.MArray (MArray, newArray)+import Data.Array.Base (unsafeRead, unsafeWrite) +import System.Environment (getArgs)+import Control.Monad (when)+import Data.Bits (shiftL)+import Text.Printf (printf)+++main :: IO () main = do     n <- getArgs >>= readIO . head :: IO Int     mapM_ (sieve . (10000 *) . (2 ^)) [n, n-1, n-2] +sieve :: Int -> IO () sieve n = do    let r = runST (do a <- newArray (2,n) True :: ST s (STUArray s Int Bool)                      go a n 2 0)    printf "Primes up to %8d %8d\n" (n::Int) (r::Int) :: IO () +go ::+   (MArray array Bool m, Num a) =>+   array Int Bool -> Int -> Int -> a -> m a go !a !m !n !c     | n == m    = return c     | otherwise = do@@ -39,5 +48,3 @@                           | otherwise = go a m (n+1) (c+1)                     in loop (n `shiftL` 1)                else go a m (n+1) c--
tests/runtests.sh view
@@ -1,14 +1,10 @@ #!/bin/sh -compile () {-    ghc --make -O2 $1 -o $2-}- time_run () {     arg=$1     shift     for e in $* ; do-	time ./$e $arg > $e.out+	time ../dist/build/$e/$e $arg > $e.out     done     diffn $* }@@ -24,12 +20,5 @@     echo '########' Failures: $ret } -compile nsieve-bits-u.hs nsU-compile nsieve-bits-c.hs nsC-compile nsieve-bits-s.hs nsS--compile meteor-contest-u.hs mcU-compile meteor-contest-c.hs mcC--time_run 8 nsU nsC nsS-time_run 2098 mcU mcC+time_run 8 nsieve-bits-u nsieve-bits-c nsieve-bits-s+time_run 2098 meteor-contest-u meteor-contest-c
tests/tests.hs view
@@ -1,39 +1,23 @@-{-# OPTIONS_GHC -fglasgow-exts #-}-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies, NoMonomorphismRestriction, UndecidableInstances #-}-import Control.Arrow-import Test.QuickCheck-import Text.Show.Functions+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+import qualified Test.QuickCheck as QC+import Test.QuickCheck (Property, (==>))+import Control.Arrow ((&&&), (***))+import Text.Show.Functions () import Data.Array.CArray+          (CArray, flatten, ixmapWithInd, rank, reshape, shape, size, sliceWith) import Data.Ix.Shapable (shapeToStride) import Data.Array.Unboxed-import Data.Binary-import Data.List-import Foreign.Storable-import Text.Printf+          (IArray, Ix, UArray,+           accum, amap, bounds, elems, inRange, ixmap, listArray, rangeSize)+import Foreign.Storable (Storable)+import Text.Printf (printf) import System.Environment (getArgs)-import System.IO-import System.Random+-- import System.Random -instance (Ix i, Arbitrary i, Storable e, Arbitrary e) => Arbitrary (CArray i e) where-    arbitrary = do-        a <- arbitrary-        b <- arbitrary-        let l = min a b-            u = max a b-        es <- vector (rangeSize (l,u))-        return $ listArray (l,u) es-    coarbitrary a = coarbitrary (assocs a) -instance (Ix i, Arbitrary i, Arbitrary e, IArray UArray e) => Arbitrary (UArray i e) where-    arbitrary = do-        a <- arbitrary-        b <- arbitrary-        let l = min a b-            u = max a b-        es <- vector (rangeSize (l,u))-        return $ listArray (l,u) es-    coarbitrary a = coarbitrary (assocs a)-+-- cf. storablevector/test class Model a b where model :: a -> b  instance (Ix i, IArray a e, Model i i', Model e e') => Model (a i e) ((i',i'),[e']) where@@ -59,27 +43,36 @@ instance (Model a a', Model b b', Model c c', Model d d') => Model (a,b,c,d) (a',b',c',d') where     model (a,b,c,d) = (model a, model b, model c, model d) -f =|= g = \a         ->-    model (f a)         == g (model a)+(=||=) ::+   (Model x1 y1, Model x y, Eq y) =>+   (x2 -> x1 -> x) -> (x2 -> y1 -> y) -> x2 -> x1 -> Bool++(=|||=) ::+   (Model x2 y2, Model x y, Eq y) =>+   (x3 -> x2 -> x1 -> x) -> (x3 -> y2 -> x1 -> y) -> x3 -> x2 -> x1 -> Bool+++infix 1 =||=, =|||=+ f =||= g = \a b       ->     model (f a b)       == g a (model b)-infix 1 =|=-infix 1 =||=- f =|||= g = \a b c     ->     model (f a b c)     == g a (model b) c-eq4 f g = \a b c d   ->-    model (f a b c d)   == g (model a) (model b) (model c) (model d)-eq5 f g = \a b c d e ->-    model (f a b c d e) == g (model a) (model b) (model c) (model d) (model e)  (===) :: (Eq b) => (a -> b) -> (a -> b) -> a -> Bool (f === g) x = f x == g x infixl 1 === +transposeArray :: CArray (Int,Int) Double -> CArray (Int,Int) Double transposeArray a = ixmap ((swap *** swap) (bounds a)) swap a     where swap = (\(i,j) -> (j,i)) ++type Test2D = CArray (Int,Int) Double -> Bool++prop_flatten_flatten, prop_reshape_flatten, prop_rank,+    prop_shape_size, prop_size, prop_shape_stride_last, prop_transpose :: Test2D+ prop_flatten_flatten = flatten . flatten === flatten prop_reshape_flatten a = reshape (0, size a - 1) a == flatten a prop_rank = length . shape === rank@@ -89,15 +82,17 @@ prop_transpose = transposeArray . transposeArray === id  ca_tests :: [(String, CArray (Int,Int) Double -> Bool)]-ca_tests = [ ("flatten flatten"   , prop_flatten_flatten)-           , ("reshape flatten"   , prop_reshape_flatten)-           , ("rank"              , prop_rank)-           , ("shape size"        , prop_shape_size)-           , ("size"              , prop_size)-           , ("shape stride last" , prop_shape_stride_last)-           , ("transpose^2"       , prop_transpose)-           ]+ca_tests =+    ("flatten flatten"   , prop_flatten_flatten) :+    ("reshape flatten"   , prop_reshape_flatten) :+    ("rank"              , prop_rank) :+    ("shape size"        , prop_shape_size) :+    ("size"              , prop_size) :+    ("shape stride last" , prop_shape_stride_last) :+    ("transpose^2"       , prop_transpose) :+    [] +prop_amap :: (Int -> Double) -> CArray Int Int -> Bool prop_amap =    (amap :: (Int -> Double) -> CArray Int Int -> CArray Int Double)           =||= (amap :: (Int -> Double) -> UArray Int Int -> UArray Int Double) @@ -107,22 +102,24 @@ prop_ixmapWithInd_amap f a = size a > 0 ==> ixmapWithInd (bounds a) id (\_ e _ -> f e) a == amap f a  type Acc = Int+prop_accum :: (Int -> Acc -> Int) -> CArray Int Int -> [(Int, Acc)] -> Property prop_accum f a ies = all (inRange (bounds a) . fst) ies     ==> (      (accum :: (Int -> Acc -> Int) -> CArray Int Int -> [(Int, Acc)] -> CArray Int Int)          =|||= (accum :: (Int -> Acc -> Int) -> UArray Int Int -> [(Int, Acc)] -> UArray Int Int)) f a ies +type Transform = CArray Int Int -> CArray Int Int++prop_composeAssoc ::+    Transform -> Transform -> Transform -> CArray Int Int -> Bool prop_composeAssoc f g h = (f . g) . h === f . (g . h)-    where types = [f,g,h] :: [CArray Int Int -> CArray Int Int] +main :: IO () main = do-    x <- getArgs-    let n = if null x then 100 else read . head $ x-        conf = Config { configMaxTest = n-                      , configMaxFail = 1000-                      , configSize = (+ 3) . (`div` 2)-                      , configEvery = \n args -> let s = show n in s ++ [ '\b' | _ <- s]-                      }-        mycheck (s,a) = printf "%-25s: " s >> check conf a+    args <- getArgs+    n <- case args of [] -> return 100; str:_ -> readIO str+    let mycheck (s,a) =+            printf "%-25s: " s >>+            QC.quickCheckWith (QC.stdArgs {QC.maxSuccess = n}) a     mapM_ mycheck ca_tests     mapM_ mycheck [ ("amap"        , prop_amap) ]     mapM_ mycheck [ ("accum"       , prop_accum) ]