summaryrefslogtreecommitdiff
path: root/testsuite/tests/codeGen/should_run/cgrun064.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/codeGen/should_run/cgrun064.hs')
-rw-r--r--testsuite/tests/codeGen/should_run/cgrun064.hs229
1 files changed, 229 insertions, 0 deletions
diff --git a/testsuite/tests/codeGen/should_run/cgrun064.hs b/testsuite/tests/codeGen/should_run/cgrun064.hs
new file mode 100644
index 0000000000..24544c4382
--- /dev/null
+++ b/testsuite/tests/codeGen/should_run/cgrun064.hs
@@ -0,0 +1,229 @@
+{-# LANGUAGE MagicHash, UnboxedTuples #-}
+
+-- !!! simple tests of copying/cloning primitive arrays
+--
+
+module Main ( main ) where
+
+import GHC.Exts hiding (IsList(..))
+import GHC.Prim
+import GHC.ST
+
+main = putStr
+ (test_copyArray
+ ++ "\n" ++ test_copyMutableArray
+ ++ "\n" ++ test_copyMutableArrayOverlap
+ ++ "\n" ++ test_cloneArray
+ ++ "\n" ++ test_cloneMutableArray
+ ++ "\n" ++ test_cloneMutableArrayEmpty
+ ++ "\n" ++ test_freezeArray
+ ++ "\n" ++ test_thawArray
+ ++ "\n"
+ )
+
+------------------------------------------------------------------------
+-- Constants
+
+-- All allocated arrays are of this size
+len :: Int
+len = 130
+
+-- We copy these many elements
+copied :: Int
+copied = len - 2
+
+------------------------------------------------------------------------
+-- copyArray#
+
+-- Copy a slice of the source array into a destination array and check
+-- that the copy succeeded.
+test_copyArray :: String
+test_copyArray =
+ let dst = runST $ do
+ src <- newArray len 0
+ fill src 0 len
+ src <- unsafeFreezeArray src
+ dst <- newArray len (-1)
+ -- Leave the first and last element untouched
+ copyArray src 1 dst 1 copied
+ unsafeFreezeArray dst
+ in shows (toList dst len) "\n"
+
+------------------------------------------------------------------------
+-- copyMutableArray#
+
+-- Copy a slice of the source array into a destination array and check
+-- that the copy succeeded.
+test_copyMutableArray :: String
+test_copyMutableArray =
+ let dst = runST $ do
+ src <- newArray len 0
+ fill src 0 len
+ dst <- newArray len (-1)
+ -- Leave the first and last element untouched
+ copyMutableArray src 1 dst 1 copied
+ unsafeFreezeArray dst
+ in shows (toList dst len) "\n"
+
+-- Perform a copy where the source and destination part overlap.
+test_copyMutableArrayOverlap :: String
+test_copyMutableArrayOverlap =
+ let arr = runST $ do
+ marr <- fromList inp
+ -- Overlap of two elements
+ copyMutableArray marr 5 marr 7 8
+ unsafeFreezeArray marr
+ in shows (toList arr (length inp)) "\n"
+ where
+ -- This case was known to fail at some point.
+ inp = [0,169,196,9,16,25,36,16,25,81,100,121,144,169,196]
+
+------------------------------------------------------------------------
+-- cloneArray#
+
+-- Clone a slice of the source array into a destination array and
+-- check that the clone succeeded.
+test_cloneArray :: String
+test_cloneArray =
+ let dst = runST $ do
+ src <- newArray len 0
+ fill src 0 len
+ src <- unsafeFreezeArray src
+ -- Don't include the first and last element.
+ return $ cloneArray src 1 copied
+ in shows (toList dst copied) "\n"
+
+------------------------------------------------------------------------
+-- cloneMutableArray#
+
+-- Clone a slice of the source array into a destination array and
+-- check that the clone succeeded.
+test_cloneMutableArray :: String
+test_cloneMutableArray =
+ let dst = runST $ do
+ src <- newArray len 0
+ fill src 0 len
+ -- Don't include the first and last element.
+ dst <- cloneMutableArray src 1 copied
+ unsafeFreezeArray dst
+ in shows (toList dst copied) "\n"
+
+-- Check that zero-length clones work.
+test_cloneMutableArrayEmpty :: String
+test_cloneMutableArrayEmpty =
+ let dst = runST $ do
+ src <- newArray len 0
+ dst <- cloneMutableArray src 0 0
+ unsafeFreezeArray dst
+ in shows (toList dst 0) "\n"
+
+------------------------------------------------------------------------
+-- freezeArray#
+
+-- Clone a slice of the source array into a destination array and
+-- check that the clone succeeded.
+test_freezeArray :: String
+test_freezeArray =
+ let dst = runST $ do
+ src <- newArray len 0
+ fill src 0 len
+ -- Don't include the first and last element.
+ freezeArray src 1 copied
+ in shows (toList dst copied) "\n"
+
+------------------------------------------------------------------------
+-- thawArray#
+
+-- Clone a slice of the source array into a destination array and
+-- check that the clone succeeded.
+test_thawArray :: String
+test_thawArray =
+ let dst = runST $ do
+ src <- newArray len 0
+ fill src 0 len
+ src <- unsafeFreezeArray src
+ -- Don't include the first and last element.
+ dst <- thawArray src 1 copied
+ unsafeFreezeArray dst
+ in shows (toList dst copied) "\n"
+
+------------------------------------------------------------------------
+-- Test helpers
+
+-- Initialize the elements of this array, starting at the given
+-- offset. The last parameter specifies the number of elements to
+-- initialize. Element at index @i@ takes the value @i*i@ (i.e. the
+-- first actually modified element will take value @off*off@).
+fill :: MArray s Int -> Int -> Int -> ST s ()
+fill marr off count = go 0
+ where
+ go i
+ | i >= count = return ()
+ | otherwise = writeArray marr (off + i) (i*i) >> go (i + 1)
+
+fromList :: [Int] -> ST s (MArray s Int)
+fromList xs0 = do
+ marr <- newArray (length xs0) bottomElem
+ let go [] i = i `seq` return marr
+ go (x:xs) i = writeArray marr i x >> go xs (i + 1)
+ go xs0 0
+ where
+ bottomElem = error "undefined element"
+
+------------------------------------------------------------------------
+-- Convenience wrappers for Array# and MutableArray#
+
+data Array a = Array { unArray :: Array# a }
+data MArray s a = MArray { unMArray :: MutableArray# s a }
+
+newArray :: Int -> a -> ST s (MArray s a)
+newArray (I# n#) a = ST $ \s# -> case newArray# n# a s# of
+ (# s2#, marr# #) -> (# s2#, MArray marr# #)
+
+indexArray :: Array a -> Int -> a
+indexArray arr (I# i#) = case indexArray# (unArray arr) i# of
+ (# a #) -> a
+
+writeArray :: MArray s a -> Int -> a -> ST s ()
+writeArray marr (I# i#) a = ST $ \ s# ->
+ case writeArray# (unMArray marr) i# a s# of
+ s2# -> (# s2#, () #)
+
+unsafeFreezeArray :: MArray s a -> ST s (Array a)
+unsafeFreezeArray marr = ST $ \ s# ->
+ case unsafeFreezeArray# (unMArray marr) s# of
+ (# s2#, arr# #) -> (# s2#, Array arr# #)
+
+copyArray :: Array a -> Int -> MArray s a -> Int -> Int -> ST s ()
+copyArray src (I# six#) dst (I# dix#) (I# n#) = ST $ \ s# ->
+ case copyArray# (unArray src) six# (unMArray dst) dix# n# s# of
+ s2# -> (# s2#, () #)
+
+copyMutableArray :: MArray s a -> Int -> MArray s a -> Int -> Int -> ST s ()
+copyMutableArray src (I# six#) dst (I# dix#) (I# n#) = ST $ \ s# ->
+ case copyMutableArray# (unMArray src) six# (unMArray dst) dix# n# s# of
+ s2# -> (# s2#, () #)
+
+cloneArray :: Array a -> Int -> Int -> Array a
+cloneArray src (I# six#) (I# n#) = Array (cloneArray# (unArray src) six# n#)
+
+cloneMutableArray :: MArray s a -> Int -> Int -> ST s (MArray s a)
+cloneMutableArray src (I# six#) (I# n#) = ST $ \ s# ->
+ case cloneMutableArray# (unMArray src) six# n# s# of
+ (# s2#, marr# #) -> (# s2#, MArray marr# #)
+
+freezeArray :: MArray s a -> Int -> Int -> ST s (Array a)
+freezeArray src (I# six#) (I# n#) = ST $ \ s# ->
+ case freezeArray# (unMArray src) six# n# s# of
+ (# s2#, arr# #) -> (# s2#, Array arr# #)
+
+thawArray :: Array a -> Int -> Int -> ST s (MArray s a)
+thawArray src (I# six#) (I# n#) = ST $ \ s# ->
+ case thawArray# (unArray src) six# n# s# of
+ (# s2#, marr# #) -> (# s2#, MArray marr# #)
+
+toList :: Array a -> Int -> [a]
+toList arr n = go 0
+ where
+ go i | i >= n = []
+ | otherwise = indexArray arr i : go (i+1)