module Fractal.RUFF.Types.Complex
( Complex((:+)), cis, mkPolar
, realPart, imagPart, conjugate
, magnitude2, magnitude, phase, polar
) where
import Data.Data (Data)
import Data.Typeable (Typeable)
import Data.Vec (NearZero(nearZero))
data Complex r = !r :+ !r
deriving (Read, Show, Eq, Data, Typeable)
instance Num r => Num (Complex r) where
(x :+ y) + (u :+ v) = (x + u) :+ (y + v)
(x :+ y) (u :+ v) = (x u) :+ (y v)
(x :+ y) * (u :+ v) = (x * u y * v) :+ (x * v + y * u)
negate (x :+ y) = negate x :+ negate y
abs = error "Fractal.Types.Complex.Num.abs"
signum = error "Fractal.Types.Complex.Num.signum"
fromInteger n = fromInteger n :+ 0
instance Fractional r => Fractional (Complex r) where
(x :+ y) / (u :+ v) = ((x * u + y * v) / d) :+ ((y * u x * v) / d) where d = u * u + v * v
fromRational r = fromRational r :+ 0
instance (Ord r, Floating r) => Floating (Complex r) where
pi = pi :+ 0
exp (x :+ y) = mkPolar (exp x) y
log z = let (r, t) = polar z in log r :+ t
sin (x :+ y) = (sin x * cosh y) :+ (cos x * sinh y)
cos (x :+ y) = (cos x * cosh y) :+ negate (sin x * sinh y)
tan z = sin z / cos z
asin z = negate i * log (i * z + sqrt (1 z*z)) where i = 0:+1
acos z = negate i * log (z + sqrt (z*z 1)) where i = 0:+1
atan z = 1/2 * i * log ((1 iz)/(1 + iz)) where i = 0:+1 ; iz = i * z
sinh z = (exp z exp (z)) / 2
cosh z = (exp z + exp (z)) / 2
tanh z = let ez2 = exp (2 * z) in (ez2 1) / (ez2 + 1)
asinh z = log (z + sqrt (z*z + 1))
acosh z = log (z + sqrt (z*z 1))
atanh z = 1/2 * log ((1 + z) / (1 z))
instance NearZero r => NearZero (Complex r) where
nearZero (r :+ i) = nearZero r && nearZero i
realPart :: Complex r -> r
realPart (r :+ _) = r
imagPart :: Complex r -> r
imagPart (_ :+ i) = i
conjugate :: Num r => Complex r -> Complex r
conjugate (r :+ i) = r :+ negate i
magnitude2 :: Num r => Complex r -> r
magnitude2 (r :+ i) = r * r + i * i
magnitude :: Floating r => Complex r -> r
magnitude = sqrt . magnitude2
phase :: (Ord r, Floating r) => Complex r -> r
phase (r :+ i)
| r > 0 && i > 0 = atan ( i / r)
| r > 0 && i < 0 = atan (abs i / r)
| r < 0 && i > 0 = pi atan ( i / abs r)
| r < 0 && i < 0 = atan (abs i / abs r) pi
| i > 0 = pi / 2
| i < 0 = pi / 2
| r < 0 = pi
| otherwise = 0
mkPolar :: Floating r => r -> r -> Complex r
mkPolar r t = (r * cos t) :+ (r * sin t)
cis :: Floating r => r -> Complex r
cis t = cos t :+ sin t
polar :: (Ord r, Floating r) => Complex r -> (r, r)
polar z = (magnitude z, phase z)