File: Tests.hs

package info (click to toggle)
haskell-vector-algorithms 0.9.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 228 kB
  • sloc: haskell: 2,404; ansic: 23; makefile: 3
file content (230 lines) | stat: -rw-r--r-- 10,611 bytes parent folder | download | duplicates (3)
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
{-# LANGUAGE RankNTypes, TypeOperators, FlexibleContexts, TypeApplications #-}

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 qualified Data.ByteString as B

import Data.Vector (Vector)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as BoxedMV

import qualified Data.Vector.Generic as G
import Data.Vector.Generic.Mutable (MVector)
import qualified Data.Vector.Generic.Mutable as MV

import qualified Data.Vector.Algorithms.Insertion    as INS
import qualified Data.Vector.Algorithms.Intro        as INT
import qualified Data.Vector.Algorithms.Merge        as M
import qualified Data.Vector.Algorithms.Radix        as R
import qualified Data.Vector.Algorithms.Heap         as H
import qualified Data.Vector.Algorithms.Optimal      as O
import qualified Data.Vector.Algorithms.AmericanFlag as AF
import qualified Data.Vector.Algorithms.Tim          as T

import qualified Data.Vector.Algorithms.Search       as SR

type Algo      e r = forall s mv. MVector mv e => mv s e -> ST s r
type SizeAlgo  e r = forall s mv. MVector mv e => mv s e -> Int -> ST s r
type BoundAlgo e r = forall s mv. MVector mv e => mv s e -> Int -> Int -> ST s r
type MonoAlgo  e r = forall s . BoxedMV.MVector s e -> ST s r

newtype WrappedAlgo      e r = WrapAlgo      { unWrapAlgo      :: Algo      e r }
newtype WrappedSizeAlgo  e r = WrapSizeAlgo  { unWrapSizeAlgo  :: SizeAlgo  e r }
newtype WrappedBoundAlgo e r = WrapBoundAlgo { unWrapBoundAlgo :: BoundAlgo e r }
newtype WrappedMonoAlgo  e r = MonoAlgo      { unWrapMonoAlgo  :: MonoAlgo  e r }

args = stdArgs
       { maxSuccess = 1000
       , maxDiscardRatio = 2
       }

check_Int_sort = forM_ algos $ \(name,algo) ->
  quickCheckWith args (label name . prop_fullsort (unWrapAlgo algo))
 where
 algos :: [(String, WrappedAlgo Int ())]
 algos = [ ("introsort", WrapAlgo INT.sort)
         , ("insertion sort", WrapAlgo INS.sort)
         , ("merge sort", WrapAlgo M.sort)
         , ("heapsort", WrapAlgo H.sort)
         , ("timsort", WrapAlgo T.sort)
         ]

check_Int_sortUniq = forM_ algos $ \(name,algo) ->
  quickCheckWith args (label name . prop_full_sortUniq (unWrapMonoAlgo algo))
 where
 algos :: [(String, WrappedMonoAlgo Int (Vector Int))]
 algos = [ ("intro_sortUniq", MonoAlgo (runFreeze INT.sortUniq))
         , ("insertion sortUniq", MonoAlgo (runFreeze INS.sortUniq))
         , ("merge sortUniq", MonoAlgo (runFreeze M.sortUniq))
         , ("heap_sortUniq", MonoAlgo (runFreeze H.sortUniq))
         , ("tim_sortUniq", MonoAlgo (runFreeze T.sortUniq))
         ]

check_Int_partialsort = forM_ algos $ \(name,algo) ->
  quickCheckWith args (label name . prop_partialsort (unWrapSizeAlgo algo))
 where
 algos :: [(String, WrappedSizeAlgo Int ())]
 algos = [ ("intro-partialsort", WrapSizeAlgo INT.partialSort)
         , ("heap partialsort", WrapSizeAlgo H.partialSort)
         ]

check_Int_select = forM_ algos $ \(name,algo) ->
  quickCheckWith args (label name . prop_select (unWrapSizeAlgo algo))
 where
 algos :: [(String, WrappedSizeAlgo Int ())]
 algos = [ ("intro-select", WrapSizeAlgo INT.select)
         , ("heap select", WrapSizeAlgo H.select)
         ]

check_nub = quickCheckWith args (label "nub Int" . (prop_nub @Int))


check_radix_sorts = do
  qc (label "radix Word8"       . prop_fullsort (R.sort :: Algo Word8  ()))
  qc (label "radix Word16"      . prop_fullsort (R.sort :: Algo Word16 ()))
  qc (label "radix Word32"      . prop_fullsort (R.sort :: Algo Word32 ()))
  qc (label "radix Word64"      . prop_fullsort (R.sort :: Algo Word64 ()))
  qc (label "radix Word"        . prop_fullsort (R.sort :: Algo Word   ()))
  qc (label "radix Int8"        . prop_fullsort (R.sort :: Algo Int8   ()))
  qc (label "radix Int16"       . prop_fullsort (R.sort :: Algo Int16  ()))
  qc (label "radix Int32"       . prop_fullsort (R.sort :: Algo Int32  ()))
  qc (label "radix Int64"       . prop_fullsort (R.sort :: Algo Int64  ()))
  qc (label "radix Int"         . prop_fullsort (R.sort :: Algo Int    ()))
  qc (label "radix (Int, Int)"  . prop_fullsort (R.sort :: Algo (Int, Int) ()))

  qc (label "flag Word8"       . prop_fullsort (AF.sort :: Algo Word8  ()))
  qc (label "flag Word16"      . prop_fullsort (AF.sort :: Algo Word16 ()))
  qc (label "flag Word32"      . prop_fullsort (AF.sort :: Algo Word32 ()))
  qc (label "flag Word64"      . prop_fullsort (AF.sort :: Algo Word64 ()))
  qc (label "flag Word"        . prop_fullsort (AF.sort :: Algo Word   ()))
  qc (label "flag Int8"        . prop_fullsort (AF.sort :: Algo Int8   ()))
  qc (label "flag Int16"       . prop_fullsort (AF.sort :: Algo Int16  ()))
  qc (label "flag Int32"       . prop_fullsort (AF.sort :: Algo Int32  ()))
  qc (label "flag Int64"       . prop_fullsort (AF.sort :: Algo Int64  ()))
  qc (label "flag Int"         . prop_fullsort (AF.sort :: Algo Int    ()))
  qc (label "flag ByteString"  . prop_fullsort (AF.sort :: Algo B.ByteString ()))
 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)
                  quickCheckWith args (label "tim sort" . prop_stable T.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 "heapsort"     . prop_permutation (H.sort :: Algo Int ())

  qc $ label "mergesort"    . prop_permutation (M.sort :: Algo Int    ())
  qc $ label "timsort"      . prop_permutation (T.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   ())
  qc $ label "flag I8"      . prop_permutation (AF.sort :: Algo Int8   ())
  qc $ label "flag I16"     . prop_permutation (AF.sort :: Algo Int16  ())
  qc $ label "flag I32"     . prop_permutation (AF.sort :: Algo Int32  ())
  qc $ label "flag I64"     . prop_permutation (AF.sort :: Algo Int64  ())
  qc $ label "flag Int"     . prop_permutation (AF.sort :: Algo Int    ())
  qc $ label "flag W8"      . prop_permutation (AF.sort :: Algo Word8  ())
  qc $ label "flag W16"     . prop_permutation (AF.sort :: Algo Word16 ())
  qc $ label "flag W32"     . prop_permutation (AF.sort :: Algo Word32 ())
  qc $ label "flag W64"     . prop_permutation (AF.sort :: Algo Word64 ())
  qc $ label "flag Word"    . prop_permutation (AF.sort :: Algo Word   ())
  qc $ label "flag ByteString" . prop_permutation (AF.sort :: Algo B.ByteString ())
  qc $ label "intropartial" . prop_sized (\x -> const (prop_permutation x))
                                         (INT.partialSort :: SizeAlgo Int ())
  qc $ label "introselect"  . prop_sized (\x -> const (prop_permutation x))
                                         (INT.select :: SizeAlgo Int ())
  qc $ label "heappartial"  . prop_sized (\x -> const (prop_permutation x))
                                         (H.partialSort :: SizeAlgo Int ())
  qc $ label "heapselect"   . prop_sized (\x -> const (prop_permutation x))
                                         (H.select :: SizeAlgo Int ())

 where
 qc prop = quickCheckWith args prop

check_corners = do
  qc "introsort empty"    $ prop_empty       (INT.sort        :: Algo Int ())
  qc "intropartial empty" $ prop_sized_empty (INT.partialSort :: SizeAlgo Int ())
  qc "introselect empty"  $ prop_sized_empty (INT.select      :: SizeAlgo Int ())
  qc "heapsort empty"     $ prop_empty       (H.sort          :: Algo Int ())
  qc "heappartial empty"  $ prop_sized_empty (H.partialSort   :: SizeAlgo Int ())
  qc "heapselect empty"   $ prop_sized_empty (H.select        :: SizeAlgo Int ())
  qc "mergesort empty"    $ prop_empty       (M.sort          :: Algo Int ())
  qc "timsort empty"      $ prop_empty       (T.sort          :: Algo Int ())
  qc "radixsort empty"    $ prop_empty       (R.sort          :: Algo Int ())
  qc "flagsort empty"     $ prop_empty       (AF.sort         :: Algo Int ())
 where
 qc s prop = quickCheckWith (stdArgs { maxSuccess = 2 }) (label s prop)

type SAlgo e r = forall s mv. MVector mv e => mv s e -> e -> ST s r
type BoundSAlgo e r = forall s mv. MVector mv e => mv s e -> e -> Int -> Int -> ST s r

check_search_range = do
  qc $ (label "binarySearchL" .)
         . prop_search_inrange (SR.binarySearchLByBounds compare :: BoundSAlgo Int Int)
  qc $ (label "binarySearchL lo-bound" .)
         . prop_search_lowbound (SR.binarySearchL :: SAlgo Int Int)
  qc $ (label "binarySearch" .)
         . prop_search_inrange (SR.binarySearchByBounds compare :: BoundSAlgo Int Int)
  qc $ (label "binarySearchR" .)
         . prop_search_inrange (SR.binarySearchRByBounds compare :: BoundSAlgo Int Int)
  qc $ (label "binarySearchR hi-bound" .)
         . prop_search_upbound (SR.binarySearchR :: SAlgo Int Int)
 where
 qc prop = quickCheckWith args prop

main = do putStrLn "Int tests:"
          check_Int_sort
          check_Int_sortUniq
          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
          putStrLn "Search in range:"
          check_search_range
          putStrLn "Corner cases:"
          check_corners
          putStrLn "Algorithms:"
          check_nub