packages feed

array-primops 0.1.0.0 → 0.2.0.0

raw patch · 7 files changed

+561/−247 lines, 7 filesdep +QuickCheckdep +array-primopsdep +tastydep ~basedep ~ghc-primPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, array-primops, tasty, tasty-quickcheck

Dependency ranges changed: base, ghc-prim

API changes (from Hackage documentation)

+ GHC.Prim.Array: snocArrayWithPadding# :: Int# -> a -> Array# a -> a -> Array# a
+ GHC.Prim.SmallArray: consSmallArray# :: a -> SmallArray# a -> SmallArray# a
+ GHC.Prim.SmallArray: deleteSmallArray# :: Int# -> SmallArray# a -> SmallArray# a
+ GHC.Prim.SmallArray: insertSmallArray# :: Int# -> a -> SmallArray# a -> SmallArray# a
+ GHC.Prim.SmallArray: snocSmallArray# :: SmallArray# a -> a -> SmallArray# a
+ GHC.Prim.SmallArray: snocSmallArrayWithPadding# :: Int# -> a -> SmallArray# a -> a -> SmallArray# a
- GHC.Prim.Array: consArray# :: Any -> Array# a -> Array# a
+ GHC.Prim.Array: consArray# :: a -> Array# a -> Array# a
- GHC.Prim.Array: insertArray# :: Int# -> Any -> Array# a -> Array# a
+ GHC.Prim.Array: insertArray# :: Int# -> a -> Array# a -> Array# a
- GHC.Prim.Array: snocArray# :: Array# a -> Any -> Array# a
+ GHC.Prim.Array: snocArray# :: Array# a -> a -> Array# a

Files

