{-# Language BlockArguments #-}
{-# Language OverloadedStrings #-}
module Cryptol.Eval.Concrete.Float where
import Data.Map(Map)
import Data.Ratio((%),numerator,denominator)
import qualified Data.Map as Map
import LibBF
import Cryptol.Utils.Ident(PrimIdent, floatPrim)
import Cryptol.Eval.Value
import Cryptol.Eval.Generic
import Cryptol.Eval.Concrete.Value
import Cryptol.Eval.Backend(SRational(..))
import Cryptol.Eval.Concrete.FloatHelpers
floatPrims :: Concrete -> Map PrimIdent Value
floatPrims sym = Map.fromList [ (floatPrim i,v) | (i,v) <- nonInfixTable ]
where
(~>) = (,)
nonInfixTable =
[ "fpNaN" ~> ilam \e -> ilam \p ->
VFloat BF { bfValue = bfNaN
, bfExpWidth = e, bfPrecWidth = p }
, "fpPosInf" ~> ilam \e -> ilam \p ->
VFloat BF { bfValue = bfPosInf
, bfExpWidth = e, bfPrecWidth = p }
, "fpFromBits" ~> ilam \e -> ilam \p -> wlam sym \bv ->
pure $ VFloat $ floatFromBits e p $ bvVal bv
, "fpToBits" ~> ilam \e -> ilam \p -> flam \x ->
pure $ word sym (e + p)
$ floatToBits e p
$ bfValue x
, "=.=" ~> ilam \_ -> ilam \_ -> flam \x -> pure $ flam \y ->
pure $ VBit
$ bitLit sym
$ bfCompare (bfValue x) (bfValue y) == EQ
, "fpIsFinite" ~> ilam \_ -> ilam \_ -> flam \x ->
pure $ VBit $ bitLit sym $ bfIsFinite $ bfValue x
, "fpAdd" ~> fpBinArithV sym fpPlus
, "fpSub" ~> fpBinArithV sym fpMinus
, "fpMul" ~> fpBinArithV sym fpMult
, "fpDiv" ~> fpBinArithV sym fpDiv
, "fpFromRational" ~>
ilam \e -> ilam \p -> wlam sym \r -> pure $ lam \x ->
do rat <- fromVRational <$> x
VFloat <$> do mode <- fpRoundMode sym r
pure $ floatFromRational e p mode
$ sNum rat % sDenom rat
, "fpToRational" ~>
ilam \_e -> ilam \_p -> flam \fp ->
case floatToRational "fpToRational" fp of
Left err -> raiseError sym err
Right r -> pure $
VRational
SRational { sNum = numerator r, sDenom = denominator r }
]