[GHC] #8539: Data.Complex shouldn't use default implementation of (**)
GHC
ghc-devs at haskell.org
Sat Aug 23 11:52:11 UTC 2014
#8539: Data.Complex shouldn't use default implementation of (**)
-------------------------------------+-------------------------------------
Reporter: | Owner:
jjaredsimpson | Status: infoneeded
Type: bug | Milestone:
Priority: low | Version: 7.6.3
Component: Prelude | Keywords:
Resolution: | Architecture: Unknown/Multiple
Operating System: | Difficulty: Easy (less than 1
Unknown/Multiple | hour)
Type of failure: Incorrect | Blocked By:
result at runtime | Related Tickets:
Test Case: |
Blocking: |
Differential Revisions: |
-------------------------------------+-------------------------------------
Comment (by Scott Turner):
The early answer,
If the real part of y is positive, then the result should be 0. If the
real part is negative, then
the result should be Infinity. If y is imaginary, the result should be
NaN.
{{{
Infinity ** y = 0 ** (negate y)
}}}
provides the basis for a satisfactory solution. One improvement is to
take Yalas's
recommendation regarding NaN!**0. In code, the implementation is
{{{
x ** y = case (x,y) of
(_ , (0:+0)) -> 1 :+ 0
((0:+0), (re:+_))
| re > 0 -> 0 :+ 0
| re < 0 -> inf :+ 0
| otherwise -> nan :+ nan
((re:+im), y)
| (isInfinite re || isInfinite im) -> case y of
(exp_re:+_) | exp_re > 0 -> inf :+ 0
| exp_re < 0 -> 0 :+ 0
| otherwise -> nan :+ nan
(x, y) -> exp (log x * y)
where inf = 1/0
nan = 0/0
}}}
Regarding the questions raised in the earlier discussion:
Q: What to do about the other operations than !**?
A: That should be a separate bug report.
Q: special case for raising to 1 to increase accuracy
A: Addressed in the earlier discussion.
Q: Do we need some tests?
A: See examples below.
Q: why we want to handle infinity!**0 and don't want to handle
infinity!**y or x!**infinity?
A: We do handle infinity!**y.
For x!**infinity, the returned value is NaN:+NaN.
The above patch could be refined using a directional interpretation of
complex infinities,
i.e. Infinity:+0, Infinity:+Infinity, 0:+Infinity, -Infinity:+0, etc.
would each yield different results, and the result would also depend on
log x. To some extent that might be managed by revising the exp function.
It gets fiddly so I recommend making the above improvement, and leaving
x!**infinity for another day.
'''Examples'''
|| ||=existing =||=patched
=||=Wolfram Alpha =||
||0 !** 2 ||NaN :+ NaN ||0.0 :+ 0.0
||0 ||
||0 !** 0 ||NaN :+ NaN ||1.0 :+ 0.0
||indeterminate ||
||0 !** -2 ||NaN :+ NaN ||Infinity :+ 0.0
||complex infinity ||
||inf:+0 !** 2 ||NaN :+ NaN ||Infinity :+ 0.0
||infinity ||
||inf:+0 !** 0 ||NaN :+ NaN ||1.0 :+ 0.0
||indeterminate ||
||inf:+0 !** -2 ||NaN :+ NaN ||0.0 :+ 0.0
||0 ||
||-1 !** 0.5 ||6.12e-17 :+ (-1.0) ||6.12e-17 :+ (-1.0)
||0:+1 ||Note 2||
||0 !** (1:+1) ||NaN :+ NaN ||0.0 :+ 0.0
||0 ||
||0 !** (0:+1) ||NaN :+ NaN ||NaN :+ NaN
||indeterminate ||
||nan:+0 !** 0 ||NaN :+ NaN ||1.0 :+ 0.0
||indeterminate ||
||1 !** inf:+0 ||NaN :+ NaN ||NaN :+ NaN
||indeterminate ||
||1 !** nan:+0 ||NaN :+ NaN ||NaN :+ NaN
||indeterminate ||
||2 !** (inf:+1) ||NaN :+ NaN ||NaN :+ NaN
||Note 1 ||
||2 !** (inf:+0) ||NaN :+ NaN ||NaN :+ NaN
||infinity ||
||2 !** ((-inf):+0) ||NaN :+ NaN ||NaN :+ NaN
||0 ||
||2 !** ((-1000000000):+1) ||0.0 :+ 0.0 ||0.0 :+ 0.0
||..... ||
||(0.8:+0.8) !** inf:+0 ||NaN :+ NaN ||NaN :+ NaN
||complex infinity ||
||(0.8:+0.6) !** inf:+0 ||NaN :+ NaN ||NaN :+ NaN
||indeterminate ||
||(0.8:+0.4) !** inf:+0 ||NaN :+ NaN ||NaN :+ NaN
||0 ||
||(0.8:+0.8) !** (-inf):+0 ||NaN :+ NaN ||NaN :+ NaN
||0 ||
||(0.8:+0.6) !** (-inf):+0 ||NaN :+ NaN ||NaN :+ NaN
||indeterminate ||
||(0.8:+0.4) !** (-inf):+0 ||NaN :+ NaN ||NaN :+ NaN
||complex infinity ||
||(0.8:+0.8) !** (inf:+1) ||NaN :+ NaN ||NaN :+ NaN
||Note 1 ||
||(0.8:+0.6) !** (inf:+1) ||NaN :+ NaN ||NaN :+ NaN
||Note 1 ||
||(0.8:+0.4) !** (inf:+1) ||NaN :+ NaN ||NaN :+ NaN
||Note 1 ||
||(0.8:+0.8) !** ((-inf):+1) ||NaN :+ NaN ||NaN :+ NaN
||Note 1 ||
||(0.8:+0.6) !** ((-inf):+1) ||NaN :+ NaN ||NaN :+ NaN
||Note 1 ||
||(0.8:+0.4) !** ((-inf):+1) ||NaN :+ NaN ||NaN :+ NaN
||Note 1 ||
Note 1:
Wolfram Alpha simplifies (infinity+i) to infinity, and as a result it
misses the point of the indicated examples.
Note 2:
The ghc result for -1!**1/2 is somewhat unexpected due to the
implementation involving complex log and an intermediate value of pi*i
which of course is not represented with perfect accuracy. If this is a
problem, it is not the one we are addressing here.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8539#comment:25>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list