------------------------------------------------------------------------
-- |
-- Module           : What4.Utils.Complex
-- Description      : Provides a complex representation that is more generic
--                    than Data.Complex.
-- Copyright        : (c) Galois, Inc 2014-2020
-- License          : BSD3
-- Maintainer       : Joe Hendrix <jhendrix@galois.com>
-- Stability        : provisional
--
-- This module provides complex numbers without the RealFloat constraints
-- that Data.Complex has.  This is useful for representing various
-- intermediate symbolic representations of complex numbers that are not
-- literally number representations.
------------------------------------------------------------------------
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module What4.Utils.Complex
  ( Complex((:+))
  , realPart
  , imagPart
  , magnitude
  , magnitudeSq
  , complexNegate
  , complexAdd
  , complexSub
  , complexMul
  , complexDiv
  , complexRecip
  , tryComplexSqrt
  , tryMagnitude
  , complexAsRational
  ) where

import Data.Hashable
import GHC.Generics (Generic)

import Data.Parameterized.Classes

-- | A complex pair over an arbitrary type.
data Complex a = !a :+ !a
  deriving (Complex a -> Complex a -> Bool
forall a. Eq a => Complex a -> Complex a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Complex a -> Complex a -> Bool
$c/= :: forall a. Eq a => Complex a -> Complex a -> Bool
== :: Complex a -> Complex a -> Bool
$c== :: forall a. Eq a => Complex a -> Complex a -> Bool
Eq, Complex a -> Complex a -> Bool
Complex a -> Complex a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Complex a)
forall a. Ord a => Complex a -> Complex a -> Bool
forall a. Ord a => Complex a -> Complex a -> Ordering
forall a. Ord a => Complex a -> Complex a -> Complex a
min :: Complex a -> Complex a -> Complex a
$cmin :: forall a. Ord a => Complex a -> Complex a -> Complex a
max :: Complex a -> Complex a -> Complex a
$cmax :: forall a. Ord a => Complex a -> Complex a -> Complex a
>= :: Complex a -> Complex a -> Bool
$c>= :: forall a. Ord a => Complex a -> Complex a -> Bool
> :: Complex a -> Complex a -> Bool
$c> :: forall a. Ord a => Complex a -> Complex a -> Bool
<= :: Complex a -> Complex a -> Bool
$c<= :: forall a. Ord a => Complex a -> Complex a -> Bool
< :: Complex a -> Complex a -> Bool
$c< :: forall a. Ord a => Complex a -> Complex a -> Bool
compare :: Complex a -> Complex a -> Ordering
$ccompare :: forall a. Ord a => Complex a -> Complex a -> Ordering
Ord, forall a. Eq a => a -> Complex a -> Bool
forall a. Num a => Complex a -> a
forall a. Ord a => Complex a -> a
forall m. Monoid m => Complex m -> m
forall a. Complex a -> Bool
forall a. Complex a -> Int
forall a. Complex a -> [a]
forall a. (a -> a -> a) -> Complex a -> a
forall m a. Monoid m => (a -> m) -> Complex a -> m
forall b a. (b -> a -> b) -> b -> Complex a -> b
forall a b. (a -> b -> b) -> b -> Complex a -> b
forall (t :: Type -> Type).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: forall a. Num a => Complex a -> a
$cproduct :: forall a. Num a => Complex a -> a
sum :: forall a. Num a => Complex a -> a
$csum :: forall a. Num a => Complex a -> a
minimum :: forall a. Ord a => Complex a -> a
$cminimum :: forall a. Ord a => Complex a -> a
maximum :: forall a. Ord a => Complex a -> a
$cmaximum :: forall a. Ord a => Complex a -> a
elem :: forall a. Eq a => a -> Complex a -> Bool
$celem :: forall a. Eq a => a -> Complex a -> Bool
length :: forall a. Complex a -> Int
$clength :: forall a. Complex a -> Int
null :: forall a. Complex a -> Bool
$cnull :: forall a. Complex a -> Bool
toList :: forall a. Complex a -> [a]
$ctoList :: forall a. Complex a -> [a]
foldl1 :: forall a. (a -> a -> a) -> Complex a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> Complex a -> a
foldr1 :: forall a. (a -> a -> a) -> Complex a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> Complex a -> a
foldl' :: forall b a. (b -> a -> b) -> b -> Complex a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> Complex a -> b
foldl :: forall b a. (b -> a -> b) -> b -> Complex a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> Complex a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> Complex a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> Complex a -> b
foldr :: forall a b. (a -> b -> b) -> b -> Complex a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> Complex a -> b
foldMap' :: forall m a. Monoid m => (a -> m) -> Complex a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> Complex a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> Complex a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> Complex a -> m
fold :: forall m. Monoid m => Complex m -> m
$cfold :: forall m. Monoid m => Complex m -> m
Foldable, forall a b. a -> Complex b -> Complex a
forall a b. (a -> b) -> Complex a -> Complex b
forall (f :: Type -> Type).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Complex b -> Complex a
$c<$ :: forall a b. a -> Complex b -> Complex a
fmap :: forall a b. (a -> b) -> Complex a -> Complex b
$cfmap :: forall a b. (a -> b) -> Complex a -> Complex b
Functor, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Complex a) x -> Complex a
forall a x. Complex a -> Rep (Complex a) x
$cto :: forall a x. Rep (Complex a) x -> Complex a
$cfrom :: forall a x. Complex a -> Rep (Complex a) x
Generic)

