perturbation based calculations
[maximus:emndl.git] / Complex.hs
1 {-
2     emndl -- exponentially transformed Mandelbrot Set renderer
3     Copyright (C) 2011  Claude Heiland-Allen <claude@mathr.co.uk>
4
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 -}
18
19 module Complex where
20
21 -- this is ugly: can't use Data.Complex because no RealFloat for MPFR
22 data Complex c = !c :+ !c deriving (Read, Show, Eq)
23
24 -- complex number arithmetic, with extra strictness and cost-centres
25 instance Num c => Num (Complex c) where
26   (a :+ b) + (c :+ d) = (a + c) :+ (b + d)
27   (a :+ b) - (c :+ d) = (a - c) :+ (b - d)
28   (a :+ b) * (c :+ d) = (a * c - b * d) :+ (a * d + b * c)
29   negate (a :+ b) = negate a :+ negate b
30   abs x = error $ "Complex.abs: " ++ show x
31   signum x = error $ "Complex.signum: " ++ show x
32   fromInteger x = fromInteger x :+ 0
33
34 instance (Fractional a) => Fractional (Complex a)  where
35   (a:+b) / (c:+d) = ((a*c + b*d) / m) :+ ((b*c - a*d) / m) where m = c*c + d*d
36   fromRational a = fromRational a :+ 0
37     
38 magnitude :: (Floating c) => Complex c -> c
39 magnitude = sqrt . magnitude2
40
41 magnitude2 :: (Num c) => Complex c -> c
42 magnitude2 (re:+im) = re * re + im * im
43
44 cis :: Floating c => c -> Complex c
45 cis a = cos a :+ sin a
46
47 mkPolar :: Floating c => c -> c -> Complex c
48 mkPolar r a = (r * cos a) :+ (r * sin a)
49
50 phase :: (Floating c, Ord c) => Complex c -> c
51 phase (re:+im) = atan2' im re
52
53 atan2' :: (Floating c, Ord c) => c -> c -> c
54 atan2' y x
55   | x > 0            =  atan (y / x)
56   | x == 0 && y > 0  =  pi/2
57   | x <  0 && y > 0  =  pi + atan (y / x)
58   | x <= 0 && y < 0  = -atan2' (-y) x
59   | y == 0 && x < 0  =  pi
60   | x == 0 && y == 0 =  y
61   | otherwise = error "Complex.atan2'"
62
63 normalize :: Floating c => Complex c -> Complex c
64 normalize z@(re:+im) = let m = magnitude z in (re / m) :+ (im / m)