Data.Complex

Data.Complex

Data.Complex 모듈은 복소수(complex number)와 그 연산을 제공해요.

출처: Haskell 2010 언어 리포트

본문

17.1 직교 형식 (Rectangular form)

data RealFloat a => Complex a = !a :+ !a

실수부와 허수부(직교 rectangular 성분)로 복소수를 만드는 형태예요. 복소수는 대수적(algebraic) 타입이에요. 복소수 z에 대해 abs zz의 크기(magnitude)를 가지되 양의 실수 방향을 향하는 숫자이고, 반면 signum zz의 위상(phase)을 가지되 크기가 1인 숫자예요.

instance RealFloat a => Eq (Complex a)
instance RealFloat a => Floating (Complex a)
instance RealFloat a => Fractional (Complex a)
instance RealFloat a => Num (Complex a)
instance (Read a, RealFloat a) => Read (Complex a)
instance RealFloat a => Show (Complex a)
realPart :: RealFloat a => Complex a -> a

복소수의 실수부를 추출해요.

imagPart :: RealFloat a => Complex a -> a

복소수의 허수부를 추출해요.

17.2 극좌표 형식 (Polar form)

mkPolar :: RealFloat a => a -> a -> Complex a

크기(magnitude)와 위상(phase)의 극좌표(polar) 성분으로 복소수를 만들어요.

cis :: RealFloat a => a -> Complex a

cis t는 크기가 1이고 위상이 t(2*pi를 법으로)인 복소수 값이에요.

polar :: RealFloat a => Complex a -> (a, a)

polar 함수는 복소수를 받아 정준 형식(canonical form)의 (크기, 위상) 쌍을 돌려줘요. 크기는 음수가 아니고, 위상은 (-pi, pi] 범위예요. 크기가 0이면 위상도 0이에요.

magnitude :: RealFloat a => Complex a -> a

복소수의 음수가 아닌 크기예요.

phase :: RealFloat a => Complex a -> a

복소수의 위상으로, 범위는 (-pi, pi]예요. 크기가 0이면 위상도 0이에요.

17.3 켤레 (Conjugate)

conjugate :: RealFloat a => Complex a -> Complex a

복소수의 켤레(conjugate)예요.

17.4 명세 (Specification)

module Data.Complex(Complex((:+)), realPart, imagPart, conjugate, mkPolar,
                    cis, polar, magnitude, phase)  where

infix  6  :+

data  (RealFloat a)     => Complex a = !a :+ !a  deriving (Eq,Read,Show)

realPart, imagPart :: (RealFloat a) => Complex a -> a
realPart (x:+y)        =  x
imagPart (x:+y)        =  y

conjugate      :: (RealFloat a) => Complex a -> Complex a
conjugate (x:+y) =  x :+ (-y)

mkPolar                :: (RealFloat a) => a -> a -> Complex a
mkPolar r theta        =  r ⋆ cos theta :+ r ⋆ sin theta

cis            :: (RealFloat a) => a -> Complex a
cis theta      =  cos theta :+ sin theta

polar          :: (RealFloat a) => Complex a -> (a,a)
polar z                =  (magnitude z, phase z)

magnitude :: (RealFloat a) => Complex a -> a
magnitude (x:+y) =  scaleFloat k
                   (sqrt ((scaleFloat mk x)^2 + (scaleFloat mk y)^2))
                  where k  = max (exponent x) (exponent y)
                        mk = - k

phase :: (RealFloat a) => Complex a -> a
phase (0 :+ 0) = 0
phase (x :+ y) = atan2 y x

instance  (RealFloat a) => Num (Complex a)  where
    (x:+y) + (x':+y') =  (x+x') :+ (y+y')
    (x:+y) - (x':+y') =  (x-x') :+ (y-y')
    (x:+y) ⋆ (x':+y') =  (x⋆x'-y⋆y') :+ (x⋆y'+y⋆x')
    negate (x:+y)     =  negate x :+ negate y
    abs z             =  magnitude z :+ 0
    signum 0          =  0
    signum z@(x:+y)   =  x/r :+ y/r  where r = magnitude z
    fromInteger n     =  fromInteger n :+ 0

instance  (RealFloat a) => Fractional (Complex a)  where
    (x:+y) / (x':+y') =  (x⋆x''+y⋆y'') / d :+ (y⋆x''-x⋆y'') / d
                         where x'' = scaleFloat k x'
                               y'' = scaleFloat k y'
                               k   = - max (exponent x') (exponent y')
                               d   = x'⋆x'' + y'⋆y''
    fromRational a    =  fromRational a :+ 0

instance  (RealFloat a) => Floating (Complex a)       where
    pi             =  pi :+ 0
    exp (x:+y)     =  expx ⋆ cos y :+ expx ⋆ sin y
                      where expx = exp x
    log z          =  log (magnitude z) :+ phase z

    sqrt 0         =  0
    sqrt z@(x:+y)  =  u :+ (if y < 0 then -v else v)
                      where (u,v) = if x < 0 then (v',u') else (u',v')
                            v'    = abs y / (u'⋆2)
                            u'    = sqrt ((magnitude z + abs x) / 2)

    sin (x:+y)     =  sin x ⋆ cosh y :+ cos x ⋆ sinh y
    cos (x:+y)     =  cos x ⋆ cosh y :+ (- sin x ⋆ sinh y)
    tan (x:+y)     =  (sinx⋆coshy:+cosx⋆sinhy)/(cosx⋆coshy:+(-sinx⋆sinhy))
                      where sinx  = sin x
                            cosx  = cos x
                            sinhy = sinh y
                            coshy = cosh y

    sinh (x:+y)    =  cos y ⋆ sinh x :+ sin  y ⋆ cosh x
    cosh (x:+y)    =  cos y ⋆ cosh x :+ sin y ⋆ sinh x
    tanh (x:+y)    =  (cosy⋆sinhx:+siny⋆coshx)/(cosy⋆coshx:+siny⋆sinhx)
                      where siny  = sin y
                            cosy  = cos y
                            sinhx = sinh x
                            coshx = cosh x

    asin z@(x:+y)  =  y':+(-x')
                      where  (x':+y') = log (((-y):+x) + sqrt (1 - z⋆z))
    acos z@(x:+y)  =  y'':+(-x'')
                      where (x'':+y'') = log (z + ((-y'):+x'))
                            (x':+y')   = sqrt (1 - z⋆z)
    atan z@(x:+y)  =  y':+(-x')
                      where (x':+y') = log (((1-y):+x) / sqrt (1+z⋆z))

    asinh z        =  log (z + sqrt (1+z⋆z))
    acosh z        =  log (z + (z+1) ⋆ sqrt ((z-1)/(z+1)))
    atanh z        =  log ((1+z) / sqrt (1-z⋆z))

더 알아보기 (Learn more)

  • 복소수의 직교 형식과 극좌표 형식, 크기와 위상의 관계는 삼각함수·쌍곡선 함수 정의와 함께 보면 좋아요.
  • RealFloat 타입 제약이 요구되는 이유와 Floating·Fractional·Num 클래스의 관계는 관련 클래스 문서를 참고해요.