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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
module Main (main) where
import Criterion.Main
import Data.List (unfoldr)
import Data.Word (Word64)
import qualified Data.Tree as T
import qualified System.Random as R
import qualified System.Random.TF as TF
import qualified System.Random.TF.Instances as TF
import qualified System.Random.SplitMix as SM
import qualified System.Random.SplitMix32 as SM32
-------------------------------------------------------------------------------
-- List
-------------------------------------------------------------------------------
-- infinite list
genList :: (g -> (Int, g)) -> g -> [Int]
genList next = unfoldr (Just . next)
-- truncated
genListN :: (g -> (Int, g)) -> g -> [Int]
genListN next = take 2048 . genList next
randomList :: Int -> [Int]
randomList = genListN R.random . R.mkStdGen
tfRandomList :: Word64 -> [Int]
tfRandomList w64 = genListN R.random $ TF.seedTFGen (w64, w64, w64, w64)
splitMixList :: Word64 -> [Int]
splitMixList w64 = genListN SM.nextInt $ SM.mkSMGen w64
splitMix32List :: Word64 -> [Int]
splitMix32List w64 = genListN SM32.nextInt $ SM32.mkSMGen $ fromIntegral w64
-------------------------------------------------------------------------------
-- Tree
-------------------------------------------------------------------------------
genTree :: (g -> (Int, g)) -> (g -> (g, g)) -> g -> T.Tree Int
genTree next split = go where
go g = case next g of
~(i, g') -> T.Node i $ case split g' of
(ga, gb) -> [go ga, go gb]
genTreeN :: (g -> (Int, g)) -> (g -> (g, g)) -> g -> T.Tree Int
genTreeN next split = cutTree 9 . genTree next split
where
cutTree :: Int -> T.Tree a -> T.Tree a
cutTree n (T.Node x forest)
| n <= 0 = T.Node x []
| otherwise = T.Node x (map (cutTree (n - 1)) forest)
randomTree :: Int -> T.Tree Int
randomTree = genTreeN R.next R.split . R.mkStdGen
tfRandomTree :: Word64 -> T.Tree Int
tfRandomTree w64 = genTreeN R.next R.split $ TF.seedTFGen (w64, w64, w64, w64)
splitMixTree :: Word64 -> T.Tree Int
splitMixTree w64 = genTreeN SM.nextInt SM.splitSMGen $ SM.mkSMGen w64
splitMix32Tree :: Word64 -> T.Tree Int
splitMix32Tree w64 = genTreeN SM32.nextInt SM32.splitSMGen $ SM32.mkSMGen $ fromIntegral w64
-------------------------------------------------------------------------------
-- List Word64
-------------------------------------------------------------------------------
-- infinite list
genList64 :: (g -> (Word64, g)) -> g -> [Word64]
genList64 r = unfoldr (Just . r)
-- truncated
genListN64 :: (g -> (Word64, g)) -> g -> [Word64]
genListN64 r = take 2048 . genList64 r
randomList64 :: Int -> [Word64]
randomList64 = genListN64 R.random . R.mkStdGen
tfRandomList64 :: Word64 -> [Word64]
tfRandomList64 w64 = genListN64 TF.random $ TF.seedTFGen (w64, w64, w64, w64)
splitMixList64 :: Word64 -> [Word64]
splitMixList64 w64 = genListN64 SM.nextWord64 $ SM.mkSMGen w64
splitMix32List64 :: Word64 -> [Word64]
splitMix32List64 w64 = genListN64 SM32.nextWord64 $ SM32.mkSMGen $ fromIntegral w64
-------------------------------------------------------------------------------
-- Tree Word64
-------------------------------------------------------------------------------
genTree64 ::(g -> (Word64, g)) -> (g -> (g, g)) -> g -> T.Tree Word64
genTree64 r split = go where
go g = case r g of
~(i, g') -> T.Node i $ case split g' of
(ga, gb) -> [go ga, go gb]
genTreeN64 :: (g -> (Word64, g)) -> (g -> (g, g)) -> g -> T.Tree Word64
genTreeN64 r split = cutTree 9 . genTree64 r split
where
cutTree :: Word64 -> T.Tree a -> T.Tree a
cutTree n (T.Node x forest)
| n <= 0 = T.Node x []
| otherwise = T.Node x (map (cutTree (n - 1)) forest)
randomTree64 :: Int -> T.Tree Word64
randomTree64 = genTreeN64 R.random R.split . R.mkStdGen
tfRandomTree64 :: Word64 -> T.Tree Word64
tfRandomTree64 w64 = genTreeN64 TF.random R.split $ TF.seedTFGen (w64, w64, w64, w64)
splitMixTree64 :: Word64 -> T.Tree Word64
splitMixTree64 w64 = genTreeN64 SM.nextWord64 SM.splitSMGen $ SM.mkSMGen w64
splitMix32Tree64 :: Word64 -> T.Tree Word64
splitMix32Tree64 w64 = genTreeN64 SM32.nextWord64 SM32.splitSMGen $ SM32.mkSMGen $ fromIntegral w64
-------------------------------------------------------------------------------
-- Main
-------------------------------------------------------------------------------
main :: IO ()
main = defaultMain
[ bgroup "list"
[ bench "random" $ nf randomList 42
, bench "tf-random" $ nf tfRandomList 42
, bench "splitmix" $ nf splitMixList 42
, bench "splitmix32" $ nf splitMix32List 42
]
, bgroup "tree"
[ bench "random" $ nf randomTree 42
, bench "tf-random" $ nf tfRandomTree 42
, bench "splitmix" $ nf splitMixTree 42
, bench "splitmix32" $ nf splitMix32Tree 42
]
, bgroup "list 64"
[ bench "random" $ nf randomList64 42
, bench "tf-random" $ nf tfRandomList64 42
, bench "splitmix" $ nf splitMixList64 42
, bench "splitmix32" $ nf splitMix32List64 42
]
, bgroup "tree 64"
[ bench "random" $ nf randomTree64 42
, bench "tf-random" $ nf tfRandomTree64 42
, bench "splitmix" $ nf splitMixTree64 42
, bench "splitmix32" $ nf splitMix32Tree64 42
]
]
|