[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