-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMoBench.hs
49 lines (42 loc) · 1.46 KB
/
MoBench.hs
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
module MoBench where
import Control.Monad
import Control.Monad.ST
import Data.Array.Unboxed
import Data.Array.ST
import Data.STRef
import Criterion
import ArrayNFData ()
import Mo ( MoQuery(..), Tag, runMo, sqrtSize )
import Util ( evalR, randIntsR, randSortedIntPairsR, sizedBench )
benchmark :: Benchmark
benchmark = bgroup "Mo"
[ -- Run Mo's algorithm with n queries on a sequence of size n
bgroup "runMo" $ map benchRunMo sizes
]
sizes :: [Int]
sizes = [100, 10000, 200000]
benchRunMo :: Int -> Benchmark
benchRunMo n = sizedBench n gen $ \ ~(xa, qrys) -> nf (countDistinct xa) qrys where
gen = evalR $ do
lrs <- randSortedIntPairsR (1, n) n
xs <- randIntsR (1, n) n
let xa = listArray (1, n) xs
qrys = [MoQuery l r i | (i, (l, r)) <- zip [1..] lrs]
pure (xa, qrys)
-- Count number of distinct elements in a range, a classic Mo problem.
countDistinct :: UArray Int Int -> [MoQuery] -> [(Tag, Int)]
countDistinct xa qrys = runST $ do
cnts <- newArray (1, n) 0 :: ST s (STUArray s Int Int)
cur <- newSTRef 0
let add i = do
c <- readArray cnts (xa!i)
when (c == 0) $ modifySTRef' cur (+1)
writeArray cnts (xa!i) $ c + 1
rem i = do
c <- readArray cnts (xa!i)
when (c == 1) $ modifySTRef' cur (subtract 1)
writeArray cnts (xa!i) $ c - 1
ans = readSTRef cur
runMo (sqrtSize n) add rem ans qrys
where
(1, n) = bounds xa