Copyright(c) The University of Glasgow 2001
LicenseBSD-style (see the file libraries/base/LICENSE)
Maintainerlibraries@haskell.org
Stabilityprovisional
Portabilityportable
Safe HaskellTrustworthy

Data.Complex

Description

Complex numbers.

Synopsis

Rectangular form

data Complex a #

Complex numbers are an algebraic type.

For a complex number z, abs z is a number with the magnitude of z, but oriented in the positive real direction, whereas signum z has the phase of z, but unit magnitude.

The Foldable and Traversable instances traverse the real part first.

Note that Complex's instances inherit the deficiencies from the type parameter's. For example, Complex Float's Ord instance has similar problems to Float's.

A number of functions have branch cuts and principal values.

Constructors

!a :+ !a infix 6

forms a complex number from its real and imaginary rectangular components.

Instances

Instances details
Monad Complex #

Since: 4.9.0.0

Instance details

Defined in Data.Complex

Methods

(>>=) :: Complex a -> (a -> Complex b) -> Complex b

(>>) :: Complex a -> Complex b -> Complex b

return :: a -> Complex a

Functor Complex #

Since: 4.9.0.0

Instance details

Defined in Data.Complex

Methods

fmap :: (a -> b) -> Complex a -> Complex b

(<$) :: a -> Complex b -> Complex a

MonadFix Complex #

Since: 4.15.0.0

Instance details

Defined in Data.Complex

Methods

mfix :: (a -> Complex a) -> Complex a

Applicative Complex #

Since: 4.9.0.0

Instance details

Defined in Data.Complex

Methods

pure :: a -> Complex a

(<*>) :: Complex (a -> b) -> Complex a -> Complex b

liftA2 :: (a -> b -> c) -> Complex a -> Complex b -> Complex c

(*>) :: Complex a -> Complex b -> Complex b

(<*) :: Complex a -> Complex b -> Complex a

Foldable Complex #

Since: 4.9.0.0

Instance details

Defined in Data.Complex

Methods

fold :: Monoid m => Complex m -> m

foldMap :: Monoid m => (a -> m) -> Complex a -> m

foldMap' :: Monoid m => (a -> m) -> Complex a -> m

foldr :: (a -> b -> b) -> b -> Complex a -> b

foldr' :: (a -> b -> b) -> b -> Complex a -> b

foldl :: (b -> a -> b) -> b -> Complex a -> b

foldl' :: (b -> a -> b) -> b -> Complex a -> b

foldr1 :: (a -> a -> a) -> Complex a -> a

foldl1 :: (a -> a -> a) -> Complex a -> a

toList :: Complex a -> [a]

null :: Complex a -> Bool

length :: Complex a -> Int

elem :: Eq a => a -> Complex a -> Bool

maximum :: Ord a => Complex a -> a

minimum :: Ord a => Complex a -> a

sum :: Num a => Complex a -> a

product :: Num a => Complex a -> a

Traversable Complex #

Since: 4.9.0.0

Instance details

Defined in Data.Complex

Methods

traverse :: Applicative f => (a -> f b) -> Complex a -> f (Complex b)

sequenceA :: Applicative f => Complex (f a) -> f (Complex a)

mapM :: Monad m => (a -> m b) -> Complex a -> m (Complex b)

sequence :: Monad m => Complex (m a) -> m (Complex a)

MonadZip Complex #

Since: 4.15.0.0

Instance details

Defined in Data.Complex

Methods

mzip :: Complex a -> Complex b -> Complex (a, b)

mzipWith :: (a -> b -> c) -> Complex a -> Complex b -> Complex c

munzip :: Complex (a, b) -> (Complex a, Complex b)

Eq a => Eq (Complex a) #

Since: 2.1

Instance details

Defined in Data.Complex

Methods

(==) :: Complex a -> Complex a -> Bool

(/=) :: Complex a -> Complex a -> Bool

RealFloat a => Floating (Complex a) #

Since: 2.1

Instance details

Defined in Data.Complex

Methods

pi :: Complex a

exp :: Complex a -> Complex a

log :: Complex a -> Complex a

sqrt :: Complex a -> Complex a

(**) :: Complex a -> Complex a -> Complex a

logBase :: Complex a -> Complex a -> Complex a

sin :: Complex a -> Complex a

cos :: Complex a -> Complex a

tan :: Complex a -> Complex a

asin :: Complex a -> Complex a

acos :: Complex a -> Complex a

atan :: Complex a -> Complex a

sinh :: Complex a -> Complex a

cosh :: Complex a -> Complex a

