Skip to content

Commit aaca8d1

Browse files
copilot-bluespec: Fix translation of special Float values to Bluespec. Refs #697.
`copilot-bluespec`'s translation from Copilot to Bluespec up-casts `Float` values to `Double` values using the `realToFrac` function. `realToFrac` incorrectly handles special floating-point values such as negative zero, infinity, and NaN values, causing `copilot-bluespec` to generate the wrong `Float` values on the Bluespec end. This commit removes the use of `realToFrac` in favor of an alternative approach based on `GHC.Float.float2Double`, which correctly handles most special floating-point values. A notable exception is NaN values, as `float2Double` does not reliably preserve the payload of a NaN value. As such, we include a special case for NaN values that takes care to preserve payloads. Co-authored-by: Ryan Scott <rscott@galois.com>
1 parent 0c987a7 commit aaca8d1

1 file changed

Lines changed: 21 additions & 2 deletions

File tree

  • copilot-bluespec/src/Copilot/Compile/Bluespec

copilot-bluespec/src/Copilot/Compile/Bluespec/Expr.hs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Data.String (IsString (..))
1818
import qualified Language.Bluespec.Classic.AST as BS
1919
import qualified Language.Bluespec.Classic.AST.Builtin.Ids as BS
2020
import Numeric.Floating.IEEE.NaN (isSignaling, setPayloadSignaling, setPayload, getPayload)
21-
import GHC.Float (double2Float, castFloatToWord32, castDoubleToWord64)
21+
import GHC.Float (double2Float, castFloatToWord32, castDoubleToWord64, float2Double)
2222

2323
-- Internal imports: Copilot
2424
import Copilot.Core
@@ -535,7 +535,7 @@ constTy ty =
535535
Word16 -> constInt ty . toInteger
536536
Word32 -> constInt ty . toInteger
537537
Word64 -> constInt ty . toInteger
538-
Float -> constFP ty . realToFrac
538+
Float -> constFP ty . nanSafeFloat2Double
539539
Double -> constFP ty
540540

541541
-- Translating a Copilot array literal to a Bluespec Vector is somewhat
@@ -563,6 +563,25 @@ constTy ty =
563563
, constTy ty'' val
564564
))
565565
(toValues v))
566+
where
567+
-- Convert a Float to a Double. This function takes care to preserve
568+
-- special floating-point values, such as negative zero, infinity, and NaN
569+
-- values.
570+
nanSafeFloat2Double :: Float -> Double
571+
nanSafeFloat2Double x
572+
| isNaN x = convertFloatNaNToDoubleNan x
573+
| otherwise = float2Double x
574+
where
575+
payload :: Double
576+
payload = float2Double $ getPayload x
577+
578+
-- float2Double does not preserve the payloads of NaN values, so we
579+
-- include a special case for translating NaNs.
580+
convertFloatNaNToDoubleNan :: Float -> Double
581+
convertFloatNaNToDoubleNan nan =
582+
if isSignaling nan
583+
then setPayloadSignaling payload
584+
else setPayload payload
566585

567586
-- | Transform a list of Copilot Core expressions of a given 'Type' into a
568587
-- Bluespec @Vector@ expression.

0 commit comments

Comments
 (0)