Difficulty: Beginner

* Shaking off the Rust* is a series of exercises with the Rust programing language. The purpose of the series is to improve both my and my dear reader's abilities with Rust by building things. Plus, by actually building stuff, we'll learn about an array of technological concepts in the process. In this installment, we're going to dig into complex numbers.

This installment's Github repo: https://github.com/josht-jpg/rust-complex-numbers

Complex numbers are simple. They have the form $a + bi$, where $a$ and $b$ are real numbers, and $i$, called the *imaginary unit*, has the property $i^2 = -1$ [1]. We call $a$ the real part of the complex number and $b$ the imaginary part. Real numbers and complex numbers follow the same laws of arithmetic [2]. Let’s explore complex numbers, and learn some stuff about Rust along the way.

As usual, we’ll begin by creating a new library with Cargo.

```
cargo new complex_numbers --lib
cd complex_numbers
```

I’m going to use a *tuple struct* to represent Complex numbers. Tuple structs are structs that do not have names for their fields. Tuple structs are useful when you want to give a name to the tuple, but naming each field would be verbose [3].

Here’s what our `Complex`

tuple struct looks like:

```
// lib.rs
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Complex(pub f64, pub f64);
```

The first number in the Complex tuple struct represents the real part of the complex number and the second number represents the imaginary part.

I’ve talked about each of those derived traits in the DNA Analysis installment of *Shaking off the Rust*, so I won’t repeat myself here.

If the traits being derived are unfamiliar to you, I urge you to give some of the Rust documentation a quick read:

These are common traits that you will see many times while working with Rust.

You can probably guess how adding complex numbers works. For any two complex numbers

$a + bi, c + di$, we have that $(a + bi) + (c + di) = (a + c) + (b + d)i$ [2].

Let’s try it in Rust:

```
pub fn add(z1: &Complex, z2: &Complex) -> Complex {
let Complex(a, b) = z1;
let Complex(c, d) = z2;
Complex(a + c, b + d)
}
```

If this is your first time seeing a tuple struct being destructured, the syntax may be confusing

`let Complex(a, b) = z1;`

By the end of this session of SOTR, that syntax will be second nature to you.

Let’s give the `add`

function a short test. We’ll see how it adds $(-2.5 + 4i)$ and $(5.5 + 1.5i)$ together (we should get back $(3 + 5.5i)$).

```
// lib.rs
/*...*/
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_test() {
let z1 = Complex(-2.5, 4.);
let z2 = Complex(5.5, 1.5);
assert_eq!(add(&z1, &z2), Complex(3., 5.5));
}
}
```

As you can see, we instantiate tuple structs with round brackets: `let z1 = Complex(-2.5, 4.);`

, rather than the curly braces we use for regular structs.

Multiplying complex numbers is also straight forward:

$(a + bi)(c + di) = ac + adi + cbi - bd = (ac - bd) + (ad + cb)i$

which follows from the relation $i^2 = -1$. Cool.

Again, trying that in Rust:

```
pub fn mult(z1: &Complex, z2: &Complex) -> Complex {
let Complex(a, b) = z1;
let Complex(c, d) = z2;
Complex(a * c - b * d, a * d + b * c)
}
```

Cool cool cool. Not too hard.

Testing this with $(-2 + 4i)$ and $(2.5 + 0.5i)$, we looking for a result of $(-7 + 9i)$:

```
#[cfg(test)]
mod tests {
/*...*/
#[test]
fn mult_test() {
let z1 = Complex(-2., 4.);
let z2 = Complex(2.5, 0.5);
assert_eq!(mult(&z1, &z2), Complex(-7., 9.));
}
}
```

Dividing complex numbers is more complex than the previous two operations.

Let’s say we want to find the result of $\frac{a+bi}{c+di}$ (here we are assuming $c + di$ is not equal to $0$). Let $x + yi$ be the quotient: $\frac{a+bi}{c+di} = x+yi$.

So $a+bi = (c+di)(x+yi)$, which can be rewritten as $a+bi = (cx - dy) + (cy + dx)i$.

Thus, we have the system of equations: $a = cd - dy, b = cy + dx$.

The unique solution to this system is: $a = \frac{ac + bd}{c^2 + d^2}, b = \frac{bc - ad}{c^2 + d^2}$ [2].

Congrats if you got through that. Let’s see what a Rust implementation looks like.

```
pub fn div(z1: &Complex, z2: &Complex) -> Complex {
let Complex(a, b) = z1;
let Complex(c, d) = z2;
Complex(
(a * c + b * d) / (c.powi(2) + d.powi(2)),
(b * c - a * d) / (c.powi(2) + d.powi(2)),
)
}
```

If this is the first time you’ve seen Rust’s `powi`

method, note that it raises numbers to an integer power [4]. You could probably guess that from reading the code - I bring it up to point out there also exists a `powf`

method, which raises numbers to a floating-point number (but is generally slower than `powi`

).

As per usual, we’ll run a test. Using a dividend of $(8 + 4i)$ and a divisor of $(3 -3i)$, we expect our program to return $(\frac{2}{3} + 2i)$.

```
#[cfg(test)]
mod tests {
/*...*/
#[test]
fn div_test() {
let z1 = Complex(8., 4.);
let z2 = Complex(3., -3.);
assert_eq!(div(&z1, &z2), Complex(2. / 3., 2.))
}
}
```

There’s something I haven’t told you. This installment of SOTR is a setup for next week’s. Here’s a hint on what we’ll be doing:

We’ll need one more operation on complex numbers for next week: the magnitude.

The magnitude of a complex number $z = a+bi$ is $|z| = \sqrt{a^2 + b^2}$.

This is easy to implement in Rust:

```
pub fn magnitude(z: &Complex) -> f64 {
let Complex(a, b) = z;
(a.powi(2) + b.powi(2)).sqrt()
}
```

And we’ll finish off with a test:

```
#[cfg(test)]
mod tests {
/*...*/
#[test]
fn magnitude_test() {
let z = Complex(-3., 4.);
assert_eq!(magnitude(&z), 5.);
}
}
```

If that passed for you then congratulations! You’ve completed this week’s exercises and are ready for next week’s admittedly more exciting installment.

Thank you for coding with me, friends. I hope this post has left you one step closer to becoming the best programmer you can be.

[1] Needham, T. (2009). *Visual Complex Analysis. *Oxford University Press.

[2] Ahlfors, L. (1953). *Complex Analysis: An Introduction to The Theory of Analytic Functions of One Complex Variable. *McGraw-Hill Education.

[3] Nichols, C. and Klabnik, S. (2018). *The Rust Programming Language.* No Starch Press.

Creating and running *Shaking off the Rust* is one of the most fulfilling things I do. But it's exhausting. By supporting me, even if it's just a dollar, you'll allow me to put more time into building this series. I really appreciate any support.

The only way to support me right now is by sponsoring me on Github. I'll probably also set up Patreon and Donorbox pages soon.

Thank you so much!

No spam. Unsubscribe anytime.