rounded-hw-0.1.0.0: test/ShowFloatSpec.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
module ShowFloatSpec where
import Data.Int
import Data.Proxy
import Numeric
import Numeric.Rounded.Hardware.Internal
import Test.Hspec
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck
import Util ()
prop_showEFloat_nearest :: forall a. RealFloat a => Proxy a -> Int -> Int32 -> Property
prop_showEFloat_nearest _proxy prec x = showEFloat mprec x' "" === showEFloatRn ToNearest mprec x' ""
where mprec = Just prec
x' = fromIntegral x / 64 :: a
prop_showFFloat_nearest :: forall a. RealFloat a => Proxy a -> Int -> Int32 -> Property
prop_showFFloat_nearest _proxy prec x = showFFloat mprec x' "" === showFFloatRn ToNearest mprec x' ""
where mprec = Just prec
x' = fromIntegral x / 64 :: a
prop_showGFloat_nearest :: forall a. RealFloat a => Proxy a -> Int -> Int32 -> Property
prop_showGFloat_nearest _proxy prec x = showGFloat mprec x' "" === showGFloatRn ToNearest mprec x' ""
where mprec = Just prec
x' = fromIntegral x / 64 :: a
prop_showEFloat :: forall a. RealFloat a => Proxy a -> Maybe Int -> a -> Property
prop_showEFloat _proxy mprec x =
let rn = showEFloatRn ToNearest mprec x ""
ru = showEFloatRn TowardInf mprec x ""
rd = showEFloatRn TowardNegInf mprec x ""
rz = showEFloatRn TowardZero mprec x ""
in rn === ru .||. rn === rd .||. rz === (if x > 0 then rd else ru)
prop_showFFloat :: forall a. RealFloat a => Proxy a -> Maybe Int -> a -> Property
prop_showFFloat _proxy mprec x =
let rn = showFFloatRn ToNearest mprec x ""
ru = showFFloatRn TowardInf mprec x ""
rd = showFFloatRn TowardNegInf mprec x ""
rz = showFFloatRn TowardZero mprec x ""
in rn === ru .||. rn === rd .||. rz === (if x > 0 then rd else ru)
prop_showGFloat :: forall a. RealFloat a => Proxy a -> Maybe Int -> a -> Property
prop_showGFloat _proxy mprec x =
let rn = showGFloatRn ToNearest mprec x ""
ru = showGFloatRn TowardInf mprec x ""
rd = showGFloatRn TowardNegInf mprec x ""
rz = showGFloatRn TowardZero mprec x ""
in rn === ru .||. rn === rd .||. rz === (if x > 0 then rd else ru)
testAgainstNumeric :: forall a. RealFloat a => Proxy a -> Spec
testAgainstNumeric proxy = do
describe "showFloat" $ do
prop "showEFloat (nearest)" $ prop_showEFloat_nearest proxy
prop "showFFloat (nearest)" $ prop_showFFloat_nearest proxy
prop "showGFloat (nearest)" $ prop_showGFloat_nearest proxy
prop "showEFloat/Int32" $ \mprec (x :: Int32) ->
showEFloat mprec (fromIntegral x :: a) "" === showEFloatRn ToNearest mprec (fromIntegral x :: a) ""
prop "showFFloat/Int32" $ \mprec (x :: Int32) ->
showFFloat mprec (fromIntegral x :: a) "" === showFFloatRn ToNearest mprec (fromIntegral x :: a) ""
prop "showGFloat/Int32" $ \mprec (x :: Int32) ->
showGFloat mprec (fromIntegral x :: a) "" === showGFloatRn ToNearest mprec (fromIntegral x :: a) ""
specT :: forall a. (RealFloat a, Arbitrary a, Show a) => Proxy a -> Spec
specT proxy = do
prop "showEFloat" $ prop_showEFloat proxy
prop "showFFloat" $ prop_showFFloat proxy
prop "showGFloat" $ prop_showGFloat proxy
-- 0.5 should be exactly representable in the type...
prop "showFFloatRn Nothing 0.5" $ \r -> showFFloatRn r Nothing (0.5 :: a) "" === "0.5"
prop "showFFloatRn (Just 0) 0.5" $ \r -> showFFloatRn r (Just 0) (0.5 :: a) "" === (if r == TowardInf then "1" else "0")
prop "showFFloatRn (Just 3) 0.5" $ \r -> showFFloatRn r (Just 3) (0.5 :: a) "" === "0.500"
prop "showGFloatRn Nothing 0.5" $ \r -> showGFloatRn r Nothing (0.5 :: a) "" === "0.5"
prop "showGFloatRn (Just 0) 0.5" $ \r -> showGFloatRn r (Just 0) (0.5 :: a) "" === (if r == TowardInf then "1" else "0")
prop "showGFloatRn (Just 3) 0.5" $ \r -> showGFloatRn r (Just 3) (0.5 :: a) "" === "0.500"
prop "showEFloatRn Nothing 0.5" $ \r -> showEFloatRn r Nothing (0.5 :: a) "" === "5.0e-1"
prop "showEFloatRn (Just 0) 0.5" $ \r -> showEFloatRn r (Just 0) (0.5 :: a) "" === "5e-1"
prop "showEFloatRn (Just 3) 0.5" $ \r -> showEFloatRn r (Just 3) (0.5 :: a) "" === "5.000e-1"
spec :: Spec
spec = do
describe "Double" $ testAgainstNumeric (Proxy :: Proxy Double)
-- The functions in Numeric yields a rounded value:
-- >>> showFFloat Nothing (137846.59375 :: Float) ""
-- "137846.6"
-- So comparing them
-- describe "Float" $ testAgainstNumeric (Proxy :: Proxy Float)
describe "Double" $ specT (Proxy :: Proxy Double)
describe "Float" $ specT (Proxy :: Proxy Float)