fp-ieee-0.1.0: test/AugmentedArithSpec.hs
{-# LANGUAGE HexFloatLiterals #-}
{-# LANGUAGE ScopedTypeVariables #-}
module AugmentedArithSpec where
import Control.Monad
import Numeric
import Numeric.Floating.IEEE
import Numeric.Floating.IEEE.Internal
import RoundingSpec (RoundTiesTowardZero (..))
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck hiding (classify)
import Util
augmentedAddition_viaRational :: (RealFloat a, Show a) => a -> a -> (a, a)
augmentedAddition_viaRational x y
| isFinite x && isFinite y && (x /= 0 || y /= 0) =
let z :: Rational
z = toRational x + toRational y
z' = roundTiesTowardZero (fromRationalR z) `asTypeOf` x
in if isInfinite z' then
(z', z')
else
let w :: Rational
w = z - toRational z'
w' = roundTiesTowardZero (fromRationalR w) `asTypeOf` x
in if w == 0 then
(z', 0 * z')
else
(z', w')
| otherwise = let z = x + y
in (z, z)
augmentedMultiplication_viaRational :: (RealFloat a, Show a) => a -> a -> (a, a)
augmentedMultiplication_viaRational x y
| isFinite x && isFinite y && x * y /= 0 =
let z :: Rational
z = toRational x * toRational y
z' = roundTiesTowardZero (fromRationalR z) `asTypeOf` x
in if isInfinite z' then
(z', z')
else
let w :: Rational
w = z - toRational z'
w' = roundTiesTowardZero (fromRationalR w) `asTypeOf` x
in if w == 0 then
(z', 0 * z')
else
(z', w')
| otherwise = let z = x * y
in (z, z)
testAugmented :: (RealFloat a, Show a) => (a -> a -> (a, a)) -> [(a, a, a, a)] -> Property
testAugmented f cases = conjoin
[ let label = showHFloat a . showChar ' ' . showHFloat b $ ""
in counterexample label $ f a b `sameFloatPairP` (r1,r2)
| (a,b,r1,r2) <- cases
]
{-# NOINLINE spec #-}
spec :: Spec
spec = modifyMaxSuccess (* 100) $ do
describe "Double" $ do
do -- augmentedAddition
prop "augmentedAddition/equality" $ forAllFloats2 $ \(x :: Double) y ->
isFinite x && isFinite y ==>
let (s,t) = augmentedAddition x y
in isFinite s ==> isFinite t .&&. toRational s + toRational t === toRational x + toRational y
let cases :: [(Double, Double, Double, Double)]
cases = [ (-0, -0, -0, -0)
]
prop "augmentedAddition" $ testAugmented augmentedAddition cases
prop "augmentedAddition_viaRational" $ testAugmented augmentedAddition_viaRational cases
prop "augmentedAddition" $ forAllFloats2 $ \(x :: Double) y ->
augmentedAddition x y `sameFloatPairP` augmentedAddition_viaRational x y
do -- augmentedMultiplication
let cases :: [(Double, Double, Double, Double)]
cases = [ (-0x1.3deed726aad4p-1023, 0x1.e179bde0a1dd2p-1, -0x1.2afa79f9d38c6p-1023, 0x0p+0)
, (-0x1.8eb0e02044f68p-1022, -0x1.c93b83a5751c8p-2, 0x1.640b37f1b9d02p-1023,-0x0p+0)
, (0x1.b877a1cd61478p-1023, -0x1.7a77bb9df06dap-1, -0x1.459753aa4d2bep-1023, -0x0p+0)
, (-0x1.d25f2402fe726p-1, -0x1.0b42f4e9eb842p-1, 0x1.e6e335433c1f9p-2, -0x1.bb70c80f1834p-58)
]
prop "augmentedMultiplication" $ testAugmented augmentedMultiplication cases
prop "augmentedMultiplication_viaRational" $ testAugmented augmentedMultiplication_viaRational cases
prop "augmentedMultiplication" $ forAllFloats2 $ \(x :: Double) y ->
augmentedMultiplication x y `sameFloatPairP` augmentedMultiplication_viaRational x y
describe "Float" $ do
do -- augmentedAddition
prop "augmentedAddition/equality" $ forAllFloats2 $ \(x :: Float) y ->
isFinite x && isFinite y ==>
let (s,t) = augmentedAddition x y
in isFinite s ==> isFinite t .&&. toRational s + toRational t === toRational x + toRational y
let cases :: [(Float, Float, Float, Float)]
cases = [(-0, -0, -0, -0)]
prop "augmentedAddition" $ testAugmented augmentedAddition cases
prop "augmentedAddition_viaRational" $ testAugmented augmentedAddition_viaRational cases
prop "augmentedAddition" $ forAllFloats2 $ \(x :: Float) y ->
augmentedAddition x y `sameFloatPairP` augmentedAddition_viaRational x y
do -- augmentedMultiplication
let cases :: [(Float, Float, Float, Float)]
cases = [ (0x1.b8508p-130, -0x1.93994p-4, -0x1.5b17p-133, -0x0p+0)
, (0x1.5433bcp-126, -0x1.69a04p-1, -0x1.e091e8p-127, -0x0p+0)
, (0x1.c7363p-128, -0x1.c5d164p-1, -0x1.937b98p-128, -0x0p+0)
, (-0x1.a31946p0, -0x1p-127, 0x1.a31944p-127, 0x0p+0)
]
prop "augmentedMultiplication" $ testAugmented augmentedMultiplication cases
prop "augmentedMultiplication_viaRational" $ testAugmented augmentedMultiplication_viaRational cases
prop "augmentedMultiplication" $ forAllFloats2 $ \(x :: Float) y ->
augmentedMultiplication x y `sameFloatPairP` augmentedMultiplication_viaRational x y