GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2020-07-14T09:04:24Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/18407Type-Level floats2020-07-14T09:04:24ZLeanderKType-Level floats## Motivation
https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3583 motivates me to actually write a feature request. Currently, there are type-level *Nats*, but I would like to have actual type-level floats. I am currently writing a linear-algebra library where I want to track certain things like the basis on the type-level and I would need to cross the type/term or term/type boundary (and the term-representation is via floats).
## Proposal
Some relevant discussion can be found on https://gitlab.haskell.org/ghc/ghc/-/issues/8697, where the focus is on rationals and not on floats, but I think both can go hand in hand. I think to implement such a feature one would need to figure out the parsing and adding floats to type-lits, but i am not a ghc-developer so I am not sure.
Ideally, I would imagine something like:
```
data Blah (num:: Float) = Blah
f :: forall num. KnownFloat num => Blah num -> Float
f = ...
g = f @1.3
```## Motivation
https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3583 motivates me to actually write a feature request. Currently, there are type-level *Nats*, but I would like to have actual type-level floats. I am currently writing a linear-algebra library where I want to track certain things like the basis on the type-level and I would need to cross the type/term or term/type boundary (and the term-representation is via floats).
## Proposal
Some relevant discussion can be found on https://gitlab.haskell.org/ghc/ghc/-/issues/8697, where the focus is on rationals and not on floats, but I think both can go hand in hand. I think to implement such a feature one would need to figure out the parsing and adding floats to type-lits, but i am not a ghc-developer so I am not sure.
Ideally, I would imagine something like:
```
data Blah (num:: Float) = Blah
f :: forall num. KnownFloat num => Blah num -> Float
f = ...
g = f @1.3
```https://gitlab.haskell.org/ghc/ghc/-/issues/17782`word2Double#` does not match `doubleFromInteger` for large values2020-02-20T18:07:43ZAlexey Kuleshevich`word2Double#` does not match `doubleFromInteger` for large values## Summary
Implementation of `word2Double#` doesn't match the one from gmp-integer: `doubleFromInteger` for many values larger than 2^63
## Steps to reproduce
Start up ghci:
```haskell
>>> import GHC.Float
>>> word2Double maxBound
1.8446744073709552e19
>>> fromIntegral (maxBound :: Word) :: Double
1.844674407370955e19
>>> import GHC.Integer
>>> :set -XMagicHash
>>> word2Double maxBound == D# (doubleFromInteger (toInteger (maxBound :: Word64)))
False
```
Here are also three quickcheck properties that depict the problem:
```haskell
it "word2Double == doubleFromInteger (2^63 <= x < 2^64)" $
property $
forAll (choose (2 ^ 63, maxBound)) $ \(w :: Word) ->
word2Double w === D# (doubleFromInteger (toInteger w))
it "word2Double == doubleFromInteger (2^54 <= x <= 2^63)" $
property $
forAll (choose (2 ^ 54, 2 ^ 63)) $ \(w :: Word) ->
word2Double w === D# (doubleFromInteger (toInteger w))
it "int2Double == doubleFromInteger (2^52 <= x < 2^63)" $
property $
forAll (choose (2 ^ 54, maxBound)) $ \(w :: Int) ->
int2Double w === D# (doubleFromInteger (toInteger w))
```
First one fails consistently, while the other two I have not seen to fail yet.
## Expected behavior
* Expect `word2Double a` to produce exactly the same result as `\(a :: Word64) -> D# (doubleFromInteger (toInteger a))` for all `a`
This bug has some funny consequences. For example compiling with or without optimizations this:
```haskell
round (fromIntegral (maxBound :: Word64) :: Double) :: Word64
```
will produce either `0` or `18446744073709549568` respectfully.
## Environment
* GHC version used: 8.8.2 (and I suspect current HEAD and all prior versions)
Optional:
* Operating System: Ubuntu LTS 18.04
* System Architecture: x86_64## Summary
Implementation of `word2Double#` doesn't match the one from gmp-integer: `doubleFromInteger` for many values larger than 2^63
## Steps to reproduce
Start up ghci:
```haskell
>>> import GHC.Float
>>> word2Double maxBound
1.8446744073709552e19
>>> fromIntegral (maxBound :: Word) :: Double
1.844674407370955e19
>>> import GHC.Integer
>>> :set -XMagicHash
>>> word2Double maxBound == D# (doubleFromInteger (toInteger (maxBound :: Word64)))
False
```
Here are also three quickcheck properties that depict the problem:
```haskell
it "word2Double == doubleFromInteger (2^63 <= x < 2^64)" $
property $
forAll (choose (2 ^ 63, maxBound)) $ \(w :: Word) ->
word2Double w === D# (doubleFromInteger (toInteger w))
it "word2Double == doubleFromInteger (2^54 <= x <= 2^63)" $
property $
forAll (choose (2 ^ 54, 2 ^ 63)) $ \(w :: Word) ->
word2Double w === D# (doubleFromInteger (toInteger w))
it "int2Double == doubleFromInteger (2^52 <= x < 2^63)" $
property $
forAll (choose (2 ^ 54, maxBound)) $ \(w :: Int) ->
int2Double w === D# (doubleFromInteger (toInteger w))
```
First one fails consistently, while the other two I have not seen to fail yet.
## Expected behavior
* Expect `word2Double a` to produce exactly the same result as `\(a :: Word64) -> D# (doubleFromInteger (toInteger a))` for all `a`
This bug has some funny consequences. For example compiling with or without optimizations this:
```haskell
round (fromIntegral (maxBound :: Word64) :: Double) :: Word64
```
will produce either `0` or `18446744073709549568` respectfully.
## Environment
* GHC version used: 8.8.2 (and I suspect current HEAD and all prior versions)
Optional:
* Operating System: Ubuntu LTS 18.04
* System Architecture: x86_649.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/16519realToFrac between Float and Double gives different results depending on comp...2020-05-18T22:18:53ZSDNWrealToFrac between Float and Double gives different results depending on compile flagsThe following simple program gives different results depending on optimization level with GHC 8.6.4
```hs
moe, larry, curly :: Double
moe = 0/0
larry = 1/0
curly = -1/0
dancingLady = [moe,larry,curly]
helloPop = map realToFrac dancingLady :: [Float]
planeNuts = map realToFrac helloPop :: [Double]
main = do
print dancingLady
print helloPop
print planeNuts
```
With `-O1` and `-O2` it prints the expected
```
[NaN,Infinity,-Infinity]
[NaN,Infinity,-Infinity]
[NaN,Infinity,-Infinity]
```
but with `-O0` or when interpreted via `ghci` it prints
```
[NaN,Infinity,-Infinity]
[-Infinity,Infinity,-Infinity]
[-3.402823669209385e38,3.402823669209385e38,-3.402823669209385e38]
```
:-(
I hope you agree this is a serious bug. At the very least I would expect the conversion to be consistent, i.e. not a function of the optimization level.The following simple program gives different results depending on optimization level with GHC 8.6.4
```hs
moe, larry, curly :: Double
moe = 0/0
larry = 1/0
curly = -1/0
dancingLady = [moe,larry,curly]
helloPop = map realToFrac dancingLady :: [Float]
planeNuts = map realToFrac helloPop :: [Double]
main = do
print dancingLady
print helloPop
print planeNuts
```
With `-O1` and `-O2` it prints the expected
```
[NaN,Infinity,-Infinity]
[NaN,Infinity,-Infinity]
[NaN,Infinity,-Infinity]
```
but with `-O0` or when interpreted via `ghci` it prints
```
[NaN,Infinity,-Infinity]
[-Infinity,Infinity,-Infinity]
[-3.402823669209385e38,3.402823669209385e38,-3.402823669209385e38]
```
:-(
I hope you agree this is a serious bug. At the very least I would expect the conversion to be consistent, i.e. not a function of the optimization level.Carter SchonwaldCarter Schonwaldhttps://gitlab.haskell.org/ghc/ghc/-/issues/16479floatRange gives unexpected results2020-08-21T10:42:15ZtoonnfloatRange gives unexpected resultsHere's the signature for `floatRange` in `base/GHC/Float.hs`:
```
-- | a constant function, returning the lowest and highest values
-- the exponent may assume
floatRange :: a -> (Int,Int)
```
And here are the results for `Float` and `Double`:
```
>>> floatRange (undefined :: Float)
(-125,128)
>>> floatRange (undefined :: Double)
(-1021, 1024)
```
This is quite surprising to me given the documentation for the function. Single-precision floating-point numbers have a maximum exponent of `127` and a minimum exponent of `-126` (`-149` for subnormalized floats). Double-precision floating-point numbers have a maximum exponent of `1023` and a minimum exponent of `-1022` (`-1074` for subnormalized doubles). This means either the documentation is faulty or the implementation is.
Tracking this down the issue seems to be the definition of the constants in `base/includes/ieee-flpt.h`:
```
/* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */
#if !defined(FLT_MIN_EXP)
# define FLT_MIN_EXP (-125)
#endif
```
And similar for the other constants, truncated:
```
# define FLT_MAX_EXP 128
# define DBL_MIN_EXP (-1021)
# define DBL_MAX_EXP 1024
```
As the comment for `FLT_MIN_EXP` states, these numbers are all shifted by 1 in the direction of positive infinity. I have no idea why this is.
The definitions for `floatRange` for `Float`, respectively `Double` are as follows:
```
floatRange _ = (FLT_MIN_EXP, FLT_MAX_EXP) -- ditto [ditto refers to "from float.h", which doesn't exist and should probably be "ieee-flpt.h"]
floatRange _ = (DBL_MIN_EXP, DBL_MAX_EXP) -- ditto
```
So if `floatRange` is supposed to do what I think it should and what its documentation says it does either these constants or the implementations of `floatRange` for `Float` and `Double` need to change.Here's the signature for `floatRange` in `base/GHC/Float.hs`:
```
-- | a constant function, returning the lowest and highest values
-- the exponent may assume
floatRange :: a -> (Int,Int)
```
And here are the results for `Float` and `Double`:
```
>>> floatRange (undefined :: Float)
(-125,128)
>>> floatRange (undefined :: Double)
(-1021, 1024)
```
This is quite surprising to me given the documentation for the function. Single-precision floating-point numbers have a maximum exponent of `127` and a minimum exponent of `-126` (`-149` for subnormalized floats). Double-precision floating-point numbers have a maximum exponent of `1023` and a minimum exponent of `-1022` (`-1074` for subnormalized doubles). This means either the documentation is faulty or the implementation is.
Tracking this down the issue seems to be the definition of the constants in `base/includes/ieee-flpt.h`:
```
/* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */
#if !defined(FLT_MIN_EXP)
# define FLT_MIN_EXP (-125)
#endif
```
And similar for the other constants, truncated:
```
# define FLT_MAX_EXP 128
# define DBL_MIN_EXP (-1021)
# define DBL_MAX_EXP 1024
```
As the comment for `FLT_MIN_EXP` states, these numbers are all shifted by 1 in the direction of positive infinity. I have no idea why this is.
The definitions for `floatRange` for `Float`, respectively `Double` are as follows:
```
floatRange _ = (FLT_MIN_EXP, FLT_MAX_EXP) -- ditto [ditto refers to "from float.h", which doesn't exist and should probably be "ieee-flpt.h"]
floatRange _ = (DBL_MIN_EXP, DBL_MAX_EXP) -- ditto
```
So if `floatRange` is supposed to do what I think it should and what its documentation says it does either these constants or the implementations of `floatRange` for `Float` and `Double` need to change.https://gitlab.haskell.org/ghc/ghc/-/issues/9534IEEE Standard 754 for Binary Floating-Point Arithmetic by Prof. W. Kahan, UCB2019-07-07T18:40:07Zjrp2014IEEE Standard 754 for Binary Floating-Point Arithmetic by Prof. W. Kahan, UCBThe attached is an implementation of the floating point accuracy test described in *The Baleful Influence of Benchmarks* section of http://www.eecs.berkeley.edu/\~wkahan/ieee754status/IEEE754.PDF
```
Results for Float:
r = 4098.0 produces 12.0 and 12.0 sig. bits
r = 4098.25 fails: root 0.99989897 isn't at least 1 <<<<
r = 4097.004 produces 12.0 and 11.999298 sig. bits
:
Worst accuracy is 11.999298 sig. bits
:
Results for Double:
r = 4098.0 produces Infinity and Infinity sig. bits
r = 4098.25 produces Infinity and 53.0 sig. bits
r = 4097.00390625 produces Infinity and 53.451178091541244 sig. bits
r = 1.6777218e7 produces Infinity and Infinity sig. bits
r = 1.677721825e7 produces Infinity and 75.0 sig. bits
r = 1.6777219e7 produces Infinity and 71.0 sig. bits
r = 9.4906267e7 produces 26.499999994288153 and 26.499999986733027 sig. bits
r = 9.490626725e7 fails: root 0.999999995635551 isn't at least 1 <<<
r = 2.684354505e8 produces 28.0 and 27.999999919383132 sig. bits
r = 2.684354515e8 produces 28.0 and 27.99999993013205 sig. bits
r = 2.68435458e8 produces 28.0 and 28.0 sig. bits
r = 2.6843545825e8 produces 28.0 and 28.00000000268723 sig. bits
r = 2.6843545700000006e8 produces 28.0 and 27.999999989251084 sig. bits
r = 4.294967298e9 produces 32.0 and 32.0 sig. bits
r = 4.29496729825e9 produces 32.0 and 32.00000000016795 sig. bits
Worst accuracy is 26.499999986733027 sig. bits
```
This seems to be comparable to a clang version, but seems to be fairly poor in comparison to some other machines, back in the day (1997).
**The attached could, possibly be turned into a testsuite test, by removing the QuickCheck tests that are included.**
Observations:
- There are a couple of failures (could be the implementation of sqrt or log).
- signum seems incorrect (signum Nan = -1.0)
- The prelude should have a copysign function
- min fails to produce the other argument if one argument is NaN
- The CFloat and CDouble variants seem to produce the same result as the native Float and Double versions
- The Haskell coding style could be improved to remove some boilerplate, make the code more idiomatic
- There may be a better way of entering the test values of r to ensure that they are accurate
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.8.3 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Test Suite |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"IEEE Standard 754 for Binary Floating-Point Arithmetic by Prof. W. Kahan, UCB","status":"New","operating_system":"","component":"Test Suite","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.8.3","keywords":["IEEE754"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"The attached is an implementation of the floating point accuracy test described in ''The Baleful Influence of Benchmarks'' section of http://www.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF\r\n\r\n\r\n{{{\r\nResults for Float:\r\nr = 4098.0 produces 12.0 and 12.0 sig. bits\r\nr = 4098.25 fails: root 0.99989897 isn't at least 1 <<<<\r\nr = 4097.004 produces 12.0 and 11.999298 sig. bits\r\n:\r\nWorst accuracy is 11.999298 sig. bits\r\n\r\n:\r\n\r\nResults for Double:\r\nr = 4098.0 produces Infinity and Infinity sig. bits\r\nr = 4098.25 produces Infinity and 53.0 sig. bits\r\nr = 4097.00390625 produces Infinity and 53.451178091541244 sig. bits\r\nr = 1.6777218e7 produces Infinity and Infinity sig. bits\r\nr = 1.677721825e7 produces Infinity and 75.0 sig. bits\r\nr = 1.6777219e7 produces Infinity and 71.0 sig. bits\r\nr = 9.4906267e7 produces 26.499999994288153 and 26.499999986733027 sig. bits\r\nr = 9.490626725e7 fails: root 0.999999995635551 isn't at least 1 <<<\r\nr = 2.684354505e8 produces 28.0 and 27.999999919383132 sig. bits\r\nr = 2.684354515e8 produces 28.0 and 27.99999993013205 sig. bits\r\nr = 2.68435458e8 produces 28.0 and 28.0 sig. bits\r\nr = 2.6843545825e8 produces 28.0 and 28.00000000268723 sig. bits\r\nr = 2.6843545700000006e8 produces 28.0 and 27.999999989251084 sig. bits\r\nr = 4.294967298e9 produces 32.0 and 32.0 sig. bits\r\nr = 4.29496729825e9 produces 32.0 and 32.00000000016795 sig. bits\r\nWorst accuracy is 26.499999986733027 sig. bits\r\n}}}\r\n\r\nThis seems to be comparable to a clang version, but seems to be fairly poor in comparison to some other machines, back in the day (1997).\r\n\r\n'''The attached could, possibly be turned into a testsuite test, by removing the QuickCheck tests that are included.'''\r\n\r\nObservations:\r\n\r\n* There are a couple of failures (could be the implementation of sqrt or log). \r\n* signum seems incorrect (signum Nan = -1.0)\r\n* The prelude should have a copysign function\r\n* min fails to produce the other argument if one argument is NaN\r\n* The CFloat and CDouble variants seem to produce the same result as the native Float and Double versions\r\n* The Haskell coding style could be improved to remove some boilerplate, make the code more idiomatic\r\n* There may be a better way of entering the test values of r to ensure that they are accurate\r\n\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->The attached is an implementation of the floating point accuracy test described in *The Baleful Influence of Benchmarks* section of http://www.eecs.berkeley.edu/\~wkahan/ieee754status/IEEE754.PDF
```
Results for Float:
r = 4098.0 produces 12.0 and 12.0 sig. bits
r = 4098.25 fails: root 0.99989897 isn't at least 1 <<<<
r = 4097.004 produces 12.0 and 11.999298 sig. bits
:
Worst accuracy is 11.999298 sig. bits
:
Results for Double:
r = 4098.0 produces Infinity and Infinity sig. bits
r = 4098.25 produces Infinity and 53.0 sig. bits
r = 4097.00390625 produces Infinity and 53.451178091541244 sig. bits
r = 1.6777218e7 produces Infinity and Infinity sig. bits
r = 1.677721825e7 produces Infinity and 75.0 sig. bits
r = 1.6777219e7 produces Infinity and 71.0 sig. bits
r = 9.4906267e7 produces 26.499999994288153 and 26.499999986733027 sig. bits
r = 9.490626725e7 fails: root 0.999999995635551 isn't at least 1 <<<
r = 2.684354505e8 produces 28.0 and 27.999999919383132 sig. bits
r = 2.684354515e8 produces 28.0 and 27.99999993013205 sig. bits
r = 2.68435458e8 produces 28.0 and 28.0 sig. bits
r = 2.6843545825e8 produces 28.0 and 28.00000000268723 sig. bits
r = 2.6843545700000006e8 produces 28.0 and 27.999999989251084 sig. bits
r = 4.294967298e9 produces 32.0 and 32.0 sig. bits
r = 4.29496729825e9 produces 32.0 and 32.00000000016795 sig. bits
Worst accuracy is 26.499999986733027 sig. bits
```
This seems to be comparable to a clang version, but seems to be fairly poor in comparison to some other machines, back in the day (1997).
**The attached could, possibly be turned into a testsuite test, by removing the QuickCheck tests that are included.**
Observations:
- There are a couple of failures (could be the implementation of sqrt or log).
- signum seems incorrect (signum Nan = -1.0)
- The prelude should have a copysign function
- min fails to produce the other argument if one argument is NaN
- The CFloat and CDouble variants seem to produce the same result as the native Float and Double versions
- The Haskell coding style could be improved to remove some boilerplate, make the code more idiomatic
- There may be a better way of entering the test values of r to ensure that they are accurate
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.8.3 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Test Suite |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"IEEE Standard 754 for Binary Floating-Point Arithmetic by Prof. W. Kahan, UCB","status":"New","operating_system":"","component":"Test Suite","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.8.3","keywords":["IEEE754"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"The attached is an implementation of the floating point accuracy test described in ''The Baleful Influence of Benchmarks'' section of http://www.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF\r\n\r\n\r\n{{{\r\nResults for Float:\r\nr = 4098.0 produces 12.0 and 12.0 sig. bits\r\nr = 4098.25 fails: root 0.99989897 isn't at least 1 <<<<\r\nr = 4097.004 produces 12.0 and 11.999298 sig. bits\r\n:\r\nWorst accuracy is 11.999298 sig. bits\r\n\r\n:\r\n\r\nResults for Double:\r\nr = 4098.0 produces Infinity and Infinity sig. bits\r\nr = 4098.25 produces Infinity and 53.0 sig. bits\r\nr = 4097.00390625 produces Infinity and 53.451178091541244 sig. bits\r\nr = 1.6777218e7 produces Infinity and Infinity sig. bits\r\nr = 1.677721825e7 produces Infinity and 75.0 sig. bits\r\nr = 1.6777219e7 produces Infinity and 71.0 sig. bits\r\nr = 9.4906267e7 produces 26.499999994288153 and 26.499999986733027 sig. bits\r\nr = 9.490626725e7 fails: root 0.999999995635551 isn't at least 1 <<<\r\nr = 2.684354505e8 produces 28.0 and 27.999999919383132 sig. bits\r\nr = 2.684354515e8 produces 28.0 and 27.99999993013205 sig. bits\r\nr = 2.68435458e8 produces 28.0 and 28.0 sig. bits\r\nr = 2.6843545825e8 produces 28.0 and 28.00000000268723 sig. bits\r\nr = 2.6843545700000006e8 produces 28.0 and 27.999999989251084 sig. bits\r\nr = 4.294967298e9 produces 32.0 and 32.0 sig. bits\r\nr = 4.29496729825e9 produces 32.0 and 32.00000000016795 sig. bits\r\nWorst accuracy is 26.499999986733027 sig. bits\r\n}}}\r\n\r\nThis seems to be comparable to a clang version, but seems to be fairly poor in comparison to some other machines, back in the day (1997).\r\n\r\n'''The attached could, possibly be turned into a testsuite test, by removing the QuickCheck tests that are included.'''\r\n\r\nObservations:\r\n\r\n* There are a couple of failures (could be the implementation of sqrt or log). \r\n* signum seems incorrect (signum Nan = -1.0)\r\n* The prelude should have a copysign function\r\n* min fails to produce the other argument if one argument is NaN\r\n* The CFloat and CDouble variants seem to produce the same result as the native Float and Double versions\r\n* The Haskell coding style could be improved to remove some boilerplate, make the code more idiomatic\r\n* There may be a better way of entering the test values of r to ensure that they are accurate\r\n\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->