GHC/Prim/Array.hs view
@@ -3,22 +3,48 @@     MagicHash, ForeignFunctionInterface,     GHCForeignImportPrim, UnliftedFFITypes #-} -module GHC.Prim.Array where+module GHC.Prim.Array (+    consArray#+  , snocArray#+  , snocArrayWithPadding#+  , insertArray#+  , deleteArray#+  ) where -import GHC.Prim (Int#, Array#, Any)+import GHC.Prim  -- | Prepend an element to an array.-foreign import prim "consArray" consArray#+foreign import prim "consArray" consArray_   :: Any -> Array# a -> Array# a  -- | Append an element to the end of an array.-foreign import prim "snocArray" snocArray#+foreign import prim "snocArray" snocArray_   :: Array# a -> Any -> Array# a +foreign import prim "snocArrayWithPadding" snocArrayWithPadding_+  :: Int# -> Any -> Array# a -> Any -> Array# a+ -- | Insert new element at position.-foreign import prim "insertArray" insertArray#+foreign import prim "insertArray" insertArray_   :: Int# -> Any -> Array# a -> Array# a --- | Delete element at position. +-- | Delete element at position. foreign import prim "deleteArray" deleteArray#   :: Int# -> Array# a -> Array# a++consArray# :: a -> Array# a -> Array# a+consArray# a arr = consArray_ (unsafeCoerce# a) arr+{-# inline consArray# #-}++snocArray# :: Array# a -> a -> Array# a+snocArray# arr a = snocArray_ arr (unsafeCoerce# a)+{-# inline snocArray# #-}++snocArrayWithPadding# :: Int# -> a -> Array# a -> a -> Array# a+snocArrayWithPadding# pad padElem arr a =+  snocArrayWithPadding_ pad (unsafeCoerce# padElem) arr (unsafeCoerce# a)+{-# inline snocArrayWithPadding# #-}++insertArray# :: Int# -> a -> Array# a -> Array# a+insertArray# i a arr = insertArray_ i (unsafeCoerce# a) arr+{-# inline insertArray# #-}
GHC/Prim/SmallArray.hs view
@@ -3,22 +3,48 @@     MagicHash, ForeignFunctionInterface,     GHCForeignImportPrim, UnliftedFFITypes #-} -module GHC.Prim.SmallArray where+module GHC.Prim.SmallArray (+    consSmallArray#+  , snocSmallArray#+  , snocSmallArrayWithPadding#+  , insertSmallArray#+  , deleteSmallArray#+  ) where -import GHC.Prim (Int#, SmallArray#, Any)+import GHC.Prim  -- | Prepend an element to an array.-foreign import prim "consSmallArray" consSmallArray#+foreign import prim "consSmallArray" consSmallArray_   :: Any -> SmallArray# a -> SmallArray# a  -- | Append an element to the end of an array.-foreign import prim "snocSmallArray" snocSmallArray#+foreign import prim "snocSmallArray" snocSmallArray_   :: SmallArray# a -> Any -> SmallArray# a +foreign import prim "snocSmallArrayWithPadding" snocSmallArrayWithPadding_+  :: Int# -> Any -> SmallArray# a -> Any -> SmallArray# a+ -- | Insert new element at position.-foreign import prim "insertSmallArray" insertSmallArray#+foreign import prim "insertSmallArray" insertSmallArray_   :: Int# -> Any -> SmallArray# a -> SmallArray# a --- | Delete element at position. +-- | Delete element at position. foreign import prim "deleteSmallArray" deleteSmallArray#   :: Int# -> SmallArray# a -> SmallArray# a++consSmallArray# :: a -> SmallArray# a -> SmallArray# a+consSmallArray# a arr = consSmallArray_ (unsafeCoerce# a) arr+{-# inline consSmallArray# #-}++snocSmallArray# :: SmallArray# a -> a -> SmallArray# a+snocSmallArray# arr a = snocSmallArray_ arr (unsafeCoerce# a)+{-# inline snocSmallArray# #-}++snocSmallArrayWithPadding# :: Int# -> a -> SmallArray# a -> a -> SmallArray# a+snocSmallArrayWithPadding# pad padElem arr a =+  snocSmallArrayWithPadding_ pad (unsafeCoerce# padElem) arr (unsafeCoerce# a)+{-# inline snocSmallArrayWithPadding# #-}++insertSmallArray# :: Int# -> a -> SmallArray# a -> SmallArray# a+insertSmallArray# i a arr = insertSmallArray_ i (unsafeCoerce# a) arr+{-# inline insertSmallArray# #-}
array-primops.cabal view
@@ -1,6 +1,6 @@  name:                array-primops-version:             0.1.0.0+version:             0.2.0.0 synopsis:            Extra foreign primops for primitive arrays license:             BSD3 license-file:        LICENSE@@ -34,21 +34,28 @@     c-sources:       cbits/array.cmm   -    if impl(ghc >= 7.10)-    -      exposed-modules:-        GHC.Prim.SmallArray--      build-depends:-        ghc-prim >= 0.4.0.0+  if impl(ghc >= 7.10)+  +    exposed-modules:+      GHC.Prim.SmallArray -      c-sources:-        cbits/smallArray.cmm+    build-depends:+      ghc-prim >= 0.4.0.0 +    c-sources:+      cbits/smallArray.cmm +test-suite tests+  hs-source-dirs: tests+  main-is: Tests.hs+  type: exitcode-stdio-1.0+  build-depends:+    QuickCheck, tasty, tasty-quickcheck, ghc-prim, base, array-primops+  ghc-options: -O2+                 benchmark benchmarks   default-language: Haskell2010-  hs-source-dirs: . benchmarks+  hs-source-dirs: benchmarks    main-is: Benchmarks.hs   type: exitcode-stdio-1.0@@ -56,10 +63,7 @@   build-depends:     base,     ghc-prim,+    array-primops,     criterion >= 1.0--  c-sources: -    cbits/array.cmm,-    cbits/smallArray.cmm    ghc-options: -O2 -fllvm
benchmarks/Benchmarks.hs view
@@ -4,16 +4,30 @@     BangPatterns, CPP, MagicHash, UnboxedTuples,     UnliftedFFITypes, GHCForeignImportPrim #-} +{-# OPTIONS -fno-full-laziness #-}+ import GHC.Types-import GHC.Prim-import GHC.ST+import GHC.Prim hiding (runSTRep)  import GHC.Prim.Array import GHC.Prim.SmallArray import Criterion.Main import Criterion.Types +#include "MachDeps.h" +runSTRep :: (forall s. State# s -> (# State# s, a #)) -> a+runSTRep f = case f realWorld# of (# _ , a #) -> a+{-# INLINE [0] runSTRep #-}++-- runSA :: (forall s. State# s -> (# State# s, SmallArray# a #)) -> SmallArray# a+-- runSA f = case f realWorld# of (# _ , arr #) -> arr+-- {-# INLINE [0] runSA #-}++-- runA :: (forall s. State# s -> (# State# s, Array# a #)) -> Array# a+-- runA f = case f realWorld# of (# _ , arr #) -> arr+-- {-# INLINE [0] runA #-}+ an  n = fromListA  [(0::Int)..n] san n = fromListSA [(0::Int)..n] @@ -21,140 +35,167 @@ a100  = an 100 a1000 = an 1000 +sa2    = san 2+sa5    = san 5 sa10   = san 10 sa100  = san 100 sa1000 = san 1000 - main = defaultMainWith (defaultConfig {timeLimit = 2}) [-  bgroup "cons" [-     -     bgroup "Array" [-        bgroup "10" [-           bench "prim" $ whnf (consA 0)     a10,-           bench "slow" $ whnf (consASlow 0) a10-           ],-        bgroup "100" [-           bench "prim" $ whnf (consA 0)     a100,-           bench "slow" $ whnf (consASlow 0) a100-           ],-        bgroup "1000" [-           bench "prim" $ whnf (consA 0)     a1000,-           bench "slow" $ whnf (consASlow 0) a1000-           ]-        ],-        +  -- bgroup "cons" [++  --    bgroup "Array" [+  --       bgroup "10" [+  --          bench "prim" $ whnf (consA 0)     a10,+  --          bench "slow" $ whnf (consASlow 0) a10+  --          ],+  --       bgroup "100" [+  --          bench "prim" $ whnf (consA 0)     a100,+  --          bench "slow" $ whnf (consASlow 0) a100+  --          ],+  --       bgroup "1000" [+  --          bench "prim" $ whnf (consA 0)     a1000,+  --          bench "slow" $ whnf (consASlow 0) a1000+  --          ]+  --       ],++  --    bgroup "SmallArray" [+  --       bgroup "10" [+  --          bench "prim" $ whnf (consSA 0)     sa10,+  --          bench "slow" $ whnf (consSASlow 0) sa10+  --          ],+  --       bgroup "100" [+  --          bench "prim" $ whnf (consSA 0)     sa100,+  --          bench "slow" $ whnf (consSASlow 0) sa100+  --          ],+  --       bgroup "1000" [+  --          bench "prim" $ whnf (consSA 0)     sa1000,+  --          bench "slow" $ whnf (consSASlow 0) sa1000+  --          ]+  --       ]+  --    ],++  -- bgroup "snoc" [++  --    bgroup "Array" [+  --       bgroup "10" [+  --          bench "prim" $ whnf (flip snocA 0)     a10,+  --          bench "slow" $ whnf (flip snocASlow 0) a10+  --          ],+  --       bgroup "100" [+  --          bench "prim" $ whnf (flip snocA 0)     a100,+  --          bench "slow" $ whnf (flip snocASlow 0) a100+  --          ],+  --       bgroup "1000" [+  --          bench "prim" $ whnf (flip snocA 0)     a1000,+  --          bench "slow" $ whnf (flip snocASlow 0) a1000+  --          ]+  --       ],++  --    bgroup "SmallArray" [+  --       bgroup "10" [+  --          bench "prim" $ whnf (flip snocSA 0)     sa10,+  --          bench "slow" $ whnf (flip snocSASlow 0) sa10+  --          ],+  --       bgroup "100" [+  --          bench "prim" $ whnf (flip snocSA 0)     sa100,+  --          bench "slow" $ whnf (flip snocSASlow 0) sa100+  --          ],+  --       bgroup "1000" [+  --          bench "prim" $ whnf (flip snocSA 0)     sa1000,+  --          bench "slow" $ whnf (flip snocSASlow 0) sa1000+  --          ]+  --       ]+  --    ],++  bgroup "insert" [++     -- bgroup "Array" [+     --    bgroup "10" [+     --       bench "prim" $ whnf (insertA 5 10)     a10,+     --       bench "slow" $ whnf (insertASlow 5 10) a10+     --       ],+     --    bgroup "100" [+     --       bench "prim" $ whnf (insertA 50 10)     a100,+     --       bench "slow" $ whnf (insertASlow 50 10) a100+     --       ],+     --    bgroup "1000" [+     --       bench "prim" $ whnf (insertA 500 10)     a1000,+     --       bench "slow" $ whnf (insertASlow 500 10) a1000+     --       ]+     --    ],+      bgroup "SmallArray" [-        bgroup "10" [-           bench "prim" $ whnf (consSA 0)     sa10,-           bench "slow" $ whnf (consSASlow 0) sa10+        bgroup "2" [+           bench "prim"   $ whnf (insertSA 0 10)      sa2,+           bench "slow"   $ whnf (insertSASlow 0 10)  sa2+           -- bench "unsafe" $ whnf (insertSAUnsafe 5 10) sa10            ],-        bgroup "100" [-           bench "prim" $ whnf (consSA 0)     sa100,-           bench "slow" $ whnf (consSASlow 0) sa100+        bgroup "5" [+           bench "prim"   $ whnf (insertSA 2 10)      sa5,+           bench "slow"   $ whnf (insertSASlow 2 10)  sa5+           -- bench "unsafe" $ whnf (insertSAUnsafe 5 10) sa10            ],-        bgroup "1000" [-           bench "prim" $ whnf (consSA 0)     sa1000,-           bench "slow" $ whnf (consSASlow 0) sa1000-           ]-        ]-     ],-  -  bgroup "snoc" [-     -     bgroup "Array" [         bgroup "10" [-           bench "prim" $ whnf (flip snocA 0)     a10,-           bench "slow" $ whnf (flip snocASlow 0) a10-           ],-        bgroup "100" [-           bench "prim" $ whnf (flip snocA 0)     a100,-           bench "slow" $ whnf (flip snocASlow 0) a100-           ],-        bgroup "1000" [-           bench "prim" $ whnf (flip snocA 0)     a1000,-           bench "slow" $ whnf (flip snocASlow 0) a1000-           ]-        ],-        -     bgroup "SmallArray" [-        bgroup "10" [-           bench "prim" $ whnf (flip snocSA 0)     sa10,-           bench "slow" $ whnf (flip snocSASlow 0) sa10+           bench "prim"   $ whnf (insertSA 5 10)      sa10,+           bench "slow"   $ whnf (insertSASlow 5 10)  sa10+           -- bench "unsafe" $ whnf (insertSAUnsafe 5 10) sa10            ],         bgroup "100" [-           bench "prim" $ whnf (flip snocSA 0)     sa100,-           bench "slow" $ whnf (flip snocSASlow 0) sa100+           bench "prim"   $ whnf (insertSA 50 10)     sa100,+           bench "slow"   $ whnf (insertSASlow 50 10) sa100+           -- bench "unsafe" $ whnf (insertSAUnsafe 50 10) sa10            ],         bgroup "1000" [-           bench "prim" $ whnf (flip snocSA 0)     sa1000,-           bench "slow" $ whnf (flip snocSASlow 0) sa1000+           bench "prim"   $ whnf (insertSA 500 10)     sa1000,+           bench "slow"   $ whnf (insertSASlow 500 10) sa1000+           -- bench "unsafe" $ whnf (insertSAUnsafe 500 10) sa10            ]         ]      ], -  bgroup "insert" [-     -     bgroup "Array" [-        bgroup "10" [-           bench "prim" $ whnf (insertA 5 10)     a10,-           bench "slow" $ whnf (insertASlow 5 10) a10-           ],-        bgroup "100" [-           bench "prim" $ whnf (insertA 50 10)     a100,-           bench "slow" $ whnf (insertASlow 50 10) a100-           ],-        bgroup "1000" [-           bench "prim" $ whnf (insertA 500 10)     a1000,-           bench "slow" $ whnf (insertASlow 500 10) a1000-           ]-        ],-        +  bgroup "delete" [++     -- bgroup "Array" [+     --    bgroup "10" [+     --       bench "prim" $ whnf (deleteA 5)     a10,+     --       bench "slow" $ whnf (deleteASlow 5) a10+     --       ],+     --    bgroup "100" [+     --       bench "prim" $ whnf (deleteA 50)     a100,+     --       bench "slow" $ whnf (deleteASlow 50) a100+     --       ],+     --    bgroup "1000" [+     --       bench "prim" $ whnf (deleteA 500)     a1000,+     --       bench "slow" $ whnf (deleteASlow 500) a1000+     --       ]+     --    ],+      bgroup "SmallArray" [-        bgroup "10" [-           bench "prim" $ whnf (insertSA 5 10)     sa10,-           bench "slow" $ whnf (insertSASlow 5 10) sa10+        bgroup "2" [+           bench "prim"   $ whnf (deleteSA 0)       sa2,+           bench "slow"   $ whnf (deleteSASlow 0)   sa2+           -- bench "unsafe" $ whnf (deleteSAUnsafe 5) sa10            ],-        bgroup "100" [-           bench "prim" $ whnf (insertSA 50 10)     sa100,-           bench "slow" $ whnf (insertSASlow 50 10) sa100+        bgroup "5" [+           bench "prim"   $ whnf (deleteSA 2)       sa5,+           bench "slow"   $ whnf (deleteSASlow 2)   sa5+           -- bench "unsafe" $ whnf (deleteSAUnsafe 5) sa10            ],-        bgroup "1000" [-           bench "prim" $ whnf (insertSA 500 10)     sa1000,-           bench "slow" $ whnf (insertSASlow 500 10) sa1000-           ]-        ]-     ],-  -  bgroup "delete" [-     -     bgroup "Array" [         bgroup "10" [-           bench "prim" $ whnf (deleteA 5)     a10,-           bench "slow" $ whnf (deleteASlow 5) a10-           ],-        bgroup "100" [-           bench "prim" $ whnf (deleteA 50)     a100,-           bench "slow" $ whnf (deleteASlow 50) a100-           ],-        bgroup "1000" [-           bench "prim" $ whnf (deleteA 500)     a1000,-           bench "slow" $ whnf (deleteASlow 500) a1000-           ]-        ],-        -     bgroup "SmallArray" [-        bgroup "10" [-           bench "prim" $ whnf (deleteSA 5)     sa10,-           bench "slow" $ whnf (deleteSASlow 5) sa10+           bench "prim"   $ whnf (deleteSA 5)       sa10,+           bench "slow"   $ whnf (deleteSASlow 5)   sa10+           -- bench "unsafe" $ whnf (deleteSAUnsafe 5) sa10            ],         bgroup "100" [-           bench "prim" $ whnf (deleteSA 50)     sa100,-           bench "slow" $ whnf (deleteSASlow 50) sa100+           bench "prim"   $ whnf (deleteSA 50)     sa100,+           bench "slow"   $ whnf (deleteSASlow 50) sa100+           -- bench "unsafe" $ whnf (deleteSAUnsafe 50) sa10            ],         bgroup "1000" [-           bench "prim" $ whnf (deleteSA 500)     sa1000,-           bench "slow" $ whnf (deleteSASlow 500) sa1000+           bench "prim"   $ whnf (deleteSA 500)     sa1000,+           bench "slow"   $ whnf (deleteSASlow 500) sa1000+           -- bench "unsafe" $ whnf (deleteSAUnsafe 500) sa10            ]         ]      ]@@ -180,7 +221,7 @@                 (# s , arr #) -> (# s, A arr #)  consA :: a -> A a -> A a-consA a (A arr) = A (consArray# (unsafeCoerce# a) arr)+consA a (A arr) = A (consArray# a arr)  consASlow :: a -> A a -> A a consASlow a (A arr) = runSTRep $ \s ->@@ -192,7 +233,7 @@           (# s, arr #) -> (# s, A arr #)  snocA :: A a -> a -> A a-snocA (A arr) a = A (snocArray# arr (unsafeCoerce# a))+snocA (A arr) a = A (snocArray# arr a)  snocASlow :: A a -> a -> A a snocASlow (A arr) a = runSTRep $ \s ->@@ -204,7 +245,7 @@           (# s, arr #) -> (# s, A arr #)  insertA :: Int -> a -> A a -> A a-insertA (I# i) a (A arr) = A (insertArray# i (unsafeCoerce# a) arr)+insertA (I# i) a (A arr) = A (insertArray# i a arr)  insertASlow :: Int -> a -> A a -> A a insertASlow (I# i) a (A arr) = runSTRep $ \s ->@@ -248,7 +289,7 @@                 (# s , arr #) -> (# s, SA arr #)  consSA :: a -> SA a -> SA a-consSA a (SA arr) = SA (consSmallArray# (unsafeCoerce# a) arr)+consSA a (SA arr) = SA (consSmallArray# a arr)  consSASlow :: a -> SA a -> SA a consSASlow a (SA arr) = runSTRep $ \s ->@@ -260,7 +301,7 @@           (# s, arr #) -> (# s, SA arr #)  snocSA :: SA a -> a -> SA a-snocSA (SA arr) a = SA (snocSmallArray# arr (unsafeCoerce# a))+snocSA (SA arr) a = SA (snocSmallArray# arr a)  snocSASlow :: SA a -> a -> SA a snocSASlow (SA arr) a = runSTRep $ \s ->@@ -272,7 +313,7 @@           (# s, arr #) -> (# s, SA arr #)  insertSA :: Int -> a -> SA a -> SA a-insertSA (I# i) a (SA arr) = SA (insertSmallArray# i (unsafeCoerce# a) arr)+insertSA (I# i) a (SA arr) = SA (insertSmallArray# i a arr)  insertSASlow :: Int -> a -> SA a -> SA a insertSASlow (I# i) a (SA arr) = runSTRep $ \s ->@@ -283,7 +324,7 @@         s -> case copySmallArray# arr i marr (i +# 1#) (size -# i) s of           s -> case unsafeFreezeSmallArray# marr s of             (# s, arr #) -> (# s, SA arr #)-            + deleteSA :: Int -> SA a -> SA a deleteSA (I# i) (SA arr) = SA (deleteSmallArray# i arr) @@ -295,4 +336,22 @@       s -> case copySmallArray# arr (i +# 1#) marr i (size -# i -# 1#) s of         s -> case unsafeFreezeSmallArray# marr s of           (# s, arr #) -> (# s, SA arr #)-                          ++insertSAUnsafe :: Int -> a -> SA a -> SA a+insertSAUnsafe (I# i) a (SA arr) = runSTRep $ \s ->+  let !len = sizeofSmallArray# arr in+  case newByteArray# (SIZEOF_HSWORD# *# (len +# 1#)) s of+    (# s, barr #) -> case copySmallArray# arr (-2#) (unsafeCoerce# barr) (-2#) (i +# 2#) s of+      s -> case writeIntOffAddr# (unsafeCoerce# barr) 1# (len +# 1#) s of+        s -> case writeSmallArray# (unsafeCoerce# barr) i a s of+          s -> case copySmallArray# arr i (unsafeCoerce# barr) (i +# 1#) (len -# i) s of+            s -> (# s, SA (unsafeCoerce# barr) #)++deleteSAUnsafe :: Int -> SA a -> SA a+deleteSAUnsafe (I# i) (SA arr) = runSTRep $ \s ->+  let !len = sizeofSmallArray# arr in+  case newByteArray# (SIZEOF_HSWORD# *# (len -# 1#)) s of+    (# s, barr #) -> case copySmallArray# arr (-2#) (unsafeCoerce# barr) (-2#) (i +# 2#) s of+      s -> case writeIntOffAddr# (unsafeCoerce# barr) 1# (len -# 1#) s of+        s -> case copySmallArray# arr (i +# 1#) (unsafeCoerce# barr) i (len -# i -# 1#) s of+          s -> (# s, SA (unsafeCoerce# barr) #)
cbits/array.cmm view
@@ -4,93 +4,136 @@ consArray(gcptr elem, gcptr src) {     W_ words, old_ptrs, new_ptrs, new_size;     gcptr dst, dst_p, src_end;-                                                               -    again: MAYBE_GC(again); -             ++    again: MAYBE_GC(again);+     old_ptrs = StgMutArrPtrs_ptrs(src);     new_ptrs = old_ptrs + 1;     new_size = new_ptrs + mutArrPtrsCardWords(new_ptrs);      words = BYTES_TO_WDS(SIZEOF_StgMutArrPtrs) + new_size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);     TICK_ALLOC_PRIM(SIZEOF_StgMutArrPtrs, WDS(new_size), 0);-    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);                                 +    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);     StgMutArrPtrs_ptrs(dst) = new_ptrs;-    StgMutArrPtrs_size(dst) = new_size;                               -                        -    dst_p   = dst + SIZEOF_StgMutArrPtrs;                   +    StgMutArrPtrs_size(dst) = new_size;++    dst_p   = dst + SIZEOF_StgMutArrPtrs;     src     = src + SIZEOF_StgMutArrPtrs;     src_end = src + WDS(old_ptrs);      W_[dst_p] = elem;     dst_p = dst_p + WDS(1); -  while:                                                       -    if (src != src_end) {                                         -        W_[dst_p] = W_[src];                                 -        dst_p = dst_p + WDS(1);                                -        src   = src   + WDS(1);                                -        goto while;                                            -    }                                                          -                                                               +  while:+    if (src != src_end) {+        W_[dst_p] = W_[src];+        dst_p = dst_p + WDS(1);+        src   = src   + WDS(1);+        goto while;+    }+     return (dst); }  snocArray(gcptr src, gcptr elem) {     W_ words, old_ptrs, new_ptrs, new_size;     gcptr dst, dst_p, src_end;-                                                               -    again: MAYBE_GC(again); -             ++    again: MAYBE_GC(again);+     old_ptrs = StgMutArrPtrs_ptrs(src);     new_ptrs = old_ptrs + 1;     new_size = new_ptrs + mutArrPtrsCardWords(new_ptrs);      words = BYTES_TO_WDS(SIZEOF_StgMutArrPtrs) + new_size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);     TICK_ALLOC_PRIM(SIZEOF_StgMutArrPtrs, WDS(new_size), 0);-    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);                                 +    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);     StgMutArrPtrs_ptrs(dst) = new_ptrs;-    StgMutArrPtrs_size(dst) = new_size;                                  -                        -    dst_p   = dst + SIZEOF_StgMutArrPtrs;                   +    StgMutArrPtrs_size(dst) = new_size;++    dst_p   = dst + SIZEOF_StgMutArrPtrs;     src     = src + SIZEOF_StgMutArrPtrs;     src_end = src + WDS(old_ptrs); -  while:                                                       -    if (src != src_end) {                                         -        W_[dst_p] = W_[src];                                 -        dst_p = dst_p + WDS(1);                                -        src   = src   + WDS(1);                                -        goto while;                                            +  while:+    if (src != src_end) {+        W_[dst_p] = W_[src];+        dst_p = dst_p + WDS(1);+        src   = src   + WDS(1);+        goto while;     }-    -    W_[dst_p] = elem;                                             -                                                               ++    W_[dst_p] = elem;+     return (dst); } +snocArrayWithPadding(W_ padding, gcptr padElem, gcptr src, gcptr elem) {+    W_ words, old_ptrs, new_ptrs, new_size;+    gcptr dst, dst_p, src_end, dst_end;++    again: MAYBE_GC(again);++    old_ptrs = StgMutArrPtrs_ptrs(src);+    new_ptrs = old_ptrs + 1 + padding;+    new_size = new_ptrs + mutArrPtrsCardWords(new_ptrs);++    words = BYTES_TO_WDS(SIZEOF_StgMutArrPtrs) + new_size;+    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);+    TICK_ALLOC_PRIM(SIZEOF_StgMutArrPtrs, WDS(new_size), 0);+    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);+    StgMutArrPtrs_ptrs(dst) = new_ptrs;+    StgMutArrPtrs_size(dst) = new_size;++    dst_p   = dst + SIZEOF_StgMutArrPtrs;+    src     = src + SIZEOF_StgMutArrPtrs;+    src_end = src + WDS(old_ptrs);+    dst_end = dst_p + WDS(new_ptrs);++  while1:+    if (src != src_end) {+        W_[dst_p] = W_[src];+        dst_p = dst_p + WDS(1);+        src   = src   + WDS(1);+        goto while1;+    }++    W_[dst_p] = elem;+    dst_p = dst_p + WDS(1);++  while2:+    if (dst_p != dst_end) {+        W_[dst_p] = padElem;+        dst_p = dst_p + WDS(1);+        goto while2;+    }    ++    return (dst);+}+ insertArray(W_ index, gcptr elem, gcptr src) {     W_ words, old_ptrs, new_ptrs, new_size;     gcptr src_p, dst, dst_p, dst_end, ins_p;-                                                               -    again: MAYBE_GC(again); -             ++    again: MAYBE_GC(again);+     old_ptrs = StgMutArrPtrs_ptrs(src);     new_ptrs = old_ptrs + 1;     new_size = new_ptrs + mutArrPtrsCardWords(new_ptrs);      words = BYTES_TO_WDS(SIZEOF_StgMutArrPtrs) + new_size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);     TICK_ALLOC_PRIM(SIZEOF_StgMutArrPtrs, WDS(new_size), 0);-    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);                                 +    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);     StgMutArrPtrs_ptrs(dst) = new_ptrs;-    StgMutArrPtrs_size(dst) = new_size;   +    StgMutArrPtrs_size(dst) = new_size;      src_p   = src + SIZEOF_StgMutArrPtrs;-    dst_p   = dst + SIZEOF_StgMutArrPtrs;                   +    dst_p   = dst + SIZEOF_StgMutArrPtrs;     ins_p   = dst_p + WDS(index);-    dst_end = dst_p + WDS(new_ptrs);    +    dst_end = dst_p + WDS(new_ptrs);      W_[ins_p] = elem; @@ -101,14 +144,14 @@        src_p = src_p + WDS(1);        goto while1;     }-    +     dst_p = dst_p + WDS(1);    while2:     if (dst_p != dst_end){        W_[dst_p] = W_[src_p];        dst_p = dst_p + WDS(1);-       src_p = src_p + WDS(1);      +       src_p = src_p + WDS(1);        goto while2;     } @@ -119,24 +162,24 @@      W_ words, old_ptrs, new_ptrs, new_size;     gcptr src_p, src_end, dst, dst_p, dst_end, del_p;-                                                               -    again: MAYBE_GC(again); -             ++    again: MAYBE_GC(again);+     old_ptrs = StgMutArrPtrs_ptrs(src);     new_ptrs = old_ptrs - 1;     new_size = new_ptrs + mutArrPtrsCardWords(new_ptrs);      words = BYTES_TO_WDS(SIZEOF_StgMutArrPtrs) + new_size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);     TICK_ALLOC_PRIM(SIZEOF_StgMutArrPtrs, WDS(new_size), 0);-    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);                                 +    SET_HDR(dst, stg_MUT_ARR_PTRS_FROZEN_info, CCCS);     StgMutArrPtrs_ptrs(dst) = new_ptrs;-    StgMutArrPtrs_size(dst) = new_size;   +    StgMutArrPtrs_size(dst) = new_size;      src_p   = src + SIZEOF_StgMutArrPtrs;-    dst_p   = dst + SIZEOF_StgMutArrPtrs;                   +    dst_p   = dst + SIZEOF_StgMutArrPtrs;     del_p   = src_p + WDS(index);-    src_end = src_p + WDS(old_ptrs);    +    src_end = src_p + WDS(old_ptrs);    while1:     if (src_p != del_p) {@@ -145,14 +188,14 @@        src_p = src_p + WDS(1);        goto while1;     }-    +     src_p = src_p + WDS(1);    while2:     if (src_p != src_end){        W_[dst_p] = W_[src_p];        dst_p = dst_p + WDS(1);-       src_p = src_p + WDS(1);      +       src_p = src_p + WDS(1);        goto while2;     } @@ -160,9 +203,9 @@ }  -     -    ++   
cbits/smallArray.cmm view
@@ -4,68 +4,109 @@ consSmallArray(gcptr elem, gcptr src) {     W_ words, old_size, new_size;     gcptr dst, dst_p, src_end;-                                                               -    again: MAYBE_GC(again); -             ++    again: MAYBE_GC(again);+     old_size = StgSmallMutArrPtrs_ptrs(src);     new_size = old_size + 1;      words = BYTES_TO_WDS(SIZEOF_StgSmallMutArrPtrs) + new_size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);     TICK_ALLOC_PRIM(SIZEOF_StgSmallMutArrPtrs, WDS(new_size), 0);-    SET_HDR(dst, stg_SMALL_MUT_ARR_PTRS_FROZEN_info, CCCS);                                 -    StgSmallMutArrPtrs_ptrs(dst) = new_size;                                -                        -    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;                   +    SET_HDR(dst, stg_SMALL_MUT_ARR_PTRS_FROZEN_info, CCCS);+    StgSmallMutArrPtrs_ptrs(dst) = new_size;++    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;     src     = src + SIZEOF_StgSmallMutArrPtrs;     src_end = src + WDS(old_size);      W_[dst_p] = elem;     dst_p = dst_p + WDS(1); -  while:                                                       -    if (src != src_end) {                                         -        W_[dst_p] = W_[src];                                 -        dst_p = dst_p + WDS(1);                                -        src   = src   + WDS(1);                                -        goto while;                                            -    }                                                          -                                                               +  while:+    if (src != src_end) {+        W_[dst_p] = W_[src];+        dst_p = dst_p + WDS(1);+        src   = src   + WDS(1);+        goto while;+    }+     return (dst); }  snocSmallArray(gcptr src, gcptr elem) {     W_ words, old_size, new_size;     gcptr dst, dst_p, src_end;-                                                               -    again: MAYBE_GC(again); -             ++    again: MAYBE_GC(again);+     old_size = StgSmallMutArrPtrs_ptrs(src);     new_size = old_size + 1;      words = BYTES_TO_WDS(SIZEOF_StgSmallMutArrPtrs) + new_size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); -    TICK_ALLOC_PRIM(SIZEOF_StgSmallMutArrPtrs, WDS(new_size), 0); -    SET_HDR(dst, stg_SMALL_MUT_ARR_PTRS_FROZEN_info, CCCS);                                 -    StgSmallMutArrPtrs_ptrs(dst) = new_size;                                -                        -    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;                   +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);+    TICK_ALLOC_PRIM(SIZEOF_StgSmallMutArrPtrs, WDS(new_size), 0);+    SET_HDR(dst, stg_SMALL_MUT_ARR_PTRS_FROZEN_info, CCCS);+    StgSmallMutArrPtrs_ptrs(dst) = new_size;++    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;     src     = src + SIZEOF_StgSmallMutArrPtrs;     src_end = src + WDS(old_size); -  while:                                                       -    if (src != src_end) {                                         -        W_[dst_p] = W_[src];                                 -        dst_p = dst_p + WDS(1);                                -        src   = src   + WDS(1);                                -        goto while;                                            +  while:+    if (src != src_end) {+        W_[dst_p] = W_[src];+        dst_p = dst_p + WDS(1);+        src   = src   + WDS(1);+        goto while;     }-    -    W_[dst_p] = elem;                                             -                                                               ++    W_[dst_p] = elem;+     return (dst); } +snocSmallArrayWithPadding(W_ padding, gcptr padElem, gcptr src, gcptr elem) {+    W_ words, old_size, new_size;+    gcptr dst, dst_p, src_end, dst_end;++    again: MAYBE_GC(again);++    old_size = StgSmallMutArrPtrs_ptrs(src);+    new_size = old_size + 1 + padding;++    words = BYTES_TO_WDS(SIZEOF_StgSmallMutArrPtrs) + new_size;+    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);+    TICK_ALLOC_PRIM(SIZEOF_StgSmallMutArrPtrs, WDS(new_size), 0);+    SET_HDR(dst, stg_SMALL_MUT_ARR_PTRS_FROZEN_info, CCCS);+    StgSmallMutArrPtrs_ptrs(dst) = new_size;++    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;+    src     = src + SIZEOF_StgSmallMutArrPtrs;+    src_end = src + WDS(old_size);+    dst_end = dst_p + WDS(new_size);++  while1:+    if (src != src_end) {+        W_[dst_p] = W_[src];+        dst_p = dst_p + WDS(1);+        src   = src   + WDS(1);+        goto while1;+    }++    W_[dst_p] = elem;+    dst_p = dst_p + WDS(1);++  while2:+    if (dst_p != dst_end) {+        W_[dst_p] = padElem;+        dst_p = dst_p + WDS(1);+        goto while2;+    }++    return (dst);+}+ insertSmallArray(W_ index, gcptr elem, gcptr src) {     W_ words, size;     gcptr src_p, dst, dst_p, dst_end, ins_p;@@ -75,15 +116,15 @@     size = StgSmallMutArrPtrs_ptrs(src) + 1;      words = BYTES_TO_WDS(SIZEOF_StgSmallMutArrPtrs) + size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);     TICK_ALLOC_PRIM(SIZEOF_StgSmallMutArrPtrs, WDS(size), 0);     SET_HDR(dst, stg_SMALL_MUT_ARR_PTRS_FROZEN_info, CCCS);     StgSmallMutArrPtrs_ptrs(dst) = size;      src_p   = src + SIZEOF_StgSmallMutArrPtrs;-    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;                   +    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;     ins_p   = dst_p + WDS(index);-    dst_end = dst_p + WDS(size);    +    dst_end = dst_p + WDS(size);      W_[ins_p] = elem; @@ -94,14 +135,14 @@        src_p = src_p + WDS(1);        goto while1;     }-    +     dst_p = dst_p + WDS(1);    while2:     if (dst_p != dst_end){        W_[dst_p] = W_[src_p];        dst_p = dst_p + WDS(1);-       src_p = src_p + WDS(1);      +       src_p = src_p + WDS(1);        goto while2;     } @@ -118,15 +159,15 @@     new_size = old_size - 1;      words = BYTES_TO_WDS(SIZEOF_StgSmallMutArrPtrs) + new_size;-    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words); +    ("ptr" dst) = ccall allocate(MyCapability() "ptr", words);     TICK_ALLOC_PRIM(SIZEOF_StgSmallMutArrPtrs, WDS(new_size), 0);     SET_HDR(dst, stg_SMALL_MUT_ARR_PTRS_FROZEN_info, CCCS);     StgSmallMutArrPtrs_ptrs(dst) = new_size;      src_p   = src + SIZEOF_StgSmallMutArrPtrs;-    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;                   +    dst_p   = dst + SIZEOF_StgSmallMutArrPtrs;     del_p   = src_p + WDS(index);-    src_end = src_p + WDS(old_size);    +    src_end = src_p + WDS(old_size);    while1:     if (src_p != del_p) {@@ -135,14 +176,14 @@        src_p = src_p + WDS(1);        goto while1;     }-    +     src_p = src_p + WDS(1);    while2:     if (src_p != src_end){        W_[dst_p] = W_[src_p];        dst_p = dst_p + WDS(1);-       src_p = src_p + WDS(1);      +       src_p = src_p + WDS(1);        goto while2;     } @@ -150,9 +191,9 @@ }  -     -    ++   
+ tests/Tests.hs view
@@ -0,0 +1,115 @@+{-# language RankNTypes, MagicHash, UnboxedTuples, BangPatterns,+    ScopedTypeVariables #-}++import GHC.Prim+import GHC.Types+import GHC.Prim.Array+import GHC.Prim.SmallArray++import Test.Tasty+import Test.Tasty.QuickCheck+import Test.QuickCheck++runSTRep :: (forall s. State# s -> (# State# s, a #)) -> a+runSTRep f = case f realWorld# of (# _ , a #) -> a+{-# INLINE [0] runSTRep #-}++insList :: Int -> a -> [a] -> [a]+insList n a as = let (as1, as2) = splitAt n as in as1 ++ a:as2++delList :: Int -> [a] -> [a]+delList n as = case splitAt n as of+  (as1, _:as2) -> as1 ++ as2+  _            -> as++data A a = A (Array# a)++consA a (A arr) = A (consArray# a arr)+snocA (A arr) a = A (snocArray# arr a)+snocAPad (I# pad) padElem (A arr) a = A (snocArrayWithPadding# pad padElem arr a)+insertA (I# i) a (A arr) = A (insertArray# i a arr)+deleteA (I# i) (A arr)   = A (deleteArray# i arr)++toListA :: forall a. A a -> [a]+toListA (A arr) = go arr 0# where+    go arr i | isTrue# (i ==# sizeofArray# arr) = []+    go arr i = case indexArray# arr i of+        (# a #) -> a : go arr (i +# 1#)++fromListA :: [a] -> A a+fromListA xs = runSTRep $ \s -> let !(I# size) = length xs in+    case newArray# size undefined s of+        (# s, marr #) -> go xs 0# s where+            go (x:xs) i s = case writeArray# marr i x s of s -> go xs (i +# 1#) s+            go _      _ s = case unsafeFreezeArray# marr s of+                (# s , arr #) -> (# s, A arr #)++data SA a = SA (SmallArray# a)++consSA a (SA arr) = SA (consSmallArray# a arr)+snocSA (SA arr) a = SA (snocSmallArray# arr a)+snocSAPad (I# pad) padElem (SA arr) a = SA (snocSmallArrayWithPadding# pad padElem arr a)+insertSA (I# i) a (SA arr) = SA (insertSmallArray# i a arr)+deleteSA (I# i) (SA arr)   = SA (deleteSmallArray# i arr)++toListSA :: forall a. SA a -> [a]+toListSA (SA arr) = go arr 0# where+    go arr i | isTrue# (i ==# sizeofSmallArray# arr) = []+    go arr i = case indexSmallArray# arr i of+        (# a #) -> a : go arr (i +# 1#)++fromListSA :: [a] -> SA a+fromListSA xs = runSTRep $ \s -> let !(I# size) = length xs in+    case newSmallArray# size undefined s of+        (# s, marr #) -> go xs 0# s where+            go (x:xs) i s = case writeSmallArray# marr i x s of s -> go xs (i +# 1#) s+            go _      _ s = case unsafeFreezeSmallArray# marr s of+                (# s , arr #) -> (# s, SA arr #)++main :: IO ()+main = defaultMain $ testGroup "tests" [+  testGroup "smallArray" [+      testProperty "cons" $ \(xs :: [Int]) x ->+        (x:xs) == toListSA (consSA x (fromListSA xs))++    , testProperty "snoc" $ \(xs :: [Int]) x ->+        (xs ++ [x]) == toListSA (snocSA (fromListSA xs) x)++    , testProperty "snocWithPadding" $ \(xs :: [Int]) x ->+        forAll (choose (0, 10)) $ \pad ->+             (xs ++ [x] ++ replicate pad 0)+          == toListSA (snocSAPad pad 0 (fromListSA xs) x)++    , testProperty "insert" $ \(xs :: [Int]) x ->+        forAll (choose (0, length xs)) $ \n ->+          insList n x xs == toListSA (insertSA n x (fromListSA xs))++    , testProperty "delete" $ \(NonEmpty (xs :: [Int])) ->+        forAll (choose (0, length xs - 1)) $ \n ->+          delList n xs == toListSA (deleteSA n (fromListSA xs))+    ],++  testGroup "array" [+      testProperty "cons" $ \(xs :: [Int]) x ->+        (x:xs) == toListA (consA x (fromListA xs))++    , testProperty "snoc" $ \(xs :: [Int]) x ->+        (xs ++ [x]) == toListA (snocA (fromListA xs) x)++    , testProperty "snocWithPadding" $ \(xs :: [Int]) x ->+        forAll (choose (0, 10)) $ \pad ->+             (xs ++ [x] ++ replicate pad 0)+          == toListA (snocAPad pad 0 (fromListA xs) x)++    , testProperty "insert" $ \(xs :: [Int]) x ->+        forAll (choose (0, length xs)) $ \n ->+          insList n x xs == toListA (insertA n x (fromListA xs))++    , testProperty "delete" $ \(NonEmpty (xs :: [Int])) ->+        forAll (choose (0, length xs - 1)) $ \n ->+          delList n xs == toListA (deleteA n (fromListA xs))+    ]+  ]+++