Common Lisp provides no data type that can accurately represent irrational numerical values. The functions in this section are described as if the results were mathematically accurate, but actually they all produce floating-point approximations to the true mathematical result in the general case. In some places mathematical identities are set forth that are intended to elucidate the meanings of the functions; however, two mathematically identical expressions may be computationally different because of errors inherent in the floating-point approximation process.
When the arguments to a function in this section are all rational and the true mathematical result is also (mathematically) rational, then unless otherwise noted an implementation is free to return either an accurate result of type rational or a single-precision floating-point approximation. If the arguments are all rational but the result cannot be expressed as a rational number, then a single-precision floating-point approximation is always returned.
If the arguments to a function are all of type (or rational (complex rational)) and the true mathematical result is (mathematically) a complex number with rational real and imaginary parts, then unless otherwise noted an implementation is free to return either an accurate result of type (or rational (complex rational)) or a single-precision floating-point approximation of type single-float (permissible only if the imaginary part of the true mathematical result is zero) or (complex single-float). If the arguments are all of type (or rational (complex rational)) but the result cannot be expressed as a rational or complex rational number, then the returned value will be of type single-float (permissible only if the imaginary part of the true mathematical result is zero) or (complex single-float).
The rules of floating-point contagion and complex contagion are effectively obeyed by all the functions in this section except expt, which treats some cases of rational exponents specially. When, possibly after contagious conversion, all of the arguments are of the same floating-point or complex floating-point type, then the result will be of that same type unless otherwise noted. ____________________________________________________________________
Implementation note: There is a “floating-point cookbook” by Cody and Waite [14] that may be a useful aid in implementing the functions defined in this section.
Along with the usual one-argument and two-argument exponential and logarithm functions, sqrt is considered to be an exponential function, because it raises a number to the power 1/2.
Returns e raised to the power number, where e is the base of the natural logarithms.
Returns base-number raised to the power power-number. If the base-number is of type rational and the power-number is an integer, the calculation will be exact and the result will be of type rational; otherwise a floating-point approximation may result.
X3J13 voted in March 1989 to clarify that provisions similar to those of the previous paragraph apply to complex numbers. If the base-number is of type (complex rational) and the power-number is an integer, the calculation will also be exact and the result will be of type (or rational (complex rational)); otherwise a floating-point or complex floating-point approximation may result.
When power-number is 0 (a zero of type integer), then the result is always the value 1 in the type of base-number, even if the base-number is zero (of any type). That is:
If the power-number is a zero of any other data type, then the result is also the value 1, in the type of the arguments after the application of the contagion rules, with one exception: it is an error if base-number is zero when the power-number is a zero not of type integer.
Implementations of expt are permitted to use different algorithms for the cases of a rational power-number and a floating-point power-number; the motivation is that in many cases greater accuracy can be achieved for the case of a rational power-number. For example, (expt pi 16) and (expt pi 16.0) may yield slightly different results if the first case is computed by repeated squaring and the second by the use of logarithms. Similarly, an implementation might choose to compute (expt x 3/2) as if it had been written (sqrt (expt x 3)), perhaps producing a more accurate result than would (expt x 1.5). It is left to the implementor to determine the best strategies.
The result of expt can be a complex number, even when neither argument is complex, if base-number is negative and power-number is not an integer. The result is always the principal complex value. Note that (expt -8 1/3) is not permitted to return -2; while -2 is indeed one of the cube roots of -8, it is not the principal cube root, which is a complex number approximately equal to #C(1.0 1.73205).
Returns the logarithm of number in the base base, which defaults to e, the base of the natural logarithms. For example:
The result of (log 8 2) may be either 3 or 3.0, depending on the implementation.
Note that log may return a complex result when given a non-complex argument if the argument is negative. For example:
X3J13 voted in January 1989 to specify certain floating-point behavior when minus zero is supported. As a part of that vote it approved a mathematical definition of complex logarithm in terms of real logarithm, absolute value, arc tangent of two real arguments, and the phase function as
Returns the principal square root of number. If the number is not complex but is negative, then the result will be a complex number. For example:
The result of (sqrt 9) may be either 3 or 3.0, depending on the implementation. The result of (sqrt -9) may be either #c(0 3) or #c(0.0 3.0).
X3J13 voted in January 1989 to specify certain floating-point behavior when minus zero is supported. As a part of that vote it approved a mathematical definition of complex square root in terms of complex logarithm and exponential functions as
Integer square root: the argument must be a non-negative integer, and the result is the greatest integer less than or equal to the exact positive square root of the argument. For example:
Some of the functions in this section, such as abs and signum, are apparently unrelated to trigonometric functions when considered as functions of real numbers only. The way in which they are extended to operate on complex numbers makes the trigonometric connection clear.
Returns the absolute value of the argument. For a non-complex number x,
and the result is always of the same type as the argument.
For a complex number z, the absolute value may be computed as
Implementation note: The careful implementor will not use this formula directly for all complex numbers but will instead handle very large or very small components specially to avoid intermediate overflow or underflow.
For example:
The result of (abs #c(3 4)) may be either 5 or 5.0, depending on the implementation.
The phase of a number is the angle part of its polar representation as a complex number. That is,
X3J13 voted in January 1989 to specify certain floating-point behavior when minus zero is supported; phase is still defined in terms of atan as above, but thanks to a change in atan the range of phase becomes − π inclusive to π inclusive. The value − π results from an argument whose real part is negative and whose imaginary part is minus zero. The phase function therefore has a branch cut along the negative real axis. The phase of + 0 + 0i is + 0, of + 0 − 0i is − 0, of − 0 + 0i is + π, and of − 0 − 0i is − π.
If the argument is a complex floating-point number, the result is a floating-point number of the same type as the components of the argument. If the argument is a floating-point number, the result is a floating-point number of the same type. If the argument is a rational number or complex rational number, the result is a single-format floating-point number.
By definition,
For a rational number, signum will return one of -1, 0, or 1 according to whether the number is negative, zero, or positive. For a floating-point number, the result will be a floating-point number of the same format whose value is − 1, 0, or 1. For a complex number z, (signum z) is a complex number of the same phase but with unit magnitude, unless z is a complex zero, in which case the result is z. For example:
For non-complex rational numbers, signum is a rational function, but it may be irrational for complex arguments.
sin returns the sine of the argument, cos the cosine, and tan the tangent. The argument is in radians. The argument may be complex.
This computes ei⋅radians. The name cis means “cos + i sin,” because ei𝜃 = cos 𝜃 + i sin 𝜃. The argument is in radians and may be any non-complex number. The result is a complex number whose real part is the cosine of the argument and whose imaginary part is the sine. Put another way, the result is a complex number whose phase is the equal to the argument (mod 2π) and whose magnitude is unity. _______________________________________________________
Implementation note: Often it is cheaper to calculate the sine and cosine of a single angle together than to perform two disjoint calculations.
asin returns the arc sine of the argument, and acos the arc cosine. The result is in radians. The argument may be complex.
The arc sine and arc cosine functions may be defined mathematically for an argument z as follows:
Kahan [25] suggests for acos the defining formula
Implementation note: These formulae are mathematically correct, assuming completely accurate computation. They may be terrible methods for floating-point computation. Implementors should consult a good text on numerical analysis. The formulae given above are not necessarily the simplest ones for real-valued computations, either; they are chosen to define the branch cuts in desirable ways for the complex case.
An arc tangent is calculated and the result is returned in radians.
With two arguments y and x, neither argument may be complex. The result is the arc tangent of the quantity y/x. The signs of y and x are used to derive quadrant information; moreover, x may be zero provided y is not zero. The value of atan is always between − π (exclusive) and π (inclusive). The following table details various special cases.
Condition | Cartesian Locus | Range of Result | |
y = +0 | x > 0 | Just above positive x-axis | + 0 |
y > 0 | x > 0 | Quadrant I | + 0 < result < π∕2 |
y > 0 | x = ±0 | Positive y-axis | π∕2 |
y > 0 | x < 0 | Quadrant II | π∕2 < result < π |
y = +0 | x < 0 | Just below negative x-axis | π |
y = −0 | x < 0 | Just above negative x-axis | π |
y < 0 | x < 0 | Quadrant III | − π < result < −π∕2 |
y < 0 | x = ±0 | Negative y-axis | − π∕2 |
y < 0 | x > 0 | Quadrant IV | − π∕2 < result < −0 |
y = −0 | x > 0 | Just below positive x-axis | − 0 |
y = +0 | x = +0 | Near origin | + 0 |
y = −0 | x = +0 | Near origin | − 0 |
y = +0 | x = −0 | Near origin | π |
y = −0 | x = −0 | Near origin | − π |
Note that the case y = 0,x = 0 is an error in the absence of minus zero, but the four cases y = ±0,x = ±0 are defined in the presence of minus zero.
With only one argument y, the argument may be complex. The result is the arc tangent of y, which may be defined by the following formula:
Implementation note: This formula is mathematically correct, assuming completely accurate computation. It may be a terrible method for floating-point computation. Implementors should consult a good text on numerical analysis. The formula given above is not necessarily the simplest one for real-valued computations, either; it is chosen to define the branch cuts in desirable ways for the complex case.
For a non-complex argument y, the result is non-complex and lies between − π∕2 and π∕2 (both exclusive).
This global variable has as its value the best possible approximation to π in long floating-point format. For example:
An approximation to π in some other precision can be obtained by writing (float pi x), where x is a floating-point number of the desired precision, or by writing (coerce pi type), where type is the name of the desired type, such as short-float.
[Function]
sinh numberThese functions compute the hyperbolic sine, cosine, tangent, arc sine, arc cosine, and arc tangent functions, which are mathematically defined for an argument z as follows:
Note that the result of acosh may be complex even if the argument is not complex; this occurs when the argument is less than 1. Also, the result of atanh may be complex even if the argument is not complex; this occurs when the absolute value of the argument is greater than 1. __________________________
Implementation note: These formulae are mathematically correct, assuming completely accurate computation. They may be terrible methods for floating-point computation. Implementors should consult a good text on numerical analysis. The formulae given above are not necessarily the simplest ones for real-valued computations, either; they are chosen to define the branch cuts in desirable ways for the complex case.
Many of the irrational and transcendental functions are multiply defined in the complex domain; for example, there are in general an infinite number of complex values for the logarithm function. In each such case, a principal value must be chosen for the function to return. In general, such values cannot be chosen so as to make the range continuous; lines in the domain called branch cuts must be defined, which in turn define the discontinuities in the range.
Common Lisp defines the branch cuts, principal values, and boundary conditions for the complex functions following a proposal for complex functions in APL [36]. The contents of this section are borrowed largely from that proposal.
Indeed, X3J13 voted in January 1989 to alter the direction of continuity for the branch cuts of atan, and also to address the treatment of branch cuts in implementations that have a distinct floating-point minus zero.
The treatment of minus zero centers in two-argument atan. If there is no minus zero, then the branch cut runs just below the negative real axis as before, and the range of two-argument atan is (−π,π]. If there is a minus zero, however, then the branch cut runs precisely on the negative real axis, skittering between pairs of numbers of the form −x ± 0i, and the range of two-argument atan is [−π,π].
The treatment of minus zero by all other irrational and transcendental functions is then specified by defining those functions in terms of two-argument atan. First, phase is defined in terms of two-argument atan, and complex abs in terms of real sqrt; then complex log is defined in terms of phase, abs, and real log; then complex sqrt in terms of complex log; and finally all others are defined in terms of these.
Kahan [25] treats these matters in some detail and also suggests specific algorithms for implementing irrational and transcendental functions in IEEE standard floating-point arithmetic [23].
Remarks in the first edition about the direction of the continuity of branch cuts continue to hold in the absence of minus zero and may be ignored if minus zero is supported; since all branch cuts happen to run along the principal axes, they run between plus zero and minus zero, and so each sort of zero is associated with the obvious quadrant.
X3J13 voted in January 1989 to specify certain floating-point behavior when minus zero is supported. As a part of that vote it approved a mathematical definition of complex square root:
X3J13 voted in January 1989 to specify certain floating-point behavior when minus zero is supported. As a part of that vote it approved a mathematical definition of phase:
The X3J13 vote on minus zero would alter that exclusive bound of − π to be inclusive if minus zero is supported.
The two-argument logarithm function is defined as log bz = (log z)∕(log b). This defines the principal values precisely. The range of the two-argument logarithm function is the entire complex plane. It is an error if z is zero. If z is non-zero and b is zero, the logarithm is taken to be zero.
The branch cut for the arc sine function is in two pieces: one along the negative real axis to the left of − 1 (inclusive), continuous with quadrant II, and one along the positive real axis to the right of 1 (inclusive), continuous with quadrant IV. The range is that strip of the complex plane containing numbers whose real part is between − π∕2 and π∕2. A number with real part equal to − π∕2 is in the range if and only if its imaginary part is non-negative; a number with real part equal to π∕2 is in the range if and only if its imaginary part is non-positive.
X3J13 voted in January 1989 to replace the formula shown above with the formula
The branch cut for the arc tangent function is in two pieces: one along the positive imaginary axis above i (exclusive), continuous with quadrant I, and one along the negative imaginary axis below −i (exclusive), continuous with quadrant III. The points i and −i are excluded from the domain. The range is that strip of the complex plane containing numbers whose real part is between − π∕2 and π∕2. A number with real part equal to − π∕2 is in the range if and only if its imaginary part is strictly negative; a number with real part equal to π∕2 is in the range if and only if its imaginary part is strictly positive. Thus the range of the arc tangent function is not identical to that of the arc sine function.
Kahan [25] suggests the formula
The branch cut for the inverse hyperbolic cosine function lies along the real axis to the left of 1 (inclusive), extending indefinitely along the negative real axis, continuous with quadrant II and (between 0 and 1) with quadrant I. The range is that half-strip of the complex plane containing numbers whose real part is non-negative and whose imaginary part is between − π (exclusive) and π (inclusive). A number with real part zero is in the range if its imaginary part is between zero (inclusive) and π (inclusive).
WARNING! The formula shown above for hyperbolic arc tangent is incorrect. It is not a matter of incorrect branch cuts; it simply does not compute anything like a hyperbolic arc tangent. This unfortunate error in the first edition was the result of mistranscribing a (correct) APL formula from Penfield’s paper [36]. The formula should have been transcribed as
A proposal was submitted to X3J13 in September 1989 to replace the formula atanh with that recommended by Kahan [25]:
The branch cut for the inverse hyperbolic tangent function is in two pieces: one along the negative real axis to the left of − 1 (inclusive), continuous with quadrant II, and one along the positive real axis to the right of 1 (inclusive), continuous with quadrant IV. The points − 1 and 1 are excluded from the domain. The range is that strip of the complex plane containing numbers whose imaginary part is between − π∕2 and π∕2. A number with imaginary part equal to − π∕2 is in the range if and only if its real part is strictly positive; a number with imaginary part equal to π∕2 is in the range if and only if its real part is strictly negative. Thus the range of the inverse hyperbolic tangent function is not the same as that of the inverse hyperbolic sine function.
With these definitions, the following useful identities are obeyed throughout the applicable portion of the complex domain, even on the branch cuts:
sin iz = i sinh z | sinh iz = i sin z | arctan iz = i arctanh z |
cos i z = cosh z | cosh i z = cos z | arcsinh i z = i arcsin z |
tan iz = i tanh z | arcsin iz = i arcsinh z | arctanh iz = i arctan z |
I thought it would be useful to provide some graphs illustrating the behavior of the irrational and transcendental functions in the complex plane. It also provides an opportunity to show off the Common Lisp code that was used to generate them.
Imagine the complex plane to be decorated as follows. The real and imaginary axes are painted with thick lines. Parallels from the axes on both sides at distances of 1, 2, and 3 are painted with thin lines; these parallels are doubly infinite lines, as are the axes. Four annuli (rings) are painted in gradated shades of gray. Ring 1, the inner ring, consists of points whose radial distances from the origin lie in the range [1∕4, 1∕2]; ring 2 is in the radial range [3∕4, 1]; ring 3, in the range [π∕2, 2]; and ring 4, in the range [3,π]. Ring j is divided into 2j+1 equal sectors, with each sector painted a different shade of gray, darkening as one proceeds counterclockwise from the positive real axis.
We can illustrate the behavior of a numerical function f by considering how it maps the complex plane to itself. More specifically, consider each point z of the decorated plane. We decorate a new plane by coloring the point f(z) with the same color that point z had in the original decorated plane. In other words, the newly decorated plane illustrates how the f maps the axes, other horizontal and vertical lines, and annuli.
In each figure we will show only a fragment of the complex plane, with the real axis horizontal in the usual manner ( −∞ to the left, + ∞ to the right) and the imaginary axis vertical ( −∞i below, + ∞i above). Each fragment shows a region containing points whose real and imaginary parts are in the range [−4.1, 4.1]. The axes of the new plane are shown as very thin lines, with large tick marks at integer coordinates and somewhat smaller tick marks at multiples of π∕2.
Figure 12.1 shows the result of plotting the identity function (quite literally); the graph exhibits the decoration of the original plane.
Figures 12.2 through 12.20 show the graphs for the functions sqrt, exp, log, sin, asin, cos, acos, tan, atan, sinh, asinh, cosh, acosh, tanh, and atanh, and as a bonus, the graphs for the functions , , (z − 1)∕(z + 1), and (1 + z)∕(1 −z). All of these are related to the trigonometric functions in various ways. For example, if f(z) = (z − 1)∕(z + 1), then tanh z = f(e2z), and if g(z) = , then cos z = g(sin z). It is instructive to examine the graph for and try to visualize how it transforms the graph for sin into the graph for cos.
Each figure is accompanied by a commentary on what maps to what and other interesting features. None of this material is terribly new; much of it may be found in any good textbook on complex analysis. I believe that the particular form in which the graphs are presented is novel, as well as the fact that the graphs have been generated as PostScript [1] code by Common Lisp code. This PostScript code was then fed directly to the typesetting equipment that set the pages for this book. Samples of this PostScript code follow the figures themselves, after which the code for the entire program is presented.
In the commentaries that accompany the figures I sometimes speak of mapping the points ±∞ or ±∞i. When I say that function f maps + ∞ to a certain point z, I mean that
This figure was produced in exactly the same manner as succeeding figures, simply by
plotting the function identity instead of a numerical function. Thus the first of these
figures was produced by the last function of the first edition. I knew it would come in
handy someday!
The sqrt function maps the complex plane into the right half of the plane by slitting it
along the negative real axis and then sweeping it around as if half-closing a folding fan.
The fan also shrinks, as if it were made of cotton and had gotten wetter at the
periphery than at the center. The positive real axis is mapped onto itself. The
negative real axis is mapped onto the positive imaginary axis (but if minus zero is
supported, then −x + 0i is mapped onto the positive imaginary axis and −x − 0i
onto the negative imaginary axis, assuming x > 0). The positive imaginary
axis is mapped onto the northeast diagonal, and the negative imaginary axis
onto the southeast diagonal. More generally, lines are mapped to rectangular
hyperbolas (or fragments thereof) centered on the origin; lines through the
origin are mapped to degenerate hyperbolas (perpendicular lines through the
origin).
The exp function maps horizontal lines to radii and maps vertical lines to circles
centered at the origin. The origin is mapped to 1. (It is instructive to compare this graph
with those of other functions that map the origin to 1, for example (1 + z)∕(1 −z), cosz,
and .) The entire real axis is mapped to the positive real axis, with −∞
mapping to the origin and + ∞ to itself. The imaginary axis is mapped to
the unit circle with infinite multiplicity (period 2π); therefore the mapping of
the imaginary infinities ±∞i is indeterminate. It follows that the entire left
half-plane is mapped to the interior of the unit circle, and the right half-plane
is mapped to the exterior of the unit circle. A line at any angle other than
horizontal or vertical is mapped to a logarithmic spiral (but this is not illustrated
here).
The log function, which is the inverse of exp, naturally maps radial lines to horizontal
lines and circles centered at the origin to vertical lines. The interior of the unit circle is
thus mapped to the entire left half-plane, and the exterior of the unit circle is mapped to
the right half-plane. The positive real axis is mapped to the entire real axis, and the
negative real axis to a horizontal line of height π. The positive and negative imaginary
axes are mapped to horizontal lines of height ± π∕2. The origin is mapped to
−∞.
A line is a degenerate circle with infinite radius; when I say “circles” here I also mean
lines. Then (z − 1)∕(z + 1) maps circles into circles. All circles through − 1 become lines;
all lines become circles through 1. The real axis is mapped onto itself: 1 to the origin,
the origin to − 1, − 1 to infinity, and infinity to 1. The imaginary axis becomes the unit
circle; i is mapped to itself, as is −i. Thus the entire right half-plane is mapped to the
interior of the unit circle, the unit circle interior to the left half-plane, the left
half-plane to the unit circle exterior, and the unit circle exterior to the right
half-plane. Imagine the complex plane to be a vast sea. The Colossus of Rhodes
straddles the origin, its left foot on i and its right foot on −i. It bends down
and briefly paddles water between its legs so furiously that the water directly
beneath is pushed out into the entire area behind it; much that was behind swirls
forward to either side; and all that was before is sucked in to lie between its
feet.
The function h(z) = (1 + z)∕(1 −z) is the inverse of f(z) = (z − 1)∕(z + 1); that is,
h(f(z)) = f(h(z)) = z. At first glance, the graph of h appears to be that of f flipped
left-to-right, or perhaps reflected in the origin, but careful consideration of the shaded
annuli reveals that this is not so; something more subtle is going on. Note that
f(f(z)) = h(h(z)) = g(z) = −1∕z. The functions f, g, h, and the identity function thus form
a group under composition, isomorphic to the group of the cyclic permutations of the
points − 1, 0, 1, and ∞, as indeed these functions accomplish the four possible cyclic
permutations on those points. This function group is a subset of the group of bilinear
transformations (az + b)∕(cz + d), all of which are conformal (angle-preserving) and map
circles onto circles. Now, doesn’t that tangle of circles through − 1 look like something
the cat got into?
We are used to seeing sin looking like a wiggly ocean wave, graphed vertically as a
function of the real axis only. Here is a different view. The entire real axis is mapped to
the segment [−1,1] of the real axis with infinite multiplicity (period 2π). The imaginary
axis is mapped to itself as if by sinh considered as a real function. The origin is mapped
to itself. Horizontal lines are mapped to ellipses with foci at ± 1 (note that two
horizontal lines equidistant from the real axis will map onto the same ellipse). Vertical
lines are mapped to hyperbolas with the same foci. There is a curious accident: the
ellipse for horizontal lines at distance ± 1 from the real axis appears to intercept the
real axis at ± π∕2 ≈±1.57… but this is not so; the intercepts are actually at
± (e + 1∕e)∕2 ≈±1.54….
Just as sin grabs horizontal lines and bends them into elliptical loops around the origin,
so its inverse asin takes annuli and yanks them more or less horizontally straight.
Because sine is not injective, its inverse as a function cannot be surjective. This is just a
highfalutin way of saying that the range of the asin function doesn’t cover the
entire plane but only a strip π wide; arc sine as a one-to-many relation would
cover the plane with an infinite number of copies of this strip side by side,
looking for all the world like the tail of a peacock with an infinite number of
feathers. The imaginary axis is mapped to itself as if by asinh considered as a real
function. The real axis is mapped to a bent path, turning corners at ± π∕2 (the
points to which ± 1 are mapped); + ∞ is mapped to π∕2 −∞i, and −∞ to
− π∕2 + ∞i.
We are used to seeing cos looking exactly like sin, a wiggly ocean wave, only displaced.
Indeed the complex mapping of cos is also similar to that of sin, with horizontal and
vertical lines mapping to the same ellipses and hyperbolas with foci at ± 1, although
mapping to them in a different manner, to be sure. The entire real axis is again mapped
to the segment [−1,1] of the real axis, but each half of the imaginary axis is
mapped to the real axis to the right of 1 (as if by cosh considered as a real
function). Therefore ±∞i both map to + ∞. The origin is mapped to 1. Whereas
sin is an odd function, cos is an even function; as a result two points in each
annulus, one the negative of the other, are mapped to the same shaded point in
this graph; the shading shown here is taken from points in the original upper
half-plane.
The graph of acos is very much like that of asin. One might think that our nervous
peacock has shuffled half a step to the right, but the shading on the annuli shows that
we have instead caught the bird exactly in mid-flight while doing a cartwheel. This is
easily understood if we recall that arccosz = (π∕2) − arcsinz; negating arcsinz rotates it
upside down, and adding the result to π∕2 translates it π∕2 to the right. The imaginary
axis is mapped upside down to the vertical line at π∕2. The point + 1 is mapped to the
origin, and − 1 to π. The image of the real axis is again cranky; + ∞ is mapped to
+ ∞i, and −∞ to π −∞i.
The usual graph of tan as a real function looks like an infinite chorus line of disco
dancers, left hands pointed skyward and right hands to the floor. The tan function is
the quotient of sin and cos but it doesn’t much look like either except for having period
2π. This goes for the complex plane as well, although the swoopy loops produced
from the annulus between π∕2 and 2 look vaguely like those from the graph of
sin inside out. The real axis is mapped onto itself with infinite multiplicity
(period 2π). The imaginary axis is mapped backwards onto [−i,i]: + ∞i is
mapped to −i and −∞i to + i. Horizontal lines below or above the real axis
become circles surrounding + i or −i, respectively. Vertical lines become circular
arcs from + i to −i; two vertical lines separated by (2k + 1)π for integer k
together become a complete circle. It seems that two arcs shown hit the real
axis at ± π∕2 = ±1.57… but that is a coincidence; they really hit the axis at
± tan1 = 1.55….
All I can say is that this peacock is a horse of another color. At first glance, the
axes seem to map in the same way as for asin and acos, but look again: this
time it’s the imaginary axis doing weird things. All infinities map multiply to
the points (2k + 1)π∕2; within the strip of principal values we may say that
the real axis is mapped to the interval [−π∕2,+π∕2] and therefore −∞ is
mapped to − π∕2 and + ∞ to + π∕2. The point + i is mapped to + ∞i,
and −i to −∞i, and so the imaginary axis is mapped into three pieces: the
segment [−∞i,−i] is mapped to [π∕2,π∕2 −∞i]; the segment [−i,i] is mapped
to the imaginary axis [−∞i,+∞i]; and the segment [+i,+∞i] is mapped to
[−π∕2 + ∞i,−π∕2].
It would seem that the graph of sinh is merely that of sin rotated 90 degrees. If
that were so, then we would have sinhz = isinz. Careful inspection of the
shading, however, reveals that this is not quite the case; in both graphs the
lightest and darkest shades, which initially are adjacent to the positive real axis,
remain adjacent to the positive real axis in both cases. To derive the graph
of sinh from sin we must therefore first rotate the complex plane by − 90
degrees, then apply sin, then rotate the result by 90 degrees. In other words,
sinhz = isin(−i)z; consistently replacing z with iz in this formula yields the familiar
identity sinhiz = isinz.
The peacock sleeps. Because arcsinh iz = iarcsinz, the graph of asinh is related to that
of asin by pre- and post-rotations of the complex plane in the same way as for sinh and
sin.
The graph of cosh does not look like that of cos rotated 90 degrees; instead it looks like
that of cos unrotated. That is because coshiz is not equal to icosz; rather,
coshiz = cosz. Interpreted, that means that the shading is pre-rotated but there is no
post-rotation.
Hmm—I’d rather not say what happened to this peacock. This feather looks a bit
mangled. Actually it is all right—the principal value for acosh is so chosen that its graph
does not look simply like a rotated version of the graph of acos, but if all values were
shown, the two graphs would fill the plane in repeating patterns related by a
rotation.
The diagram for tanh is simply that of tan turned on its ear: itanz = tanhiz. The
imaginary axis is mapped onto itself with infinite multiplicity (period 2π), and the real
axis is mapped onto the segment [−1,+1]: + ∞ is mapped to + 1, and −∞ to − 1.
Vertical lines to the left or right of the real axis are mapped to circles surrounding
− 1 or 1, respectively. Horizontal lines are mapped to circular arcs anchored
at − 1 and + 1; two horizontal lines separated by a distance (2k + 1)π for
integer k are together mapped into a complete circle. How do we know these
really are circles? Well, tanhz = ((exp2z) − 1)∕((exp2z) + 1), which is the
composition of the bilinear transform (z − 1)∕(z + 1), the exponential expz, and
the magnification 2z. Magnification maps lines to lines of the same slope; the
exponential maps horizontal lines to circles and vertical lines to radial lines; and a
bilinear transform maps generalized circles (including lines) to generalized circles.
Q.E.D.
Here is a curious graph indeed for so simple a function! The origin is mapped to 1. The
real axis segment [0,1] is mapped backwards (and non-linearly) into itself; the segment
[1,+∞] is mapped non-linearly onto the positive imaginary axis. The negative real axis
is mapped to the same points as the positive real axis. Both halves of the imaginary axis
are mapped into [1,+∞] on the real axis. Horizontal lines become vaguely vertical, and
vertical lines become vaguely horizontal. Circles centered at the origin are transformed
into Cassinian (half-)ovals; the unit circle is mapped to a (half-)lemniscate of Bernoulli.
The outermost annulus appears to have its inner edge at π on the real axis
and its outer edge at 3 on the imaginary axis, but this is another accident;
the intercept on the real axis, for example, is not really at π ≈ 3.14… but at
= ≈ 3.16….
The graph of q(z) = looks like that of p(z) = except for the shading.
You might not expect p and q to be related in the same way that cos and cosh are,
but after a little reflection (or perhaps I should say, after turning it around in
one’s mind) one can see that q(iz) = p(z). This formula is indeed of exactly
the same form as coshiz = cosz. The function maps both halves of
the real axis into [1,+∞] on the real axis. The segments [0,i] and [0,−i] of
the imaginary axis are each mapped backwards onto segment [0,1] of the real
axis; [i,+∞i] and [−, −∞i] are each mapped onto the positive imaginary axis
(but if minus zero is supported then opposite sides of the imaginary axis map
to opposite halves of the imaginary axis—for example, q(+0 + 2i) = i but
q(−0 + 2i) = −i).
Here is a sample of the PostScript code that generated figure 12.1, showing the initial scaling, translation, and clipping parameters; the code for one sector of the innermost annulus; and the code for the negative imaginary axis. Comment lines indicate how path or boundary segments were generated separately and then spliced (in order to allow for the places that a singularity might lurk, in which case the generating code can “inch up” to the problematical argument value).
The size of the entire PostScript file for the identity function was about 68 kilobytes (2757 lines, including comments). The smallest files were the plots for atan and atanh, about 65 kilobytes apiece; the largest were the plots for sin, cos, sinh, and cosh, about 138 kilobytes apiece.
[2598 lines omitted]
[84 lines omitted]
Here is the program that generated the PostScript code for the graphs shown in figures 12.1 through 12.20. It contains a mixture of fairly general mechanisms and ad hoc kludges for plotting functions of a single complex argument while gracefully handling extremely large and small values, branch cuts, singularities, and periodic behavior. The aim was to provide a simple user interface that would not require the caller to provide special advice for each function to be plotted. The file for figure 12.1, for example, was generated by the call (picture ’identity), which resulted in the writing of a file named identity-plot.ps.
The program assumes that any periodic behavior will have a period that is a multiple of 2π; that branch cuts will fall along the real or imaginary axis; and that singularities or very large or small values will occur only at the origin, at ± 1 or ±i, or on the boundaries of the annuli (particularly those with radius π∕2 or π). The central function is parametric-path, which accepts four arguments: two real numbers that are the endpoints of an interval of real numbers, a function that maps this interval into a path in the complex plane, and the function to be plotted; the task of parametric-path is to generate PostScript code (a series of lineto operations) that will plot an approximation to the image of the parametric path as transformed by the function to be plotted. Each of the functions hline, vline, -hline, -vline, radial, and circumferential takes appropriate parameters and returns a function suitable for use as the third argument to parametric-path. There is some code that defends against errors (by using ignore-errors) and against certain peculiarities of IEEE floating-point arithmetic (the code that checks for not-a-number (NaN) results).
The program is offered here without further comment or apology.