packages feed

copilot-verifier-0.1: examples/Copilot/Verifier/Examples/ShouldPass/Arith.hs

{-# LANGUAGE RebindableSyntax #-}

module Copilot.Verifier.Examples.ShouldPass.Arith where

import Control.Monad (when)
import qualified Prelude as P

import Language.Copilot
import Copilot.Compile.C99
import Copilot.Verifier ( Verbosity(..), VerifierOptions(..)
                        , defaultVerifierOptions, verifyWithOptions )
import Copilot.Theorem.What4 (prove, Solver(..))

-- The largest unsigned 32-bit prime
lastPrime :: Stream Word32
lastPrime = 31
--lastPrime = 4294967291 -- Whelp, this prime seems too big for the solvers to handle well

multRingSpec :: Spec
multRingSpec = do
  _ <- prop "clamp nonzero" (forAll ((clamp > 0) && (clamp < lastPrime)))
  _ <- prop "reduced" (forAll (acc < lastPrime))
  _ <- prop "nonzero" (forAll (acc > 0 && (acc < lastPrime)))

  trigger "outofrange" (not (acc > 0 && acc < lastPrime)) [arg acc]

  return ()

  where
  -- a stream of external values
  vals  = externW32 "values" Nothing

  -- Generate a value in [1, lastPrime), which
  -- is the multiplictive group of Z_p
  clamp :: Stream Word32
  clamp = (vals `mod` (lastPrime - 1)) + 1

  -- Successively multiply new values
  acc :: Stream Word32
  acc = [1] ++ unsafeCast ((cast acc * cast clamp) `mod` (cast lastPrime :: Stream Word64))

verifySpec :: Verbosity -> IO ()
verifySpec verb =
  do s <- reify multRingSpec
     r <- prove Z3 s
     when (verb P.>= Default) $
       print r
     verifyWithOptions defaultVerifierOptions{verbosity = verb}
                       mkDefaultCSettings ["reduced"] "multRingSpec" s

--verifySpec _ = interpret 10 engineMonitor