Strange behaviour in my signum

I started preparing patches for #7858. My abs patch works well, my signum patch not at all. The gist of the bug is that abs and signum return erroneous values for for the input -0.0. abs (-0.0 :: Float) should return 0.0, not -0.0. My patch fixes this. For signum the situation is reverse. My patch does *not* fix this. It does not work using GHC nor GHCi (GHCi -ddump-simpl demonstrated below). The code for my signum is correct, as may be demonstrated by putting signumFix x | x == 0.0 = x | isNaN x = x | x > 0.0 = 1 | otherwise = negate 1 in a file signumfix.hs and :l signumfix.hs into GHCi. signumFix (-0.0 :: Float) should now return -0.0, where signum returns 0.0 with the same argument. Following this email come the patches. Please review the second patch. If you can spot what I am doing wrong, I would be grateful. Prelude> abs (-0.0 :: Float) ==================== Simplified expression ==================== let { it_aqt :: GHC.Types.Float [LclId, Str=DmdType, Unf=Unf{Src=<vanilla>, TopLvl=False, Arity=0, Value=False, ConLike=False, WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 70 0}] it_aqt = GHC.Num.abs @ GHC.Types.Float GHC.Float.$fNumFloat (GHC.Num.negate @ GHC.Types.Float GHC.Float.$fNumFloat (GHC.Types.F# (__float 0.0))) } in GHC.Base.thenIO @ () @ [()] (System.IO.print @ GHC.Types.Float GHC.Float.$fShowFloat it_aqt) (GHC.Base.returnIO @ [()] (GHC.Types.: @ () (it_aqt `cast` (UnivCo representational GHC.Types.Float () :: GHC.Types.Float ~# ())) (GHC.Types.[] @ ()))) 0.0 Prelude> signum (-0.0 :: Float) ==================== Simplified expression ==================== let { it_aKQ :: GHC.Types.Float [LclId, Str=DmdType, Unf=Unf{Src=<vanilla>, TopLvl=False, Arity=0, Value=False, ConLike=False, WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 70 0}] it_aKQ = GHC.Num.signum @ GHC.Types.Float GHC.Float.$fNumFloat (GHC.Num.negate @ GHC.Types.Float GHC.Float.$fNumFloat (GHC.Types.F# (__float 0.0))) } in GHC.Base.thenIO @ () @ [()] (System.IO.print @ GHC.Types.Float GHC.Float.$fShowFloat it_aKQ) (GHC.Base.returnIO @ [()] (GHC.Types.: @ () (it_aKQ `cast` (UnivCo representational GHC.Types.Float () :: GHC.Types.Float ~# ())) (GHC.Types.[] @ ()))) 0.0 Alexander Berntsen (2): Make Prelude.abs handle -0.0 correctly (#7858) Make Prelude.signum handle -0.0 correctly (#7858) libraries/base/GHC/Float.lhs | 28 ++++++++++++++++++---------- libraries/base/changelog.md | 2 ++ 2 files changed, 20 insertions(+), 10 deletions(-) -- 1.8.3.2

Make the `Float` and `Double` implementations of `abs` handle -0.0 correctly per IEEE-754. --- libraries/base/GHC/Float.lhs | 12 ++++++++---- libraries/base/changelog.md | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/base/GHC/Float.lhs b/libraries/base/GHC/Float.lhs index e0c4f4a..442e13c 100644 --- a/libraries/base/GHC/Float.lhs +++ b/libraries/base/GHC/Float.lhs @@ -205,8 +205,10 @@ instance Num Float where (-) x y = minusFloat x y negate x = negateFloat x (*) x y = timesFloat x y - abs x | x >= 0.0 = x - | otherwise = negateFloat x + abs x + | isNegativeZero x = 0 + | x >= 0.0 = x + | otherwise = negateFloat x signum x | x == 0.0 = 0 | x > 0.0 = 1 | otherwise = negate 1 @@ -370,8 +372,10 @@ instance Num Double where (-) x y = minusDouble x y negate x = negateDouble x (*) x y = timesDouble x y - abs x | x >= 0.0 = x - | otherwise = negateDouble x + abs x + | isNegativeZero x = 0 + | x >= 0.0 = x + | otherwise = negateDouble x signum x | x == 0.0 = 0 | x > 0.0 = 1 | otherwise = negate 1 diff --git a/libraries/base/changelog.md b/libraries/base/changelog.md index a72e4e6..9eb279e 100644 --- a/libraries/base/changelog.md +++ b/libraries/base/changelog.md @@ -10,6 +10,8 @@ * Weaken RealFloat constraints on some `Data.Complex` functions + * Make `abs` handle -0.0 correctly for `Float` and `Double`. + ## 4.7.0.0 *Apr 2014* * Bundled with GHC 7.8.1 -- 1.8.3.2

