When introducing complex algebra, we postponed discussion of what it means to raise a complex number to a non-integer power, such as $z^{1/2}$, $z^{4/3}$, or $z^{\pi}$. It is now time to open that can of worms. This will involve two important new concepts: branch points and branch cuts.
Given a complex number in its polar representation, $z = r\exp[i\theta]$, raising to the power of $p$ could be handled this way:
$$z^p = \left(re^{i\theta}\right)^p = r^p e^{ip\theta}.$$Let's take a closer look at the complex exponential term $e^{ip\theta}$. Since $\theta = \mathrm{arg}(z)$ is an angle, we can change it by any integer multiple of $2\pi$ without altering the value of $z$. Taking this into account, we can re-write the above equation more carefully as
$$z^p = \left(r\,e^{i(\theta + 2\pi n)}\right)^p = \left(r^p e^{ip\theta} \right) e^{2\pi i n p} \quad\; \mathrm{where}\;\; n\in\mathbb{Z}.$$Thus, there is an ambiguous factor of $\exp(2\pi i n p)$, where $n$ can be any integer. If $p$ is an integer, there is no problem, since $2\pi n p$ will be an integer multiple of $2\pi$, so $z^p$ has the same value regardless of $n$:
$$z^p = r^p e^{ip\theta} \;\;\textrm{unambiguously} \;\;\;(\text{if}\,p\in\mathbb{Z}).$$But if $p$ is not an integer, there is no unique answer, since $\exp\left(2 \pi i np\right)$ has different values for different $n$. In that case, "raising to the power of $p$" is a multi-valued operation. It cannot be treated as a function in the usual sense, since functions must have unambiguous outputs.
Let's take a closer look at the problematic exponential term,
$$\exp\left(2\pi i np\right), \quad n \in \mathbb{Z}.$$If $p$ is irrational, $2\pi np$ never repeats modulo $2\pi$. Thus, $z^p$ has an infinite set of values, one for each integer $n$.
More interesting is the case of a non-integer rational power. Any rational number can be written as $p = P/Q$ where $P$ and $Q$ are integers with no common divisor. It can be proven using modular arithmetic (though we will not go into the details) that $2\pi n\, (P/Q)$ has exactly $Q$ unique values modulo $2\pi$:
$$ 2\pi n\, \left(\frac{P}{Q}\right) = 2\pi \times \left\{0,\, \frac{1}{Q},\, \frac{2}{Q},\, \dots, \frac{(Q-1)}{Q} \right\} \quad(\mathrm{modulo} \; 2\pi).$$This set of values is independent of the numerator $P$, which merely affects the sequence in which the numbers are generated. We can clarify this using a few simple examples:
Example |
Consider the complex square root operation, $z^{1/2}$. If we write $z$ in its polar respresentation, $$z = r e^{i\theta},$$ then $$z^{1/2} = \left[r \, e^{i(\theta + 2 \pi n)} \right]^{1/2} = r^{1/2} \, e^{i\theta/2} \, e^{i \pi n}, \quad n \in \mathbb{Z}.$$ The factor of $e^{i\pi n}$ has two possible values: $+1$ for even $n$, and $-1$ for odd $n$. Hence, $$z^{1/2} = r^{1/2} \, e^{i\theta/2} \;\times\; \left\{1, -1\right\}.$$ |
Example |
Consider the cube root operation $z^{1/3}$. Again, we write $z$ in its polar representation, and obtain $$z^{1/3} = r^{1/3} \, e^{i\theta/3} \, e^{2\pi i n/3}, \quad n \in \mathbb{Z}.$$ The factor of $\exp(2\pi i n/3)$ has the following values for different $n$: $$\begin{array}{|c||c|c|c|c|c|c|c|c|c|} \hline n &\cdots & -2 & -1 & 0 & 1 & 2 & 3 & 4 & \cdots \\ \hline e^{2\pi i n/3} &\cdots & e^{2\pi i /3} & e^{-2\pi i /3} & \;\,\;1\;\,\; & e^{2\pi i /3} & e^{-2\pi i /3} & \;\,\;1\;\,\; & e^{2\pi i /3} & \cdots \\ \hline \end{array}$$ From the pattern, we see that there are three possible values of the exponential factor: $$e^{2\pi i n/3} = \left\{1, e^{2\pi i /3}, e^{-2\pi i /3}\right\}.$$ Therefore, the cube root operation has three distinct values: $$z^{1/3} = r^{1/3} \, e^{i\theta/3} \;\times\; \left\{1, e^{2\pi i /3}, e^{-2\pi i /3}\right\}.$$ |
Example |
Consider the operation $z^{2/3}$. Again, writing $z$ in its polar representation, $$z^{2/3} = r^{2/3} \, e^{2i\theta/3} \, e^{4\pi i n/3}, \quad n \in \mathbb{Z}.$$ The factor of $\exp(4\pi i n/3)$ has the following values for different $n$: $$\begin{array}{|c||c|c|c|c|c|c|c|c|c|} \hline n &\cdots & -2 & -1 & 0 & 1 & 2 & 3 & 4 & \cdots \\ \hline e^{4\pi i n/3} &\cdots & e^{-2\pi i /3} & e^{2\pi i /3} & \;\,\;1\;\,\; & e^{-2\pi i /3} & e^{2\pi i /3} & \;\,\;1\;\,\; & e^{-2\pi i /3} & \cdots \\ \hline \end{array}$$ Hence, there are three possible values of this exponential factor, $$e^{2\pi i n (2/3)} = \left\{1, e^{2\pi i /3}, e^{-2\pi i /3}\right\}.$$ Note that this is the exact same set we obtained for $e^{2\pi i n/3}$ in the previous example, in agreement with the earlier assertion that the numerator $P$ has no effect on the set of values. Thus, $$z^{2/3} = r^{2/3} \, e^{2i\theta/3} \;\times\; \left\{1, e^{2\pi i /3}, e^{-2\pi i /3}\right\}.$$ |
From the above examples, we deduce the following expression for rational powers:
$$z^{P/Q} = r^{P/Q} \; e^{i\theta\, (P/Q)}\, \times \Big\{1,\, e^{2\pi i /Q},\, e^{4\pi i /Q},\, \dots, e^{2\pi i (1-Q)/Q} \Big\}.$$The quantities in the curly brackets are called the roots of unity. In the complex plane, they sit at $Q$ evenly-spaced points on the unit circle, with $1$ as one of the values, as shown in the following figure.
In [3]:
## Demo: plot the roots of unity in the complex plane
%matplotlib inline
from ipywidgets import interact, IntSlider
from numpy import linspace, sin, cos, exp, pi, arange
import matplotlib.pyplot as plt
def plot_unity_roots(q):
plt.figure(figsize=(10,5))
ax = plt.subplot(1,1,1)
ax.set_aspect('equal')
## (Plot the circular arc that the points lie on.)
phi = linspace(-pi, pi, 50)
plt.plot(cos(phi), sin(phi), color='grey')
## Plot the roots of unity.
z = exp(1j*2*pi*arange(0, q)/q)
plt.plot(z.real, z.imag, 'o', color='blue', markersize=10)
## Axes, etc.
plt.title('{}-roots of unity'.format(q))
plt.axis([-1.2, 1.2, -1.2, 1.2])
plt.xlabel('Re(z)'); plt.ylabel('Im(z)')
plt.show()
interact(plot_unity_roots, q = IntSlider(min=1, max=20, step=1, value=5, description='Q'));
Here is another way to think about non-integer powers. Recall what it means to raise a number to, say, the power of 5: we simply multiply the number by itself five times. What about raising a number to a non-integer power $p$? For the real case, the power is defined as a combination of exponential and logarithm functions:
$$x^p \equiv \exp\Big[\,p\ln(x)\Big].$$This definition relies on the fact that, for real inputs, the logarithm is a well-defined function. That, in turn, comes from the definition of the logarithm as the inverse of the exponential function. Since the real exponential is one-to-one, its inverse is also one-to-one.
The complex exponential, however, is many-to-one, since changing its input by any multiple of $2\pi i$ yields the same output:
$$\exp(z + 2\pi i n) = \exp(z) \cdot e^{2\pi i n} = \exp(z) \quad \mathrm{for~all}\;\, n \in \mathbb{Z}.$$The inverse of the complex exponential is the complex logarithm. Since the complex exponential is many-to-one, the complex logarithm does not have a unique output. Instead, $\ln(z)$ refers to an infinite discrete set of values, separated by integer multiples of $2\pi i$. We can express this state of affairs in the following way:
$$\ln(z) = \big[\ln(z)\big]_{\mathrm{p.v.}}\, +\; 2 \pi i n, \quad n \in \mathbb{Z}.$$Here, $[\ln(z)]_{\mathrm{p.v.}}$ denotes the principal value of $\ln(z)$, which refers to a reference value of the logarithm operation (which we'll define later). Do not think of the principal value as the "actual" result of the $\ln(z)$ operation! There are multiple values, each equally legitimate; the principal value is merely one of these possible results.
We now apply the formula $z^p \equiv \exp\left[p\ln(z)\right]$, with $\ln(z)$ as the multi-valued complex logarithm. Then
$$\begin{align}z^p &= \exp\Big\{p\big(\big[\ln(z)\big]_{\mathrm{p.v.}} + 2\pi i n\big)\Big\}\\ &= \exp\Big\{p\,\big[\ln(z)\big]_{\mathrm{p.v.}}\Big\} \times e^{2\pi i np}, \quad n \in \mathbb{Z}.\end{align}$$The final factor, which is responsible for the multi-valuedness, are precisely the roots of unity.
We have discussed two examples of multi-valued complex operations: non-integer powers and the complex logarithm. However, we usually prefer to deal with functions rather than multi-valued operations. One reason is that the concept of the complex derivative is based on functions, not multi-valued operations.
There is a standard procedure to convert multi-valued operations into functions. First, we define one or more curve(s) in the complex plane, called branch cuts (the reason for this name will be explained later). Next, we modify the domain (i.e., the set of permissible inputs) by excluding all values of $z$ lying on a branch cut. Then the outputs of the multi-valued operation can be grouped into discrete branches, with each branch behaving just like a function.
The above procedure can be understood through the example of the square root.
We have previously seen that the complex square root, $z^{1/2}$, has two possible values. We can define the two branches as follows:
In the following plot, you can observe how varying $z$ affects the positions of $f_+(z)$ and $f_-(z)$ in the complex plane:
In [10]:
## Demo: plot the branches of the square root, in the complex plane
%matplotlib inline
from ipywidgets import interact, FloatSlider
from numpy import linspace, exp, sin, cos, pi, sqrt, real, imag
import matplotlib.pyplot as plt
def plot_sqrt_branches(argz, absz):
xlim, ylim = 3, 3
z = absz * exp(1j * argz)
plt.figure(figsize=(10,10)) # Show z in the left subplot
ax1 = plt.subplot(1,2,1)
ax1.set_aspect('equal')
plt.plot([-xlim, xlim], [0, 0], '--', linewidth=1, color="grey")
plt.plot([0, 0], [-ylim, ylim], '--', linewidth=1, color="grey")
plt.plot([-xlim, 0], [0, 0], linewidth=3, color="red", label='Branch cut')
plt.plot([0, xlim], [0, 0], '--', linewidth=1, color="grey")
plt.plot([0, real(z)], [0, imag(z)], linewidth=1, color="grey")
dr, phi = 0.25 * absz, linspace(0, argz, 30)
plt.plot(dr*cos(phi), dr*sin(phi), linewidth=1, color="grey")
plt.plot(real(z), imag(z), 'o', markersize=10, color="yellowgreen", label='z')
plt.title("Use sliders to adjust the value of z")
plt.axis([-xlim, xlim, -ylim, ylim])
plt.xlabel('x'); plt.ylabel('y')
plt.legend(numpoints=1, loc='best')
ax2 = plt.subplot(1,2,2) # Show f1 and f2 in the right subplot
ax2.set_aspect('equal')
x = sqrt(absz) * cos(0.5*argz)
y = sqrt(absz) * sin(0.5*argz)
plt.plot([-xlim, xlim], [0, 0], '--', linewidth=1, color="grey")
plt.plot([0, 0], [-ylim, ylim], '--', linewidth=1, color="grey")
plt.plot(x, y, '*', markersize=12, color="mediumblue", label='f_+(z)')
plt.plot(-x, -y, '*', markersize=12, color="darkorange", label='f_-(z)')
plt.title("Branches of the complex square root")
plt.axis([-xlim, xlim, -ylim, ylim])
plt.xlabel('x'); plt.ylabel('y')
plt.legend(numpoints=1, loc='best')
plt.show()
interact(plot_sqrt_branches,
argz = FloatSlider(min=-3.1, max=3.1, step=0.1, value=0.0, description='arg(z)'),
absz = FloatSlider(min=0.0, max=2.0, step=0.2, value=2.0, description='|z|'));
The red line in the figure indicates the branch cut. Our definitions of $f_+(z)$ and $f_-(z)$ implicitly depend on the choice of placing the branch cut on the negative real axis, which led to the representation of the argument of $z$ as $\theta \in (-\pi,\pi)$.
In the above plot, note that $f_+(z)$ always lies in the right half of the complex plane, whereas $f_-(z)$ lies in the left half of the complex plane. Both $f_+$ and $f_-$ are well-defined functions with unambiguous outputs, albeit with domains that do not cover the entire complex plane. Moreover, they are analytic over their entire domain (i.e., all of the complex plane except the branch cut); this can be proven using the Cauchy-Riemann equations, and is left as an exercise.
The end-point of the branch cut is called a branch point. For $z = 0$, both branches give the same result: $f_+(0) = f_-(0) = 0$. We will have more to say about branch points below.
In the above example, you may be wondering why the branch cut has to lie along the negative real axis. In fact, this choice is not unique. For instance, we could place the branch cut along the positive real axis. This corresponds to specifying the input $z$ using a different interval for $\theta$:
$$z = re^{i\theta}, \quad \theta \in (0, 2\pi).$$Next, we use the same formulas as before to define the branches of the complex square root:
$$f_\pm(z) = \pm r^{1/2} \, e^{i\theta/2}.$$But because the domain of $\theta$ has been changed to $(0, 2\pi)$, the set of inputs $z$ now excludes the positive real axis. With this new choice of branch cut, the branches are shown in the following figure.
In [14]:
## Demo: plot the branches of the square root, in the complex plane
%matplotlib inline
from ipywidgets import interact, FloatSlider
from numpy import linspace, exp, sin, cos, pi, sqrt, real, imag
import matplotlib.pyplot as plt
def plot_sqrt_branches(argz, absz):
xlim, ylim = 3, 3
z = absz * exp(1j*argz)
plt.figure(figsize=(10,10)) # Show z in the left subplot
ax1 = plt.subplot(1,2,1)
ax1.set_aspect('equal')
plt.plot([-xlim, xlim], [0, 0], '--', linewidth=1, color="grey")
plt.plot([0, 0], [-ylim, ylim], '--', linewidth=1, color="grey")
plt.plot([0, xlim], [0, 0], linewidth=3, color="red", label='Branch cut')
plt.plot([0, xlim], [0, 0], '--', linewidth=1, color="grey")
plt.plot([0, real(z)], [0, imag(z)], linewidth=1, color="grey")
dr, phi = 0.25 * absz, linspace(0, argz, 30)
plt.plot(dr*cos(phi), dr*sin(phi), linewidth=1, color="grey")
plt.plot(real(z), imag(z), 'o', markersize=10, color="yellowgreen", label='z')
plt.title("Use sliders to adjust the value of z")
plt.axis([-xlim, xlim, -ylim, ylim])
plt.xlabel('x'); plt.ylabel('y')
plt.legend(numpoints=1, loc='best')
ax2 = plt.subplot(1,2,2) # Show f1 and f2 in the right subplot
ax2.set_aspect('equal')
x = sqrt(absz) * cos(0.5*argz)
y = sqrt(absz) * sin(0.5*argz)
plt.plot([-xlim, xlim], [0, 0], '--', linewidth=1, color="grey")
plt.plot([0, 0], [-ylim, ylim], '--', linewidth=1, color="grey")
plt.plot(x, y, '*', markersize=12, color="mediumblue", label='f_+(z)')
plt.plot(-x, -y, '*', markersize=12, color="darkorange", label='f_-(z)')
plt.title("Branches of the complex square root")
plt.axis([-xlim, xlim, -ylim, ylim])
plt.xlabel('x'); plt.ylabel('y')
plt.legend(numpoints=1, loc='best')
plt.show()
interact(plot_sqrt_branches,
argz = FloatSlider(min=0.1, max=6.2, step=0.1, value=3.14, description='arg(z)'),
absz = FloatSlider(min=0.0, max=2.0, step=0.2, value=2.0, description='|z|'));
These two branch functions are different from what we had before. Now, $f_+(z)$ is always in the upper half of the complex plane, and $f_-(z)$ in the lower half of the complex plane. However, both branches still have the same value at the branch point: $f_+(0) = f_-(0) = 0$.
The branch cut serves as a boundary where\ two branches are "glued" together. We can think of "crossing" a branch cut as having the effect of moving continuously from one branch to another. In the above figure, for example, consider the case where $\mathrm{arg}(z) = 0.1$, just above the branch cut. Observe that $f_+(z)$ lies just above the positive real axis, and $f_-(z)$ lies just below the negative real axis. Next, change the argument to $\mathrm{arg}(z) = 6.2$, so that $z$ lies just below the branch cut. This is equivalent to a small downwards displacement of $z$, "crossing" the branch cut. Observe that $f_-(z)$ now lies just below the positive real axis, near where $f_+(z)$ was previously, and $f_+(z)$ now lies just above the negative real axis where $f_-(z)$ was previously. Crossing the branch cut thus swaps the values of the positive and negative branches.
The three-dimensional plot below provides another way to visualize the role of the branch cut. Here, the horizontal axes correspond to $x = \mathrm{Re}(z)$ and $y = \mathrm{Im}(z)$. The vertical axis shows the arguments for the two values of the complex square root, with $\mathrm{arg}\big[f_+(z)\big]$ plotted in orange and $\mathrm{arg}\big[f_-(z)\big]$ plotted in blue. As you vary the choice of the branch cut, observe that this affects which values of the multi-valued operation are assigned to the $+$ (orange) branch, and which values are assigned to the $-$ (blue) branch. Hence, the choice of branch cut is just a choice about how to divide up the branches of a multi-valued operation.
In [16]:
## Demo: 3D plot of the arguments of the square root.
## This may take some time to run.
%matplotlib inline
from ipywidgets import interact, FloatSlider
from numpy import linspace, meshgrid, cos, sin, pi, ones
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.tri as mtri
def plot_sqrt_arg(thetab):
rmin, rmax, nr = 0.05, 3., 25
rvec = linspace(rmin, rmax, nr)
npmin, dphi = 10, 0.1
def plot_branch(ax, phimin, phimax, m, plus_branch):
delta_phi = phimax - phimin
if delta_phi < 1e-4: return
## Generate a triangular mesh for the surface
nphi = max(npmin, int(delta_phi/dphi))
phivec = linspace(phimin, phimax, nphi)
rr, pp = meshgrid(rvec, phivec)
xt, yt = rr*cos(pp), rr*sin(pp)
x, y = xt.flatten(), yt.flatten()
tri = mtri.Triangulation(x, y).triangles
phi = 0.5*pp.flatten() + m * pi
if plus_branch:
col = "darkorange"
else:
col = "royalblue"
ax.plot_trisurf(x, y, phi, triangles=tri,
linewidth=0.1, alpha=1.0, color=col)
fig = plt.figure(figsize=(12,6))
ax = fig.add_subplot(1, 1, 1, projection='3d')
## Draw some guides to the eye
phi = linspace(-pi, pi, 200)
ax.plot(rmax*cos(phi), rmax*sin(phi), -pi*ones(len(phi)), color="grey")
ax.plot([0, rmax*cos(thetab)], [0, rmax*sin(thetab)], [-pi, -pi],
linewidth=3, color="red")
## We will plot the branches in several segments, then join them.
## Main parts of + branch and - branch:
if thetab < 0:
plot_branch(ax, thetab, 0, 0, True)
plot_branch(ax, 0, pi, 0, True)
plot_branch(ax, -pi, thetab, 0, False)
else:
plot_branch(ax, thetab, pi, 0, True)
plot_branch(ax, -pi, 0, 0, False)
plot_branch(ax, 0, thetab, 0, False)
theta1 = min(thetab, 0)
plot_branch(ax, -pi + 0.001, theta1, 1, True) # Upper part of + branch
plot_branch(ax, theta1, 0, 1, False) # Upper part of - branch
theta2 = max(thetab, 0)
plot_branch(ax, 0, theta2, -1, True) # Lower part of + branch
plot_branch(ax, theta2, pi, -1, False) # Lower part of - branch
## Set plot axis parameters
ax.view_init(elev=30., azim=-100)
ax.set_xlabel('x'); ax.set_ylabel('y'); ax.set_zlabel('arg(f)')
ax.set_xlim3d(-rmax, rmax); ax.set_ylim3d(-rmax, rmax); ax.set_zlim3d(-pi, pi)
plt.show()
interact(plot_sqrt_arg,
thetab = FloatSlider(min=-3.1, max=3.1, step=0.1, value=-3.1,
description='Branch cut angle'));
The tip of each branch cut is called a branch point. A branch point is a point where different branches yield the same output, and the usual multi-valuedness goes away. Whereas the choice of branch cuts is non-unique, the positions of the branch points of a multi-valued operation are uniquely determined.
For the purposes of this course, you mostly only need to remember the branch points arising from two common cases:
We can easily see that $z^p$ must have a branch point at $z = 0$: its only possible value at the origin is $0$, regardless of which root of unity we choose. To understand the other branch points listed above, a clearer understanding of the concept of "infinity" for complex numbers is required, so we will discuss that now.
When talking about $z = \infty$, we are referring to something called complex infinity, which can be regarded as a complex number with infinite magnitude and undefined argument.
The fact that the argument is undefined may seem strange, but actually we already know of another complex number with this feature: $z = 0$ has zero magnitude and undefined argument. These two special complex numbers are the reciprocals of each other: $1/\infty = 0$ and $1/0 = \infty$.
The complex $\infty$ behaves differently from the familiar concept of infinity associated with real numbers. For real numbers, positive infinity ($+\infty$) is distinct from negative infinity ($-\infty$). But this doesn't hold for complex numbers, since complex numbers occupy a two-dimensional plane rather than a line. Thus, for complex numbers it does not make sense to define "positive infinity" and "negative infinity" as distinct entities. Instead, we work with a single complex $\infty$.
From this discussion, we can see why $z^p$ has a branch point at $z = \infty$. For any finite and nonzero $z$, we can write $z = re^{i\theta}$, where $r$ is a positive number. The $z^p$ operation then yields a set of complex numbers of the form $r^p \, e^{ip\theta}\,\times\, \{\text{root of unity}\}$. For each number in this set, the magnitude goes to infinity as $r \rightarrow \infty$. In this limit, the argument (i.e., the choice of root of unity) becomes irrelevant, and the result is simply $\infty$.
By similar reasoning, one can prove that $\ln(z)$ has branch points at $z = 0$ and $z = \infty$. This is left as an exercise.
Having discussed the simplest multi-valued operations, $z^p$ and $\ln(z)$, here is how to assign branch cuts for more general multi-valued operations. This is a two-step process:
The choice of where to place branch cuts is not unique. Branch cuts are usually chosen to be straight lines, for simplicity, but this is not necessary. Different choices of branch cuts correspond to different ways of partitioning the values of the multi-valued operation into separate branches.
We can illustrate the process of assigning branch cuts, and defining branch functions, using the following nontrivial multi-valued operation:
$$f(z) = \ln\left(\frac{z+1}{z-1}\right).$$This is multi-valued because of the presence of the complex logarithm. The branch points are $z = 1$ and $z = -1$, as these are the points where the input to the logarithm becomes $\infty$ or $0$ respectively. Note that $z = \infty$ is not a branch point; at $z = \infty$, the input to the logarithm is $-1$, which is not a branch point for the logarithm.
We can assign any branch cut that joins the branch points at $z = \pm 1$. A convenient choice is shown below:
This choice of branch cut is nice because we can express the $z+1$ and $z - 1$ terms using the polar representations
$$\begin{align}z + 1 &= r_1\,e^{i\theta_1}, \\ z - 1 &= r_2\, e^{i\theta_2},\end{align}$$where $r_1$, $r_2$, $\theta_1$, and $\theta_2$ are shown graphically in the above figure. The positioning of the branch cut corresponds to a particular choice for the ranges of the complex arguments $\theta_1$ and $\theta_2$. As we'll shortly see, the present choice of branch cut corresponds to
$$\theta_1 \in (-\pi,\pi), \quad \theta_2 \in (-\pi,\pi).$$Hence, in terms of this polar representation, $f(z)$ can be written as
$$f(z) = \ln\left(\frac{r_1}{r_2}\right) + i(\theta_1 - \theta_2 + 2\pi m), \quad m\in\mathbb{Z},$$$$\mathrm{where}\; z = -1 + r_1\,e^{i\theta_1} = 1 + r_2\,e^{i\theta_2},\quad\theta_1, \theta_2 \in (-\pi,\pi).$$The choice of $m$ specifies the branch, and we can choose $m = 0$ as the principal branch.
Let's now verify that setting $\theta_1 \in (-\pi,\pi)$ and $\theta_2 \in (-\pi,\pi)$ is consistent with our choice of branch cut. Consider the principal branch, and compare the outputs of the above formula for $z$ just above the real axis, and for $z$ just below the real axis. There are three cases of interest. Firstly, for $\mathrm{Re}(z) < 1$ (to the left of the leftmost branch point),
$$\begin{aligned}\mathrm{Im}(z) &= 0^+ \;\;\Rightarrow\;\; f(z) = \ln\left(\frac{r_1}{r_2}\right) + i\Big((\pi) - (\pi)\Big) \quad = \ln\left(\frac{r_1}{r_2}\right) \\ \mathrm{Im}(z) &= 0^- \;\;\Rightarrow \;\; f(z) = \ln\left(\frac{r_1}{r_2}\right) + i\Big((-\pi) - (-\pi)\Big) = \ln\left(\frac{r_1}{r_2}\right).\end{aligned}$$Thus, there is no discontinuity along this segment of the real axis.
Secondly, for $-1 < \mathrm{Re}(z) < 1$ (between the two branch points),
$$\begin{aligned}\mathrm{Im}(z) &= 0^+ \;\;\Rightarrow\;\; f(z) = \ln\left(\frac{r_1}{r_2}\right) + i\Big((0) - (\pi)\Big) \;\;= \ln\left(\frac{r_1}{r_2}\right) -i\pi \\ \mathrm{Im}(z) &= 0^- \;\;\Rightarrow\;\; f(z) = \ln\left(\frac{r_1}{r_2}\right) + i\Big((0) - (-\pi)\Big) = \ln\left(\frac{r_1}{r_2}\right) + i\pi.\end{aligned}$$Hence, in the segment between the two branch points, there is a discontinuity of $\pm 2\pi i$ on different sides of the real axis. The value of this discontinuity is exactly equal, of course, to the separation between the different branches of the complex logarithm.
Finally, for $\mathrm{Re}(z) > 1$ (to the right of the rightmost branch point), there is again no discontinuity:
$$\begin{aligned}\mathrm{Im}(z) &= 0^+ \;\;\Rightarrow\;\; f(z) = \ln\left(\frac{r_1}{r_2}\right) + i\Big((0) - (0)\Big) = \ln\left(\frac{r_1}{r_2}\right) \\ \mathrm{Im}(z) &= 0^- \;\;\Rightarrow\;\; f(z) = \ln\left(\frac{r_1}{r_2}\right) + i\Big((0) - (0)\Big) = \ln\left(\frac{r_1}{r_2}\right).\end{aligned}$$