infix 6 :+

traverseComplex :: Applicative f => (a -> f b) -> Complex a -> f (Complex b)
traverseComplex :: forall (f :: Type -> Type) a b.
Applicative f =>
(a -> f b) -> Complex a -> f (Complex b)
traverseComplex = \a -> f b
f (a
x :+ a
y) -> forall a. a -> a -> Complex a
(:+) forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
x forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> a -> f b
f a
y
{-# INLINE traverseComplex #-}

instance Traversable Complex where
  traverse :: forall (f :: Type -> Type) a b.
Applicative f =>
(a -> f b) -> Complex a -> f (Complex b)
traverse = forall (f :: Type -> Type) a b.
Applicative f =>
(a -> f b) -> Complex a -> f (Complex b)
traverseComplex

instance Hashable a => Hashable (Complex a) where

instance PolyEq x y => PolyEq (Complex x) (Complex y) where
  polyEqF :: Complex x -> Complex y -> Maybe (Complex x :~: Complex y)
polyEqF (x
rx :+ x
ix) (y
ry :+ y
iy) = do
    x :~: y
Refl <- forall u v. PolyEq u v => u -> v -> Maybe (u :~: v)
polyEqF x
rx y
ry
    x :~: y
Refl <- forall u v. PolyEq u v => u -> v -> Maybe (u :~: v)
polyEqF x
ix y
iy
    forall (m :: Type -> Type) a. Monad m => a -> m a
return forall {k} (a :: k). a :~: a
Refl

realPart :: Complex a -> a
realPart :: forall a. Complex a -> a
realPart (a
a :+ a
_) = a
a

imagPart :: Complex a -> a
imagPart :: forall a. Complex a -> a
imagPart (a
_ :+ a
b) = a
b

instance (Eq a, Num a, Show a) => Show (Complex a) where
  show :: Complex a -> String
show (a
r :+ a
0) = forall a. Show a => a -> String
show a
r
  show (a
0 :+ a
i) = forall a. Show a => a -> String
show a
i forall a. [a] -> [a] -> [a]
++ String
"i"
  show (a
r :+ a
i) = forall a. Show a => a -> String
show a
r forall a. [a] -> [a] -> [a]
++ String
" + " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
i forall a. [a] -> [a] -> [a]
++ String
"i"

complexNegate :: Num a => Complex a -> Complex a
complexNegate :: forall a. Num a => Complex a -> Complex a
complexNegate (a
r :+ a
i) = forall a. Num a => a -> a
negate a
r forall a. a -> a -> Complex a
:+ forall a. Num a => a -> a
negate a
i

complexAdd :: Num a => Complex a -> Complex a -> Complex a
complexAdd :: forall a. Num a => Complex a -> Complex a -> Complex a
complexAdd (a
rx :+ a
ix) (a
ry :+ a
iy) = (a
rx forall a. Num a => a -> a -> a
+ a
ry) forall a. a -> a -> Complex a
:+ (a
ix forall a. Num a => a -> a -> a
+ a
iy)

complexSub :: Num a => Complex a -> Complex a -> Complex a
complexSub :: forall a. Num a => Complex a -> Complex a -> Complex a
complexSub (a
rx :+ a
ix) (a
ry :+ a
iy) = (a
rx forall a. Num a => a -> a -> a
- a
ry) forall a. a -> a -> Complex a
:+ (a
ix forall a. Num a => a -> a -> a
- a
iy)

{-# SPECIALIZE complexMul :: Complex Rational -> Complex Rational -> Complex Rational #-}
complexMul :: Num a => Complex a -> Complex a -> Complex a
complexMul :: forall a. Num a => Complex a -> Complex a -> Complex a
complexMul (a
rx :+ a
ix) (a
ry :+ a
iy) = (a
rx forall a. Num a => a -> a -> a
* a
ry forall a. Num a => a -> a -> a
- a
ix forall a. Num a => a -> a -> a
* a
iy) forall a. a -> a -> Complex a
:+ (a
ix forall a. Num a => a -> a -> a
* a
ry forall a. Num a => a -> a -> a
+ a
rx forall a. Num a => a -> a -> a
* a
iy)

instance Floating a => Num (Complex a) where
  + :: Complex a -> Complex a -> Complex a
(+) = forall a. Num a => Complex a -> Complex a -> Complex a
complexAdd
  (-) = forall a. Num a => Complex a -> Complex a -> Complex a
complexSub
  negate :: Complex a -> Complex a
negate = forall a. Num a => Complex a -> Complex a
complexNegate
  * :: Complex a -> Complex a -> Complex a
(*) = forall a. Num a => Complex a -> Complex a -> Complex a
complexMul
  abs :: Complex a -> Complex a
abs Complex a
c = forall a. Floating a => Complex a -> a
magnitude Complex a
c forall a. a -> a -> Complex a
:+ a
0
  signum :: Complex a -> Complex a
signum c :: Complex a
c@(a
r :+ a
i) = a
rforall a. Fractional a => a -> a -> a
/a
m forall a. a -> a -> Complex a
:+ a
iforall a. Fractional a => a -> a -> a
/a
m
    where m :: a
m = forall a. Floating a => Complex a -> a
magnitude Complex a
c
  fromInteger :: Integer -> Complex a
fromInteger Integer
x = forall a. Num a => Integer -> a
fromInteger Integer
x forall a. a -> a -> Complex a
:+ a
0

instance (Ord a, Floating a) => Real (Complex a) where
  toRational :: Complex a -> Rational
toRational = forall a. HasCallStack => String -> a
error String
"toRational undefined on complex numbers"

instance Floating a => Fractional (Complex a) where
  fromRational :: Rational -> Complex a
fromRational Rational
r = forall a. Fractional a => Rational -> a
fromRational Rational
r forall a. a -> a -> Complex a
:+ a
0
  recip :: Complex a -> Complex a
recip = forall a. Fractional a => Complex a -> Complex a
complexRecip
  / :: Complex a -> Complex a -> Complex a
(/) = forall a. Fractional a => Complex a -> Complex a -> Complex a
complexDiv


complexDiv :: Fractional a => Complex a -> Complex a -> Complex a
complexDiv :: forall a. Fractional a => Complex a -> Complex a -> Complex a
complexDiv Complex a
x Complex a
y = forall a. Num a => Complex a -> Complex a -> Complex a
complexMul Complex a
x (forall a. Fractional a => Complex a -> Complex a
complexRecip Complex a
y)

complexRecip :: Fractional a => Complex a -> Complex a
complexRecip :: forall a. Fractional a => Complex a -> Complex a
complexRecip (a
r :+ a
i) = (a
rforall a. Fractional a => a -> a -> a
/a
m) forall a. a -> a -> Complex a
:+ (forall a. Num a => a -> a
negate a
iforall a. Fractional a => a -> a -> a
/a
m)
  where m :: a
m = a
rforall a. Num a => a -> a -> a
*a
r forall a. Num a => a -> a -> a
+ a
iforall a. Num a => a -> a -> a
*a
i

-- | Returns the "complex argument" of the complex number.
phase :: RealFloat a => Complex a -> a
phase :: forall a. RealFloat a => Complex a -> a
phase (a
0 :+ a
0)   = a
0
phase (a
x:+a
y)     = forall a. RealFloat a => a -> a -> a
atan2 a
y a
x

instance (RealFloat a) => Floating (Complex a) where
  pi :: Complex a
pi             =  forall a. Floating a => a
pi forall a. a -> a -> Complex a
:+ a
0
  exp :: Complex a -> Complex a
exp (a
x:+a
y)     =  a
expx forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
cos a
y forall a. a -> a -> Complex a
:+ a
expx forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sin a
y
    where expx :: a
expx = forall a. Floating a => a -> a
exp a
x
  log :: Complex a -> Complex a
log Complex a
z          =  forall a. Floating a => a -> a
log (forall a. Floating a => Complex a -> a
magnitude Complex a
z) forall a. a -> a -> Complex a
:+ forall a. RealFloat a => Complex a -> a
phase Complex a
z

  sqrt :: Complex a -> Complex a
sqrt (a
0:+a
0)    =  Complex a
0
  sqrt (a
x:+a
0) | a
x forall a. Ord a => a -> a -> Bool
> a
0  = forall a. Floating a => a -> a
sqrt a
x forall a. a -> a -> Complex a
:+ a
0
              | a
x forall a. Eq a => a -> a -> Bool
== a
0 = a
0 forall a. a -> a -> Complex a
:+ a
0
              | a
x forall a. Ord a => a -> a -> Bool
< a
0  = a
0 forall a. a -> a -> Complex a
:+ forall a. Floating a => a -> a
sqrt (-a
x)
  sqrt (a
0:+a
y) | a
y forall a. Ord a => a -> a -> Bool
> a
0 = let u :: a
u = forall a. Floating a => a -> a
sqrt (a
yforall a. Fractional a => a -> a -> a
/a
2) in (a
u forall a. a -> a -> Complex a
:+ a
u)
              | a
y forall a. Ord a => a -> a -> Bool
< a
0 = let u :: a
u = forall a. Floating a => a -> a
sqrt (forall a. Num a => a -> a
negate a
yforall a. Fractional a => a -> a -> a
/a
2) in (a
u forall a. a -> a -> Complex a
:+ forall a. Num a => a -> a
negate a
u)
  sqrt z :: Complex a
z@(a
x:+a
y)  =  a
u forall a. a -> a -> Complex a
:+ (if a
y forall a. Ord a => a -> a -> Bool
< a
0 then -a
v else a
v)
                      where m :: a
m = forall a. Floating a => Complex a -> a
magnitude Complex a
z
                            u :: a
u    = forall a. Floating a => a -> a
sqrt ((a
m forall a. Num a => a -> a -> a
+ a
x) forall a. Fractional a => a -> a -> a
/ a
2)
                            v :: a
v    = forall a. Floating a => a -> a
sqrt ((a
m forall a. Num a => a -> a -> a
- a
x) forall a. Fractional a => a -> a -> a
/ a
2)

  sin :: Complex a -> Complex a
sin (a
x:+a
y) = (forall a. Floating a => a -> a
sin a
xforall a. Num a => a -> a -> a
*forall a. Floating a => a -> a
cosh a
y) forall a. a -> a -> Complex a
:+ (forall a. Floating a => a -> a
cos a
x forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sinh a
y)
  cos :: Complex a -> Complex a
cos (a
x:+a
y) = (forall a. Floating a => a -> a
cos a
xforall a. Num a => a -> a -> a
*forall a. Floating a => a -> a
cosh a
y) forall a. a -> a -> Complex a
:+ (- forall a. Floating a => a -> a
sin a
x forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sinh a
y)
  tan :: Complex a -> Complex a
tan (a
x:+a
y) = (a
sin_xforall a. Num a => a -> a -> a
*a
cos_xforall a. Fractional a => a -> a -> a
/a
m) forall a. a -> a -> Complex a
:+ (a
sinh_yforall a. Num a => a -> a -> a
*a
cosh_yforall a. Fractional a => a -> a -> a
/a
m)
    where sin_x :: a
sin_x  = forall a. Floating a => a -> a
sin a
x
          cos_x :: a
cos_x  = forall a. Floating a => a -> a
cos a
x
          sinh_y :: a
sinh_y = forall a. Floating a => a -> a
sinh a
y
          cosh_y :: a
cosh_y = forall a. Floating a => a -> a
cosh a
y
          u :: a
u = a
cos_x forall a. Num a => a -> a -> a
* a
cosh_y
          v :: a
v = a
sin_x forall a. Num a => a -> a -> a
* a
sinh_y
          m :: a
m = a
uforall a. Num a => a -> a -> a
*a
u forall a. Num a => a -> a -> a
+ a
vforall a. Num a => a -> a -> a
*a
v



  sinh :: Complex a -> Complex a
sinh (a
x:+a
y)    =  forall a. Floating a => a -> a
cos a
y forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sinh a
x forall a. a -> a -> Complex a
:+ forall a. Floating a => a -> a
sin a
y forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
cosh a
x
  cosh :: Complex a -> Complex a
cosh (a
x:+a
y)    =  forall a. Floating a => a -> a
cos a
y forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
cosh a
x forall a. a -> a -> Complex a
:+ forall a. Floating a => a -> a
sin a
y forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sinh a
x
  tanh :: Complex a -> Complex a
tanh (a
x:+a
y)    =  (a
cosyforall a. Num a => a -> a -> a
*a
sinhxforall a. a -> a -> Complex a
:+a
sinyforall a. Num a => a -> a -> a
*a
coshx)forall a. Fractional a => a -> a -> a
/(a
cosyforall a. Num a => a -> a -> a
*a
coshxforall a. a -> a -> Complex a
:+a
sinyforall a. Num a => a -> a -> a
*a
sinhx)
    where siny :: a
siny  = forall a. Floating a => a -> a
sin a
y
          cosy :: a
cosy  = forall a. Floating a => a -> a
cos a
y
          sinhx :: a
sinhx = forall a. Floating a => a -> a
sinh a
x
          coshx :: a
coshx = forall a. Floating a => a -> a
cosh a
x

  asin :: Complex a -> Complex a
asin z :: Complex a
z@(a
x:+a
y)  =  a
y'forall a. a -> a -> Complex a
:+(-a
x')
    where  (a
x':+a
y') = forall a. Floating a => a -> a
log (((-a
y)forall a. a -> a -> Complex a
:+a
x) forall a. Num a => a -> a -> a
+ forall a. Floating a => a -> a
sqrt (Complex a
1 forall a. Num a => a -> a -> a
- Complex a
zforall a. Num a => a -> a -> a
*Complex a
z))
  acos :: Complex a -> Complex a
acos Complex a
z         =  a
y''forall a. a -> a -> Complex a
:+(-a
x'')
    where (a
x'':+a
y'') = forall a. Floating a => a -> a
log (Complex a
z forall a. Num a => a -> a -> a
+ ((-a
y')forall a. a -> a -> Complex a
:+a
x'))
          (a
x':+a
y')   = forall a. Floating a => a -> a
sqrt (Complex a
1 forall a. Num a => a -> a -> a
- Complex a
zforall a. Num a => a -> a -> a
*Complex a
z)
  atan :: Complex a -> Complex a
atan z :: Complex a
z@(a
x:+a
y)  =  a
y'forall a. a -> a -> Complex a
:+(-a
x')
    where (a
x':+a
y') = forall a. Floating a => a -> a
log (((a
1forall a. Num a => a -> a -> a
-a
y)forall a. a -> a -> Complex a
:+a
x) forall a. Fractional a => a -> a -> a
/ forall a. Floating a => a -> a
sqrt (Complex a
1forall a. Num a => a -> a -> a
+Complex a
zforall a. Num a => a -> a -> a
*Complex a
z))

  asinh :: Complex a -> Complex a
asinh Complex a
z        =  forall a. Floating a => a -> a
log (Complex a
z forall a. Num a => a -> a -> a
+ forall a. Floating a => a -> a
sqrt (Complex a
1forall a. Num a => a -> a -> a
+Complex a
zforall a. Num a => a -> a -> a
*Complex a
z))
  acosh :: Complex a -> Complex a
acosh Complex a
z        =  forall a. Floating a => a -> a
log (Complex a
z forall a. Num a => a -> a -> a
+ (Complex a
zforall a. Num a => a -> a -> a
+Complex a
1) forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sqrt ((Complex a
zforall a. Num a => a -> a -> a
-Complex a
1)forall a. Fractional a => a -> a -> a
/(Complex a
zforall a. Num a => a -> a -> a
+Complex a
1)))
  atanh :: Complex a -> Complex a
atanh Complex a
z        =  Complex a
0.5 forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
log ((Complex a
1.0forall a. Num a => a -> a -> a
+Complex a
z) forall a. Fractional a => a -> a -> a
/ (Complex a
1.0forall a. Num a => a -> a -> a
-Complex a
z))

instance (Ord a, Floating a) => RealFrac (Complex a) where
  properFraction :: forall b. Integral b => Complex a -> (b, Complex a)
properFraction = forall a. HasCallStack => String -> a
error String
"properFraction undefined on complex numbers"

magnitude :: Floating a => Complex a -> a
magnitude :: forall a. Floating a => Complex a -> a
magnitude Complex a
c = forall a. Floating a => a -> a
sqrt (forall a. Num a => Complex a -> a
magnitudeSq Complex a
c)

-- | Returns square of magnitude.
magnitudeSq :: Num a => Complex a -> a
magnitudeSq :: forall a. Num a => Complex a -> a
magnitudeSq (a
r :+ a
i) = a
rforall a. Num a => a -> a -> a
*a
rforall a. Num a => a -> a -> a
+a
iforall a. Num a => a -> a -> a
*a
i

tryMagnitude :: Num a
             => (a -> b) -- ^ Sqrt function
             -> Complex a
             -> b
tryMagnitude :: forall a b. Num a => (a -> b) -> Complex a -> b
tryMagnitude a -> b
sqrtFn = a -> b
sqrtFn forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => Complex a -> a
magnitudeSq

tryComplexSqrt :: (Ord a, Fractional a, Monad m)
               => (a -> m a) -- ^ Square-root function defined for non-negative values a.
               -> Complex a
               -> m (Complex a)
tryComplexSqrt :: forall a (m :: Type -> Type).
(Ord a, Fractional a, Monad m) =>
(a -> m a) -> Complex a -> m (Complex a)
tryComplexSqrt a -> m a
sqrtFn Complex a
c = do
  a
m <- a -> m a
sqrtFn (forall a. Num a => Complex a -> a
magnitudeSq Complex a
c)
  let r :: a
r = forall a. Complex a -> a
realPart Complex a
c
      i :: a
i = forall a. Complex a -> a
imagPart Complex a
c
  a
r' <- a -> m a
sqrtFn forall a b. (a -> b) -> a -> b
$ (a
m forall a. Num a => a -> a -> a
+ a
r) forall a. Fractional a => a -> a -> a
/ a
2
  a
i' <- a -> m a
sqrtFn forall a b. (a -> b) -> a -> b
$ (a
m forall a. Num a => a -> a -> a
- a
r) forall a. Fractional a => a -> a -> a
/ a
2
  let i'' :: a
i'' = if (a
i forall a. Ord a => a -> a -> Bool
>= a
0) then a
i' else -a
i'
  forall (m :: Type -> Type) a. Monad m => a -> m a
return (a
r' forall a. a -> a -> Complex a
:+ a
i'')

complexAsRational :: Complex Rational -> Maybe Rational
complexAsRational :: Complex Rational -> Maybe Rational
complexAsRational (Rational
r :+ Rational
i) | Rational
i forall a. Eq a => a -> a -> Bool
== Rational
0 = forall a. a -> Maybe a
Just Rational
r
                           | Bool
otherwise = forall a. Maybe a
Nothing