Make the `Float` and `Double` implementations of `signum` handle -0.0 correctly per IEEE-754. --- libraries/base/GHC/Float.lhs | 16 ++++++++++------ libraries/base/changelog.md | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/base/GHC/Float.lhs b/libraries/base/GHC/Float.lhs index 442e13c..294ebd5 100644 --- a/libraries/base/GHC/Float.lhs +++ b/libraries/base/GHC/Float.lhs @@ -209,9 +209,11 @@ instance Num Float where | isNegativeZero x = 0 | x >= 0.0 = x | otherwise = negateFloat x - signum x | x == 0.0 = 0 - | x > 0.0 = 1 - | otherwise = negate 1 + signum x + | x == 0.0 = x + | isNaN x = x + | x > 0.0 = 1 + | otherwise = negate 1 {-# INLINE fromInteger #-} fromInteger i = F# (floatFromInteger i) @@ -376,9 +378,11 @@ instance Num Double where | isNegativeZero x = 0 | x >= 0.0 = x | otherwise = negateDouble x - signum x | x == 0.0 = 0 - | x > 0.0 = 1 - | otherwise = negate 1 + signum x + | x == 0.0 = x + | isNaN x = x + | x > 0.0 = 1 + | otherwise = negate 1 {-# INLINE fromInteger #-} fromInteger i = D# (doubleFromInteger i) diff --git a/libraries/base/changelog.md b/libraries/base/changelog.md index 9eb279e..bc52660 100644 --- a/libraries/base/changelog.md +++ b/libraries/base/changelog.md @@ -10,7 +10,7 @@ * Weaken RealFloat constraints on some `Data.Complex` functions - * Make `abs` handle -0.0 correctly for `Float` and `Double`. + * Make `abs` and `signum` handle -0.0 correctly for `Float` and `Double`. ## 4.7.0.0 *Apr 2014* -- 1.8.3.2

Alexander Thanks for working on this. I suggest you add your draft patches and comments to the ticket #7858. Otherwise there is a terrible danger that they'll get lost. Simon | -----Original Message----- | From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of | Alexander Berntsen | Sent: 19 April 2014 19:02 | To: ghc-devs@haskell.org | Subject: Strange behaviour in my signum | | I started preparing patches for #7858. My abs patch works well, my | signum patch not at all. | | The gist of the bug is that abs and signum return erroneous values for | for the input -0.0. abs (-0.0 :: Float) should return 0.0, not -0.0. My | patch fixes this. For signum the situation is reverse. My patch does | *not* fix this. | | It does not work using GHC nor GHCi (GHCi -ddump-simpl demonstrated | below). The code for my signum is correct, as may be demonstrated by | putting | | signumFix x | | x == 0.0 = x | | isNaN x = x | | x > 0.0 = 1 | | otherwise = negate 1 | | in a file signumfix.hs and :l signumfix.hs into GHCi. signumFix (-0.0 | :: | Float) should now return -0.0, where signum returns 0.0 with the same | argument. | | Following this email come the patches. Please review the second patch. | If you can spot what I am doing wrong, I would be grateful. | | | | | Prelude> abs (-0.0 :: Float) | | ==================== Simplified expression ==================== let { | it_aqt :: GHC.Types.Float | [LclId, | Str=DmdType, | Unf=Unf{Src=<vanilla>, TopLvl=False, Arity=0, Value=False, | ConLike=False, WorkFree=False, Expandable=False, | Guidance=IF_ARGS [] 70 0}] | it_aqt = | GHC.Num.abs | @ GHC.Types.Float | GHC.Float.$fNumFloat | (GHC.Num.negate | @ GHC.Types.Float | GHC.Float.$fNumFloat | (GHC.Types.F# (__float 0.0))) } in GHC.Base.thenIO | @ () | @ [()] | (System.IO.print @ GHC.Types.Float GHC.Float.$fShowFloat it_aqt) | (GHC.Base.returnIO | @ [()] | (GHC.Types.: | @ () | (it_aqt | `cast` (UnivCo representational GHC.Types.Float () | :: GHC.Types.Float ~# ())) | (GHC.Types.[] @ ()))) | | | 0.0 | | | | | Prelude> signum (-0.0 :: Float) | | ==================== Simplified expression ==================== let { | it_aKQ :: GHC.Types.Float | [LclId, | Str=DmdType, | Unf=Unf{Src=<vanilla>, TopLvl=False, Arity=0, Value=False, | ConLike=False, WorkFree=False, Expandable=False, | Guidance=IF_ARGS [] 70 0}] | it_aKQ = | GHC.Num.signum | @ GHC.Types.Float | GHC.Float.$fNumFloat | (GHC.Num.negate | @ GHC.Types.Float | GHC.Float.$fNumFloat | (GHC.Types.F# (__float 0.0))) } in GHC.Base.thenIO | @ () | @ [()] | (System.IO.print @ GHC.Types.Float GHC.Float.$fShowFloat it_aKQ) | (GHC.Base.returnIO | @ [()] | (GHC.Types.: | @ () | (it_aKQ | `cast` (UnivCo representational GHC.Types.Float () | :: GHC.Types.Float ~# ())) | (GHC.Types.[] @ ()))) | | | 0.0 | | Alexander Berntsen (2): | Make Prelude.abs handle -0.0 correctly (#7858) | Make Prelude.signum handle -0.0 correctly (#7858) | | libraries/base/GHC/Float.lhs | 28 ++++++++++++++++++---------- | libraries/base/changelog.md | 2 ++ | 2 files changed, 20 insertions(+), 10 deletions(-) | | -- | 1.8.3.2 | | _______________________________________________ | ghc-devs mailing list | ghc-devs@haskell.org | http://www.haskell.org/mailman/listinfo/ghc-devs
participants (2)
-
Alexander Berntsen
-
Simon Peyton Jones