[GHC] #15271: 1e1000000000 :: Double yields 0.0 instead of Infinity

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.6.1 Component: Compiler | Version: 8.4.3 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Incorrect result Unknown/Multiple | at runtime Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- (This bug report is about the incorrect result not the poor performance.) Very large positive exponent in floating point literal at Double type gives `0` instead of `Infinity` in `ghci-8.4.3` (self-compiled on Debian Buster x86_64 / amd64): {{{ $ ghci GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help Prelude> :set +s Prelude> 1e100000000 :: Double Infinity (5.70 secs, 68,552 bytes) Prelude> 1e1000000000 :: Double 0.0 (69.35 secs, 60,088 bytes) }}} Writing `10^` instead of `1e` completes almost instantly with the correct result (`Infinity`) in both cases. More precisely, {{{ Prelude> 1e646457008 :: Double Infinity (40.80 secs, 64,272 bytes) Prelude> 1e646457009 :: Double 0.0 (40.46 secs, 60,088 bytes) }}} Note: {{{#!hs (floor $ 2^31 / logBase 2 10 + 16) == 646457009 }}} This vague numerology makes me think something C `int`-related is overflowing somewhere (GMP? integer-gmp? GHC?). Standalone test program: {{{#!hs main = do print 1e646457008 print 1e646457009 }}} Interestingly, it doesn't occur, or at least not near the same threshold, in 32-bit `ghci-8.0.1` (Debian Stretch i686), though it aborts when getting too large (the 32-bit i686 machine has 1GB RAM and 4GB swap, the 64-bit x86_64/amd64 has 32GB RAM). The sheer time it takes to run makes bisecting the exact threshold on i686 not something I want to take on (though if someone writes some code that can do it programmatically I'd be happy to run it overnight if it would help). {{{ $ ghci GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Prelude> :set +s Prelude> 1e646457008 :: Double Infinity (415.26 secs, 17,908 bytes) Prelude> 1e646457009 :: Double Infinity (417.66 secs, 17,820 bytes) Prelude> 1e746457298 :: Double Infinity (490.00 secs, 17,820 bytes) Prelude> 1e1000000000 :: Double GNU MP: Cannot allocate memory (size=419438600) Aborted $ }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.6.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by claude: Old description:
(This bug report is about the incorrect result not the poor performance.)
Very large positive exponent in floating point literal at Double type gives `0` instead of `Infinity` in `ghci-8.4.3` (self-compiled on Debian Buster x86_64 / amd64):
{{{ $ ghci GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help Prelude> :set +s Prelude> 1e100000000 :: Double Infinity (5.70 secs, 68,552 bytes) Prelude> 1e1000000000 :: Double 0.0 (69.35 secs, 60,088 bytes) }}}
Writing `10^` instead of `1e` completes almost instantly with the correct result (`Infinity`) in both cases.
More precisely,
{{{ Prelude> 1e646457008 :: Double Infinity (40.80 secs, 64,272 bytes) Prelude> 1e646457009 :: Double 0.0 (40.46 secs, 60,088 bytes) }}}
Note:
{{{#!hs (floor $ 2^31 / logBase 2 10 + 16) == 646457009 }}}
This vague numerology makes me think something C `int`-related is overflowing somewhere (GMP? integer-gmp? GHC?).
Standalone test program:
{{{#!hs main = do print 1e646457008 print 1e646457009 }}}
Interestingly, it doesn't occur, or at least not near the same threshold, in 32-bit `ghci-8.0.1` (Debian Stretch i686), though it aborts when getting too large (the 32-bit i686 machine has 1GB RAM and 4GB swap, the 64-bit x86_64/amd64 has 32GB RAM). The sheer time it takes to run makes bisecting the exact threshold on i686 not something I want to take on (though if someone writes some code that can do it programmatically I'd be happy to run it overnight if it would help).
{{{ $ ghci GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Prelude> :set +s Prelude> 1e646457008 :: Double Infinity (415.26 secs, 17,908 bytes) Prelude> 1e646457009 :: Double Infinity (417.66 secs, 17,820 bytes) Prelude> 1e746457298 :: Double Infinity (490.00 secs, 17,820 bytes) Prelude> 1e1000000000 :: Double GNU MP: Cannot allocate memory (size=419438600) Aborted $ }}}
New description: (This bug report is about the incorrect result not the poor performance.) Very large positive exponent in floating point literal at Double type gives `0` instead of `Infinity` in `ghci-8.4.3` (self-compiled on Debian Buster x86_64 / amd64): {{{ $ ghci GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help Prelude> :set +s Prelude> 1e100000000 :: Double Infinity (5.70 secs, 68,552 bytes) Prelude> 1e1000000000 :: Double 0.0 (69.35 secs, 60,088 bytes) }}} Writing `10^` instead of `1e` completes almost instantly with the correct result (`Infinity`) in both cases. More precisely, {{{ Prelude> 1e646457008 :: Double Infinity (40.80 secs, 64,272 bytes) Prelude> 1e646457009 :: Double 0.0 (40.46 secs, 60,088 bytes) }}} Note: {{{#!hs (floor $ 2^31 / logBase 2 10 + 16) == 646457009 }}} This vague numerology makes me think something C `int`-related is overflowing somewhere (GMP? integer-gmp? GHC?). Standalone test program: {{{#!hs main = do print 1e646457008 print 1e646457009 }}} Interestingly, it doesn't occur, or at least not near the same threshold, in 32-bit `ghci-8.0.1` (Debian Stretch i686), though it aborts when getting too large (the 32-bit i686 machine has 1GB RAM and 4GB swap, the 64-bit x86_64/amd64 has 32GB RAM). The sheer time it takes to run makes bisecting the exact threshold on i686 not something I want to take on (though if someone writes some code that can do it programmatically I'd be happy to run it overnight if it would help). {{{ $ ghci GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Prelude> :set +s Prelude> 1e646457008 :: Double Infinity (415.26 secs, 17,908 bytes) Prelude> 1e646457009 :: Double Infinity (417.66 secs, 17,820 bytes) Prelude> 1e746457298 :: Double Infinity (490.00 secs, 17,820 bytes) Prelude> 1e1000000000 :: Double GNU MP: Cannot allocate memory (size=419438600) Aborted $ }}} `ghci-8.0.2` on Debian Buster amd64 exhibits the problem also. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.6.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by sighingnow): Currently we store literal rationals as `Rational` in parsed ast, that means, for `1e5`, we will have: {{{#!hs (HsFractional (FL (SourceText "1e1000") (False) (:% (100000) (1)))) }}} Note that we have evaluate `1e5` as `100000`. A possible fix for this problem would be: 1. In `readRational__` (in compiler/utils/Util.hs), we only validate the format of literal numbers, don't evaluate it. 2. We evaluate the literal to numeric value during code generation, after typechecking. Then we can know the type of the literal number and once when we know the value is larger than the maximum bound of `Float/Double` type, we can safely feed a `Infinity` value into the cell, without evaluating the whole literal string and knowing the true `Rational` value of the literal. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by fangyizhou): I digged into this and I am suspecting there is an integer overflow at `fromRat''` in `GHC.Float`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by fangyizhou): {{{ main = do print 1e646457008 -- This is infinity print 1e646457009 -- This incorrectly printed 0.0 print 1e1555550000 -- This is still infinity print 1e1000000000 -- This incorrectly printed 0.0 }}} This is some wraparound behaviour, which is why I thought there is an integer overflow. I used `trace` to print the value of `(I# (ln# -# ld# +# 1# -# md#))` (https://github.com/ghc/ghc/blob/21f0f56164f50844c2150c62f950983b2376f8b6/lib...) 1e646457008 -> 2147483645 (infinity) 1e646457009 -> 2147483648 (0.0, overflow to negative) 1e1000000000 -> 3321928042 (infinity, overflow to positive) 1e1555550000 -> 5167425196 (0.0, overflow to negative) Any suggestions on how to fix? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by osa1): * cc: osa1 (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by fangyizhou): I found the issue. In `rtsPrimFloat.c`, a `StgInt` is passed as an argument to `ldexp`, which expects an `int` for the argument. On platforms where `StgInt` is 64-bit and `int` is 32-bit wraparound behaviour will be observed. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | PhabLink:D5271 -------------------------------------+------------------------------------- Changes (by fangyizhou): * owner: (none) => fangyizhou * differential: => PhabLink:D5271 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: patch Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Changes (by osa1): * status: new => patch * differential: PhabLink:D5271 => Phab:D5271 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: patch Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Comment (by sighingnow): @fangyizhou, have you tested Phab:D5271 with the last case in the description ? Even on Windows 64, `1e1000000000 :: Double` consumes GBs of memory. Maybe the problem still exists with this patch. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: patch Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Comment (by fangyizhou): Replying to [comment:10 sighingnow]:
@fangyizhou, have you tested Phab:D5271 with the last case in the description ? Even on Windows 64, `1e1000000000 :: Double` consumes GBs of memory. Maybe the problem still exists with this patch.
What do you mean? I didn't fix the memory issue because line 1 of this bug report says this matters correctness instead of performace -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: patch Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Comment (by sighingnow): Replying to [comment:11 fangyizhou]:
What do you mean? I didn't fix the memory issue because line 1 of this bug report says this matters correctness instead of performace
Well, thanks for the clarification :) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity
-------------------------------------+-------------------------------------
Reporter: claude | Owner: fangyizhou
Type: bug | Status: patch
Priority: normal | Milestone: 8.8.1
Component: Compiler | Version: 8.4.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Incorrect result | Unknown/Multiple
at runtime | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D5271
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: closed Priority: normal | Milestone: 8.6.2 Component: Compiler | Version: 8.4.3 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => closed * resolution: => fixed * milestone: 8.8.1 => 8.6.2 Comment: Merged to `ghc-8.6` with 37d14601af6ff5c2c590d30fccbb6eb56b88780e. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: merge Priority: normal | Milestone: 8.4.5 Component: Compiler | Version: 8.4.3 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: closed => merge * milestone: 8.6.2 => 8.4.5 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:15 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: merge Priority: normal | Milestone: 8.6.3 Component: Compiler | Version: 8.4.3 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Changes (by osa1): * milestone: 8.4.5 => 8.6.3 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15271: 1e1000000000 :: Double yields 0.0 instead of Infinity -------------------------------------+------------------------------------- Reporter: claude | Owner: fangyizhou Type: bug | Status: closed Priority: normal | Milestone: 8.6.3 Component: Compiler | Version: 8.4.3 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5271 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: merge => closed -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15271#comment:17 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC