Add a rule for multiplication

When the constraint is of the form, `k1 * x = k2 * y`, and `gcd k1 k2 /= 1`,
simplify the constraint to `(k1 / gcd k1 k2) * x = (k2 / gcd k1 k2) * y`.
(NOTE: this doesn't produce a new constraint that uses division, but
evaluates the two two constants.)
This commit is contained in:
Trevor Elliott 2017-03-24 16:41:12 -07:00
parent d498212684
commit 1e723d5265

View File

@ -5,10 +5,11 @@ module Cryptol.TypeCheck.Solver.Numeric
import Control.Applicative(Alternative(..)) import Control.Applicative(Alternative(..))
import Control.Monad (guard,mzero) import Control.Monad (guard,mzero)
import Data.Foldable (asum)
import Cryptol.Utils.Patterns import Cryptol.Utils.Patterns
import Cryptol.TypeCheck.PP import Cryptol.TypeCheck.PP
import Cryptol.TypeCheck.Type import Cryptol.TypeCheck.Type hiding (tMul)
import Cryptol.TypeCheck.TypePat import Cryptol.TypeCheck.TypePat
import Cryptol.TypeCheck.Solver.Types import Cryptol.TypeCheck.Solver.Types
import Cryptol.TypeCheck.Solver.InfNat import Cryptol.TypeCheck.Solver.InfNat
@ -27,6 +28,7 @@ cryIsEqual ctxt t1 t2 =
<|> ( guard (t1 == t2) >> return (SolvedIf [])) <|> ( guard (t1 == t2) >> return (SolvedIf []))
<|> tryEqMin t1 t2 <|> tryEqMin t1 t2
<|> tryEqMin t2 t1 <|> tryEqMin t2 t1
<|> tryEqMulConst t1 t2
@ -200,4 +202,35 @@ tryEqK ctxt ty lk =
tryEqMulConst :: Type -> Type -> Match Solved
tryEqMulConst l r =
do (l1,l2) <- aMul l
(r1,r2) <- aMul r
asum [ do l1' <- aNat l1
r1' <- aNat r1
return (build l1' l2 r1' r2)
, do l2' <- aNat l2
r1' <- aNat r1
return (build l2' l1 r1' r2)
, do l1' <- aNat l1
r2' <- aNat r2
return (build l1' l2 r2' r1)
, do l2' <- aNat l2
r2' <- aNat r2
return (build l2' l1 r2' r1)
]
where
build lk l' rk r' =
let d = gcd lk rk
lk' = lk `div` d
rk' = rk `div` d
in if d == 1
then Unsolved
else (SolvedIf [ tMul (tNum lk') l' =#= tMul (tNum rk') r' ])