1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
<title>The Haskell 98 Library Report: Complex Numbers</title>
<body bgcolor="#ffffff"> <i>The Haskell 98 Library Report</i><br> <a href="index.html">top</a> | <a href="ratio.html">back</a> | <a href="numeric.html">next</a> | <a href="libindex.html">contents</a> <br><hr>
<a name="lib-num"></a><a name="sect3"></a>
<h2>3<tt> </tt>Complex Numbers</h2>
<p>
<table border=2 cellpadding=3>
<tr><td>
<tt><br>
module Complex ( <br>
Complex((:+)), realPart, imagPart, conjugate, <br>
mkPolar, cis, polar, magnitude, phase ) where<br>
<br>
infix 6 :+<br>
<br>
data (RealFloat a) => Complex a = !a :+ !a<br>
<br>
realPart, imagPart :: (RealFloat a) => Complex a -> a<br>
conjugate :: (RealFloat a) => Complex a -> Complex a<br>
mkPolar :: (RealFloat a) => a -> a -> Complex a<br>
cis :: (RealFloat a) => a -> Complex a<br>
polar :: (RealFloat a) => Complex a -> (a,a)<br>
magnitude, phase :: (RealFloat a) => Complex a -> a<br>
<br>
instance (RealFloat a) => Eq (Complex a) where ...<br>
instance (RealFloat a) => Read (Complex a) where ...<br>
instance (RealFloat a) => Show (Complex a) where ...<br>
instance (RealFloat a) => Num (Complex a) where ...<br>
instance (RealFloat a) => Fractional (Complex a) where ...<br>
instance (RealFloat a) => Floating (Complex a) where ...<br>
</tt></td></tr></table>
<p>
Complex numbers are an algebraic type.
The constructor <tt>(:+)</tt> forms a complex number from its
real and imaginary rectangular components. This constructor is
strict: if either the real part or the imaginary part of the number is
_|_, the entire number is _|_. A complex number may also
be formed from polar components of magnitude and phase by the function
<tt>mkPolar</tt>. The function <tt>cis
</tt>produces a complex number from an angle <I>t</I>.
Put another way, <tt>cis</tt> <I>t</I> is a complex value with magnitude <I>1
</I>and phase <I>t</I> (modulo <I>2</I><font face="symbol">p</font>).<p>
The function <tt>polar</tt> takes a complex number and
returns a (magnitude, phase) pair in canonical form: The magnitude is
nonnegative, and the phase, in the range (- <font face="symbol">p</font>, <font face="symbol">p</font>]; if the
magnitude is zero, then so is the phase. <p>
The functions <tt>realPart</tt> and
<tt>imagPart</tt> extract the rectangular components of a
complex number and the functions <tt>magnitude</tt> and
<tt>phase</tt> extract the polar components of a complex
number. The function <tt>conjugate</tt> computes the
conjugate of a complex number in the usual way.<p>
The magnitude and sign of a complex number are defined as follows:
<tt><br>
<br>
abs z = magnitude z :+ 0<br>
signum 0 = 0<br>
signum z@(x:+y) = x/r :+ y/r where r = magnitude z<br>
<br>
</tt>That is, <tt>abs</tt> z is a number with the magnitude of z, but oriented
in the positive real direction, whereas <tt>signum</tt> z has the phase of
z, but unit magnitude.<p>
<a name="sect3.1"></a>
<h3>3.1<tt> </tt>Library <tt>Complex</tt></h3>
<tt><br>
<br>
module Complex(Complex((:+)), realPart, imagPart, conjugate, mkPolar,<br>
cis, polar, magnitude, phase) where<br>
<br>
infix 6 :+<br>
<br>
data (RealFloat a) => Complex a = !a :+ !a deriving (Eq,Read,Show)<br>
<br>
<br>
realPart, imagPart :: (RealFloat a) => Complex a -> a<br>
realPart (x:+y) = x<br>
imagPart (x:+y) = y<br>
<br>
conjugate :: (RealFloat a) => Complex a -> Complex a<br>
conjugate (x:+y) = x :+ (-y)<br>
<br>
mkPolar :: (RealFloat a) => a -> a -> Complex a<br>
mkPolar r theta = r * cos theta :+ r * sin theta<br>
<br>
cis :: (RealFloat a) => a -> Complex a<br>
cis theta = cos theta :+ sin theta<br>
<br>
polar :: (RealFloat a) => Complex a -> (a,a)<br>
polar z = (magnitude z, phase z)<br>
<br>
magnitude :: (RealFloat a) => Complex a -> a<br>
magnitude (x:+y) = scaleFloat k<br>
(sqrt ((scaleFloat mk x)^2 + (scaleFloat mk y)^2))<br>
where k = max (exponent x) (exponent y)<br>
mk = - k<br>
<br>
phase :: (RealFloat a) => Complex a -> a<br>
phase (0 :+ 0) = 0<br>
phase (x :+ y) = atan2 y x<br>
<br>
<br>
instance (RealFloat a) => Num (Complex a) where<br>
(x:+y) + (x':+y') = (x+x') :+ (y+y')<br>
(x:+y) - (x':+y') = (x-x') :+ (y-y')<br>
(x:+y) * (x':+y') = (x*x'-y*y') :+ (x*y'+y*x')<br>
negate (x:+y) = negate x :+ negate y<br>
abs z = magnitude z :+ 0<br>
signum 0 = 0<br>
signum z@(x:+y) = x/r :+ y/r where r = magnitude z<br>
fromInteger n = fromInteger n :+ 0<br>
<br>
instance (RealFloat a) => Fractional (Complex a) where<br>
(x:+y) / (x':+y') = (x*x''+y*y'') / d :+ (y*x''-x*y'') / d<br>
where x'' = scaleFloat k x'<br>
y'' = scaleFloat k y'<br>
k = - max (exponent x') (exponent y')<br>
d = x'*x'' + y'*y''<br>
<br>
fromRational a = fromRational a :+ 0<br>
<br>
instance (RealFloat a) => Floating (Complex a) where<br>
pi = pi :+ 0<br>
exp (x:+y) = expx * cos y :+ expx * sin y<br>
where expx = exp x<br>
log z = log (magnitude z) :+ phase z<br>
<br>
sqrt 0 = 0<br>
sqrt z@(x:+y) = u :+ (if y < 0 then -v else v)<br>
where (u,v) = if x < 0 then (v',u') else (u',v')<br>
v' = abs y / (u'*2)<br>
u' = sqrt ((magnitude z + abs x) / 2)<br>
<br>
sin (x:+y) = sin x * cosh y :+ cos x * sinh y<br>
cos (x:+y) = cos x * cosh y :+ (- sin x * sinh y)<br>
tan (x:+y) = (sinx*coshy:+cosx*sinhy)/(cosx*coshy:+(-sinx*sinhy))<br>
where sinx = sin x<br>
cosx = cos x<br>
sinhy = sinh y<br>
coshy = cosh y<br>
<br>
sinh (x:+y) = cos y * sinh x :+ sin y * cosh x<br>
cosh (x:+y) = cos y * cosh x :+ sin y * sinh x<br>
tanh (x:+y) = (cosy*sinhx:+siny*coshx)/(cosy*coshx:+siny*sinhx)<br>
where siny = sin y<br>
cosy = cos y<br>
sinhx = sinh x<br>
coshx = cosh x<br>
<br>
asin z@(x:+y) = y':+(-x')<br>
where (x':+y') = log (((-y):+x) + sqrt (1 - z*z))<br>
acos z@(x:+y) = y'':+(-x'')<br>
where (x'':+y'') = log (z + ((-y'):+x'))<br>
(x':+y') = sqrt (1 - z*z)<br>
atan z@(x:+y) = y':+(-x')<br>
where (x':+y') = log (((1-y):+x) / sqrt (1+z*z))<br>
<br>
asinh z = log (z + sqrt (1+z*z))<br>
acosh z = log (z + (z+1) * sqrt ((z-1)/(z+1)))<br>
atanh z = log ((1+z) / sqrt (1-z*z))<br>
<p>
<hr><i>The Haskell 98 Library Report</i><br><a href="index.html">top</a> | <a href="ratio.html">back</a> | <a href="numeric.html">next</a> | <a href="libindex.html">contents</a> <br><font size=2>1 February, 1999</font>
<p>
</tt>
|