{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.BitPrecise.MergeSort where
import Data.SBV
import Data.SBV.Tools.CodeGen
type E = SWord8
merge :: [E] -> [E] -> [E]
merge :: [E] -> [E] -> [E]
merge [] [E]
ys = [E]
ys
merge [E]
xs [] = [E]
xs
merge xs :: [E]
xs@(E
x:[E]
xr) ys :: [E]
ys@(E
y:[E]
yr) = forall a. Mergeable a => SBool -> a -> a -> a
ite (E
x forall a. OrdSymbolic a => a -> a -> SBool
.< E
y) (E
x forall a. a -> [a] -> [a]
: [E] -> [E] -> [E]
merge [E]
xr [E]
ys) (E
y forall a. a -> [a] -> [a]
: [E] -> [E] -> [E]
merge [E]
xs [E]
yr)
mergeSort :: [E] -> [E]
mergeSort :: [E] -> [E]
mergeSort [] = []
mergeSort [E
x] = [E
x]
mergeSort [E]
xs = [E] -> [E] -> [E]
merge ([E] -> [E]
mergeSort [E]
th) ([E] -> [E]
mergeSort [E]
bh)
where ([E]
th, [E]
bh) = forall a. Int -> [a] -> ([a], [a])
splitAt (forall (t :: * -> *) a. Foldable t => t a -> Int
length [E]
xs forall a. Integral a => a -> a -> a
`div` Int
2) [E]
xs
nonDecreasing :: [E] -> SBool
nonDecreasing :: [E] -> SBool
nonDecreasing [] = SBool
sTrue
nonDecreasing [E
_] = SBool
sTrue
nonDecreasing (E
a:E
b:[E]
xs) = E
a forall a. OrdSymbolic a => a -> a -> SBool
.<= E
b SBool -> SBool -> SBool
.&& [E] -> SBool
nonDecreasing (E
bforall a. a -> [a] -> [a]
:[E]
xs)
isPermutationOf :: [E] -> [E] -> SBool
isPermutationOf :: [E] -> [E] -> SBool
isPermutationOf [E]
as [E]
bs = forall {a}.
(Mergeable a, EqSymbolic a) =>
[a] -> [(a, SBool)] -> SBool
go [E]
as (forall a b. [a] -> [b] -> [(a, b)]
zip [E]
bs (forall a. a -> [a]
repeat SBool
sTrue)) SBool -> SBool -> SBool
.&& forall {a}.
(Mergeable a, EqSymbolic a) =>
[a] -> [(a, SBool)] -> SBool
go [E]
bs (forall a b. [a] -> [b] -> [(a, b)]
zip [E]
as (forall a. a -> [a]
repeat SBool
sTrue))
where go :: [a] -> [(a, SBool)] -> SBool
go [] [(a, SBool)]
_ = SBool
sTrue
go (a
x:[a]
xs) [(a, SBool)]
ys = let (SBool
found, [(a, SBool)]
ys') = forall {a}.
(Mergeable a, EqSymbolic a) =>
a -> [(a, SBool)] -> (SBool, [(a, SBool)])
mark a
x [(a, SBool)]
ys in SBool
found SBool -> SBool -> SBool
.&& [a] -> [(a, SBool)] -> SBool
go [a]
xs [(a, SBool)]
ys'
mark :: a -> [(a, SBool)] -> (SBool, [(a, SBool)])
mark a
_ [] = (SBool
sFalse, [])
mark a
x ((a
y,SBool
v):[(a, SBool)]
ys) = forall a. Mergeable a => SBool -> a -> a -> a
ite (SBool
v SBool -> SBool -> SBool
.&& a
x forall a. EqSymbolic a => a -> a -> SBool
.== a
y)
(SBool
sTrue, (a
y, SBool -> SBool
sNot SBool
v)forall a. a -> [a] -> [a]
:[(a, SBool)]
ys)
(let (SBool
r, [(a, SBool)]
ys') = a -> [(a, SBool)] -> (SBool, [(a, SBool)])
mark a
x [(a, SBool)]
ys in (SBool
r, (a
y,SBool
v)forall a. a -> [a] -> [a]
:[(a, SBool)]
ys'))
correctness :: Int -> IO ThmResult
correctness :: Int -> IO ThmResult
correctness Int
n = forall a. Provable a => a -> IO ThmResult
prove forall a b. (a -> b) -> a -> b
$ do [E]
xs <- forall a. SymVal a => Int -> Symbolic [SBV a]
mkFreeVars Int
n
let ys :: [E]
ys = [E] -> [E]
mergeSort [E]
xs
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [E] -> SBool
nonDecreasing [E]
ys SBool -> SBool -> SBool
.&& [E] -> [E] -> SBool
isPermutationOf [E]
xs [E]
ys
codeGen :: Int -> IO ()
codeGen :: Int -> IO ()
codeGen Int
n = forall a. Maybe FilePath -> FilePath -> SBVCodeGen a -> IO a
compileToC (forall a. a -> Maybe a
Just (FilePath
"mergeSort" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> FilePath
show Int
n)) FilePath
"mergeSort" forall a b. (a -> b) -> a -> b
$ do
[E]
xs <- forall a. SymVal a => Int -> FilePath -> SBVCodeGen [SBV a]
cgInputArr Int
n FilePath
"xs"
forall a. SymVal a => FilePath -> [SBV a] -> SBVCodeGen ()
cgOutputArr FilePath
"ys" ([E] -> [E]
mergeSort [E]
xs)