1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
-- Tests for creating and initializing a @SmallArray#@ including the
-- optimiziation where GHC inlines the code instead of calling the
-- @newSmallArray#@ primop if the length is small enough and known at compile
-- time.
module Main where
import GHC.Exts
import GHC.ST
import Control.Monad (forM_)
main :: IO ()
main = do
let !a00 = newSmallArrayWith42 0
!a01 = newSmallArrayWith42 1
!a02 = newSmallArrayWith42 2
!a03 = newSmallArrayWith42 3
!a04 = newSmallArrayWith42 4
!a05 = newSmallArrayWith42 5
!a06 = newSmallArrayWith42 6
!a07 = newSmallArrayWith42 7
!a08 = newSmallArrayWith42 8
!a09 = newSmallArrayWith42 9
!a10 = newSmallArrayWith42 10
!a11 = newSmallArrayWith42 11
!a12 = newSmallArrayWith42 12
!a13 = newSmallArrayWith42 13
!a14 = newSmallArrayWith42 14
!a15 = newSmallArrayWith42 15
!a16 = newSmallArrayWith42 16
!a17 = newSmallArrayWith42 17
!a18 = newSmallArrayWith42 18
!a19 = newSmallArrayWith42 19
!a20 = newSmallArrayWith42 20
!a21 = newSmallArrayWith42 21
!a22 = newSmallArrayWith42 22
!a23 = newSmallArrayWith42 23
!a24 = newSmallArrayWith42 24
!a25 = newSmallArrayWith42 25
!a26 = newSmallArrayWith42 26
!a27 = newSmallArrayWith42 27
!a28 = newSmallArrayWith42 28
!a29 = newSmallArrayWith42 29
!a30 = newSmallArrayWith42 30
!a31 = newSmallArrayWith42 31
!a32 = newSmallArrayWith42 32
!a33 = newSmallArrayWith42 33
!a34 = newSmallArrayWith42 34
!a35 = newSmallArrayWith42 35
!a36 = newSmallArrayWith42 36
!a37 = newSmallArrayWith42 37
!a38 = newSmallArrayWith42 38
!a39 = newSmallArrayWith42 39
!all = [ a00, a01, a02, a03, a04, a05, a06, a07, a08, a09
, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19
, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29
, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39
]
forM_ all (print . toListArray)
data Array a = Array { unArray :: SmallArray# a }
newSmallArrayWith42 :: Int -> Array Int
newSmallArrayWith42 n = (runST (newArray n 42))
-- inline to make sure the length is known at compile time
{-# INLINE newSmallArrayWith42 #-}
newArray :: Int -> a -> ST s (Array a)
newArray (I# n#) a = ST $ \s1# -> case newSmallArray# n# a s1# of
(# s2#, marr# #) -> case unsafeFreezeSmallArray# marr# s2# of
(# s3#, arr# #) -> (# s3#, Array arr# #)
-- inline to make sure the length is known at compile time
{-# INLINE newArray #-}
toListArray :: Array a -> [a]
toListArray arr = go 0
where
go i | i >= lengthArray arr = []
| otherwise = indexArray arr i : go (i+1)
indexArray :: Array a -> Int -> a
indexArray arr i@(I# i#)
| i < 0 || i >= len =
error $ "bounds error, offset " ++ show i ++ ", length " ++ show len
| otherwise = case indexSmallArray# (unArray arr) i# of
(# a #) -> a
where len = lengthArray arr
lengthArray :: Array a -> Int
lengthArray arr = I# (sizeofSmallArray# (unArray arr))
|