tanh :: Complex a -> Complex a

asinh :: Complex a -> Complex a

acosh :: Complex a -> Complex a

atanh :: Complex a -> Complex a

log1p :: Complex a -> Complex a

expm1 :: Complex a -> Complex a

log1pexp :: Complex a -> Complex a

log1mexp :: Complex a -> Complex a

RealFloat a => Fractional (Complex a) #

Since: 2.1

Instance details

Defined in Data.Complex

Methods

(/) :: Complex a -> Complex a -> Complex a

recip :: Complex a -> Complex a

fromRational :: Rational -> Complex a

Data a => Data (Complex a) #

Since: 2.1

Instance details

Defined in Data.Complex

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Complex a -> c (Complex a)

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Complex a)

toConstr :: Complex a -> Constr

dataTypeOf :: Complex a -> DataType

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Complex a))

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Complex a))

gmapT :: (forall b. Data b => b -> b) -> Complex a -> Complex a

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Complex a -> r

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Complex a -> r

gmapQ :: (forall d. Data d => d -> u) -> Complex a -> [u]

gmapQi :: Int -> (forall d. Data d => d -> u) -> Complex a -> u

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Complex a -> m (Complex a)

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Complex a -> m (Complex a)

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Complex a -> m (Complex a)

RealFloat a => Num (Complex a) #

Since: 2.1

Instance details

Defined in Data.Complex

Methods

(+) :: Complex a -> Complex a -> Complex a

(-) :: Complex a -> Complex a -> Complex a

(*) :: Complex a -> Complex a -> Complex a

negate :: Complex a -> Complex a

abs :: Complex a -> Complex a

signum :: Complex a -> Complex a

fromInteger :: Integer -> Complex a

Read a => Read (Complex a) #

Since: 2.1

Instance details

Defined in Data.Complex

Methods

readsPrec :: Int -> ReadS (Complex a)

readList :: ReadS [Complex a]

readPrec :: ReadPrec (Complex a)

readListPrec :: ReadPrec [Complex a]

Show a => Show (Complex a) #

Since: 2.1

Instance details

Defined in Data.Complex

Methods

showsPrec :: Int -> Complex a -> ShowS

show :: Complex a -> String

showList :: [Complex a] -> ShowS

Generic (Complex a) #

Since: 4.9.0.0

Instance details

Defined in Data.Complex

Associated Types

type Rep (Complex a) :: Type -> Type

Methods

from :: Complex a -> Rep (Complex a) x

to :: Rep (Complex a) x -> Complex a

Storable a => Storable (Complex a) #

Since: 4.8.0.0

Instance details

Defined in Data.Complex

Methods

sizeOf :: Complex a -> Int

alignment :: Complex a -> Int

peekElemOff :: Ptr (Complex a) -> Int -> IO (Complex a)

pokeElemOff :: Ptr (Complex a) -> Int -> Complex a -> IO ()

peekByteOff :: Ptr b -> Int -> IO (Complex a)

pokeByteOff :: Ptr b -> Int -> Complex a -> IO ()

peek :: Ptr (Complex a) -> IO (Complex a)

poke :: Ptr (Complex a) -> Complex a -> IO ()

Generic1 Complex #

Since: 4.9.0.0

Instance details

Defined in Data.Complex

Associated Types

type Rep1 Complex :: k -> Type

Methods

from1 :: forall (a :: k). Complex a -> Rep1 Complex a

to1 :: forall (a :: k). Rep1 Complex a -> Complex a

type Rep (Complex a) # 
Instance details

Defined in Data.Complex

