complex without the realfloat
[ruff:gruff.git] / src / UnComplex.hs
1 {-# LANGUAGE DeriveDataTypeable #-}
2
3 -- Complex numbers without the 'RealFloat' constraint.
4 module UnComplex
5   ( Complex((:+)), cis, mkPolar
6   , realPart, imagPart, conjugate
7   , magnitude2, magnitude, phase, polar
8   ) where
9
10 import Data.Data (Data)
11 import Data.Typeable (Typeable)
12
13 -- | Complex number type without the 'RealFloat' constraint.
14 data Complex r = !r :+ !r
15   deriving (Read, Show, Eq, Data, Typeable)
16
17 instance Functor Complex where fmap f (x:+y) = f x :+ f y
18
19 instance Num r => Num (Complex r) where
20   (x :+ y) + (u :+ v) = (x + u) :+ (y + v)
21   (x :+ y) - (u :+ v) = (x - u) :+ (y - v)
22   (x :+ y) * (u :+ v) = (x * u - y * v) :+ (x * v + y * u)
23   negate (x :+ y) = negate x :+ negate y
24   abs = error "Fractal.RUFF.Types.Complex.Num.abs"
25   signum = error "Fractal.RUFF.Types.Complex.Num.signum"
26   fromInteger n = fromInteger n :+ 0
27
28 instance Fractional r => Fractional (Complex r) where
29   (x :+ y) / (u :+ v) = ((x * u + y * v) / d) :+ ((y * u - x * v) / d) where d = u * u + v * v
30   fromRational r = fromRational r :+ 0
31
32 instance (Ord r, Floating r) => Floating (Complex r) where
33   pi = pi :+ 0
34   exp (x :+ y) = mkPolar (exp x) y
35   log z = let (r, t) = polar z in log r :+ t
36   sin (x :+ y) = (sin x * cosh y) :+        (cos x * sinh y)
37   cos (x :+ y) = (cos x * cosh y) :+ negate (sin x * sinh y)
38   tan z = sin z / cos z
39   asin z = negate i * log (i * z + sqrt (1 - z*z)) where i = 0:+1
40   acos z = negate i * log (z + sqrt (z*z - 1)) where i = 0:+1
41   atan z = 1/2 * i * log ((1 - iz)/(1 + iz)) where i = 0:+1 ; iz = i * z
42   sinh z = (exp z - exp (-z)) / 2
43   cosh z = (exp z + exp (-z)) / 2
44   tanh z = let ez2 = exp (2 * z) in (ez2 - 1) / (ez2 + 1)
45   asinh z = log (z + sqrt (z*z + 1))
46   acosh z = log (z + sqrt (z*z - 1))
47   atanh z = 1/2 * log ((1 + z) / (1 - z))
48
49 -- | Extract the real part.
50 realPart :: Complex r -> r
51 realPart (r :+ _) = r
52
53 -- | Extract the imaginary part.
54 imagPart :: Complex r -> r
55 imagPart (_ :+ i) = i
56
57 -- | Complex conjugate.
58 conjugate :: Num r => Complex r -> Complex r
59 conjugate (r :+ i) = r :+ negate i
60
61 -- | Complex magnitude squared.
62 magnitude2 :: Num r => Complex r -> r
63 magnitude2 (r :+ i) = r * r + i * i
64
65 -- | Complex magnitude.
66 magnitude :: Floating r => Complex r -> r
67 magnitude = sqrt . magnitude2
68
69 -- | Complex phase.
70 phase :: (Ord r, Floating r) => Complex r -> r
71 phase (r :+ i)
72   | r > 0 && i > 0 =      atan (    i /     r)
73   | r > 0 && i < 0 =    - atan (abs i /     r)
74   | r < 0 && i > 0 = pi - atan (    i / abs r)
75   | r < 0 && i < 0 =      atan (abs i / abs r) - pi
76   | i > 0          =      pi / 2
77   | i < 0          =    - pi / 2
78   | r < 0          =      pi
79   | otherwise      =      0
80
81 -- | Complex number with the given magnitude and phase.
82 mkPolar :: Floating r => r -> r -> Complex r
83 mkPolar r t = (r * cos t) :+ (r * sin t)
84
85 -- | Complex number with magnitude 1 and the given phase.
86 cis :: Floating r => r -> Complex r
87 cis t = cos t :+ sin t
88
89 -- | Convert to polar form.
90 polar :: (Ord r, Floating r) => Complex r -> (r, r)
91 polar z = (magnitude z, phase z)