{-# LANGUAGE TypeOperators, TypeSynonymInstances, FlexibleInstances #-}
{-# OPTIONS -fno-warn-orphans #-}
-- | Strict complex doubles.
module Data.Array.Repa.Algorithms.Complex
        ( Complex
        , mag
        , arg)
where


-- | Complex doubles.
type Complex 
        = (Double, Double)

instance Num Complex where

  {-# INLINE abs #-}
  abs :: Complex -> Complex
abs Complex
x                 = (Complex -> Double
mag Complex
x, Double
0)

  {-# INLINE signum #-}
  signum :: Complex -> Complex
signum (Double
re, Double
_)        = (Double -> Double
forall a. Num a => a -> a
signum Double
re, Double
0)

  {-# INLINE fromInteger #-}
  fromInteger :: Integer -> Complex
fromInteger Integer
n         = (Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
n, Double
0.0)

  {-# INLINE (+) #-}
  (Double
r, Double
i) + :: Complex -> Complex -> Complex
+ (Double
r', Double
i')     = (Double
rDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
r', Double
iDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
i')

  {-# INLINE (-) #-}
  (Double
r, Double
i) - :: Complex -> Complex -> Complex
- (Double
r', Double
i')     = (Double
rDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
r', Double
iDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
i')

  {-# INLINE (*) #-}
  (Double
r, Double
i) * :: Complex -> Complex -> Complex
* (Double
r', Double
i')     = (Double
rDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
r' Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
iDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
i', Double
rDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
i' Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r'Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
i)


instance Fractional Complex where
  {-# INLINE (/) #-}
  (Double
a, Double
b) / :: Complex -> Complex -> Complex
/ (Double
c, Double
d)               
        = let   den :: Double
den     = Double
cDouble -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
2 :: Int) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
dDouble -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
2 :: Int)
                re :: Double
re      = (Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
c Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
b Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
d) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
den
                im :: Double
im      = (Double
b Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
c Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
d) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
den
          in    (Double
re, Double
im)
        
  fromRational :: Rational -> Complex
fromRational Rational
x        = (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
x, Double
0)
        
-- | Take the magnitude of a complex number.
mag :: Complex -> Double
{-# INLINE mag #-}
mag :: Complex -> Double
mag (Double
r, Double
i)      = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
r Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
r Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
i Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
i)


-- | Take the argument (phase) of a complex number, in the range [-pi .. pi].
arg :: Complex -> Double
{-# INLINE arg #-}
arg :: Complex -> Double
arg (Double
re, Double
im)
 = Double -> Double
normaliseAngle (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 Double
im Double
re

 where  normaliseAngle :: Double -> Double
        normaliseAngle :: Double -> Double
normaliseAngle Double
f
         | Double
f Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< - Double
forall a. Floating a => a
pi     
         = Double -> Double
normaliseAngle (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi)
        
         | Double
f Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
forall a. Floating a => a
pi
         = Double -> Double
normaliseAngle (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi)

         | Bool
otherwise
         = Double
f