Skip to content

Commit 5f23443

Browse files
committed
Update piecewise fallback with mergesort optimizations
1 parent 25be351 commit 5f23443

File tree

1 file changed

+43
-27
lines changed

1 file changed

+43
-27
lines changed

src/PiecewiseFallbackSort.hs

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
-- Based on DpsMergeSort4.hs and Insertion.hs with analysis
22
{-# LANGUAGE CPP #-}
33

4+
{-# OPTIONS_GHC -Wno-name-shadowing #-}
5+
46
module PiecewiseFallbackSort where
57

68
import qualified Language.Haskell.Liquid.Bag as B
@@ -31,33 +33,45 @@ import Array.List as A
3133
left ts == left ys && right ts == right ys }>
3234
/ [A.size xs] @-}
3335
msortInplace :: (Show a, HasPrimOrd a) => Int -> A.Array a -. A.Array a -. (A.Array a, A.Array a)
34-
msortInplace cutoff src tmp = -- cutoff > 0, though it may not be necessary to show sorting correctness
35-
let !(Ur len, src') = A.size2 src in
36-
if len <= 1 then (src', tmp) -- MHB added
37-
else if len <= cutoff then (isort_top' src', tmp)
38-
else
39-
let !(srcA, srcB) = splitMid src'
40-
!(tmpA, tmpB) = splitMid tmp
41-
!(src1, src2) = splitMid srcA
42-
!(src3, src4) = splitMid srcB
43-
!(tmp1, tmp2) = splitMid tmpA
44-
!(tmp3, tmp4) = splitMid tmpB
45-
!(src1', tmp1') = msortInplace cutoff src1 tmp1
46-
!(src2', tmp2') = msortInplace cutoff src2 tmp2
47-
!(src3', tmp3') = msortInplace cutoff src3 tmp3
48-
!(src4', tmp4') = msortInplace cutoff src4 tmp4
49-
tmpA' = A.append tmp1' tmp2'
50-
tmpB' = A.append tmp3' tmp4'
51-
!(srcA'', tmpA'') = merge src1' src2' tmpA'
52-
!(srcB'', tmpB'') = merge src3' src4' tmpB'
53-
src'' = A.append srcA'' srcB''
54-
!(tmp''', src''') = merge tmpA'' tmpB'' src''
55-
in (src''', tmp''') ? lem_toBag_splitMid src
56-
? lem_toBag_splitMid tmp
57-
? lem_toBag_splitMid srcA
58-
? lem_toBag_splitMid srcB
59-
? lem_toBag_splitMid tmpA
60-
? lem_toBag_splitMid tmpB
36+
msortInplace cutoff src tmp = go cutoff src tmp where
37+
{-@ go :: n:Int -> xs:Array a
38+
-> { ys:(Array a ) | A.size ys == A.size xs && left xs == left ys &&
39+
right xs == right ys }
40+
-> (Array a, Array a)<{\zs ts -> toBag xs == toBag zs && isSorted' zs &&
41+
token xs == token zs && token ys == token ts &&
42+
A.size xs == A.size zs && A.size ys == A.size ts &&
43+
left zs == left xs && right zs == right xs &&
44+
left ts == left ys && right ts == right ys }>
45+
/ [A.size xs] @-}
46+
go :: (Show a, HasPrimOrd a) => Int -> A.Array a -. A.Array a -. (A.Array a, A.Array a)
47+
go cutoff src tmp =
48+
let !(Ur len, src') = A.size2 src in
49+
if len <= 1 then (src', tmp) -- MHB added
50+
else if len <= cutoff then (isort_top' src', tmp)
51+
else
52+
let !(srcA, srcB) = splitMid src'
53+
!(tmpA, tmpB) = splitMid tmp
54+
!(src1, src2) = splitMid srcA
55+
!(src3, src4) = splitMid srcB
56+
!(tmp1, tmp2) = splitMid tmpA
57+
!(tmp3, tmp4) = splitMid tmpB
58+
!(src1', tmp1') = msortInplace cutoff src1 tmp1
59+
!(src2', tmp2') = msortInplace cutoff src2 tmp2
60+
!(src3', tmp3') = msortInplace cutoff src3 tmp3
61+
!(src4', tmp4') = msortInplace cutoff src4 tmp4
62+
tmpA' = A.append tmp1' tmp2'
63+
tmpB' = A.append tmp3' tmp4'
64+
!(srcA'', tmpA'') = merge src1' src2' tmpA'
65+
!(srcB'', tmpB'') = merge src3' src4' tmpB'
66+
src'' = A.append srcA'' srcB''
67+
!(tmp''', src''') = merge tmpA'' tmpB'' src''
68+
in (src''', tmp''') ? lem_toBag_splitMid src
69+
? lem_toBag_splitMid tmp
70+
? lem_toBag_splitMid srcA
71+
? lem_toBag_splitMid srcB
72+
? lem_toBag_splitMid tmpA
73+
? lem_toBag_splitMid tmpB
74+
{-# INLINE msortInplace #-}
6175

6276
{-@ pfsort' :: y:a
6377
-> { xs:(Array a) | A.size xs > 0 && left xs == 0 && right xs == size xs && y == A.get xs 0 }
@@ -72,6 +86,7 @@ pfsort' anyVal src =
7286
then truncate((18820.2738 / (exp ((log (fromIntegral len)) * 0.5) )) :: Float)
7387
else 28) src' (A.makeArray len anyVal) in
7488
case A.free _tmp of !() -> src''
89+
{-# INLINE pfsort' #-}
7590

7691
{-@ pfsort :: { xs:(A.Array a) | left xs == 0 && right xs == size xs }
7792
-> { ys:_ | toBag xs == toBag ys && isSorted' ys &&
@@ -81,3 +96,4 @@ pfsort src =
8196
let !(Ur len, src') = A.size2 src in
8297
if len == 0 then src'
8398
else let !(Ur x0, src'') = A.get2 0 src' in pfsort' x0 src''
99+
{-# INLINABLE pfsort #-}

0 commit comments

Comments
 (0)