Ticket #1254 (closed bug: fixed)

Opened 6 years ago

Last modified 4 years ago

truncate = float2Int rule is incorrect

Reported by: brian@… Owned by:
Priority: lowest Milestone: 6.8.1
Component: libraries/base Version: 6.7
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: powerpc
Type of failure: Difficulty: Easy (less than 1 hour)
Test Case: arith005 Blocked By:
Blocking: Related Tickets:

Description

This is only on powerpc...

$ cat Test.hs
module Main where

f = read "2147483648"  :: Float -- Hack to prevent inlining
main = print (truncate f :: Int)
b@brian:~$ ghc -no-recomp -O Test.hs   && ./a.out  
2147483647
b@brian:~$ ghc -no-recomp -O Test.hs -frules-off && ./a.out  
-2147483648

In GHC.Float we have

{-# RULES "truncate/Float->Int" truncate = float2Int #-}
...
float2Int   (F# x) = I# (float2Int# x)

But when there is oveflow float2Int# on PPC doesn't behave the same way as fromIntegral . (truncate::Float -> Integer), it does on x86 though.

I'm not sure if this should be fixed in the libraries or in the codegen. I'd probably argue that float2Int# should stay the same though, so programmers have access to a fast float to int conversion when they know overflow isn't an issue. Something like uncheckedFloat2Int# (like the shift ops) with a float2Int# wrapper is probably right.

As a side note, the builtin rule in PrelRules? for float2Int is also incorrect as it goes via Integer. If float2Int# in the codegen is modified this will become correct but if the uncheckedFloat2Int# route is taken then that rule should probably be fixed.

I may fix this sometime, but for now I just wanted to document it.

Change History

Changed 6 years ago by guest

  • summary changed from truncate = int2Float rule is incorrect to truncate = float2Int rule is incorrect

Changed 6 years ago by guest

Also... this all probably applies to Double too.

Changed 6 years ago by simonmar

  • testcase set to arith005
  • milestone changed from _|_ to 6.8

There's more: float2Int# is implemented in the C backend as a cast. The C spec does not define the result of the cast when the result would be outside the range of the destination type, so we get unpredictable results.

The Haskell report doesn't say what should happen in the case of truncate when the result doesn't fit, and the description for properFraction doesn't either. Therefore I guess the result is undefined for Haskell 98, we should clarify for Haskell'.

Bottom line: I think the test should be fixed (arith005), and this isn't a bug.

Changed 6 years ago by simonmar

  • status changed from new to closed
  • resolution set to fixed

arith005 now avoids overflow when testing truncate, so we now get consistent results. I'm therefore closing the bug.

Changed 6 years ago by igloo

  • milestone changed from 6.8 branch to 6.8.1

Changed 5 years ago by simonmar

  • os changed from Multiple to Unknown/Multiple

Changed 4 years ago by simonmar

  • difficulty changed from Easy (1 hr) to Easy (less than 1 hour)
Note: See TracTickets for help on using tickets.