Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions copilot-bluespec/CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2026-03-31
* Fix translation of special Float values to Bluespec. (#697)

2026-03-07
* Version bump (4.7). (#714)

Expand Down
18 changes: 16 additions & 2 deletions copilot-bluespec/src/Copilot/Compile/Bluespec/Expr.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Data.String (IsString (..))
import qualified Language.Bluespec.Classic.AST as BS
import qualified Language.Bluespec.Classic.AST.Builtin.Ids as BS
import Numeric.Floating.IEEE.NaN (isSignaling, setPayloadSignaling, setPayload, getPayload)
import GHC.Float (double2Float, castFloatToWord32, castDoubleToWord64)
import GHC.Float (double2Float, castFloatToWord32, castDoubleToWord64, float2Double)

-- Internal imports: Copilot
import Copilot.Core
Expand Down Expand Up @@ -535,7 +535,7 @@ constTy ty =
Word16 -> constInt ty . toInteger
Word32 -> constInt ty . toInteger
Word64 -> constInt ty . toInteger
Float -> constFP ty . realToFrac
Float -> constFP ty . nanSafeFloat2Double
Double -> constFP ty

-- Translating a Copilot array literal to a Bluespec Vector is somewhat
Expand Down Expand Up @@ -563,6 +563,20 @@ constTy ty =
, constTy ty'' val
))
(toValues v))
where
-- Convert a Float to a Double. This function takes care to preserve
-- special floating-point values, such as negative zero, infinity, and NaN
-- values.
nanSafeFloat2Double :: Float -> Double
nanSafeFloat2Double x
-- float2Double does not preserve the payloads of NaN values, so we
-- include special cases for translating NaNs.
| isNaN x && isSignaling x = setPayloadSignaling payload
| isNaN x = setPayload payload
| otherwise = float2Double x
where
payload :: Double
payload = float2Double $ getPayload x

-- | Transform a list of Copilot Core expressions of a given 'Type' into a
-- Bluespec @Vector@ expression.
Expand Down
3 changes: 3 additions & 0 deletions copilot-theorem/CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2026-03-31
* Handle special Float values correctly for counterexamples. (#697)

2026-03-07
* Version bump (4.7). (#714)

Expand Down
1 change: 1 addition & 0 deletions copilot-theorem/copilot-theorem.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ library
, containers >= 0.4 && < 0.9
, data-default >= 0.7 && < 0.9
, directory >= 1.3 && < 1.4
, fp-ieee >= 0.1 && < 0.2
, libBF >= 0.6.2 && < 0.7
, mtl >= 2.0 && < 2.4
, panic >= 0.4.0 && < 0.5
Expand Down
19 changes: 17 additions & 2 deletions copilot-theorem/src/Copilot/Theorem/What4.hs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ import Data.Parameterized.NatRepr
import Data.Parameterized.Nonce
import Data.Parameterized.Some
import qualified Data.Parameterized.Vector as V
import GHC.Float (castWord32ToFloat, castWord64ToDouble)
import GHC.Float (castWord32ToFloat, castWord64ToDouble, double2Float)
import LibBF (BigFloat, bfToDouble, pattern NearEven)
import Numeric.Floating.IEEE.NaN (getPayload, isSignaling, setPayload, setPayloadSignaling)
import qualified Panic as Panic

import Copilot.Theorem.What4.Translate
Expand Down Expand Up @@ -707,7 +708,7 @@ valFromExpr ge xe = case xe of
XFloat e ->
Some . CopilotValue CT.Float <$>
iFloatGroundEval WFP.SingleFloatRepr e
(realToFrac . fst . bfToDouble NearEven)
(nanSafeDoubleToFloat . fst . bfToDouble NearEven)
fromRational
(castWord32ToFloat . fromInteger . BV.asUnsigned)
XDouble e ->
Expand Down Expand Up @@ -757,3 +758,17 @@ valFromExpr ge xe = case xe of
WB.FloatIEEERepr -> ieeeK <$> WG.groundEval ge e
WB.FloatRealRepr -> realK <$> WG.groundEval ge e
WB.FloatUninterpretedRepr -> uninterpK <$> WG.groundEval ge e

-- Convert a Double to a Float. This function takes care to preserve
-- special floating-point values, such as negative zero, infinity, and NaN
-- values.
nanSafeDoubleToFloat :: Double -> Float
nanSafeDoubleToFloat x
-- double2Float does not preserve the payloads of NaN values, so we
-- include a special case for translating NaNs.
| isNaN x && isSignaling x = setPayloadSignaling payload
| isNaN x = setPayload payload
| otherwise = double2Float x
where
payload :: Float
payload = double2Float $ getPayload x