
#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