type Rep (Complex a) = D1 ('MetaData "Complex" "Data.Complex" "main" 'False) (C1 ('MetaCons ":+" ('InfixI 'NotAssociative 6) 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 a) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 a)))
type Rep1 Complex # 
Instance details

Defined in Data.Complex

type Rep1 Complex = D1 ('MetaData "Complex" "Data.Complex" "main" 'False) (C1 ('MetaCons ":+" ('InfixI 'NotAssociative 6) 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) Par1 :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) Par1))

realPart :: Complex a -> a #

Extracts the real part of a complex number.

imagPart :: Complex a -> a #

Extracts the imaginary part of a complex number.

Polar form

mkPolar :: Floating a => a -> a -> Complex a #

Form a complex number from polar components of magnitude and phase.

cis :: Floating a => a -> Complex a #

cis t is a complex value with magnitude 1 and phase t (modulo 2*pi).

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

The function polar takes a complex number and returns a (magnitude, phase) pair: the magnitude is nonnegative, and the phase in the range [-pi, pi].

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

The nonnegative magnitude of a complex number.

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

The phase of a complex number, in the range [-pi, pi]. If the number has a negative real part, and +/- 0 imaginary part the result will be +/- pi. The phase of 0:+0 is 0; of 0:+(-0) is -0; of (-0):+0 is pi; of (-0):+(-0) is -pi.

Other operations

conjugate :: Num a => Complex a -> Complex a #

The conjugate of a complex number.

iTimes :: RealFloat a => Complex a -> Complex a #

iTimes z == z * (0:+1), but without any rounding issues or loss of negative zero. E.g. iTimes((-0):+0) == (-0):+(-0) whereas ((-0):+0)*(0:+1) == (-0):+0

Operations with complex and real numbers

These operators combine complex and real numbers, without converting the real numbers to complex first. E.g. (3:+(-0)) +: 1 == 4:+(-0) whereas (3:+(-0)) + 1 == (3:+(-0)) + (1:+0) == 4:+0

(+:) :: RealFloat a => Complex a -> a -> Complex a infixl 6 #

(-:) :: RealFloat a => Complex a -> a -> Complex a infixl 6 #

(*:) :: RealFloat a => Complex a -> a -> Complex a infixl 7 #

(/:) :: RealFloat a => Complex a -> a -> Complex a infixl 7 #

Branch Cuts and Principal Values

The "inverse" complex functions have branch cuts and principal values in ranges as follows:

(inverse) functionbranch cut(s)range x or (x:+y) where
phase[-∞, -0]-π <= x <= π
sqrt[-∞, -0)x >= +0.0
log[-∞, -0]-π <= y <= π
asin[-∞, -1) and (1, ∞]-π/2 <= x <= π/2
acos[-∞, -1) and (1, ∞]+0.0 <= x <= π
atan[-∞i, -i) and (i, ∞i]-π/2 <= x <= π/2
asinh[-∞i, -i) and (i, ∞i]-π/2 <= y <= π/2
acosh[-∞, 1)x >= +0.0 and -π <= y <= π
atanh[-∞, -1) and (1, ∞]-π/2 <= y <= π/2

Note that phase maps complex numbers to real numbers and the other functions map complex numbers to complex numbers. All of the branch cuts fall on axes.

In this table, the expression x >= +0.0 and similar excludes x where isNegativeZero x is True.

The behaviour of types Complex a for a value on a branch cut is different, depending on whether floating type a supports signed zeros.

For types that support signed zeros (i.e. IEEE 754 types), the branch cuts can be considered to be "between" 0.0 and -0.0. The mappings of 0.0 will be continuous with those of values greater than 0.0, and the mappings of -0.0 will be continuous with those of values less than 0.0.

For types that don't support signed zeros, the mappings of points on a branch cut are continuous with mappings of points in one of the adjacent quadrants as indicated in the table below. In addition, the range of the functions excludes certain values, also indicated in the table.

(inverse) functionbranch cut(s) continuous withrange excludes
phaseQII
sqrtQII(0, -∞i]
logQII[-∞-πi, ∞-πi]
asinQII and QIV(-π/2, -π/2-∞i], (π/2, π/2+∞i]
acosQII and QIV(0, -∞i], (π, π+∞i]
atanQIII and QI[-π/2, -π/2+∞i], [π/2, π/2-∞i]
asinhQIII and QI(-π/2i, ∞-π/2i], (π/2i, -∞+π/2i]
acoshQII (x<0), QI (x>0)(0, -πi], [-πi, ∞-πi]
atanhQII and QIV[-π/2i, -∞-π/2i], [π/2i, ∞+π/2i]

where the quadrants are labelled:

negative realpositive real
positive imaginaryQIIQI
negative imaginaryQIIIQIV

Some (inverse) functions also have branch points as follows:

(inverse) functionbranch pointvalue at branch point
log0.0 :+ 0.0(-Infinity) :+ 0.0
atan0.0 :+ 1.00.0 :+ Infinity
atan0.0 :+ (-1.0)0.0 :+ (-Infinity)
atanh1.0 :+ 0.0Infinity :+ 0.0
atanh(-1.0) :+ 0.0(-Infinity) :+ 0.0

For log, branch points with a negative zero real part are included in the branch cut, giving different results for branch points with positive and negative zero in the imaginary part. For other branch points, a negative zero input will be reflected in the output.

Haskell's branch cuts, continuities, ranges and branch points follow the recommendations by Kahan (Branch Cuts for Complex Elementary Functions or Much Ado About Nothing's Sign Bit, 1987), and are consitant with those in some other languages such as Common Lisp.

Explanation

Branch Cuts

This is an explanation of the branch cuts for the function sqrt. The same principles apply to the other functions.

Consider sqrt of real numbers. Both 2.0^2 and (-2.0)^2 have the value 4.0, but sqrt 4.0 returns only 2.0. In general sqrt returns only the non-negative square root, a standard widely adopted. In other words the range of sqrt, over real numbers, is [0, ∞]: half of the real number line.

sqrt over complex numbers has analagous behaviour. The square of both 1:+2 and its negative (-1):+(-2) is the same value (-3):+4. sqrt maps (-3):+4 back to only one of these: 1:+2, the principal value. The standard principal values for sqrt are those x:+y where x >= 0: half of the complex plane.

The table below shows the square of two sequences of complex numbers:

vw = -vz = v^2 (== w^2)
( 0.050):+2.0(-0.050):+(-2.0)(-4):+( 0.2)
( 0.025):+2.0(-0.025):+(-2.0)(-4):+( 0.1)
( 0.000):+2.0( 0.000):+(-2.0)(-4):+( 0.0)
(-0.025):+2.0( 0.025):+(-2.0)(-4):+(-0.1)
(-0.050):+2.0( 0.050):+(-2.0)(-4):+(-0.2)

Each corresponding v and w has the same square z. sqrt maps each of these z values back to the principal value (whichever of v or w has a non-negative real part, as highlighted in bold). Hence, although the sequence z is continuous, sqrt z is discontinuous, with the results jumping from a imaginary 2.0 to imaginary -2.0 as the imaginary part of z crosses the real axis.

The discontinuity in sqrt illustrated here happens at -4 on the real axis. There would be similar discontinuities at all other points on the negative real axis. Hence the negative real axis [-∞, -0) forms a line of discontinuity, called a branch cut. The location of the branch cuts and the range of the function are related.

In the case of sqrt $ (-4):+( 0.0), either v or w could be chosen, but:

  • When dealing with floating point numbers that support negative zeros, the result is chosen so that sqrt $ (-4):+( 0.0) is continuous with points sqrt $ (-4):+y where y>0, hence ( 0.000):+2.0, and sqrt $ (-4):+(-0.0) is continuous with points sqrt $ (-4):+y where y<0, hence ( 0.000):(-2.0). It is helpful to think of the branch cut as being "between" 0.0 and -0.0.
  • When dealing with floating point numbers that don't support negative zeros, an arbitrary but standard choice is made. The standard choice in this case is that sqrt $ (-4):+( 0.0) is ( 0.000):+2.0. Hence sqrt of points on the branch cut are continuous with sqrt of points in QII on the complex plane. In addition, sqrt will not map anything to ( 0.000):+(-2.0), or any other point on the negative imaginary axis (0, -∞i], which is excluded from the range.

    Note that "continous with" doesn't mean "maps into" or "maps towards". For example, the first branch cut listed for cos is marked as "continuous with QII". Hence both (-2) :+ 0 (a point on this branch cut) and (-2) :+ 0.1 (a nearby point in QII) are both mapped by cos to locations near each other, but in QIV.

The result for (unsigned) 0.0 (for types that don't support signed zeros) is not necessarily the same as that for "positive" 0.0 (for those that types that do). For example:

>>> asin $ 2.0 :+ 0.0 :: Complex SomeNonIEEEFloatingType
1.570 :+ (-1.316)
>>> asin $ 2.0 :+ 0.0 :: Complex SomeIEEEFloatingType
1.570 :+ 1.316

Branch Points

This is an explanation of the branch point for the function log. The same principles apply to the other functions.

Mathematically \(e^x\to0\) as \(x\to-\infty\) and \(\log 0\) is undefined. Computationally it is usually helpful (and is required by IEEE 754) to give -Infinity:

>>> log 0.0
-Infinity

For complex numbers, exp (x:+y) == mkPolar (exp x) y, i.e. a point distance exp x from the origin, at angle y. As x tends to -Infinity, this point tends to 0.0 :+ 0.0, but from different angles depending on y. Hence exp $ (-1/0.0) :+ y gives 0.0 :+ 0.0 for any y.

The inverse function log could map 0.0 :+ 0.0 to any -Infinity :+ y. The point 0.0 :+ 0.0 is called a branch point of log. An arbirary, but standard, choice (which must be within the principle value range) is made for the result, as shown in the table above:

>>> log $ 0.0 :+ 0.0
(-Infinity) :+ 0.0