```{-# 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 x			= (mag x, 0)

{-# INLINE signum #-}
signum (re, _)	= (signum re, 0)

{-# INLINE fromInteger #-}
fromInteger n		= (fromInteger n, 0.0)

{-# INLINE (+) #-}
(r, i) + (r', i')	= (r+r', i+i')

{-# INLINE (-) #-}
(r, i) - (r', i')	= (r-r', i-i')

{-# INLINE (*) #-}
(r, i) * (r', i')	= (r*r' - i*i', r*i' + r'*i)

instance Fractional Complex where
{-# INLINE (/) #-}
(a, b) / (c, d)
= let	den	= c^(2 :: Int) + d^(2 :: Int)
re	= (a * c + b * d) / den
im	= (b * c - a * d) / den
in	(re, im)

fromRational x	= (fromRational x, 0)

-- | Take the magnitude of a complex number.
mag :: Complex -> Double
{-# INLINE mag #-}
mag (r, i)	= sqrt (r * r + i * i)

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

where 	normaliseAngle :: Double -> Double
normaliseAngle f
| f < - pi
= normaliseAngle (f + 2 * pi)

| f > pi
= normaliseAngle (f - 2 * pi)

| otherwise
= f
```