{-# LANGUAGE ImpredicativeTypes, RankNTypes, TypeOperators #-}
module Main (main) where
import Properties
import Util
import Test.QuickCheck
import Control.Monad
import Control.Monad.ST
import Data.Int
import Data.Word
import Data.Array.Vector
import Data.Array.Vector.Algorithms.Combinators
import qualified Data.Array.Vector.Algorithms.Insertion as INS
import qualified Data.Array.Vector.Algorithms.Intro as INT
import qualified Data.Array.Vector.Algorithms.Merge as M
import qualified Data.Array.Vector.Algorithms.Radix as R
import qualified Data.Array.Vector.Algorithms.TriHeap as TH
import qualified Data.Array.Vector.Algorithms.Optimal as O
type Algo e = forall s. MUArr e s -> ST s ()
type SizeAlgo e = forall s. MUArr e s -> Int -> ST s ()
args = stdArgs
{ maxSuccess = 300
, maxDiscard = 200
}
check_Int_sort = forM_ algos $ \(name,algo) ->
quickCheckWith args (label name . prop_fullsort algo)
where
algos :: [(String, Algo Int)]
algos = [ ("introsort", INT.sort)
, ("insertion sort", INS.sort)
, ("merge sort", M.sort)
, ("tri-heapsort", TH.sort)
]
check_Int_partialsort = forM_ algos $ \(name,algo) ->
quickCheckWith args (label name . prop_partialsort algo)
where
algos :: [(String, SizeAlgo Int)]
algos = [ ("intro-partialsort", INT.partialSort)
, ("tri-heap partialsort", TH.partialSort)
]
check_Int_select = forM_ algos $ \(name,algo) ->
quickCheckWith args (label name . prop_select algo)
where
algos :: [(String, SizeAlgo Int)]
algos = [ ("intro-select", INT.select)
, ("tri-heap select", TH.select)
]
check_radix_sorts = do
qc (label "Word8" . prop_fullsort (R.sort :: Algo Word8))
qc (label "Word16" . prop_fullsort (R.sort :: Algo Word16))
qc (label "Word32" . prop_fullsort (R.sort :: Algo Word32))
qc (label "Word64" . prop_fullsort (R.sort :: Algo Word64))
qc (label "Word" . prop_fullsort (R.sort :: Algo Word))
qc (label "Int8" . prop_fullsort (R.sort :: Algo Int8))
qc (label "Int16" . prop_fullsort (R.sort :: Algo Int16))
qc (label "Int32" . prop_fullsort (R.sort :: Algo Int32))
qc (label "Int64" . prop_fullsort (R.sort :: Algo Int64))
qc (label "Int" . prop_fullsort (R.sort :: Algo Int))
qc (label "Int :*: Int" . prop_fullsort (R.sort :: Algo (Int :*: Int)))
where
qc algo = quickCheckWith args algo
check_schwartzian = do
quickCheckWith args (prop_schwartzian i2w INS.sortBy)
where
i2w :: Int -> Word
i2w = fromIntegral
check_stable = do quickCheckWith args (label "merge sort" . prop_stable M.sortBy)
quickCheckWith args (label "radix sort" . prop_stable_radix R.sortBy)
check_optimal = do qc . label "size 2" $ prop_optimal 2 O.sort2ByOffset
qc . label "size 3" $ prop_optimal 3 O.sort3ByOffset
qc . label "size 4" $ prop_optimal 4 O.sort4ByOffset
where
qc = quickCheck
check_permutation = do
qc $ label "introsort" . prop_permutation (INT.sort :: Algo Int)
qc $ label "intropartial" . prop_sized (const . prop_permutation)
(INT.partialSort :: SizeAlgo Int)
qc $ label "introselect" . prop_sized (const . prop_permutation)
(INT.select :: SizeAlgo Int)
qc $ label "heapsort" . prop_permutation (TH.sort :: Algo Int)
qc $ label "heappartial" . prop_sized (const . prop_permutation)
(TH.partialSort :: SizeAlgo Int)
qc $ label "heapselect" . prop_sized (const . prop_permutation)
(TH.select :: SizeAlgo Int)
qc $ label "mergesort" . prop_permutation (M.sort :: Algo Int)
qc $ label "radix I8" . prop_permutation (R.sort :: Algo Int8)
qc $ label "radix I16" . prop_permutation (R.sort :: Algo Int16)
qc $ label "radix I32" . prop_permutation (R.sort :: Algo Int32)
qc $ label "radix I64" . prop_permutation (R.sort :: Algo Int64)
qc $ label "radix Int" . prop_permutation (R.sort :: Algo Int)
qc $ label "radix W8" . prop_permutation (R.sort :: Algo Word8)
qc $ label "radix W16" . prop_permutation (R.sort :: Algo Word16)
qc $ label "radix W32" . prop_permutation (R.sort :: Algo Word32)
qc $ label "radix W64" . prop_permutation (R.sort :: Algo Word64)
qc $ label "radix Word" . prop_permutation (R.sort :: Algo Word)
where
qc prop = quickCheckWith args prop
main = do putStrLn "Int tests:"
check_Int_sort
check_Int_partialsort
check_Int_select
putStrLn "Radix sort tests:"
check_radix_sorts
putStrLn "Schwartzian transform (Int -> Word):"
check_schwartzian
putStrLn "Stability:"
check_stable
putStrLn "Optimals:"
check_optimal
putStrLn "Permutation:"
check_permutation